summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.git-blame-ignore-revs2
-rw-r--r--bfdd/bfd.h4
-rw-r--r--bfdd/bfd_packet.c6
-rw-r--r--bgpd/bgp_advertise.c3
-rw-r--r--bgpd/bgp_attr.c200
-rw-r--r--bgpd/bgp_attr.h2
-rw-r--r--bgpd/bgp_bfd.c3
-rw-r--r--bgpd/bgp_bmp.c38
-rw-r--r--bgpd/bgp_bmp.h2
-rw-r--r--bgpd/bgp_damp.c6
-rw-r--r--bgpd/bgp_debug.c11
-rw-r--r--bgpd/bgp_debug.h3
-rw-r--r--bgpd/bgp_ecommunity.c97
-rw-r--r--bgpd/bgp_ecommunity.h60
-rw-r--r--bgpd/bgp_evpn.c330
-rw-r--r--bgpd/bgp_evpn.h8
-rw-r--r--bgpd/bgp_evpn_mh.c175
-rw-r--r--bgpd/bgp_evpn_mh.h10
-rw-r--r--bgpd/bgp_evpn_private.h3
-rw-r--r--bgpd/bgp_fsm.c18
-rw-r--r--bgpd/bgp_label.c2
-rw-r--r--bgpd/bgp_main.c2
-rw-r--r--bgpd/bgp_mpath.c24
-rw-r--r--bgpd/bgp_mplsvpn.c68
-rw-r--r--bgpd/bgp_mplsvpn.h10
-rw-r--r--bgpd/bgp_network.c4
-rw-r--r--bgpd/bgp_nexthop.c4
-rw-r--r--bgpd/bgp_nexthop.h1
-rw-r--r--bgpd/bgp_nht.c9
-rw-r--r--bgpd/bgp_open.c32
-rw-r--r--bgpd/bgp_packet.c23
-rw-r--r--bgpd/bgp_route.c696
-rw-r--r--bgpd/bgp_route.h20
-rw-r--r--bgpd/bgp_routemap.c79
-rw-r--r--bgpd/bgp_routemap_nb_config.c6
-rw-r--r--bgpd/bgp_rpki.c24
-rw-r--r--bgpd/bgp_snmp_bgp4.c4
-rw-r--r--bgpd/bgp_table.h9
-rw-r--r--bgpd/bgp_updgrp_adv.c23
-rw-r--r--bgpd/bgp_vpn.c2
-rw-r--r--bgpd/bgp_vty.c334
-rw-r--r--bgpd/bgp_vty.h2
-rw-r--r--bgpd/bgp_zebra.c315
-rw-r--r--bgpd/bgp_zebra.h13
-rw-r--r--bgpd/bgpd.c69
-rw-r--r--bgpd/bgpd.h15
-rw-r--r--bgpd/rfapi/rfapi.c6
-rw-r--r--configure.ac19
-rw-r--r--debian/changelog12
-rw-r--r--debian/control2
-rw-r--r--doc/developer/building-libyang.rst2
-rw-r--r--doc/developer/cross-compiling.rst2
-rw-r--r--doc/developer/northbound/advanced-topics.rst12
-rw-r--r--doc/developer/northbound/architecture.rst2
-rw-r--r--doc/developer/northbound/demos.rst20
-rw-r--r--doc/developer/northbound/links.rst8
-rw-r--r--doc/developer/northbound/operational-data-rpcs-and-notifications.rst50
-rw-r--r--doc/developer/northbound/plugins-sysrepo.rst4
-rw-r--r--doc/developer/static-linking.rst2
-rw-r--r--doc/developer/zebra.rst15
-rw-r--r--doc/user/bgp.rst38
-rw-r--r--doc/user/bmp.rst7
-rw-r--r--doc/user/installation.rst5
-rw-r--r--doc/user/isisd.rst29
-rw-r--r--doc/user/ospf6d.rst6
-rw-r--r--doc/user/ospf_fundamentals.rst10
-rw-r--r--doc/user/ospfd.rst64
-rw-r--r--doc/user/rpki.rst9
-rw-r--r--isisd/isis_adjacency.c4
-rw-r--r--isisd/isis_lfa.c5
-rw-r--r--isisd/isis_pdu.c2
-rw-r--r--isisd/isis_spf.c2
-rw-r--r--isisd/isis_sr.c7
-rw-r--r--isisd/isis_sr.h2
-rw-r--r--isisd/isis_srv6.c6
-rw-r--r--isisd/isis_srv6.h2
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--lib/command.c2
-rw-r--r--lib/command.h2
-rw-r--r--lib/frr_pthread.c35
-rw-r--r--lib/frr_pthread.h11
-rw-r--r--lib/keychain_nb.c8
-rw-r--r--lib/lib_errors.c18
-rw-r--r--lib/lib_errors.h3
-rw-r--r--lib/libfrr.c11
-rw-r--r--lib/libfrr.h11
-rw-r--r--lib/libospf.h1
-rw-r--r--lib/mgmt_fe_client.c54
-rw-r--r--lib/mgmt_fe_client.h45
-rw-r--r--lib/mgmt_msg_native.c2
-rw-r--r--lib/mgmt_msg_native.h63
-rw-r--r--lib/nexthop.c8
-rw-r--r--lib/nexthop.h4
-rw-r--r--lib/northbound.c219
-rw-r--r--lib/northbound.h44
-rw-r--r--lib/northbound_confd.c1494
-rw-r--r--lib/northbound_oper.c34
-rw-r--r--lib/plist.c30
-rw-r--r--lib/routemap_cli.c4
-rw-r--r--lib/srv6.c4
-rw-r--r--lib/stream.c6
-rw-r--r--lib/stream.h2
-rw-r--r--lib/subdir.am13
-rw-r--r--lib/vrf.c2
-rw-r--r--lib/vty.c40
-rw-r--r--lib/vty.h4
-rw-r--r--lib/yang.c63
-rw-r--r--lib/yang.h16
-rw-r--r--lib/zclient.c39
-rw-r--r--lib/zclient.h2
-rw-r--r--mgmtd/mgmt_fe_adapter.c194
-rw-r--r--mgmtd/mgmt_fe_adapter.h20
-rw-r--r--mgmtd/mgmt_txn.c96
-rw-r--r--mgmtd/mgmt_txn.h41
-rw-r--r--mgmtd/mgmt_vty.c59
-rw-r--r--mgmtd/subdir.am1
-rw-r--r--nhrpd/nhrp_nhs.c12
-rw-r--r--ospf6d/ospf6_gr_helper.c9
-rw-r--r--ospf6d/ospf6_interface.c602
-rw-r--r--ospf6d/ospf6_neighbor.c102
-rw-r--r--ospfd/ospf_apiserver.c27
-rw-r--r--ospfd/ospf_apiserver.h8
-rw-r--r--ospfd/ospf_flood.c5
-rw-r--r--ospfd/ospf_interface.c49
-rw-r--r--ospfd/ospf_interface.h19
-rw-r--r--ospfd/ospf_ism.c2
-rw-r--r--ospfd/ospf_main.c24
-rw-r--r--ospfd/ospf_neighbor.c4
-rw-r--r--ospfd/ospf_nsm.c4
-rw-r--r--ospfd/ospf_packet.c102
-rw-r--r--ospfd/ospf_snmp.c26
-rw-r--r--ospfd/ospf_sr.c4
-rw-r--r--ospfd/ospf_vty.c326
-rw-r--r--ospfd/ospf_zebra.c14
-rw-r--r--ospfd/ospfd.c7
-rw-r--r--pimd/pim_cmd.c15
-rw-r--r--pimd/pim_cmd_common.c11
-rw-r--r--pimd/pim_iface.c2
-rw-r--r--redhat/frr.spec.in18
-rw-r--r--sharpd/sharp_vty.c6
-rw-r--r--snapcraft/snapcraft.yaml.in2
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref6
-rw-r--r--tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json45
-rw-r--r--tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json44
-rw-r--r--tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py16
-rw-r--r--tests/topotests/bfd_topo3/test_bfd_topo3.py2
-rw-r--r--tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py7
-rw-r--r--tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json1
-rw-r--r--tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json1
-rw-r--r--tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py2
-rw-r--r--tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py4
-rw-r--r--tests/topotests/bgp_community_alias/test_bgp-community-alias.py2
-rw-r--r--tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py4
-rw-r--r--tests/topotests/bgp_confed1/test_bgp_confed1.py5
-rw-r--r--tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py4
-rw-r--r--tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py2
-rw-r--r--tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py282
-rw-r--r--tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py78
-rw-r--r--tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py354
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py5
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py4
-rw-r--r--tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py2
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/__init__.py0
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf4
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf4
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf30
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf25
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py92
-rw-r--r--tests/topotests/bgp_evpn_mh/leaf1/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/leaf2/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/spine1/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/spine2/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/test_evpn_mh.py2
-rw-r--r--tests/topotests/bgp_evpn_mh/torm11/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm12/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm21/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm22/evpn.conf1
-rwxr-xr-xtests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py6
-rw-r--r--tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py4
-rw-r--r--tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py9
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/__init__.py0
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf32
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf10
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py95
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py4
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf (renamed from tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf)7
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf (renamed from tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf)5
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf5
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf19
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf13
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py108
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py19
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py36
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py24
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py4
-rw-r--r--tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py4
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json2
-rw-r--r--tests/topotests/bgp_link_bw_ip/r5/bgpd.conf1
-rw-r--r--tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py34
-rw-r--r--tests/topotests/bgp_llgr/test_bgp_llgr.py2
-rw-r--r--tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py2
-rw-r--r--tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py10
-rw-r--r--tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py73
-rw-r--r--tests/topotests/bgp_oad/test_bgp_oad.py4
-rw-r--r--tests/topotests/bgp_orf/test_bgp_orf.py4
-rw-r--r--tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py1
-rw-r--r--tests/topotests/bgp_path_selection/test_bgp_path_selection.py27
-rw-r--r--tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py4
-rw-r--r--tests/topotests/bgp_peer_group/r1/bgpd.conf4
-rw-r--r--tests/topotests/bgp_peer_group/r1/zebra.conf3
-rw-r--r--tests/topotests/bgp_peer_group/r2/bgpd.conf4
-rw-r--r--tests/topotests/bgp_peer_group/r2/zebra.conf3
-rw-r--r--tests/topotests/bgp_peer_group/test_bgp_peer-group.py49
-rw-r--r--tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py4
-rw-r--r--tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py4
-rw-r--r--tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py4
-rw-r--r--tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py7
-rw-r--r--tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py4
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py4
-rw-r--r--tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py4
-rw-r--r--tests/topotests/bgp_software_version/test_bgp_software_version.py4
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py20
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json1
-rw-r--r--tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json1
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json1
-rw-r--r--tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json1
-rw-r--r--tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py3
-rw-r--r--tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py2
-rw-r--r--tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py135
-rw-r--r--tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py49
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py104
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py27
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py52
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py78
-rwxr-xr-xtests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py18
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py334
-rw-r--r--tests/topotests/config_timing/test_config_timing.py8
-rwxr-xr-xtests/topotests/conftest.py21
-rw-r--r--tests/topotests/eigrp_topo1/test_eigrp_topo1.py1
-rw-r--r--tests/topotests/evpn_pim_1/spine/bgp.summ.json1
-rw-r--r--tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py6
-rw-r--r--tests/topotests/example_test/test_template.py1
-rw-r--r--tests/topotests/fpm_testing_topo1/test_fpm_topo1.py3
-rwxr-xr-xtests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py19
-rw-r--r--tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py105
-rw-r--r--tests/topotests/isis_te_topo1/test_isis_te_topo1.py36
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/open/__init__.py32
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/__init__.py30
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/af.py6
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/nlri.py62
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py119
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/rd.py24
-rw-r--r--tests/topotests/lib/common_config.py16
-rw-r--r--tests/topotests/lib/snmptest.py13
-rw-r--r--tests/topotests/lib/topojson.py8
-rw-r--r--tests/topotests/lib/topotest.py18
-rw-r--r--tests/topotests/mgmt_fe_client/mgmt_pb2.py5035
-rw-r--r--tests/topotests/mgmt_tests/test_yang_mgmt.py239
-rw-r--r--tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py2
-rw-r--r--tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py2
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py4
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py4
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py17
-rw-r--r--tests/topotests/munet/__main__.py43
-rw-r--r--tests/topotests/munet/args.py89
-rw-r--r--tests/topotests/munet/base.py6
-rw-r--r--tests/topotests/munet/mucmd.py14
-rw-r--r--tests/topotests/munet/munet-schema.json42
-rw-r--r--tests/topotests/munet/mutest/__main__.py74
-rw-r--r--tests/topotests/munet/mutest/userapi.py98
-rw-r--r--tests/topotests/munet/native.py261
-rw-r--r--tests/topotests/munet/parser.py10
-rw-r--r--tests/topotests/munet/testing/fixtures.py12
-rw-r--r--tests/topotests/munet/testing/hooks.py93
-rw-r--r--tests/topotests/munet/watchlog.py1
-rw-r--r--tests/topotests/nb_config/test_nb_config.py22
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py33
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_nssa.py2
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py6
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_single_area.py2
-rw-r--r--tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py6
-rw-r--r--tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py28
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py8
-rw-r--r--tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py4
-rw-r--r--tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf26
-rw-r--r--tests/topotests/ospf_p2mp/r1/frr-p2mp.conf23
-rw-r--r--tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf29
-rw-r--r--tests/topotests/ospf_p2mp/r2/frr-p2mp.conf26
-rw-r--r--tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf28
-rw-r--r--tests/topotests/ospf_p2mp/r3/frr-p2mp.conf25
-rw-r--r--tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf28
-rw-r--r--tests/topotests/ospf_p2mp/r4/frr-p2mp.conf25
-rw-r--r--tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py472
-rw-r--r--tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py467
-rw-r--r--tests/topotests/ospf_single_switch/test_ospf_single_switch.py20
-rw-r--r--tests/topotests/ospfapi/test_ospf_clientapi.py24
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py2
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py4
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py2
-rw-r--r--tests/topotests/pim_basic/test_pim.py5
-rw-r--r--tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py222
-rw-r--r--tests/topotests/route_scale/scale_test_common.py2
-rw-r--r--tests/topotests/route_scale/test_route_scale1.py18
-rw-r--r--tests/topotests/route_scale/test_route_scale2.py18
-rwxr-xr-xtests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py24
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py14
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py12
-rwxr-xr-xtests/topotests/tc_basic/test_tc_basic.py17
-rw-r--r--tests/topotests/zebra_netlink/test_zebra_netlink.py2
-rw-r--r--tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py49
-rw-r--r--tools/etc/iproute2/rt_protos.d/frr.conf1
-rwxr-xr-xtools/frr-reload.py69
-rwxr-xr-xtools/indent.py4
-rw-r--r--vtysh/vtysh.c168
-rw-r--r--vtysh/vtysh.h14
-rw-r--r--yang/confd/confd.frr-ripd.yang24
-rw-r--r--yang/confd/confd.frr-ripngd.yang24
-rw-r--r--yang/frr-bgp-route-map.yang4
-rw-r--r--yang/frr-zebra.yang6
-rw-r--r--yang/subdir.am27
-rw-r--r--zebra/interface.c7
-rw-r--r--zebra/rt_netlink.c25
-rw-r--r--zebra/rtadv.c10
-rw-r--r--zebra/zapi_msg.c7
-rw-r--r--zebra/zebra_cli.c2
-rw-r--r--zebra/zebra_dplane.c13
-rw-r--r--zebra/zebra_dplane.h7
-rw-r--r--zebra/zebra_evpn.c6
-rw-r--r--zebra/zebra_evpn_mac.c2
-rw-r--r--zebra/zebra_evpn_mh.c6
-rw-r--r--zebra/zebra_mpls.c18
-rw-r--r--zebra/zebra_mpls.h5
-rw-r--r--zebra/zebra_mpls_vty.c2
-rw-r--r--zebra/zebra_nb_config.c1
-rw-r--r--zebra/zebra_nb_state.c4
-rw-r--r--zebra/zebra_neigh.c12
-rw-r--r--zebra/zebra_netns_id.c4
-rw-r--r--zebra/zebra_netns_notify.c4
-rw-r--r--zebra/zebra_nhg.c7
-rw-r--r--zebra/zebra_vty.c150
-rw-r--r--zebra/zserv.c4
353 files changed, 11936 insertions, 6793 deletions
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 1ecdfd2fb3..9b6932c285 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -20,3 +20,5 @@ c14777c6bfd0a446c85243d3a9835054a259c276
8451921b70044a2c1075e7ba391f095fabee2550
bf8d3d6aca3f20255a621ed1c148fd05b3a8ae5c
96941f80927ce31a41f7d1905717f099187be723
+# apply `black` python formatting for all tests/topotests
+1a1c2a9f84d0ad1bdadc0cb47d6175d4ccc32544
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 66bf706808..f4ff884e00 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -105,6 +105,8 @@ struct bfd_echo_pkt {
#define BFD_CBIT 0x08
#define BFD_ABIT 0x04
#define BFD_DEMANDBIT 0x02
+#define BFD_MBIT 0x01
+#define BFD_GETMBIT(flags) (flags & BFD_MBIT)
#define BFD_SETDEMANDBIT(flags, val) \
{ \
if ((val)) \
@@ -133,7 +135,7 @@ struct bfd_echo_pkt {
if ((val)) \
flags |= val; \
}
-#define BFD_GETCBIT(flags) (flags & BFD_FBIT)
+#define BFD_GETCBIT(flags) (flags & BFD_CBIT)
#define BFD_ECHO_VERSION 1
#define BFD_ECHO_PKT_LEN sizeof(struct bfd_echo_pkt)
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index fec195c77e..8110f434c2 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -898,6 +898,12 @@ void bfd_recv_cb(struct event *t)
return;
}
+ if (BFD_GETMBIT(cp->flags)) {
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
+ "detect non-zero Multipoint (M) flag");
+ return;
+ }
+
if (cp->discrs.my_discr == 0) {
cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"'my discriminator' is zero");
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index a81f288c7a..d519749f6b 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -182,12 +182,15 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
adj->uptime = monotime(NULL);
adj->addpath_rx_id = addpath_id;
BGP_ADJ_IN_ADD(dest, adj);
+ peer->stat_pfx_adj_rib_in++;
bgp_dest_lock_node(dest);
}
void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai)
{
bgp_attr_unintern(&bai->attr);
+ if (bai->peer)
+ bai->peer->stat_pfx_adj_rib_in--;
BGP_ADJ_IN_DEL(*dest, bai);
*dest = bgp_dest_unlock_node(*dest);
peer_unlock(bai->peer); /* adj_in peer reference */
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 5320a5f57e..913634bf59 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -915,12 +915,13 @@ static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty)
"\n",
attr->flag, attr->distance, attr->med, attr->local_pref,
attr->origin, attr->weight, attr->label, sid, attr->aigp_metric);
- vty_out(vty,
- "\taspath: %s Community: %s Extended Community: %s Large Community: %s\n",
+ vty_out(vty, "\taspath: %s Community: %s Large Community: %s\n",
aspath_print(attr->aspath),
community_str(attr->community, false, false),
- ecommunity_str(attr->ecommunity),
lcommunity_str(attr->lcommunity, false, false));
+ vty_out(vty, "\tExtended Community: %s Extended IPv6 Community: %s\n",
+ ecommunity_str(attr->ecommunity),
+ ecommunity_str(attr->ipv6_ecommunity));
}
void attr_show_all(struct vty *vty)
@@ -1389,6 +1390,15 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
(args->startp - STREAM_DATA(BGP_INPUT(peer)))
+ args->total);
+ /* Partial optional attributes that are malformed should not cause
+ * the whole session to be reset. Instead treat it as a withdrawal
+ * of the routes, if possible.
+ */
+ if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS) &&
+ CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL) &&
+ CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
+ return BGP_ATTR_PARSE_WITHDRAW;
+
switch (args->type) {
/* where an attribute is relatively inconsequential, e.g. it does not
* affect route selection, and can be safely ignored, then any such
@@ -1398,6 +1408,7 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
case BGP_ATTR_AS4_AGGREGATOR:
case BGP_ATTR_AGGREGATOR:
case BGP_ATTR_ATOMIC_AGGREGATE:
+ case BGP_ATTR_PREFIX_SID:
return BGP_ATTR_PARSE_PROCEED;
/* Core attributes, particularly ones which may influence route
@@ -1425,19 +1436,21 @@ bgp_attr_malformed(struct bgp_attr_parser_args *args, uint8_t subcode,
BGP_NOTIFY_UPDATE_ERR, subcode,
notify_datap, length);
return BGP_ATTR_PARSE_ERROR;
+ default:
+ /* Unknown attributes, that are handled by this function
+ * should be treated as withdraw, to prevent one more CVE
+ * from being introduced.
+ * RFC 7606 says:
+ * The "treat-as-withdraw" approach is generally preferred
+ * and the "session reset" approach is discouraged.
+ */
+ flog_err(EC_BGP_ATTR_FLAG,
+ "%s(%u) attribute received, while it is not known how to handle it, treating as withdraw",
+ lookup_msg(attr_str, args->type, NULL), args->type);
+ break;
}
- /* Partial optional attributes that are malformed should not cause
- * the whole session to be reset. Instead treat it as a withdrawal
- * of the routes, if possible.
- */
- if (CHECK_FLAG(flags, BGP_ATTR_FLAG_TRANS)
- && CHECK_FLAG(flags, BGP_ATTR_FLAG_OPTIONAL)
- && CHECK_FLAG(flags, BGP_ATTR_FLAG_PARTIAL))
- return BGP_ATTR_PARSE_WITHDRAW;
-
- /* default to reset */
- return BGP_ATTR_PARSE_ERROR_NOTIFYPLS;
+ return BGP_ATTR_PARSE_WITHDRAW;
}
/* Find out what is wrong with the path attribute flag bits and log the error.
@@ -2638,10 +2651,7 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
goto ipv6_ext_community_ignore;
- ipv6_ecomm = ecommunity_parse_ipv6(
- stream_pnt(peer->curr), length,
- CHECK_FLAG(peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+ ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length);
bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
/* XXX: fix ecommunity_parse to use stream API */
@@ -2651,6 +2661,10 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
+ /* Extract link bandwidth, if any. */
+ (void)ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(attr),
+ &attr->link_bw);
+
return BGP_ATTR_PARSE_PROCEED;
ipv6_ext_community_ignore:
@@ -3163,8 +3177,6 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
struct attr *const attr = args->attr;
enum bgp_attr_parse_ret ret;
- attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID);
-
uint8_t type;
uint16_t length;
size_t headersz = sizeof(type) + sizeof(length);
@@ -3214,6 +3226,8 @@ enum bgp_attr_parse_ret bgp_attr_prefix_sid(struct bgp_attr_parser_args *args)
}
}
+ SET_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_PREFIX_SID));
+
return BGP_ATTR_PARSE_PROCEED;
}
@@ -4342,6 +4356,69 @@ static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
return false;
}
+static void bgp_packet_ecommunity_attribute(struct stream *s, struct peer *peer,
+ struct ecommunity *ecomm,
+ bool transparent, int attribute)
+{
+ if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD || transparent) {
+ if (ecomm->size * ecomm->unit_size > 255) {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS |
+ BGP_ATTR_FLAG_EXTLEN);
+ stream_putc(s, attribute);
+ stream_putw(s, ecomm->size * ecomm->unit_size);
+ } else {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, attribute);
+ stream_putc(s, ecomm->size * ecomm->unit_size);
+ }
+ stream_put(s, ecomm->val, ecomm->size * ecomm->unit_size);
+ } else {
+ uint8_t *pnt;
+ int tbit;
+ int ecom_tr_size = 0;
+ uint32_t i;
+
+ for (i = 0; i < ecomm->size; i++) {
+ pnt = ecomm->val + (i * ecomm->unit_size);
+ tbit = *pnt;
+
+ if (CHECK_FLAG(tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
+ continue;
+
+ ecom_tr_size++;
+ }
+
+ if (ecom_tr_size) {
+ if (ecom_tr_size * ecomm->unit_size > 255) {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS |
+ BGP_ATTR_FLAG_EXTLEN);
+ stream_putc(s, attribute);
+ stream_putw(s, ecom_tr_size * ecomm->unit_size);
+ } else {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, attribute);
+ stream_putc(s, ecom_tr_size * ecomm->unit_size);
+ }
+
+ for (i = 0; i < ecomm->size; i++) {
+ pnt = ecomm->val + (i * ecomm->unit_size);
+ tbit = *pnt;
+
+ if (CHECK_FLAG(tbit,
+ ECOMMUNITY_FLAG_NON_TRANSITIVE))
+ continue;
+
+ stream_put(s, pnt, ecomm->unit_size);
+ }
+ }
+ }
+}
+
/* Make attribute packet. */
bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
struct stream *s, struct attr *attr,
@@ -4644,82 +4721,31 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
}
- /* Extended Communities attribute. */
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
- && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
- struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
+ /* Extended IPv6/Communities attributes. */
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) {
bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_RSERVER_CLIENT) &&
from &&
CHECK_FLAG(from->af_flags[afi][safi],
PEER_FLAG_RSERVER_CLIENT);
- if (peer->sort == BGP_PEER_IBGP ||
- peer->sort == BGP_PEER_CONFED || transparent) {
- if (ecomm->size * 8 > 255) {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS
- | BGP_ATTR_FLAG_EXTLEN);
- stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
- stream_putw(s, ecomm->size * 8);
- } else {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
- stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
- stream_putc(s, ecomm->size * 8);
- }
- stream_put(s, ecomm->val, ecomm->size * 8);
- } else {
- uint8_t *pnt;
- int tbit;
- int ecom_tr_size = 0;
- uint32_t i;
+ if (CHECK_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
+ struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
- for (i = 0; i < ecomm->size; i++) {
- pnt = ecomm->val + (i * 8);
- tbit = *pnt;
-
- if (CHECK_FLAG(tbit,
- ECOMMUNITY_FLAG_NON_TRANSITIVE))
- continue;
+ bgp_packet_ecommunity_attribute(s, peer, ecomm,
+ transparent,
+ BGP_ATTR_EXT_COMMUNITIES);
+ }
- ecom_tr_size++;
- }
+ if (CHECK_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES))) {
+ struct ecommunity *ecomm =
+ bgp_attr_get_ipv6_ecommunity(attr);
- if (ecom_tr_size) {
- if (ecom_tr_size * 8 > 255) {
- stream_putc(
- s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS
- | BGP_ATTR_FLAG_EXTLEN);
- stream_putc(s,
- BGP_ATTR_EXT_COMMUNITIES);
- stream_putw(s, ecom_tr_size * 8);
- } else {
- stream_putc(
- s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
- stream_putc(s,
- BGP_ATTR_EXT_COMMUNITIES);
- stream_putc(s, ecom_tr_size * 8);
- }
-
- for (i = 0; i < ecomm->size; i++) {
- pnt = ecomm->val + (i * 8);
- tbit = *pnt;
-
- if (CHECK_FLAG(
- tbit,
- ECOMMUNITY_FLAG_NON_TRANSITIVE))
- continue;
-
- stream_put(s, pnt, 8);
- }
- }
+ bgp_packet_ecommunity_attribute(s, peer, ecomm,
+ transparent,
+ BGP_ATTR_IPV6_EXT_COMMUNITIES);
}
}
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 5386f24a0b..a8ba36d2d9 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -301,7 +301,7 @@ struct attr {
uint32_t rmap_table_id;
/* Link bandwidth value, if any. */
- uint32_t link_bw;
+ uint64_t link_bw;
/* EVPN ES */
esi_t esi;
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 21864cf1a6..14ff5f2e11 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -597,6 +597,9 @@ DEFUN(no_neighbor_bfd_profile, no_neighbor_bfd_profile_cmd,
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
+ if (!peer->bfd_config)
+ return CMD_SUCCESS;
+
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
bgp_group_configure_bfd(peer);
else
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 5fcb8c5645..14066ae29d 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -1592,6 +1592,15 @@ static void bmp_stat_put_u32(struct stream *s, size_t *cnt, uint16_t type,
(*cnt)++;
}
+static void bmp_stat_put_u64(struct stream *s, size_t *cnt, uint16_t type,
+ uint64_t value)
+{
+ stream_putw(s, type);
+ stream_putw(s, 8);
+ stream_putq(s, value);
+ (*cnt)++;
+}
+
static void bmp_stats(struct event *thread)
{
struct bmp_targets *bt = EVENT_ARG(thread);
@@ -1633,8 +1642,13 @@ static void bmp_stats(struct event *thread)
peer->stat_pfx_dup_withdraw);
bmp_stat_put_u32(s, &count, BMP_STATS_UPD_7606_WITHDRAW,
peer->stat_upd_7606);
- bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID,
- peer->stat_pfx_nh_invalid);
+ if (bt->stats_send_experimental)
+ bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID,
+ peer->stat_pfx_nh_invalid);
+ bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_IN,
+ peer->stat_pfx_adj_rib_in);
+ bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_LOC_RIB,
+ peer->stat_pfx_loc_rib);
stream_putl_at(s, count_pos, count);
@@ -1889,6 +1903,7 @@ static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name)
bt->name = XSTRDUP(MTYPE_BMP_TARGETSNAME, name);
bt->bgp = bgp;
bt->bmpbgp = bmp_bgp_get(bgp);
+ bt->stats_send_experimental = true;
bmp_session_init(&bt->sessions);
bmp_qhash_init(&bt->updhash);
bmp_qlist_init(&bt->updlist);
@@ -2469,6 +2484,21 @@ DEFPY(bmp_stats_cfg,
return CMD_SUCCESS;
}
+DEFPY(bmp_stats_send_experimental,
+ bmp_stats_send_experimental_cmd,
+ "[no] bmp stats send-experimental",
+ NO_STR
+ BMP_STR
+ "Send BMP statistics messages\n"
+ "Send experimental BMP stats [65531-65534]\n")
+{
+ VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
+
+ bt->stats_send_experimental = !!no;
+
+ return CMD_SUCCESS;
+}
+
#define BMP_POLICY_IS_LOCRIB(str) ((str)[0] == 'l') /* __l__oc-rib */
#define BMP_POLICY_IS_PRE(str) ((str)[1] == 'r') /* p__r__e-policy */
@@ -2761,6 +2791,9 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty)
if (bt->acl_name)
vty_out(vty, " ip access-list %s\n", bt->acl_name);
+ if (!bt->stats_send_experimental)
+ vty_out(vty, " no bmp stats send-experimental\n");
+
if (bt->stat_msec)
vty_out(vty, " bmp stats interval %d\n",
bt->stat_msec);
@@ -2816,6 +2849,7 @@ static int bgp_bmp_init(struct event_loop *tm)
install_element(BMP_NODE, &no_bmp_listener_cmd);
install_element(BMP_NODE, &bmp_connect_cmd);
install_element(BMP_NODE, &bmp_acl_cmd);
+ install_element(BMP_NODE, &bmp_stats_send_experimental_cmd);
install_element(BMP_NODE, &bmp_stats_cmd);
install_element(BMP_NODE, &bmp_monitor_cmd);
install_element(BMP_NODE, &bmp_mirror_cmd);
diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h
index dadd99eb6d..33247c4025 100644
--- a/bgpd/bgp_bmp.h
+++ b/bgpd/bgp_bmp.h
@@ -240,6 +240,8 @@ struct bmp_targets {
uint64_t cnt_accept, cnt_aclrefused;
+ bool stats_send_experimental;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bmp_targets);
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 80425ebe7a..6b6387b1b5 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -150,7 +150,7 @@ static void bgp_reuse_timer(struct event *t)
bgp_aggregate_increment(
bgp, bgp_dest_get_prefix(bdi->dest),
bdi->path, bdi->afi, bdi->safi);
- bgp_process(bgp, bdi->dest, bdi->afi,
+ bgp_process(bgp, bdi->dest, bdi->path, bdi->afi,
bdi->safi);
}
@@ -306,8 +306,10 @@ void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi,
bgp_path_info_unset_flag(bdi->dest, path,
BGP_PATH_HISTORY | BGP_PATH_DAMPED);
- if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
+ if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) {
bgp_path_info_delete(bdi->dest, path);
+ bgp_process(path->peer->bgp, bdi->dest, path, afi, safi);
+ }
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
}
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index c1b06a0ae3..b4651ad0ba 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -50,7 +50,6 @@ unsigned long conf_bgp_debug_keepalive;
unsigned long conf_bgp_debug_update;
unsigned long conf_bgp_debug_bestpath;
unsigned long conf_bgp_debug_zebra;
-unsigned long conf_bgp_debug_allow_martians;
unsigned long conf_bgp_debug_nht;
unsigned long conf_bgp_debug_update_groups;
unsigned long conf_bgp_debug_vpn;
@@ -71,7 +70,6 @@ unsigned long term_bgp_debug_keepalive;
unsigned long term_bgp_debug_update;
unsigned long term_bgp_debug_bestpath;
unsigned long term_bgp_debug_zebra;
-unsigned long term_bgp_debug_allow_martians;
unsigned long term_bgp_debug_nht;
unsigned long term_bgp_debug_update_groups;
unsigned long term_bgp_debug_vpn;
@@ -2165,7 +2163,6 @@ DEFUN (no_debug_bgp,
TERM_DEBUG_OFF(as4, AS4_SEGMENT);
TERM_DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS);
TERM_DEBUG_OFF(zebra, ZEBRA);
- TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS);
TERM_DEBUG_OFF(nht, NHT);
TERM_DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
TERM_DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
@@ -2241,9 +2238,6 @@ DEFUN_NOSH (show_debugging_bgp,
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
vty_out(vty, " BGP graceful-restart debugging is on\n");
- if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
- vty_out(vty, " BGP allow martian next hop debugging is on\n");
-
if (BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF))
vty_out(vty,
" BGP route leak from vrf to vpn debugging is on\n");
@@ -2356,11 +2350,6 @@ static int bgp_config_write_debug(struct vty *vty)
}
}
- if (CONF_BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
- vty_out(vty, "debug bgp allow-martians\n");
- write++;
- }
-
if (CONF_BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)) {
vty_out(vty, "debug bgp vpn leak-from-vrf\n");
write++;
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index 8b66326d29..673926f24c 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -61,7 +61,6 @@ extern unsigned long conf_bgp_debug_keepalive;
extern unsigned long conf_bgp_debug_update;
extern unsigned long conf_bgp_debug_bestpath;
extern unsigned long conf_bgp_debug_zebra;
-extern unsigned long conf_bgp_debug_allow_martians;
extern unsigned long conf_bgp_debug_nht;
extern unsigned long conf_bgp_debug_update_groups;
extern unsigned long conf_bgp_debug_vpn;
@@ -80,7 +79,6 @@ extern unsigned long term_bgp_debug_keepalive;
extern unsigned long term_bgp_debug_update;
extern unsigned long term_bgp_debug_bestpath;
extern unsigned long term_bgp_debug_zebra;
-extern unsigned long term_bgp_debug_allow_martians;
extern unsigned long term_bgp_debug_nht;
extern unsigned long term_bgp_debug_update_groups;
extern unsigned long term_bgp_debug_vpn;
@@ -120,7 +118,6 @@ struct bgp_debug_filter {
#define BGP_DEBUG_UPDATE_PREFIX 0x04
#define BGP_DEBUG_UPDATE_DETAIL 0x08
#define BGP_DEBUG_ZEBRA 0x01
-#define BGP_DEBUG_ALLOW_MARTIANS 0x01
#define BGP_DEBUG_NHT 0x01
#define BGP_DEBUG_UPDATE_GROUPS 0x01
#define BGP_DEBUG_VPN_LEAK_FROM_VRF 0x01
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index e1b462ae56..d392b6585c 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -237,11 +237,10 @@ struct ecommunity *ecommunity_parse(uint8_t *pnt, unsigned short length,
disable_ieee_floating);
}
-struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length,
- bool disable_ieee_floating)
+struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length)
{
return ecommunity_parse_internal(pnt, length, IPV6_ECOMMUNITY_SIZE,
- disable_ieee_floating);
+ false);
}
/* Duplicate the Extended Communities Attribute structure. */
@@ -1026,10 +1025,6 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
uint32_t bw_tmp, bw;
char bps_buf[20] = {0};
-#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
-#define ONE_MBPS_BYTES (1000 * 1000 / 8)
-#define ONE_KBPS_BYTES (1000 / 8)
-
as = (*pnt++ << 8);
as |= (*pnt++);
(void)ptr_get_be32(pnt, &bw_tmp);
@@ -1053,6 +1048,33 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
return len;
}
+static int ipv6_ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt)
+{
+ int len = 0;
+ as_t as;
+ uint64_t bw;
+ char bps_buf[20] = { 0 };
+
+ pnt += 2; /* Reserved */
+ pnt = ptr_get_be64(pnt, &bw);
+ (void)ptr_get_be32(pnt, &as);
+
+ if (bw >= ONE_GBPS_BYTES)
+ snprintf(bps_buf, sizeof(bps_buf), "%.3f Gbps",
+ (float)(bw / ONE_GBPS_BYTES));
+ else if (bw >= ONE_MBPS_BYTES)
+ snprintf(bps_buf, sizeof(bps_buf), "%.3f Mbps",
+ (float)(bw / ONE_MBPS_BYTES));
+ else if (bw >= ONE_KBPS_BYTES)
+ snprintf(bps_buf, sizeof(bps_buf), "%.3f Kbps",
+ (float)(bw / ONE_KBPS_BYTES));
+ else
+ snprintfrr(bps_buf, sizeof(bps_buf), "%" PRIu64 " bps", bw * 8);
+
+ len = snprintfrr(buf, bufsz, "LB:%u:%" PRIu64 " (%s)", as, bw, bps_buf);
+ return len;
+}
+
bool ecommunity_has_route_target(struct ecommunity *ecom)
{
uint32_t i;
@@ -1153,6 +1175,12 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
ecommunity_lb_str(
encbuf, sizeof(encbuf), pnt,
ecom->disable_ieee_floating);
+ } else if (sub_type ==
+ ECOMMUNITY_EXTENDED_LINK_BANDWIDTH &&
+ type == ECOMMUNITY_ENCODE_AS4) {
+ ipv6_ecommunity_lb_str(encbuf,
+ sizeof(encbuf),
+ pnt);
} else if (sub_type == ECOMMUNITY_NODE_TARGET &&
type == ECOMMUNITY_ENCODE_IP) {
ecommunity_node_target_str(
@@ -1368,6 +1396,9 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
if (sub_type == ECOMMUNITY_LINK_BANDWIDTH)
ecommunity_lb_str(encbuf, sizeof(encbuf), pnt,
ecom->disable_ieee_floating);
+ else if (sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH)
+ ipv6_ecommunity_lb_str(encbuf, sizeof(encbuf),
+ pnt);
else
unk_ecom = 1;
} else if (type == ECOMMUNITY_ENCODE_IP_NON_TRANS) {
@@ -1805,7 +1836,7 @@ ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
* return the BGP link bandwidth extended community, if present;
* the actual bandwidth is returned via param
*/
-const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
+const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw)
{
const uint8_t *eval;
uint32_t i;
@@ -1819,23 +1850,36 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
for (i = 0; i < ecom->size; i++) {
const uint8_t *pnt;
uint8_t type, sub_type;
- uint32_t bwval;
- eval = pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
+ eval = pnt = (ecom->val + (i * ecom->unit_size));
type = *pnt++;
sub_type = *pnt++;
if ((type == ECOMMUNITY_ENCODE_AS ||
type == ECOMMUNITY_ENCODE_AS_NON_TRANS) &&
sub_type == ECOMMUNITY_LINK_BANDWIDTH) {
+ uint32_t bwval;
+
pnt += 2; /* bandwidth is encoded as AS:val */
pnt = ptr_get_be32(pnt, &bwval);
(void)pnt; /* consume value */
if (bw)
- *bw = ecom->disable_ieee_floating
- ? bwval
- : ieee_float_uint32_to_uint32(
- bwval);
+ *bw = (uint64_t)(ecom->disable_ieee_floating
+ ? bwval
+ : ieee_float_uint32_to_uint32(
+ bwval));
+ return eval;
+ } else if (type == ECOMMUNITY_ENCODE_AS4 &&
+ sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH) {
+ uint64_t bwval;
+
+ pnt += 2; /* Reserved */
+ pnt = ptr_get_be64(pnt, &bwval);
+ (void)pnt;
+
+ if (bw)
+ *bw = bwval;
+
return eval;
}
}
@@ -1846,13 +1890,13 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
uint64_t cum_bw,
- bool disable_ieee_floating)
+ bool disable_ieee_floating,
+ bool extended)
{
struct ecommunity *new;
- struct ecommunity_val lb_eval;
const uint8_t *eval;
uint8_t type;
- uint32_t cur_bw;
+ uint64_t cur_bw;
/* Nothing to replace if link-bandwidth doesn't exist or
* is non-transitive - just return existing extcommunity.
@@ -1876,10 +1920,21 @@ struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
*/
if (cum_bw > 0xFFFFFFFF)
cum_bw = 0xFFFFFFFF;
- encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, false,
- &lb_eval, disable_ieee_floating);
- new = ecommunity_dup(ecom);
- ecommunity_add_val(new, &lb_eval, true, true);
+
+ if (extended) {
+ struct ecommunity_val_ipv6 lb_eval;
+
+ encode_lb_extended_extcomm(as, cum_bw, false, &lb_eval);
+ new = ecommunity_dup(ecom);
+ ecommunity_add_val_ipv6(new, &lb_eval, true, true);
+ } else {
+ struct ecommunity_val lb_eval;
+
+ encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw,
+ false, &lb_eval, disable_ieee_floating);
+ new = ecommunity_dup(ecom);
+ ecommunity_add_val(new, &lb_eval, true, true);
+ }
return new;
}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index d20ad01c35..929e4e60be 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -10,6 +10,10 @@
#include "bgpd/bgp_rpki.h"
#include "bgpd/bgpd.h"
+#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
+#define ONE_MBPS_BYTES (1000 * 1000 / 8)
+#define ONE_KBPS_BYTES (1000 / 8)
+
/* Refer to rfc7153 for the IANA registry definitions. These are
* updated by other standards like rfc7674.
*/
@@ -52,10 +56,14 @@
* 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect
*/
#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c
-/* from draft-ietf-idr-flow-spec-v6-09
- * 0x0b Flow-spec Redirect to IPv6
+/* RFC 8956 */
+#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d
+
+/* https://datatracker.ietf.org/doc/html/draft-li-idr-link-bandwidth-ext-01
+ * Sub-type is allocated by IANA, just the draft is not yet updated with the
+ * new value.
*/
-#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b
+#define ECOMMUNITY_EXTENDED_LINK_BANDWIDTH 0x0006
/* Low-order octet of the Extended Communities type field for EVPN types */
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
@@ -226,12 +234,13 @@ static uint32_t uint32_to_ieee_float_uint32(uint32_t u)
* Encode BGP Link Bandwidth extended community
* bandwidth (bw) is in bytes-per-sec
*/
-static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
+static inline void encode_lb_extcomm(as_t as, uint64_t bw, bool non_trans,
struct ecommunity_val *eval,
bool disable_ieee_floating)
{
- uint32_t bandwidth =
- disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw);
+ uint64_t bandwidth = disable_ieee_floating
+ ? bw
+ : uint32_to_ieee_float_uint32(bw);
memset(eval, 0, sizeof(*eval));
eval->val[0] = ECOMMUNITY_ENCODE_AS;
@@ -246,6 +255,33 @@ static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
eval->val[7] = bandwidth & 0xff;
}
+/*
+ * Encode BGP Link Bandwidth inside IPv6 Extended Community,
+ * bandwidth is in bytes per second.
+ */
+static inline void encode_lb_extended_extcomm(as_t as, uint64_t bandwidth,
+ bool non_trans,
+ struct ecommunity_val_ipv6 *eval)
+{
+ memset(eval, 0, sizeof(*eval));
+ eval->val[0] = ECOMMUNITY_ENCODE_AS4;
+ if (non_trans)
+ eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
+ eval->val[1] = ECOMMUNITY_EXTENDED_LINK_BANDWIDTH;
+ eval->val[4] = (bandwidth >> 56) & 0xff;
+ eval->val[5] = (bandwidth >> 48) & 0xff;
+ eval->val[6] = (bandwidth >> 40) & 0xff;
+ eval->val[7] = (bandwidth >> 32) & 0xff;
+ eval->val[8] = (bandwidth >> 24) & 0xff;
+ eval->val[9] = (bandwidth >> 16) & 0xff;
+ eval->val[10] = (bandwidth >> 8) & 0xff;
+ eval->val[11] = bandwidth & 0xff;
+ eval->val[12] = (as >> 24) & 0xff;
+ eval->val[13] = (as >> 16) & 0xff;
+ eval->val[14] = (as >> 8) & 0xff;
+ eval->val[15] = as & 0xff;
+}
+
static inline void encode_origin_validation_state(enum rpki_states state,
struct ecommunity_val *eval)
{
@@ -327,8 +363,7 @@ extern void ecommunity_free(struct ecommunity **);
extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
bool disable_ieee_floating);
extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
- unsigned short length,
- bool disable_ieee_floating);
+ unsigned short length);
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
extern struct ecommunity *ecommunity_merge(struct ecommunity *,
struct ecommunity *);
@@ -387,11 +422,10 @@ extern void bgp_remove_ecomm_from_aggregate_hash(
struct ecommunity *ecommunity);
extern void bgp_aggr_ecommunity_remove(void *arg);
extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
- uint32_t *bw);
-extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
- struct ecommunity *ecom,
- uint64_t cum_bw,
- bool disable_ieee_floating);
+ uint64_t *bw);
+extern struct ecommunity *
+ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, uint64_t cum_bw,
+ bool disable_ieee_floating, bool extended);
extern bool soo_in_ecom(struct ecommunity *ecom, struct ecommunity *soo);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index a846484f0e..1c3b4e05c6 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -892,11 +892,10 @@ struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn,
/*
* Add (update) or delete MACIP from zebra.
*/
-static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- const struct ethaddr *mac,
- struct in_addr remote_vtep_ip, int add,
- uint8_t flags, uint32_t seq, esi_t *esi)
+static enum zclient_send_status bgp_zebra_send_remote_macip(
+ struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p,
+ const struct ethaddr *mac, struct in_addr remote_vtep_ip, int add,
+ uint8_t flags, uint32_t seq, esi_t *esi)
{
struct stream *s;
uint16_t ipa_len;
@@ -904,8 +903,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
bool esi_valid;
/* Check socket. */
- if (!zclient || zclient->sock < 0)
- return 0;
+ if (!zclient || zclient->sock < 0) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: No zclient or zclient->sock exists",
+ __func__);
+ return ZCLIENT_SEND_SUCCESS;
+ }
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
@@ -913,7 +916,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
zlog_debug(
"%s: No zebra instance to talk to, not installing remote macip",
__func__);
- return 0;
+ return ZCLIENT_SEND_SUCCESS;
}
if (!esi)
@@ -979,24 +982,26 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip,
esi);
- if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
- return -1;
-
- return 0;
+ return zclient_send_message(zclient);
}
/*
* Add (update) or delete remote VTEP from zebra.
*/
-static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- int flood_control, int add)
+static enum zclient_send_status
+bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p, int flood_control,
+ int add)
{
struct stream *s;
/* Check socket. */
- if (!zclient || zclient->sock < 0)
- return 0;
+ if (!zclient || zclient->sock < 0) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: No zclient or zclient->sock exists",
+ __func__);
+ return ZCLIENT_SEND_SUCCESS;
+ }
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
@@ -1004,7 +1009,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
zlog_debug(
"%s: No zebra instance to talk to, not installing remote vtep",
__func__);
- return 0;
+ return ZCLIENT_SEND_SUCCESS;
}
s = zclient->obuf;
@@ -1021,7 +1026,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
EC_BGP_VTEP_INVALID,
"Bad remote IP when trying to %s remote VTEP for VNI %u",
add ? "ADD" : "DEL", (vpn ? vpn->vni : 0));
- return -1;
+ return ZCLIENT_SEND_FAILURE;
}
stream_putl(s, flood_control);
@@ -1034,10 +1039,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p);
- if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
- return -1;
-
- return 0;
+ return zclient_send_message(zclient);
}
/*
@@ -1263,14 +1265,14 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr)
}
/* Install EVPN route into zebra. */
-static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- struct bgp_path_info *pi)
+enum zclient_send_status evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p,
+ struct bgp_path_info *pi)
{
- int ret;
uint8_t flags;
int flood_control = VXLAN_FLOOD_DISABLED;
uint32_t seq;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
flags = 0;
@@ -1348,6 +1350,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
flood_control = VXLAN_FLOOD_DISABLED;
break;
}
+
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, flood_control, 1);
}
@@ -1355,11 +1358,13 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
}
/* Uninstall EVPN route from zebra. */
-static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- struct bgp_path_info *pi, bool is_sync)
+enum zclient_send_status evpn_zebra_uninstall(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p,
+ struct bgp_path_info *pi,
+ bool is_sync)
{
- int ret;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
ret = bgp_zebra_send_remote_macip(
@@ -1374,7 +1379,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
ret = bgp_evpn_remote_es_evi_del(bgp, vpn, p);
else
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p,
- VXLAN_FLOOD_DISABLED, 0);
+ VXLAN_FLOOD_DISABLED, 0);
return ret;
}
@@ -1424,7 +1429,7 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -1438,14 +1443,29 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* Note: vpn is NULL for local EAD-ES routes.
*/
int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct bgp_dest *dest)
+ struct bgp_dest *dest, struct bgp_path_info *pi)
{
- struct bgp_path_info *old_select, *new_select;
+ struct bgp_path_info *old_select, *new_select, *first;
struct bgp_path_info_pair old_and_new;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
int ret = 0;
+ first = bgp_dest_get_bgp_path_info(dest);
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+ if (pi != first) {
+ if (pi->next)
+ pi->next->prev = pi->prev;
+ if (pi->prev)
+ pi->prev->next = pi->next;
+
+ if (first)
+ first->prev = pi;
+ pi->next = first;
+ pi->prev = NULL;
+ bgp_dest_set_bgp_path_info(dest, pi);
+ }
+
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
@@ -1465,12 +1485,18 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
&& !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
&& !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
- if (bgp_zebra_has_route_changed(old_select))
- ret = evpn_zebra_install(
- bgp, vpn,
- (const struct prefix_evpn *)bgp_dest_get_prefix(
- dest),
- old_select);
+ if (bgp_zebra_has_route_changed(old_select)) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+ evpn_zebra_install(bgp, vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(
+ dest),
+ old_select);
+ else
+ bgp_zebra_route_install(dest, old_select, bgp,
+ true, vpn, false);
+ }
+
UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
bgp_zebra_clear_route_change_flags(dest);
@@ -1502,10 +1528,14 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
&& (new_select->sub_type == BGP_ROUTE_IMPORTED ||
bgp_evpn_attr_is_sync(new_select->attr))) {
- ret = evpn_zebra_install(
- bgp, vpn,
- (struct prefix_evpn *)bgp_dest_get_prefix(dest),
- new_select);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+ evpn_zebra_install(bgp, vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(dest),
+ new_select);
+ else
+ bgp_zebra_route_install(dest, new_select, bgp, true,
+ vpn, false);
/* If an old best existed and it was a "local" route, the only
* reason
@@ -1522,13 +1552,19 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
evpn_delete_old_local_route(bgp, vpn, dest,
old_select, new_select);
} else {
- if (old_select && old_select->type == ZEBRA_ROUTE_BGP
- && old_select->sub_type == BGP_ROUTE_IMPORTED)
- ret = evpn_zebra_uninstall(
- bgp, vpn,
- (const struct prefix_evpn *)bgp_dest_get_prefix(
- dest),
- old_select, false);
+ if (old_select && old_select->type == ZEBRA_ROUTE_BGP &&
+ old_select->sub_type == BGP_ROUTE_IMPORTED) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
+ CHECK_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN))
+ evpn_zebra_uninstall(bgp, vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(
+ dest),
+ old_select, false);
+ else
+ bgp_zebra_route_install(dest, old_select, bgp,
+ false, vpn, false);
+ }
}
/* Clear any route change flags. */
@@ -1561,7 +1597,8 @@ static struct bgp_path_info *bgp_evpn_route_get_local_path(
static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
struct bgp *bgp_vrf, afi_t afi,
safi_t safi, struct bgp_dest *dest,
- struct attr *attr, int *route_changed)
+ struct attr *attr, int *route_changed,
+ struct bgp_path_info **entry)
{
struct attr *attr_new = NULL;
struct bgp_path_info *pi = NULL;
@@ -1599,8 +1636,8 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
/* add the route entry to route node*/
bgp_path_info_add(dest, pi);
+ *entry = pi;
} else {
-
tmp_pi = local_pi;
if (!attrhash_cmp(tmp_pi->attr, attr)) {
@@ -1622,6 +1659,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
tmp_pi->attr = attr_new;
tmp_pi->uptime = monotime(NULL);
}
+ *entry = local_pi;
}
return 0;
}
@@ -1637,6 +1675,7 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
struct bgp_dest *dest = NULL;
struct bgp *bgp_evpn = NULL;
int route_changed = 0;
+ struct bgp_path_info *pi = NULL;
bgp_evpn = bgp_get_evpn();
if (!bgp_evpn)
@@ -1718,11 +1757,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
/* create or update the route entry within the route node */
update_evpn_type5_route_entry(bgp_evpn, bgp_vrf, afi, safi, dest, &attr,
- &route_changed);
+ &route_changed, &pi);
/* schedule for processing and unlock node */
if (route_changed) {
- bgp_process(bgp_evpn, dest, afi, safi);
+ bgp_process(bgp_evpn, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -2062,9 +2101,19 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP
&& (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
bgp_evpn_attr_is_sync(curr_select->attr)))
- evpn_zebra_install(bgp, vpn,
- (const struct prefix_evpn *)bgp_dest_get_prefix(dest),
- curr_select);
+ if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP &&
+ (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
+ bgp_evpn_attr_is_sync(curr_select->attr))) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+ evpn_zebra_install(bgp, vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(
+ dest),
+ curr_select);
+ else
+ bgp_zebra_route_install(dest, curr_select, bgp,
+ true, vpn, false);
+ }
}
/*
@@ -2222,7 +2271,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* route would win, and we should evict the defunct local route
* and (re)install the remote route into zebra.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
/*
* If the new local route was not selected evict it and tell zebra
* to re-add the best remote dest. BGP doesn't retain non-best local
@@ -2245,8 +2294,16 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* has been removed.
*/
new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
- if (!new_is_sync && old_is_sync)
- evpn_zebra_uninstall(bgp, vpn, p, pi, true);
+ if (!new_is_sync && old_is_sync) {
+ if (CHECK_FLAG(bgp->flags,
+ BGP_FLAG_DELETE_IN_PROGRESS))
+ evpn_zebra_uninstall(bgp, vpn, p, pi,
+ true);
+ else
+ bgp_zebra_route_install(dest, pi, bgp,
+ false, vpn,
+ true);
+ }
}
}
bgp_path_info_unlock(pi);
@@ -2270,7 +2327,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
false /* setup_sync */, NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -2330,7 +2387,7 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
delete_evpn_route_entry(bgp_evpn, afi, safi, dest, &pi);
if (pi)
- bgp_process(bgp_evpn, dest, afi, safi);
+ bgp_process(bgp_evpn, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
return 0;
}
@@ -2370,7 +2427,7 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -2378,9 +2435,8 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
*/
delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
if (pi) {
- dest = bgp_path_info_reap(dest, pi);
- assert(dest);
- evpn_route_select_install(bgp, vpn, dest);
+ bgp_path_info_delete(dest, pi);
+ evpn_route_select_install(bgp, vpn, dest, pi);
}
/* dest should still exist due to locking make coverity happy */
@@ -2494,7 +2550,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* advertised to peers; otherwise, ensure it is evicted and
* (re)install the remote route into zebra.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
route_change = 0;
@@ -2512,8 +2568,17 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* has been removed.
*/
new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
- if (!new_is_sync && old_is_sync)
- evpn_zebra_uninstall(bgp, vpn, &evp, pi, true);
+ if (!new_is_sync && old_is_sync) {
+ if (CHECK_FLAG(bgp->flags,
+ BGP_FLAG_DELETE_IN_PROGRESS))
+ (void)evpn_zebra_uninstall(bgp, vpn,
+ &evp, pi,
+ true);
+ else
+ bgp_zebra_route_install(dest, pi, bgp,
+ false, vpn,
+ true);
+ }
}
}
@@ -2533,7 +2598,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, global_pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -2618,7 +2683,7 @@ static void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
if (pi)
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
/* Unlock RD node. */
@@ -2795,7 +2860,22 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
delete_all_type2_routes(bgp, vpn);
build_evpn_type3_prefix(&p, vpn->originator_ip);
+
+ /*
+ * To handle the following scenario:
+ * - Say, the new zebra announce fifo list has few vni Evpn prefixes yet
+ * to be sent to zebra.
+ * - At this point if we have triggers like "no advertise-all-vni" or
+ * "networking restart", where a vni is going down.
+ *
+ * Perform the below
+ * 1) send withdraw routes to zebra immediately in case it is installed.
+ * 2) before we blow up the vni table, we need to walk the list and
+ * pop all the dest whose za_vpn points to this vni.
+ */
+ SET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
ret = delete_evpn_route(bgp, vpn, &p);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
if (ret)
return ret;
@@ -3072,7 +3152,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
safi);
/* Perform route selection and update zebra, if required. */
- bgp_process(bgp_vrf, dest, afi, safi);
+ bgp_process(bgp_vrf, dest, pi, afi, safi);
/* Process for route leaking. */
vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi);
@@ -3184,7 +3264,7 @@ static int install_evpn_route_entry_in_vni_common(
bgp_evpn_remote_ip_hash_add(vpn, pi);
/* Perform route selection and update zebra, if required. */
- ret = evpn_route_select_install(bgp, vpn, dest);
+ ret = evpn_route_select_install(bgp, vpn, dest, pi);
/* if the best path is a local path with a non-zero ES
* sync info against the local path may need to be updated
@@ -3226,7 +3306,7 @@ static int uninstall_evpn_route_entry_in_vni_common(
bgp_path_info_delete(dest, pi);
/* Perform route selection and update zebra, if required. */
- ret = evpn_route_select_install(bgp, vpn, dest);
+ ret = evpn_route_select_install(bgp, vpn, dest, pi);
/* if the best path is a local path with a non-zero ES
* sync info against the local path may need to be updated
@@ -3434,7 +3514,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
bgp_evpn_path_nh_del(bgp_vrf, pi);
/* Perform route selection and update zebra, if required. */
- bgp_process(bgp_vrf, dest, afi, safi);
+ bgp_process(bgp_vrf, dest, pi, afi, safi);
/* Unlock route node. */
bgp_dest_unlock_node(dest);
@@ -3799,7 +3879,7 @@ int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf,
* Install or uninstall mac-ip routes are appropriate for this
* particular VRF.
*/
-static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
+static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, bool install)
{
afi_t afi;
safi_t safi;
@@ -3863,9 +3943,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
* particular VNI.
*/
static int install_uninstall_routes_for_vni(struct bgp *bgp,
- struct bgpevpn *vpn,
- bgp_evpn_route_type rtype,
- int install)
+ struct bgpevpn *vpn, bool install)
{
afi_t afi;
safi_t safi;
@@ -3896,7 +3974,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
(const struct prefix_evpn *)bgp_dest_get_prefix(
dest);
- if (evp->prefix.route_type != rtype)
+ if (evp->prefix.route_type != BGP_EVPN_IMET_ROUTE &&
+ evp->prefix.route_type != BGP_EVPN_AD_ROUTE &&
+ evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
continue;
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
@@ -3923,16 +4003,16 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
bgp, vpn, evp, pi);
if (ret) {
- flog_err(
- EC_BGP_EVPN_FAIL,
- "%u: Failed to %s EVPN %s route in VNI %u",
- bgp->vrf_id,
- install ? "install"
- : "uninstall",
- rtype == BGP_EVPN_MAC_IP_ROUTE
- ? "MACIP"
- : "IMET",
- vpn->vni);
+ flog_err(EC_BGP_EVPN_FAIL,
+ "%u: Failed to %s EVPN %s route in VNI %u",
+ bgp->vrf_id,
+ install ? "install"
+ : "uninstall",
+ evp->prefix.route_type ==
+ BGP_EVPN_MAC_IP_ROUTE
+ ? "MACIP"
+ : "IMET",
+ vpn->vni);
bgp_dest_unlock_node(rd_dest);
bgp_dest_unlock_node(dest);
@@ -3950,7 +4030,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
*/
static int install_routes_for_vrf(struct bgp *bgp_vrf)
{
- install_uninstall_routes_for_vrf(bgp_vrf, 1);
+ install_uninstall_routes_for_vrf(bgp_vrf, true);
return 0;
}
@@ -3961,29 +4041,17 @@ static int install_routes_for_vrf(struct bgp *bgp_vrf)
*/
static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
{
- int ret;
-
- /* Install type-3 routes followed by type-2 routes - the ones applicable
+ /*
+ * Install type-3 routes followed by type-2 routes - the ones applicable
* for this VNI.
*/
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
- 1);
- if (ret)
- return ret;
-
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
- 1);
- if (ret)
- return ret;
-
- return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
- 1);
+ return install_uninstall_routes_for_vni(bgp, vpn, true);
}
/* uninstall routes from l3vni vrf. */
static int uninstall_routes_for_vrf(struct bgp *bgp_vrf)
{
- install_uninstall_routes_for_vrf(bgp_vrf, 0);
+ install_uninstall_routes_for_vrf(bgp_vrf, false);
return 0;
}
@@ -3993,25 +4061,11 @@ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf)
*/
static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
{
- int ret;
-
- /* Uninstall type-2 routes followed by type-3 routes - the ones
- * applicable
- * for this VNI.
+ /*
+ * Uninstall type-2 routes followed by type-3 routes - the ones
+ * applicable for this VNI.
*/
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
- 0);
- if (ret)
- return ret;
-
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
- 0);
- if (ret)
- return ret;
-
-
- return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
- 0);
+ return install_uninstall_routes_for_vni(bgp, vpn, false);
}
/*
@@ -4431,7 +4485,7 @@ static void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn,
}
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, global_pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -4481,7 +4535,7 @@ static void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
false /* setup_sync */, NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -4526,7 +4580,7 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -6262,6 +6316,17 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
*/
void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
{
+ struct bgp_dest *dest = NULL;
+
+ while (zebra_announce_count(&bm->zebra_announce_head)) {
+ dest = zebra_announce_pop(&bm->zebra_announce_head);
+ if (dest->za_vpn == vpn) {
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_dest_unlock_node(dest);
+ } else
+ zebra_announce_add_tail(&bm->zebra_announce_head, dest);
+ }
+
bgp_evpn_remote_ip_hash_destroy(vpn);
bgp_evpn_vni_es_cleanup(vpn);
bgpevpn_unlink_from_l3vni(vpn);
@@ -6425,9 +6490,10 @@ void bgp_filter_evpn_routes_upon_martian_change(
for (dest = bgp_table_top(table); dest;
dest = bgp_route_next(dest)) {
+ struct bgp_path_info *next;
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
bool affected = false;
const struct prefix *p;
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index c641a64f62..11a6f45dd0 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -186,4 +186,12 @@ extern bool is_route_injectable_into_evpn_non_supp(struct bgp_path_info *pi);
extern void bgp_aggr_supp_withdraw_from_evpn(struct bgp *bgp, afi_t afi,
safi_t safi);
+extern enum zclient_send_status evpn_zebra_install(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p,
+ struct bgp_path_info *pi);
+extern enum zclient_send_status
+evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p, struct bgp_path_info *pi,
+ bool is_sync);
#endif /* _QUAGGA_BGP_EVPN_H */
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index d88c52d1f6..d63e011560 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -45,13 +45,14 @@ static void bgp_evpn_local_es_down(struct bgp *bgp,
struct bgp_evpn_es *es);
static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp,
struct bgp_evpn_es *es);
-static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
+static struct bgp_evpn_es_vtep *
+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct in_addr vtep_ip, bool esr, uint8_t df_alg,
+ uint16_t df_pref, int *zret);
+static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp,
struct bgp_evpn_es *es,
struct in_addr vtep_ip,
- bool esr, uint8_t df_alg,
- uint16_t df_pref);
-static void bgp_evpn_es_vtep_del(struct bgp *bgp,
- struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr);
+ bool esr);
static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es);
static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es);
static struct bgp_evpn_es_evi *
@@ -91,15 +92,19 @@ static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info);
*/
static int bgp_evpn_es_route_select_install(struct bgp *bgp,
struct bgp_evpn_es *es,
- struct bgp_dest *dest)
+ struct bgp_dest *dest,
+ struct bgp_path_info *pi)
{
int ret = 0;
+ int zret = 0;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
struct bgp_path_info *old_select; /* old best */
struct bgp_path_info *new_select; /* new best */
struct bgp_path_info_pair old_and_new;
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
@@ -120,7 +125,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
bgp_evpn_es_vtep_add(bgp, es, old_select->attr->nexthop,
true /*esr*/,
old_select->attr->df_alg,
- old_select->attr->df_pref);
+ old_select->attr->df_pref, &zret);
}
UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
bgp_zebra_clear_route_change_flags(dest);
@@ -149,7 +154,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
&& new_select->sub_type == BGP_ROUTE_IMPORTED) {
bgp_evpn_es_vtep_add(bgp, es, new_select->attr->nexthop,
true /*esr */, new_select->attr->df_alg,
- new_select->attr->df_pref);
+ new_select->attr->df_pref, &zret);
} else {
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
&& old_select->sub_type == BGP_ROUTE_IMPORTED)
@@ -231,7 +236,7 @@ static int bgp_evpn_es_route_install(struct bgp *bgp,
}
/* Perform route selection and update zebra, if required. */
- ret = bgp_evpn_es_route_select_install(bgp, es, dest);
+ ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi);
bgp_dest_unlock_node(dest);
@@ -272,7 +277,7 @@ static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
bgp_path_info_delete(dest, pi);
/* Perform route selection and update zebra, if required. */
- ret = bgp_evpn_es_route_select_install(bgp, es, dest);
+ ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi);
/* Unlock route node. */
bgp_dest_unlock_node(dest);
@@ -447,7 +452,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
attr->mp_nexthop_global_in);
}
- /* Return back the route entry. */
+ /* Return back th*e route entry. */
*ri = tmp_pi;
return 0;
}
@@ -511,7 +516,7 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -562,7 +567,7 @@ int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn)
delete_evpn_route_entry(bgp, afi, safi, bd, &pi);
if (pi)
- bgp_process(bgp, bd, afi, safi);
+ bgp_process(bgp, bd, pi, afi, safi);
}
}
@@ -668,7 +673,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp,
* this is just to set the flags correctly
* as local route in the ES always wins.
*/
- bgp_evpn_es_route_select_install(bgp, es, dest);
+ bgp_evpn_es_route_select_install(bgp, es, dest, pi);
bgp_dest_unlock_node(dest);
/* If this is a new route or some attribute has changed, export the
@@ -686,7 +691,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp,
attr_new, &global_pi, &route_changed);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -1008,7 +1013,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
* this is just to set the flags correctly as local route in
* the ES always wins.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
bgp_dest_unlock_node(dest);
/* If this is a new route or some attribute has changed, export the
@@ -1025,7 +1030,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
attr_new, &global_pi, &route_changed);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -1371,23 +1376,28 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es,
}
/* Send the remote ES to zebra for NHG programming */
-static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
- struct bgp_evpn_es_vtep *es_vtep, bool add)
+static enum zclient_send_status
+bgp_zebra_send_remote_es_vtep(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep,
+ bool add)
{
struct bgp_evpn_es *es = es_vtep->es;
struct stream *s;
uint32_t flags = 0;
/* Check socket. */
- if (!zclient || zclient->sock < 0)
- return 0;
+ if (!zclient || zclient->sock < 0) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: No zclient or zclient->sock exists",
+ __func__);
+ return ZCLIENT_SEND_SUCCESS;
+ }
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("No zebra instance, not installing remote es %s",
es->esi_str);
- return 0;
+ return ZCLIENT_SEND_SUCCESS;
}
if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
@@ -1418,12 +1428,12 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
return zclient_send_message(zclient);
}
-static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
- struct bgp_evpn_es_vtep *es_vtep,
- bool param_change)
+static enum zclient_send_status bgp_evpn_es_vtep_re_eval_active(
+ struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, bool param_change)
{
bool old_active;
bool new_active;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
old_active = CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
/* currently we need an active EVI reference to use the VTEP as
@@ -1445,7 +1455,7 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
es_vtep->df_alg, es_vtep->df_pref);
/* send remote ES to zebra */
- bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
+ ret = bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
/* The NHG is updated first for efficient failover handling.
* Note the NHG can be de-activated while there are bgp
@@ -1457,13 +1467,14 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
/* queue up the es for background consistency checks */
bgp_evpn_es_cons_checks_pend_add(es_vtep->es);
}
+
+ return ret;
}
-static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
- struct bgp_evpn_es *es,
- struct in_addr vtep_ip,
- bool esr, uint8_t df_alg,
- uint16_t df_pref)
+static struct bgp_evpn_es_vtep *
+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct in_addr vtep_ip, bool esr, uint8_t df_alg,
+ uint16_t df_pref, int *zret)
{
struct bgp_evpn_es_vtep *es_vtep;
bool param_change = false;
@@ -1490,15 +1501,17 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
++es_vtep->evi_cnt;
}
- bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
+ *zret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
return es_vtep;
}
-static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
- struct bgp_evpn_es_vtep *es_vtep, bool esr)
+static enum zclient_send_status
+bgp_evpn_es_vtep_do_del(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep,
+ bool esr)
{
bool param_change = false;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("es %s vtep %pI4 del %s", es_vtep->es->esi_str,
@@ -1515,18 +1528,25 @@ static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
--es_vtep->evi_cnt;
}
- bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
+ ret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
bgp_evpn_es_vtep_free(es_vtep);
+
+ return ret;
}
-static void bgp_evpn_es_vtep_del(struct bgp *bgp,
- struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr)
+static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp,
+ struct bgp_evpn_es *es,
+ struct in_addr vtep_ip,
+ bool esr)
{
struct bgp_evpn_es_vtep *es_vtep;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip);
if (es_vtep)
- bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
+ ret = bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
+
+ return ret;
}
/********************** ES MAC-IP paths *************************************
@@ -3399,12 +3419,14 @@ static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find(
/* A VTEP can be added as "active" attach to an ES if EAD-per-ES and
* EAD-per-EVI routes are rxed from it.
*/
-static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
- struct bgp_evpn_es_evi_vtep *evi_vtep)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
+ struct bgp_evpn_es_evi_vtep *evi_vtep)
{
bool old_active;
bool new_active;
uint32_t ead_activity_flags;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
old_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
@@ -3425,7 +3447,7 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
new_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
if (old_active == new_active)
- return;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("es %s evi %u vtep %pI4 %s",
@@ -3434,24 +3456,27 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
new_active ? "active" : "inactive");
/* add VTEP to parent es */
- if (new_active)
- evi_vtep->es_vtep = bgp_evpn_es_vtep_add(
- bgp, evi_vtep->es_evi->es, evi_vtep->vtep_ip,
- false /*esr*/, 0, 0);
- else {
+ if (new_active) {
+ evi_vtep->es_vtep =
+ bgp_evpn_es_vtep_add(bgp, evi_vtep->es_evi->es,
+ evi_vtep->vtep_ip, false /*esr*/,
+ 0, 0, &ret);
+ } else {
if (evi_vtep->es_vtep) {
- bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
- false /*esr*/);
+ ret = bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
+ false /*esr*/);
evi_vtep->es_vtep = NULL;
}
}
/* queue up the parent es for background consistency checks */
bgp_evpn_es_cons_checks_pend_add(evi_vtep->es_evi->es);
+
+ return ret;
}
-static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
- struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
- bool ead_es)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_add(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi,
+ struct in_addr vtep_ip, bool ead_es)
{
struct bgp_evpn_es_evi_vtep *evi_vtep;
@@ -3475,18 +3500,19 @@ static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
else
SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
- bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
+ return bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
}
-static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
- struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
- bool ead_es)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_del(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi,
+ struct in_addr vtep_ip, bool ead_es)
{
struct bgp_evpn_es_evi_vtep *evi_vtep;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip);
if (!evi_vtep)
- return;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("del es %s evi %u vtep %pI4 %s",
@@ -3503,8 +3529,10 @@ static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
else
UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
- bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
+ ret = bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
bgp_evpn_es_evi_vtep_free(evi_vtep);
+
+ return ret;
}
/* compare ES-IDs for the ES-EVI RB tree maintained per-VNI */
@@ -3780,18 +3808,20 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
/* Add remote ES-EVI entry. This is actually the remote VTEP add and the
* ES-EVI is implicity created on first VTEP's reference.
*/
-int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p)
+enum zclient_send_status bgp_evpn_remote_es_evi_add(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p)
{
char buf[ESI_STR_LEN];
struct bgp_evpn_es *es;
struct bgp_evpn_es_evi *es_evi;
bool ead_es;
const esi_t *esi = &p->prefix.ead_addr.esi;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (!vpn)
/* local EAD-ES need not be sent back to zebra */
- return 0;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("add remote %s es %s evi %u vtep %pI4",
@@ -3808,27 +3838,29 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
es_evi = bgp_evpn_es_evi_new(es, vpn);
ead_es = !!p->prefix.ead_addr.eth_tag;
- bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
- ead_es);
+ ret = bgp_evpn_es_evi_vtep_add(bgp, es_evi,
+ p->prefix.ead_addr.ip.ipaddr_v4, ead_es);
bgp_evpn_es_evi_remote_info_re_eval(es_evi);
- return 0;
+ return ret;
}
/* A remote VTEP has withdrawn. The es-evi-vtep will be deleted and the
* parent es-evi freed up implicitly in last VTEP's deref.
*/
-int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p)
+enum zclient_send_status bgp_evpn_remote_es_evi_del(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p)
{
char buf[ESI_STR_LEN];
struct bgp_evpn_es *es;
struct bgp_evpn_es_evi *es_evi;
bool ead_es;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (!vpn)
/* local EAD-ES need not be sent back to zebra */
- return 0;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug(
@@ -3847,7 +3879,7 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
esi_to_str(&p->prefix.ead_addr.esi, buf,
sizeof(buf)),
vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4);
- return 0;
+ return ret;
}
es_evi = bgp_evpn_es_evi_find(es, vpn);
if (!es_evi) {
@@ -3860,14 +3892,15 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
sizeof(buf)),
vpn->vni,
&p->prefix.ead_addr.ip.ipaddr_v4);
- return 0;
+ return ret;
}
ead_es = !!p->prefix.ead_addr.eth_tag;
- bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
- ead_es);
+ ret = bgp_evpn_es_evi_vtep_del(bgp, es_evi,
+ p->prefix.ead_addr.ip.ipaddr_v4, ead_es);
bgp_evpn_es_evi_remote_info_re_eval(es_evi);
- return 0;
+
+ return ret;
}
/* If a VNI is being deleted we need to force del all remote VTEPs */
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index cebabb9fd0..5d393c37a2 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -418,10 +418,12 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi);
extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni);
extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni);
-extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p);
-extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p);
+extern enum zclient_send_status
+bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p);
+extern enum zclient_send_status
+bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p);
extern void bgp_evpn_mh_init(void);
extern void bgp_evpn_mh_finish(void);
void bgp_evpn_vni_es_init(struct bgpevpn *vpn);
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 5af99afa34..07bba9b426 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -716,7 +716,8 @@ extern void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_path_info **pi);
int vni_list_cmp(void *p1, void *p2);
extern int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct bgp_dest *dest);
+ struct bgp_dest *dest,
+ struct bgp_path_info *pi);
extern struct bgp_dest *
bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi, safi_t safi,
const struct prefix_evpn *evp, struct prefix_rd *prd,
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index a2d3172882..7866adbdcd 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1796,6 +1796,22 @@ bgp_connect_fail(struct peer_connection *connection)
return bgp_stop(connection);
}
+/* after connect is called(), getpeername is able to return
+ * port and address on non established streams
+ */
+static void bgp_connect_in_progress_update_connection(struct peer *peer)
+{
+ bgp_getsockname(peer);
+ if (!peer->su_remote && !BGP_CONNECTION_SU_UNSPEC(peer->connection)) {
+ /* if connect initiated, then dest port and dest addresses are well known */
+ peer->su_remote = sockunion_dup(&peer->connection->su);
+ if (sockunion_family(peer->su_remote) == AF_INET)
+ peer->su_remote->sin.sin_port = htons(peer->port);
+ else if (sockunion_family(peer->su_remote) == AF_INET6)
+ peer->su_remote->sin6.sin6_port = htons(peer->port);
+ }
+}
+
/* This function is the first starting point of all BGP connection. It
* try to connect to remote peer with non-blocking IO.
*/
@@ -1892,6 +1908,8 @@ static enum bgp_fsm_state_progress bgp_start(struct peer_connection *connection)
__func__, peer->connection->fd);
return BGP_FSM_FAILURE;
}
+ bgp_connect_in_progress_update_connection(peer);
+
/*
* - when the socket becomes ready, poll() will signify POLLOUT
* - if it fails to connect, poll() will signify POLLHUP
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 7327ab5182..68104967b2 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -74,7 +74,7 @@ int bgp_parse_fec_update(void)
bgp_set_valid_label(&dest->local_label);
}
SET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, NULL, afi, safi);
bgp_dest_unlock_node(dest);
return 1;
}
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 851c4880c3..44d5ee68cc 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -207,6 +207,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
bgp_evpn_mh_finish();
bgp_nhg_finish();
+ zebra_announce_fini(&bm->zebra_announce_head);
+
/* reverse bgp_dump_init */
bgp_dump_finish();
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index 296e64003d..e12d84b84c 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -521,7 +521,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_maxpaths_cfg *mpath_cfg)
{
uint16_t maxpaths, mpath_count, old_mpath_count;
- uint32_t bwval;
+ uint64_t bwval;
uint64_t cum_bw, old_cum_bw;
struct listnode *mp_node, *mp_next_node;
struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
@@ -613,8 +613,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
cur_mpath);
prev_mpath = cur_mpath;
mpath_count++;
- if (ecommunity_linkbw_present(
- bgp_attr_get_ecommunity(
+ if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
+ cur_mpath->attr),
+ &bwval) ||
+ ecommunity_linkbw_present(
+ bgp_attr_get_ipv6_ecommunity(
cur_mpath->attr),
&bwval))
cum_bw += bwval;
@@ -700,8 +703,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
prev_mpath = new_mpath;
mpath_changed = 1;
mpath_count++;
- if (ecommunity_linkbw_present(
- bgp_attr_get_ecommunity(
+ if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
+ new_mpath->attr),
+ &bwval) ||
+ ecommunity_linkbw_present(
+ bgp_attr_get_ipv6_ecommunity(
new_mpath->attr),
&bwval))
cum_bw += bwval;
@@ -724,8 +730,12 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
if (new_best) {
bgp_path_info_mpath_count_set(new_best, mpath_count - 1);
if (mpath_count <= 1 ||
- !ecommunity_linkbw_present(
- bgp_attr_get_ecommunity(new_best->attr), &bwval))
+ (!ecommunity_linkbw_present(bgp_attr_get_ecommunity(
+ new_best->attr),
+ &bwval) &&
+ !ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(
+ new_best->attr),
+ &bwval)))
all_paths_lb = false;
else
cum_bw += bwval;
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 91bc3b1a88..d17fdc7169 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -388,6 +388,9 @@ void vpn_leak_zebra_vrf_sid_update_per_af(struct bgp *bgp, afi_t afi)
tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
*tovpn_sid_ls = *tovpn_sid;
+ if (bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent)
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls;
}
@@ -435,6 +438,8 @@ void vpn_leak_zebra_vrf_sid_update_per_vrf(struct bgp *bgp)
tovpn_sid_ls = XCALLOC(MTYPE_BGP_SRV6_SID, sizeof(struct in6_addr));
*tovpn_sid_ls = *tovpn_sid;
+ if (bgp->tovpn_zebra_vrf_sid_last_sent)
+ XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
bgp->tovpn_zebra_vrf_sid_last_sent = tovpn_sid_ls;
}
@@ -482,6 +487,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_af(struct bgp *bgp, afi_t afi)
bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC, NULL);
XFREE(MTYPE_BGP_SRV6_SID,
bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent);
+ bgp->vpn_policy[afi].tovpn_zebra_vrf_sid_last_sent = NULL;
}
/*
@@ -508,6 +514,7 @@ void vpn_leak_zebra_vrf_sid_withdraw_per_vrf(struct bgp *bgp)
bgp->vrf_id, ZEBRA_SEG6_LOCAL_ACTION_UNSPEC,
NULL);
XFREE(MTYPE_BGP_SRV6_SID, bgp->tovpn_zebra_vrf_sid_last_sent);
+ bgp->tovpn_zebra_vrf_sid_last_sent = NULL;
}
/*
@@ -1201,7 +1208,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
/* Process change. */
bgp_aggregate_increment(to_bgp, p, bpi, afi, safi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
if (debug)
zlog_debug("%s: ->%s: %pBD Found route, changed attr",
@@ -1263,7 +1270,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
bgp_aggregate_increment(to_bgp, p, new, afi, safi);
bgp_path_info_add(bn, new);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, new, afi, safi);
if (debug)
zlog_debug("%s: ->%s: %pBD: Added new route", __func__,
@@ -1434,6 +1441,16 @@ _vpn_leak_from_vrf_get_per_nexthop_label(struct bgp_path_info *pi,
return blnc->label;
}
+static mpls_label_t bgp_mplsvpn_get_vpn_label(struct vpn_policy *bgp_policy)
+{
+ if (bgp_policy->tovpn_label == MPLS_LABEL_NONE &&
+ CHECK_FLAG(bgp_policy->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+ bgp_lp_get(LP_TYPE_VRF, bgp_policy, vpn_leak_label_callback);
+ return MPLS_INVALID_LABEL;
+ }
+ return bgp_policy->tovpn_label;
+}
+
/* Filter out all the cases where a per nexthop label is not possible:
* - return an invalid label when the nexthop is invalid
* - return the per VRF label when the per nexthop label is not supported
@@ -1462,7 +1479,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to the per VRF label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
if (is_bgp_static_route == false && afi == AFI_IP &&
@@ -1474,7 +1491,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to the per VRF label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
if (is_bgp_static_route == false && afi == AFI_IP6 &&
@@ -1488,7 +1505,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to the per VRF label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
/* Check the next-hop reachability.
@@ -1510,7 +1527,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* table. Fallback to the per-vrf label
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
if (!nh_valid || !pi->nexthop || pi->nexthop->nexthop_num == 0 ||
@@ -1533,7 +1550,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to per-vrf label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
return _vpn_leak_from_vrf_get_per_nexthop_label(pi, to_bgp, from_bgp,
@@ -1748,12 +1765,10 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
label_val = vpn_leak_from_vrf_get_per_nexthop_label(
afi, path_vrf, from_bgp, to_bgp);
else
- /* per VRF label mode */
- label_val = from_bgp->vpn_policy[afi].tovpn_label;
+ label_val =
+ bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
- if (label_val == MPLS_INVALID_LABEL &&
- CHECK_FLAG(from_bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP)) {
+ if (label_val == MPLS_INVALID_LABEL) {
/* no valid label for the moment
* when the 'bgp_mplsvpn_get_label_per_nexthop_cb' callback gets
* a valid label value, it will call the current function again.
@@ -1949,7 +1964,7 @@ void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */
bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
}
bgp_dest_unlock_node(bn);
}
@@ -1969,7 +1984,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
struct bgp_table *table;
struct bgp_dest *bn;
- struct bgp_path_info *bpi;
+ struct bgp_path_info *bpi, *next;
/* This is the per-RD table of prefixes */
table = bgp_dest_get_bgp_table_info(pdest);
@@ -1984,7 +1999,8 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
__func__, bn);
}
- for (; bpi; bpi = bpi->next) {
+ for (; (bpi != NULL) && (next = bpi->next, 1);
+ bpi = next) {
if (debug)
zlog_debug("%s: type %d, sub_type %d",
__func__, bpi->type,
@@ -2005,7 +2021,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
to_bgp, bgp_dest_get_prefix(bn),
bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
bgp_mplsvpn_path_nh_label_unlink(
bpi->extra->vrfleak->parent);
}
@@ -2499,7 +2515,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
bpi);
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
}
bgp_dest_unlock_node(bn);
}
@@ -2508,7 +2524,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
{
struct bgp_dest *bn;
- struct bgp_path_info *bpi;
+ struct bgp_path_info *bpi, *next;
safi_t safi = SAFI_UNICAST;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@@ -2519,9 +2535,8 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
*/
for (bn = bgp_table_top(to_bgp->rib[afi][safi]); bn;
bn = bgp_route_next(bn)) {
-
- for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
- bpi = bpi->next) {
+ for (bpi = bgp_dest_get_bgp_path_info(bn);
+ (bpi != NULL) && (next = bpi->next, 1); bpi = next) {
if (bpi->extra && bpi->extra->vrfleak &&
bpi->extra->vrfleak->bgp_orig != to_bgp &&
bpi->extra->vrfleak->parent &&
@@ -2531,7 +2546,7 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
bgp_dest_get_prefix(bn),
bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
}
}
}
@@ -2560,8 +2575,11 @@ void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi)
continue;
for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
- for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
- bpi = bpi->next) {
+ struct bgp_path_info *next;
+
+ for (bpi = bgp_dest_get_bgp_path_info(bn);
+ (bpi != NULL) && (next = bpi->next, 1);
+ bpi = next) {
if (bpi->extra && bpi->extra->vrfleak &&
bpi->extra->vrfleak->bgp_orig == to_bgp)
continue;
@@ -4182,7 +4200,7 @@ static int bgp_mplsvpn_nh_label_bind_get_local_label_cb(mpls_label_t label,
if (!table)
continue;
SET_FLAG(pi->net->flags, BGP_NODE_LABEL_CHANGED);
- bgp_process(table->bgp, pi->net, table->afi, table->safi);
+ bgp_process(table->bgp, pi->net, pi, table->afi, table->safi);
}
return 0;
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index cd25899965..92a9fba887 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -170,16 +170,6 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
return 0;
}
- /* Is there an "auto" export label that isn't allocated yet? */
- if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
- (bgp_vrf->vpn_policy[afi].tovpn_label == MPLS_LABEL_NONE)) {
-
- if (pmsg)
- *pmsg = "auto label not allocated";
- return 0;
- }
-
/* Is there a "manual" export label that isn't allocated yet? */
if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index dbb34b048f..b409cbe706 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -875,11 +875,7 @@ int bgp_getsockname(struct peer *peer)
}
peer->su_local = sockunion_getsockname(peer->connection->fd);
- if (!peer->su_local)
- return -1;
peer->su_remote = sockunion_getpeername(peer->connection->fd);
- if (!peer->su_remote)
- return -1;
if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote,
&peer->nexthop, peer)) {
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index d12dc22330..98eb9565bf 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -1003,6 +1003,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
if (bnc->is_evpn_gwip_nexthop)
json_object_boolean_true_add(json_nexthop,
"isEvpnGatewayIp");
+ json_object_string_addf(json, "resolvedPrefix", "%pFX",
+ &bnc->resolved_prefix);
} else {
vty_out(vty, " %s valid [IGP metric %d], #paths %d",
buf, bnc->metric, bnc->path_count);
@@ -1010,6 +1012,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
vty_out(vty, ", peer %s", peer->host);
if (bnc->is_evpn_gwip_nexthop)
vty_out(vty, " EVPN Gateway IP");
+ vty_out(vty, "\n Resolved prefix %pFX",
+ &bnc->resolved_prefix);
vty_out(vty, "\n");
}
bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 830883872e..430c8f17e8 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -90,6 +90,7 @@ struct bgp_nexthop_cache {
struct bgp_nexthop_cache_head *tree;
struct prefix prefix;
+ struct prefix resolved_prefix;
void *nht_info; /* In BGP, peer session */
LIST_HEAD(path_list, bgp_path_info) paths;
unsigned int path_count;
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index 786d07c5a9..4734d542e5 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -357,9 +357,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
return 0;
}
- if (CHECK_FLAG(pi->attr->flag,
- ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- srte_color = bgp_attr_get_color(pi->attr);
+ srte_color = bgp_attr_get_color(pi->attr);
} else if (peer) {
/*
@@ -626,6 +624,8 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
} else if (nhr->nexthop_num) {
struct peer *peer = bnc->nht_info;
+ prefix_copy(&bnc->resolved_prefix, &nhr->prefix);
+
/* notify bgp fsm if nbr ip goes from invalid->valid */
if (!bnc->nexthop_num)
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
@@ -731,6 +731,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
}
}
} else {
+ memset(&bnc->resolved_prefix, 0, sizeof(bnc->resolved_prefix));
bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
bnc->flags &= ~BGP_NEXTHOP_VALID;
bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID;
@@ -1432,7 +1433,7 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
}
}
- bgp_process(bgp_path, dest, afi, safi);
+ bgp_process(bgp_path, dest, path, afi, safi);
}
if (peer) {
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 15738e673b..1c3bb6e775 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -1452,8 +1452,10 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
/* All OPEN option is parsed. Check capability when strict compare
flag is enabled.*/
if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
- /* If Unsupported Capability exists. */
- if (error != error_data) {
+ /* If Unsupported Capability exists or local capability does
+ * not negotiated with remote peer
+ */
+ if (error != error_data || !strict_capability_same(peer)) {
bgp_notify_send_with_data(peer->connection,
BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNSUP_CAPBL,
@@ -1461,14 +1463,6 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
error - error_data);
return -1;
}
-
- /* Check local capability does not negotiated with remote
- peer. */
- if (!strict_capability_same(peer)) {
- bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNSUP_CAPBL);
- return -1;
- }
}
/* Extended Message Support */
@@ -1503,17 +1497,11 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
"%s [Error] Configured AFI/SAFIs do not overlap with received MP capabilities",
peer->host);
- if (error != error_data)
- bgp_notify_send_with_data(peer->connection,
- BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNSUP_CAPBL,
- error_data,
- error - error_data);
- else
- bgp_notify_send(peer->connection,
- BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNSUP_CAPBL);
- return -1;
+ bgp_notify_send_with_data(peer->connection,
+ BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_UNSUP_CAPBL,
+ error_data,
+ error - error_data);
}
}
return 0;
@@ -1975,7 +1963,7 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
}
/* Dynamic capability. */
- if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
+ if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY)) {
SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
ext_opt_params
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 78878013f8..9c194eac1c 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -3734,6 +3734,10 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
zlog_err("%pBP: Capability length error", peer);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ /*
+ * If we did not return then
+ * pnt += length;
+ */
return BGP_Stop;
}
action = *pnt;
@@ -3746,7 +3750,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
action);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- return BGP_Stop;
+ goto done;
}
if (bgp_debug_neighbor_events(peer))
@@ -3758,12 +3762,16 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
zlog_err("%pBP: Capability length error", peer);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
+ /*
+ * If we did not return then
+ * pnt += length;
+ */
return BGP_Stop;
}
/* Ignore capability when override-capability is set. */
if (CHECK_FLAG(peer->flags, PEER_FLAG_OVERRIDE_CAPABILITY))
- continue;
+ goto done;
capability = lookup_msg(capcode_str, hdr->code, "Unknown");
@@ -3778,7 +3786,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
peer, capability,
sizeof(struct capability_mp_data),
hdr->length);
- return BGP_Stop;
+ goto done;
}
memcpy(&mpc, pnt + 3, sizeof(struct capability_mp_data));
@@ -3793,7 +3801,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
peer, capability,
iana_afi2str(pkt_afi),
iana_safi2str(pkt_safi));
- continue;
+ goto done;
}
/* Address family check. */
@@ -3820,7 +3828,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
if (peer_active_nego(peer))
bgp_clear_route(peer, afi, safi);
else
- return BGP_Stop;
+ goto done;
}
break;
case CAPABILITY_CODE_RESTART:
@@ -3830,7 +3838,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
bgp_notify_send(peer->connection,
BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- return BGP_Stop;
+ goto done;
}
bgp_dynamic_capability_graceful_restart(pnt, action,
@@ -3866,7 +3874,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
bgp_notify_send(peer->connection,
BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- return BGP_Stop;
+ goto done;
}
uint8_t role;
@@ -3888,6 +3896,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
break;
}
+done:
pnt += hdr->length + 3;
}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index d726edcc9f..5f6ef5ae07 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -114,6 +114,46 @@ static const struct message bgp_pmsi_tnltype_str[] = {
#define VRFID_NONE_STR "-"
#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
+static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi,
+ char *buf, size_t len)
+{
+ uint32_t flags = pi->flags;
+
+ if (flags == 0) {
+ snprintfrr(buf, len, "None ");
+ return buf;
+ }
+
+ snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ CHECK_FLAG(flags, BGP_PATH_IGP_CHANGED) ? "IGP Changed " : "",
+ CHECK_FLAG(flags, BGP_PATH_DAMPED) ? "Damped" : "",
+ CHECK_FLAG(flags, BGP_PATH_HISTORY) ? "History " : "",
+ CHECK_FLAG(flags, BGP_PATH_SELECTED) ? "Selected " : "",
+ CHECK_FLAG(flags, BGP_PATH_VALID) ? "Valid " : "",
+ CHECK_FLAG(flags, BGP_PATH_ATTR_CHANGED) ? "Attr Changed "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_DMED_CHECK) ? "Dmed Check " : "",
+ CHECK_FLAG(flags, BGP_PATH_DMED_SELECTED) ? "Dmed Selected "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_STALE) ? "Stale " : "",
+ CHECK_FLAG(flags, BGP_PATH_REMOVED) ? "Removed " : "",
+ CHECK_FLAG(flags, BGP_PATH_COUNTED) ? "Counted " : "",
+ CHECK_FLAG(flags, BGP_PATH_MULTIPATH) ? "Mpath " : "",
+ CHECK_FLAG(flags, BGP_PATH_MULTIPATH_CHG) ? "Mpath Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_RIB_ATTR_CHG) ? "Rib Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_ANNC_NH_SELF) ? "NH Self " : "",
+ CHECK_FLAG(flags, BGP_PATH_LINK_BW_CHG) ? "LinkBW Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_ACCEPT_OWN) ? "Accept Own " : "",
+ CHECK_FLAG(flags, BGP_PATH_MPLSVPN_LABEL_NH) ? "MPLS Label "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_MPLSVPN_NH_LABEL_BIND)
+ ? "MPLS Label Bind "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_UNSORTED) ? "Unsorted " : "");
+
+ return buf;
+}
+
DEFINE_HOOK(bgp_process,
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
struct peer *peer, bool withdraw),
@@ -442,10 +482,13 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
top->prev = pi;
bgp_dest_set_bgp_path_info(dest, pi);
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
bgp_path_info_lock(pi);
bgp_dest_lock_node(dest);
peer_lock(pi->peer); /* bgp_path_info peer reference */
bgp_dest_set_defer_flag(dest, false);
+ if (pi->peer)
+ pi->peer->stat_pfx_loc_rib++;
hook_call(bgp_snmp_update_stats, dest, pi, true);
}
@@ -462,8 +505,30 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
bgp_dest_set_bgp_path_info(dest, pi->next);
bgp_path_info_mpath_dequeue(pi);
+
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ if (pi->peer)
+ pi->peer->stat_pfx_loc_rib--;
+ hook_call(bgp_snmp_update_stats, dest, pi, false);
+
bgp_path_info_unlock(pi);
+ return bgp_dest_unlock_node(dest);
+}
+
+static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest,
+ struct bgp_path_info *pi)
+{
+ bgp_path_info_mpath_dequeue(pi);
+
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ if (pi->peer)
+ pi->peer->stat_pfx_loc_rib--;
hook_call(bgp_snmp_update_stats, dest, pi, false);
+ bgp_path_info_unlock(pi);
return bgp_dest_unlock_node(dest);
}
@@ -553,6 +618,15 @@ void bgp_path_info_unset_flag(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp_pcount_adjust(dest, pi);
}
+static bool use_bgp_med_value(struct attr *attr, struct bgp *bgp)
+{
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC) ||
+ CHECK_FLAG(bgp->flags, BGP_FLAG_MED_MISSING_AS_WORST))
+ return true;
+
+ return false;
+}
+
/* Get MED value. If MED value is missing and "bgp bestpath
missing-as-worst" is specified, treat it as the worst value. */
static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
@@ -679,12 +753,18 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug) {
+ char buf1[256], buf2[256];
+
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,
- exist_buf, exist->flags);
+ zlog_debug("%s(%s): Comparing %s flags %s with %s flags %s",
+ pfx_buf, bgp->name_pretty, new_buf,
+ bgp_route_dump_path_info_flags(new, buf1,
+ sizeof(buf1)),
+ exist_buf,
+ bgp_route_dump_path_info_flags(exist, buf2,
+ sizeof(buf2)));
}
newattr = new->attr;
@@ -2697,17 +2777,26 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* the most sense. However, don't modify if the link-bandwidth has
* been explicitly set by user policy.
*/
- if (nh_reset &&
- bgp_path_info_mpath_chkwtd(bgp, pi) &&
+ if (nh_reset && bgp_path_info_mpath_chkwtd(bgp, pi) &&
(cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
- !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
- bgp_attr_set_ecommunity(
- attr,
- ecommunity_replace_linkbw(
- bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
- CHECK_FLAG(
- peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
+ !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET)) {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH))
+ bgp_attr_set_ipv6_ecommunity(
+ attr,
+ ecommunity_replace_linkbw(bgp->as,
+ bgp_attr_get_ipv6_ecommunity(
+ attr),
+ cum_bw, false, true));
+ else
+ bgp_attr_set_ecommunity(
+ attr,
+ ecommunity_replace_linkbw(
+ bgp->as, bgp_attr_get_ecommunity(attr),
+ cum_bw,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE),
+ false));
+ }
return true;
}
@@ -2736,17 +2825,18 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info_pair *result, afi_t afi,
safi_t safi)
{
- struct bgp_path_info *new_select;
- struct bgp_path_info *old_select;
+ struct bgp_path_info *new_select, *look_thru;
+ struct bgp_path_info *old_select, *worse, *first;
struct bgp_path_info *pi;
struct bgp_path_info *pi1;
struct bgp_path_info *pi2;
- struct bgp_path_info *nextpi = NULL;
int paths_eq, do_mpath;
- bool debug;
+ bool debug, any_comparisons;
struct list mp_list;
char pfx_buf[PREFIX2STR_BUFFER] = {};
char path_buf[PATH_ADDPATH_STR_BUFFER];
+ enum bgp_path_selection_reason reason = bgp_path_selection_none;
+ bool unsorted_items = true;
bgp_mp_list_init(&mp_list);
do_mpath =
@@ -2757,16 +2847,16 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug)
prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
- dest->reason = bgp_path_selection_none;
/* bgp deterministic-med */
new_select = NULL;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
-
/* Clear BGP_PATH_DMED_SELECTED for all paths */
for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
- pi1 = pi1->next)
+ pi1 = pi1->next) {
bgp_path_info_unset_flag(dest, pi1,
BGP_PATH_DMED_SELECTED);
+ UNSET_FLAG(pi1->flags, BGP_PATH_DMED_CHECK);
+ }
for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
pi1 = pi1->next) {
@@ -2829,68 +2919,273 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
}
}
- /* Check old selected route and new selected route. */
+ /*
+ * Let's grab the unsorted items from the list
+ */
+ struct bgp_path_info *unsorted_list = NULL;
+ struct bgp_path_info *unsorted_list_spot = NULL;
+ struct bgp_path_info *unsorted_holddown = NULL;
+
old_select = NULL;
- new_select = NULL;
- for (pi = bgp_dest_get_bgp_path_info(dest);
- (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
- enum bgp_path_selection_reason reason;
+ pi = bgp_dest_get_bgp_path_info(dest);
+ while (pi && CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED)) {
+ struct bgp_path_info *next = pi->next;
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
old_select = pi;
- if (BGP_PATH_HOLDDOWN(pi)) {
- /* reap REMOVED routes, if needs be
+ /*
+ * Pull off pi off the list
+ */
+ if (pi->next)
+ pi->next->prev = NULL;
+
+ bgp_dest_set_bgp_path_info(dest, pi->next);
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ /*
+ * Place it on the unsorted list
+ */
+ if (unsorted_list_spot) {
+ unsorted_list_spot->next = pi;
+ pi->prev = unsorted_list_spot;
+ pi->next = NULL;
+ } else {
+ unsorted_list = pi;
+
+ pi->next = NULL;
+ pi->prev = NULL;
+ }
+
+ unsorted_list_spot = pi;
+ pi = next;
+ }
+
+ if (!old_select) {
+ old_select = bgp_dest_get_bgp_path_info(dest);
+ if (old_select &&
+ !CHECK_FLAG(old_select->flags, BGP_PATH_SELECTED))
+ old_select = NULL;
+ }
+
+ if (!unsorted_list)
+ unsorted_items = true;
+ else
+ unsorted_items = false;
+
+ any_comparisons = false;
+ worse = NULL;
+ while (unsorted_list) {
+ first = unsorted_list;
+ unsorted_list = unsorted_list->next;
+
+ if (unsorted_list)
+ unsorted_list->prev = NULL;
+ first->next = NULL;
+ first->prev = NULL;
+
+ /*
+ * It's not likely that the just received unsorted entry
+ * is in holddown and scheduled for removal but we should
+ * check
+ */
+ if (BGP_PATH_HOLDDOWN(first)) {
+ /*
+ * reap REMOVED routes, if needs be
* selected route must stay for a while longer though
*/
if (debug)
- zlog_debug(
- "%s: %pBD(%s) pi from %s in holddown",
- __func__, dest, bgp->name_pretty,
- pi->peer->host);
+ zlog_debug("%s: %pBD(%s) pi %p from %s in holddown",
+ __func__, dest, bgp->name_pretty,
+ first, first->peer->host);
- if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) &&
- (pi != old_select)) {
- dest = bgp_path_info_reap(dest, pi);
+ if (old_select != first &&
+ CHECK_FLAG(first->flags, BGP_PATH_REMOVED)) {
+ dest = bgp_path_info_reap_unsorted(dest, first);
assert(dest);
- }
+ } else {
+ /*
+ * We are in hold down, so we cannot sort this
+ * item yet. Let's wait, so hold the unsorted
+ * to the side
+ */
+ if (unsorted_holddown) {
+ first->next = unsorted_holddown;
+ unsorted_holddown->prev = first;
+ unsorted_holddown = first;
+ } else
+ unsorted_holddown = first;
+ UNSET_FLAG(first->flags, BGP_PATH_UNSORTED);
+ }
continue;
}
- if (pi->peer && pi->peer != bgp->peer_self
- && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
- if (!peer_established(pi->peer->connection)) {
+ bgp_path_info_unset_flag(dest, first, BGP_PATH_DMED_CHECK);
+
+ worse = NULL;
+
+ struct bgp_path_info *look_thru_next;
+
+ for (look_thru = bgp_dest_get_bgp_path_info(dest); look_thru;
+ look_thru = look_thru_next) {
+ /* look thru can be reaped save the next pointer */
+ look_thru_next = look_thru->next;
+
+ /*
+ * Now we have the first unsorted and the best selected
+ * Let's do best path comparison
+ */
+ if (BGP_PATH_HOLDDOWN(look_thru)) {
+ /* reap REMOVED routes, if needs be
+ * selected route must stay for a while longer though
+ */
if (debug)
- zlog_debug(
- "%s: %pBD(%s) non self peer %s not estab state",
- __func__, dest,
- bgp->name_pretty,
- pi->peer->host);
+ zlog_debug("%s: %pBD(%s) pi from %s %p in holddown",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host,
+ look_thru);
+
+ if (CHECK_FLAG(look_thru->flags,
+ BGP_PATH_REMOVED) &&
+ (look_thru != old_select)) {
+ dest = bgp_path_info_reap(dest,
+ look_thru);
+ assert(dest);
+ }
continue;
}
- bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
+ if (look_thru->peer &&
+ look_thru->peer != bgp->peer_self &&
+ !CHECK_FLAG(look_thru->peer->sflags,
+ PEER_STATUS_NSF_WAIT))
+ if (!peer_established(
+ look_thru->peer->connection)) {
+ if (debug)
+ zlog_debug("%s: %pBD(%s) non self peer %s not estab state",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host);
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) &&
- (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
- if (debug)
- zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
- dest, bgp->name_pretty,
- pi->peer->host);
- continue;
+ continue;
+ }
+
+ bgp_path_info_unset_flag(dest, look_thru,
+ BGP_PATH_DMED_CHECK);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) &&
+ (!CHECK_FLAG(look_thru->flags,
+ BGP_PATH_DMED_SELECTED))) {
+ bgp_path_info_unset_flag(dest, look_thru,
+ BGP_PATH_DMED_CHECK);
+ if (debug)
+ zlog_debug("%s: %pBD(%s) pi %s dmed",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host);
+
+ worse = look_thru;
+ continue;
+ }
+
+ reason = dest->reason;
+ any_comparisons = true;
+ if (bgp_path_info_cmp(bgp, first, look_thru, &paths_eq,
+ mpath_cfg, debug, pfx_buf, afi,
+ safi, &reason)) {
+ first->reason = reason;
+ worse = look_thru;
+ /*
+ * We can stop looking
+ */
+ break;
+ }
+
+ look_thru->reason = reason;
+ }
+
+ if (!any_comparisons)
+ first->reason = bgp_path_selection_first;
+
+ /*
+ * At this point worse if NON-NULL is where the first
+ * pointer should be before. if worse is NULL then
+ * first is bestpath too. Let's remove first from the
+ * list and place it in the right spot
+ */
+
+ if (!worse) {
+ struct bgp_path_info *end =
+ bgp_dest_get_bgp_path_info(dest);
+
+ for (; end && end->next != NULL; end = end->next)
+ ;
+
+ if (end)
+ end->next = first;
+ else
+ bgp_dest_set_bgp_path_info(dest, first);
+ first->prev = end;
+ first->next = NULL;
+
+ dest->reason = first->reason;
+ } else {
+ if (worse->prev)
+ worse->prev->next = first;
+ first->next = worse;
+ if (worse) {
+ first->prev = worse->prev;
+ worse->prev = first;
+ } else
+ first->prev = NULL;
+
+ if (dest->info == worse) {
+ bgp_dest_set_bgp_path_info(dest, first);
+ dest->reason = first->reason;
+ }
}
+ UNSET_FLAG(first->flags, BGP_PATH_UNSORTED);
+ }
+
+ if (!unsorted_items) {
+ new_select = bgp_dest_get_bgp_path_info(dest);
+ while (new_select && BGP_PATH_HOLDDOWN(new_select))
+ new_select = new_select->next;
+
+ if (new_select) {
+ if (new_select->reason == bgp_path_selection_none)
+ new_select->reason = bgp_path_selection_first;
+ else if (new_select == bgp_dest_get_bgp_path_info(dest) &&
+ new_select->next == NULL)
+ new_select->reason = bgp_path_selection_first;
+ dest->reason = new_select->reason;
+ } else
+ dest->reason = bgp_path_selection_none;
+ } else
+ new_select = old_select;
- reason = dest->reason;
- if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
- debug, pfx_buf, afi, safi,
- &dest->reason)) {
- if (new_select == NULL &&
- reason != bgp_path_selection_none)
- dest->reason = reason;
- new_select = pi;
+
+ /*
+ * Reinsert all the unsorted_holddown items for future processing
+ * at the end of the list.
+ */
+ if (unsorted_holddown) {
+ struct bgp_path_info *top = bgp_dest_get_bgp_path_info(dest);
+ struct bgp_path_info *prev = NULL;
+
+ while (top != NULL) {
+ prev = top;
+ top = top->next;
}
+
+ if (prev) {
+ prev->next = unsorted_holddown;
+ unsorted_holddown->prev = prev;
+ } else
+ bgp_dest_set_bgp_path_info(dest, unsorted_holddown);
}
/* Now that we know which path is the bestpath see if any of the other
@@ -3339,7 +3634,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
return;
}
+#ifdef ENABLE_BGP_VNC
const struct prefix *p = bgp_dest_get_prefix(dest);
+#endif
debug = bgp_debug_bestpath(dest);
if (debug)
@@ -3402,9 +3699,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|| new_select->sub_type
== BGP_ROUTE_IMPORTED))
-
- bgp_zebra_announce(dest, p, old_select,
- bgp, afi, safi);
+ bgp_zebra_route_install(dest, old_select,
+ bgp, true, NULL,
+ false);
}
}
@@ -3464,7 +3761,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
if (debug)
- zlog_debug("%s: setting SELECTED flag", __func__);
+ zlog_debug("%s: %pBD setting SELECTED flag", __func__,
+ dest);
bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
bgp_path_info_unset_flag(dest, new_select,
BGP_PATH_ATTR_CHANGED);
@@ -3498,14 +3796,6 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
}
#endif
- group_announce_route(bgp, afi, safi, dest, new_select);
-
- /* unicast routes must also be annouced to labeled-unicast update-groups
- */
- if (safi == SAFI_UNICAST)
- group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
- new_select);
-
/* FIB update. */
if (bgp_fibupd_safi(safi) && (bgp->inst_type != BGP_INSTANCE_TYPE_VIEW)
&& !bgp_option_check(BGP_OPT_NO_FIB)) {
@@ -3521,10 +3811,11 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
*/
if (old_select &&
is_route_parent_evpn(old_select))
- bgp_zebra_withdraw(p, old_select, bgp, afi,
- safi);
+ bgp_zebra_route_install(dest, old_select, bgp,
+ false, NULL, false);
- bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
+ bgp_zebra_route_install(dest, new_select, bgp, true,
+ NULL, false);
} else {
/* Withdraw the route from the kernel. */
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
@@ -3532,11 +3823,20 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
- bgp_zebra_withdraw(p, old_select, bgp, afi,
- safi);
+ bgp_zebra_route_install(dest, old_select, bgp,
+ false, NULL, false);
}
}
+ group_announce_route(bgp, afi, safi, dest, new_select);
+
+ /* unicast routes must also be annouced to labeled-unicast update-groups
+ */
+ if (safi == SAFI_UNICAST)
+ group_announce_route(bgp, afi, SAFI_LABELED_UNICAST, dest,
+ new_select);
+
+
bgp_process_evpn_route_injection(bgp, afi, safi, dest, new_select,
old_select);
@@ -3687,13 +3987,38 @@ static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
return pqnode;
}
-void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
+void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi)
{
#define ARBITRARY_PROCESS_QLEN 10000
struct work_queue *wq = bgp->process_queue;
struct bgp_process_queue *pqnode;
int pqnode_reuse = 0;
+ /*
+ * Indicate that *this* pi is in an unsorted
+ * situation, even if the node is already
+ * scheduled.
+ */
+ if (pi) {
+ struct bgp_path_info *first = bgp_dest_get_bgp_path_info(dest);
+
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+
+ if (pi != first) {
+ if (pi->next)
+ pi->next->prev = pi->prev;
+ if (pi->prev)
+ pi->prev->next = pi->next;
+
+ if (first)
+ first->prev = pi;
+ pi->next = first;
+ pi->prev = NULL;
+ bgp_dest_set_bgp_path_info(dest, pi);
+ }
+ }
+
/* already scheduled for processing? */
if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
return;
@@ -3942,7 +4267,7 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
}
hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
- bgp_process(peer->bgp, dest, afi, safi);
+ bgp_process(peer->bgp, dest, pi, afi, safi);
}
static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
@@ -4430,7 +4755,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
/* remove from RIB previous entry */
- bgp_zebra_withdraw(p, pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, false, NULL,
+ false);
}
if (peer->sort == BGP_PEER_EBGP) {
@@ -4547,7 +4873,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
!= BGP_DAMP_SUPPRESSED) {
bgp_aggregate_increment(bgp, p, pi, afi,
safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
} else /* Duplicate - odd */
{
@@ -4575,7 +4901,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_path_info_unset_flag(
dest, pi, BGP_PATH_STALE);
bgp_dest_set_defer_flag(dest, false);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
@@ -4865,7 +5191,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
if (SAFI_UNICAST == safi
@@ -5010,7 +5336,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
/* Process change. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
if (SAFI_UNICAST == safi
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
@@ -5581,7 +5907,7 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
struct bgp_clear_node_queue *cnq = data;
struct bgp_dest *dest = cnq->dest;
struct peer *peer = wq->spec.data;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
struct bgp *bgp;
afi_t afi = bgp_dest_table(dest)->afi;
safi_t safi = bgp_dest_table(dest)->safi;
@@ -5592,7 +5918,8 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
/* It is possible that we have multiple paths for a prefix from a peer
* if that peer is using AddPath.
*/
- for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
if (pi->peer != peer)
continue;
@@ -5854,7 +6181,7 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
struct bgp_table *table;
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
@@ -5869,8 +6196,9 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
for (rm = bgp_table_top(table); rm;
rm = bgp_route_next(rm))
- for (pi = bgp_dest_get_bgp_path_info(rm); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(rm);
+ (pi != NULL) && (next = pi->next, 1);
+ pi = next) {
if (pi->peer != peer)
continue;
if (CHECK_FLAG(
@@ -5903,8 +6231,8 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
} else {
for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
dest = bgp_route_next(dest))
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
if (pi->peer != peer)
continue;
if (CHECK_FLAG(peer->af_sflags[afi][safi],
@@ -6056,8 +6384,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
|| pi->sub_type == BGP_ROUTE_IMPORTED)) {
if (bgp_fibupd_safi(safi))
- bgp_zebra_withdraw(p, pi, bgp, afi,
- safi);
+ bgp_zebra_withdraw_actual(dest, pi, bgp);
}
dest = bgp_path_info_reap(dest, pi);
@@ -6518,7 +6845,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
if (SAFI_MPLS_VPN == safi &&
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
@@ -6576,7 +6903,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_dest_unlock_node(dest);
/* Process change. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
if (SAFI_UNICAST == safi &&
(bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
@@ -6615,6 +6942,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
/* Withdraw static BGP route from routing table. */
if (pi) {
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
rfapiProcessWithdraw(pi->peer, NULL, p, prd, pi->attr,
@@ -6633,7 +6961,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
/* Unlock bgp_node_lookup. */
@@ -6825,6 +7153,10 @@ int bgp_static_set(struct vty *vty, bool negate, const char *ip_str,
bgp_static->label = label;
bgp_static->prd = prd;
+ if (rd_str)
+ bgp_static->prd_pretty = XSTRDUP(MTYPE_BGP,
+ rd_str);
+
if (rmap) {
XFREE(MTYPE_ROUTE_MAP_NAME,
bgp_static->rmap.name);
@@ -7034,7 +7366,7 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
safi);
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
}
@@ -7397,8 +7729,10 @@ static void bgp_aggregate_install(
/*
* Mark the old as unusable
*/
- if (pi)
+ if (pi) {
bgp_path_info_delete(dest, pi);
+ bgp_process(bgp, dest, pi, afi, safi);
+ }
attr = bgp_attr_aggregate_intern(
bgp, origin, aspath, community, ecommunity, lcommunity,
@@ -7423,7 +7757,7 @@ static void bgp_aggregate_install(
SET_FLAG(new->flags, BGP_PATH_VALID);
bgp_path_info_add(dest, new);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
} else {
uninstall_aggregate_route:
for (pi = orig; pi; pi = pi->next)
@@ -7435,7 +7769,7 @@ static void bgp_aggregate_install(
/* Withdraw static BGP route from routing table. */
if (pi) {
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
@@ -7521,7 +7855,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
const struct prefix *dest_p;
struct bgp_dest *dest, *top;
struct bgp_path_info *pi;
- bool toggle_suppression;
/* We've found a different MED we must revert any suppressed routes. */
top = bgp_node_get(table, p);
@@ -7531,7 +7864,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- toggle_suppression = false;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -7542,17 +7874,14 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
if (suppress) {
/* Suppress route if not suppressed already. */
if (aggr_suppress_path(aggregate, pi))
- toggle_suppression = true;
+ bgp_process(bgp, dest, pi, afi, safi);
continue;
}
/* Install route if there is no more suppression. */
if (aggr_unsuppress_path(aggregate, pi))
- toggle_suppression = true;
+ bgp_process(bgp, dest, pi, afi, safi);
}
-
- if (toggle_suppression)
- bgp_process(bgp, dest, afi, safi);
}
bgp_dest_unlock_node(top);
}
@@ -7611,7 +7940,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
struct bgp_path_info *pi;
- unsigned long match = 0;
uint8_t atomic_aggregate = 0;
/* If the bgp instance is being deleted or self peer is deleted
@@ -7661,8 +7989,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (!bgp_check_advertise(bgp, dest, safi))
continue;
- match = 0;
-
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -7686,7 +8012,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (aggregate->summary_only
&& AGGREGATE_MED_VALID(aggregate)) {
if (aggr_suppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
/*
@@ -7702,7 +8028,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
&& AGGREGATE_MED_VALID(aggregate)
&& aggr_suppress_map_test(bgp, aggregate, pi)) {
if (aggr_suppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
aggregate->count++;
@@ -7763,8 +8089,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
aggregate,
bgp_attr_get_lcommunity(pi->attr));
}
- if (match)
- bgp_process(bgp, dest, afi, safi);
}
if (aggregate->as_set) {
bgp_compute_aggregate_aspath_val(aggregate);
@@ -7824,7 +8148,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct bgp_dest *top;
struct bgp_dest *dest;
struct bgp_path_info *pi;
- unsigned long match;
table = bgp->rib[afi][safi];
@@ -7836,7 +8159,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- match = 0;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
@@ -7854,10 +8176,11 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (pi->extra && pi->extra->aggr_suppressors &&
listcount(pi->extra->aggr_suppressors)) {
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
- aggregate->count--;
+ if (aggregate->count > 0)
+ aggregate->count--;
if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
aggregate->incomplete_origin_count--;
@@ -7896,10 +8219,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
pi->attr));
}
}
-
- /* If this node was suppressed, process the change. */
- if (match)
- bgp_process(bgp, dest, afi, safi);
}
if (aggregate->as_set) {
aspath_free(aggregate->aspath);
@@ -8048,7 +8367,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
struct community *community = NULL;
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
- unsigned long match = 0;
/* If the bgp instance is being deleted or self peer is deleted
* then do not create aggregate route
@@ -8065,12 +8383,12 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, pi->net, pi, afi, safi);
if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
&& aggr_suppress_map_test(bgp, aggregate, pi))
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, pi->net, pi, afi, safi);
/*
* This must be called after `summary`, `suppress-map` check to avoid
@@ -8112,10 +8430,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
aggregate, bgp_attr_get_lcommunity(pi->attr));
}
- /* If this node was suppressed, process the change. */
- if (match)
- bgp_process(bgp, pi->net, afi, safi);
-
origin = BGP_ORIGIN_IGP;
if (aggregate->incomplete_origin_count > 0)
origin = BGP_ORIGIN_INCOMPLETE;
@@ -8725,7 +9039,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Process change. */
bgp_aggregate_increment(bgp, p, bpi, afi,
SAFI_UNICAST);
- bgp_process(bgp, bn, afi, SAFI_UNICAST);
+ bgp_process(bgp, bn, bpi, afi, SAFI_UNICAST);
bgp_dest_unlock_node(bn);
aspath_unintern(&attr.aspath);
@@ -8748,7 +9062,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
bgp_path_info_add(bn, new);
bgp_dest_unlock_node(bn);
SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
- bgp_process(bgp, bn, afi, SAFI_UNICAST);
+ bgp_process(bgp, bn, new, afi, SAFI_UNICAST);
if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|| (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
@@ -8789,7 +9103,7 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
}
bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
}
bgp_dest_unlock_node(dest);
}
@@ -8823,7 +9137,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
bgp_path_info_delete(dest, pi);
if (!CHECK_FLAG(bgp->flags,
BGP_FLAG_DELETE_IN_PROGRESS))
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
else {
dest = bgp_path_info_reap(dest, pi);
assert(dest);
@@ -8969,6 +9283,9 @@ static void route_vty_short_status_out(struct vty *vty,
if (path->extra && bgp_path_suppressed(path))
json_object_boolean_true_add(json_path, "suppressed");
+ if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED))
+ json_object_boolean_true_add(json_path, "unsorted");
+
if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
json_object_boolean_true_add(json_path, "valid");
@@ -9031,6 +9348,8 @@ static void route_vty_short_status_out(struct vty *vty,
/* Selected */
if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
vty_out(vty, "h");
+ else if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED))
+ vty_out(vty, "u");
else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
vty_out(vty, "d");
else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
@@ -9046,6 +9365,9 @@ static void route_vty_short_status_out(struct vty *vty,
vty_out(vty, "i");
else
vty_out(vty, " ");
+
+ /* adding space between next column */
+ vty_out(vty, " ");
}
static char *bgp_nexthop_hostname(struct peer *peer,
@@ -9400,14 +9722,16 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
/* MED/Metric */
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
+ if (use_bgp_med_value(attr, path->peer->bgp)) {
+ uint32_t value = bgp_med_value(attr, path->peer->bgp);
+
if (json_paths)
- json_object_int_add(json_path, "metric", attr->med);
+ json_object_int_add(json_path, "metric", value);
else if (wide)
- vty_out(vty, "%7u", attr->med);
+ vty_out(vty, "%7u", value);
else
- vty_out(vty, "%10u", attr->med);
- else if (!json_paths) {
+ vty_out(vty, "%10u", value);
+ } else if (!json_paths) {
if (wide)
vty_out(vty, "%*s", 7, " ");
else
@@ -9528,7 +9852,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
/* called from terminal list command */
-void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
+void route_vty_out_tmp(struct vty *vty, struct bgp *bgp, struct bgp_dest *dest,
const struct prefix *p, struct attr *attr, safi_t safi,
bool use_json, json_object *json_ar, bool wide)
{
@@ -9587,10 +9911,11 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
&attr->mp_nexthop_global_in);
}
- if (attr->flag
- & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
- json_object_int_add(json_net, "metric",
- attr->med);
+ if (use_bgp_med_value(attr, bgp)) {
+ uint32_t value = bgp_med_value(attr, bgp);
+
+ json_object_int_add(json_net, "metric", value);
+ }
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF))
json_object_int_add(json_net, "locPrf",
@@ -9630,13 +9955,15 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
else
vty_out(vty, "%*s", len, " ");
}
- if (attr->flag
- & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC))
+
+ if (use_bgp_med_value(attr, bgp)) {
+ uint32_t value = bgp_med_value(attr, bgp);
+
if (wide)
- vty_out(vty, "%7u", attr->med);
+ vty_out(vty, "%7u", value);
else
- vty_out(vty, "%10u", attr->med);
- else if (wide)
+ vty_out(vty, "%10u", value);
+ } else if (wide)
vty_out(vty, " ");
else
vty_out(vty, " ");
@@ -10145,6 +10472,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object *json_cluster_list = NULL;
json_object *json_cluster_list_list = NULL;
json_object *json_ext_community = NULL;
+ json_object *json_ext_ipv6_community = NULL;
json_object *json_last_update = NULL;
json_object *json_pmsi = NULL;
json_object *json_nexthop_global = NULL;
@@ -10633,11 +10961,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, " Origin %s",
bgp_origin_long_str[attr->origin]);
- if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC)) {
+ if (use_bgp_med_value(attr, bgp)) {
+ uint32_t value = bgp_med_value(attr, bgp);
+
if (json_paths)
- json_object_int_add(json_path, "metric", attr->med);
+ json_object_int_add(json_path, "metric", value);
else
- vty_out(vty, ", metric %u", attr->med);
+ vty_out(vty, ", metric %u", value);
}
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LOCAL_PREF)) {
@@ -10851,6 +11181,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
}
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES)) {
+ if (json_paths) {
+ json_ext_ipv6_community = json_object_new_object();
+ json_object_string_add(json_ext_ipv6_community, "string",
+ bgp_attr_get_ipv6_ecommunity(attr)
+ ->str);
+ json_object_object_add(json_path,
+ "extendedIpv6Community",
+ json_ext_ipv6_community);
+ } else {
+ vty_out(vty, " Extended IPv6 Community: %s\n",
+ bgp_attr_get_ipv6_ecommunity(attr)->str);
+ }
+ }
+
/* Line 6 display Large community */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
if (json_paths) {
@@ -11877,7 +12222,7 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
} else {
if (incremental_print) {
vty_out(vty, "\"prefix\": \"%pFX\",\n", p);
- vty_out(vty, "\"version\": \"%" PRIu64 "\",\n",
+ vty_out(vty, "\"version\": \"%" PRIu64 "\",",
dest->version);
} else {
json_object_string_addf(json, "prefix", "%pFX",
@@ -13668,21 +14013,23 @@ enum bgp_pcounts {
PCOUNT_COUNTED,
PCOUNT_BPATH_SELECTED,
PCOUNT_PFCNT, /* the figure we display to users */
+ PCOUNT_UNSORTED,
PCOUNT_MAX,
};
static const char *const pcount_strs[] = {
- [PCOUNT_ADJ_IN] = "Adj-in",
- [PCOUNT_DAMPED] = "Damped",
- [PCOUNT_REMOVED] = "Removed",
- [PCOUNT_HISTORY] = "History",
- [PCOUNT_STALE] = "Stale",
- [PCOUNT_VALID] = "Valid",
- [PCOUNT_ALL] = "All RIB",
- [PCOUNT_COUNTED] = "PfxCt counted",
- [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
- [PCOUNT_PFCNT] = "Useable",
- [PCOUNT_MAX] = NULL,
+ [PCOUNT_ADJ_IN] = "Adj-in",
+ [PCOUNT_DAMPED] = "Damped",
+ [PCOUNT_REMOVED] = "Removed",
+ [PCOUNT_HISTORY] = "History",
+ [PCOUNT_STALE] = "Stale",
+ [PCOUNT_VALID] = "Valid",
+ [PCOUNT_ALL] = "All RIB",
+ [PCOUNT_COUNTED] = "PfxCt counted",
+ [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
+ [PCOUNT_PFCNT] = "Useable",
+ [PCOUNT_UNSORTED] = "Unsorted",
+ [PCOUNT_MAX] = NULL,
};
struct peer_pcounts {
@@ -13723,6 +14070,8 @@ static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
pc->count[PCOUNT_PFCNT]++;
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
pc->count[PCOUNT_BPATH_SELECTED]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED))
+ pc->count[PCOUNT_UNSORTED]++;
if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
pc->count[PCOUNT_COUNTED]++;
@@ -14281,7 +14630,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
json_ar, json_net,
"%pFX", rn_p);
} else
- route_vty_out_tmp(vty, dest, rn_p,
+ route_vty_out_tmp(vty, bgp, dest, rn_p,
&attr, safi, use_json,
json_ar, wide);
bgp_attr_flush(&attr);
@@ -14344,11 +14693,15 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
"%pFX",
rn_p);
} else
- route_vty_out_tmp(
- vty, dest, rn_p,
- &attr, safi,
- use_json,
- json_ar, wide);
+ route_vty_out_tmp(vty,
+ bgp,
+ dest,
+ rn_p,
+ &attr,
+ safi,
+ use_json,
+ json_ar,
+ wide);
(*output_count)++;
} else {
(*filtered_count)++;
@@ -14386,9 +14739,10 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
json_ar, json_net,
"%pFX", rn_p);
} else
- route_vty_out_tmp(
- vty, dest, rn_p, pi->attr, safi,
- use_json, json_ar, wide);
+ route_vty_out_tmp(vty, bgp, dest, rn_p,
+ pi->attr, safi,
+ use_json, json_ar,
+ wide);
(*output_count)++;
}
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 2d82f0f206..25fc327a17 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -59,15 +59,15 @@ enum bgp_show_adj_route_type {
#define BGP_SHOW_SCODE_HEADER \
"Status codes: s suppressed, d damped, " \
- "h history, * valid, > best, = multipath,\n" \
+ "h history, u unsorted, * valid, > best, = multipath,\n" \
" i internal, r RIB-failure, S Stale, R Removed\n"
#define BGP_SHOW_OCODE_HEADER \
"Origin codes: i - IGP, e - EGP, ? - incomplete\n"
#define BGP_SHOW_NCODE_HEADER "Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self\n"
#define BGP_SHOW_RPKI_HEADER \
"RPKI validation codes: V valid, I invalid, N Not found\n\n"
-#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
-#define BGP_SHOW_HEADER_WIDE " Network Next Hop Metric LocPrf Weight Path\n"
+#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
+#define BGP_SHOW_HEADER_WIDE " Network Next Hop Metric LocPrf Weight Path\n"
/* Maximum number of labels we can process or send with a prefix. We
* really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN.
@@ -327,6 +327,7 @@ struct bgp_path_info {
#define BGP_PATH_ACCEPT_OWN (1 << 16)
#define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17)
#define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18)
+#define BGP_PATH_UNSORTED (1 << 19)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
uint8_t type;
@@ -345,6 +346,8 @@ struct bgp_path_info {
unsigned short instance;
+ enum bgp_path_selection_reason reason;
+
/* Addpath identifiers */
uint32_t addpath_rx_id;
struct bgp_addpath_info_data tx_addpath;
@@ -801,7 +804,8 @@ extern void bgp_withdraw(struct peer *peer, const struct prefix *p,
struct bgp_route_evpn *evpn);
/* for bgp_nexthop and bgp_damp */
-extern void bgp_process(struct bgp *, struct bgp_dest *, afi_t, safi_t);
+extern void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi);
/*
* Add an end-of-initial-update marker to the process queue. This is just a
@@ -845,10 +849,10 @@ extern void route_vty_out(struct vty *vty, const struct prefix *p,
extern void route_vty_out_tag(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
safi_t safi, json_object *json);
-extern void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
- const struct prefix *p, struct attr *attr,
- safi_t safi, bool use_json, json_object *json_ar,
- bool wide);
+extern void route_vty_out_tmp(struct vty *vty, struct bgp *bgp,
+ struct bgp_dest *dest, const struct prefix *p,
+ struct attr *attr, safi_t safi, bool use_json,
+ json_object *json_ar, bool wide);
extern void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
struct bgp_path_info *path, int display,
json_object *json);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 15828b6594..4875697aa1 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1944,7 +1944,6 @@ route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
path = object;
path->attr->srte_color = *srte_color;
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
return RMAP_OKAY;
}
@@ -3196,7 +3195,7 @@ struct rmap_ecomm_lb_set {
#define RMAP_ECOMM_LB_SET_CUMUL 2
#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
bool non_trans;
- uint32_t bw;
+ uint64_t bw;
};
static enum route_map_cmd_result_t
@@ -3206,8 +3205,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
struct bgp_path_info *path;
struct peer *peer;
struct ecommunity ecom_lb = {0};
- struct ecommunity_val lb_eval;
- uint32_t bw_bytes = 0;
+ uint64_t bw_bytes = 0;
uint16_t mpath_count = 0;
struct ecommunity *new_ecom;
struct ecommunity *old_ecom;
@@ -3221,13 +3219,13 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
/* Build link bandwidth extended community */
as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
- bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
+ bw_bytes = (rels->bw * 1000 * 1000) / 8;
} else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
/* process this only for the best path. */
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
return RMAP_OKAY;
- bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
+ bw_bytes = bgp_path_info_mpath_cumbw(path);
if (!bw_bytes)
return RMAP_OKAY;
@@ -3237,31 +3235,53 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
return RMAP_OKAY;
- bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
+ bw_bytes = (peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
mpath_count = bgp_path_info_mpath_count(path) + 1;
bw_bytes *= mpath_count;
}
- encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
- CHECK_FLAG(peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) {
+ struct ecommunity_val_ipv6 lb_eval;
- /* add to route or merge with existing */
- old_ecom = bgp_attr_get_ecommunity(path->attr);
- if (old_ecom) {
- new_ecom = ecommunity_dup(old_ecom);
- ecommunity_add_val(new_ecom, &lb_eval, true, true);
- if (!old_ecom->refcnt)
- ecommunity_free(&old_ecom);
+ encode_lb_extended_extcomm(as, bw_bytes, rels->non_trans,
+ &lb_eval);
+
+ old_ecom = bgp_attr_get_ipv6_ecommunity(path->attr);
+ if (old_ecom) {
+ new_ecom = ecommunity_dup(old_ecom);
+ ecommunity_add_val_ipv6(new_ecom, &lb_eval, true, true);
+ if (!old_ecom->refcnt)
+ ecommunity_free(&old_ecom);
+ } else {
+ ecom_lb.size = 1;
+ ecom_lb.unit_size = IPV6_ECOMMUNITY_SIZE;
+ ecom_lb.val = (uint8_t *)lb_eval.val;
+ new_ecom = ecommunity_dup(&ecom_lb);
+ }
+
+ bgp_attr_set_ipv6_ecommunity(path->attr, new_ecom);
} else {
- ecom_lb.size = 1;
- ecom_lb.unit_size = ECOMMUNITY_SIZE;
- ecom_lb.val = (uint8_t *)lb_eval.val;
- new_ecom = ecommunity_dup(&ecom_lb);
- }
+ struct ecommunity_val lb_eval;
+
+ encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+
+ old_ecom = bgp_attr_get_ecommunity(path->attr);
+ if (old_ecom) {
+ new_ecom = ecommunity_dup(old_ecom);
+ ecommunity_add_val(new_ecom, &lb_eval, true, true);
+ if (!old_ecom->refcnt)
+ ecommunity_free(&old_ecom);
+ } else {
+ ecom_lb.size = 1;
+ ecom_lb.unit_size = ECOMMUNITY_SIZE;
+ ecom_lb.val = (uint8_t *)lb_eval.val;
+ new_ecom = ecommunity_dup(&ecom_lb);
+ }
- /* new_ecom will be intern()'d or attr_flush()'d in call stack */
- bgp_attr_set_ecommunity(path->attr, new_ecom);
+ bgp_attr_set_ecommunity(path->attr, new_ecom);
+ }
/* Mark that route-map has set link bandwidth; used in attribute
* setting decisions.
@@ -3275,7 +3295,7 @@ static void *route_set_ecommunity_lb_compile(const char *arg)
{
struct rmap_ecomm_lb_set *rels;
uint8_t lb_type;
- uint32_t bw = 0;
+ uint64_t bw = 0;
char bw_str[40] = {0};
char *p, *str;
bool non_trans = false;
@@ -3317,13 +3337,8 @@ static enum route_map_cmd_result_t
route_set_ecommunity_color(void *rule, const struct prefix *prefix,
void *object)
{
- struct bgp_path_info *path;
-
- path = object;
-
route_set_ecommunity(rule, prefix, object);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
return RMAP_OKAY;
}
@@ -6875,7 +6890,7 @@ DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
DEFUN_YANG (set_ecommunity_lb,
set_ecommunity_lb_cmd,
- "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
+ "set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]",
SET_STR
"BGP extended community attribute\n"
"Link bandwidth extended community\n"
@@ -6929,7 +6944,7 @@ DEFUN_YANG (set_ecommunity_lb,
DEFUN_YANG (no_set_ecommunity_lb,
no_set_ecommunity_lb_cmd,
- "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
+ "no set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]",
NO_STR
SET_STR
"BGP extended community attribute\n"
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index c1d6ee12e1..15c32eaa28 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -2937,7 +2937,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
struct routemap_hook_context *rhc;
enum ecommunity_lb_type lb_type;
char str[VTY_BUFSIZ];
- uint16_t bandwidth;
+ uint32_t bandwidth;
int ret;
/* Add configuration. */
@@ -2951,8 +2951,8 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
switch (lb_type) {
case EXPLICIT_BANDWIDTH:
- bandwidth = yang_dnode_get_uint16(args->dnode, "bandwidth");
- snprintf(str, sizeof(str), "%d", bandwidth);
+ bandwidth = yang_dnode_get_uint32(args->dnode, "bandwidth");
+ snprintf(str, sizeof(str), "%u", bandwidth);
break;
case CUMULATIVE_BANDWIDTH:
snprintf(str, sizeof(str), "%s", "cumulative");
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 56b0263bf6..67f59edb93 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -2088,16 +2088,18 @@ DEFPY (show_rpki_prefix_table,
DEFPY (show_rpki_as_number,
show_rpki_as_number_cmd,
- "show rpki as-number ASNUM$by_asn [vrf NAME$vrfname] [json$uj]",
+ "show rpki as-number <0$zero|ASNUM$by_asn> [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Lookup by ASN in prefix table\n"
+ "AS Number of 0, see RFC-7607\n"
"AS Number\n"
VRF_CMD_HELP_STR
JSON_STR)
{
struct json_object *json = NULL;
struct rpki_vrf *rpki_vrf;
+ as_t as;
if (uj)
json = json_object_new_object();
@@ -2118,18 +2120,24 @@ DEFPY (show_rpki_as_number,
return CMD_WARNING;
}
- print_prefix_table_by_asn(vty, by_asn, rpki_vrf, json);
+ if (zero)
+ as = 0;
+ else
+ as = by_asn;
+
+ print_prefix_table_by_asn(vty, as, rpki_vrf, json);
return CMD_SUCCESS;
}
DEFPY (show_rpki_prefix,
show_rpki_prefix_cmd,
- "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASNUM$asn] [vrf NAME$vrfname] [json$uj]",
+ "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [0$zero|ASNUM$asn] [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Lookup IP prefix and optionally ASN in prefix table\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
+ "AS Number of 0, see RFC-7607\n"
"AS Number\n"
VRF_CMD_HELP_STR
JSON_STR)
@@ -2138,6 +2146,7 @@ DEFPY (show_rpki_prefix,
json_object *json_records = NULL;
enum asnotation_mode asnotation;
struct rpki_vrf *rpki_vrf;
+ as_t as;
if (uj)
json = json_object_new_object();
@@ -2153,6 +2162,11 @@ DEFPY (show_rpki_prefix,
return CMD_WARNING;
}
+ if (zero)
+ as = 0;
+ else
+ as = asn;
+
struct lrtr_ip_addr addr;
char addr_str[INET6_ADDRSTRLEN];
size_t addr_len = strchr(prefix_str, '/') - prefix_str;
@@ -2174,7 +2188,7 @@ DEFPY (show_rpki_prefix,
enum pfxv_state result;
if (pfx_table_validate_r(rpki_vrf->rtr_config->pfx_table, &matches,
- &match_count, asn, &addr, prefix->prefixlen,
+ &match_count, as, &addr, prefix->prefixlen,
&result) != PFX_SUCCESS) {
if (json) {
json_object_string_add(json, "error", "Prefix lookup failed.");
@@ -2198,7 +2212,7 @@ DEFPY (show_rpki_prefix,
const struct pfx_record *record = &matches[i];
if (record->max_len >= prefix->prefixlen &&
- ((asn != 0 && (uint32_t)asn == record->asn) || asn == 0)) {
+ ((as != 0 && (uint32_t)as == record->asn) || asn == 0)) {
print_record(&matches[i], vty, json_records,
asnotation);
}
diff --git a/bgpd/bgp_snmp_bgp4.c b/bgpd/bgp_snmp_bgp4.c
index 3d04dc2ece..755777c167 100644
--- a/bgpd/bgp_snmp_bgp4.c
+++ b/bgpd/bgp_snmp_bgp4.c
@@ -401,7 +401,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[],
/* Set OID offset for prefix. */
offset = name + v->namelen;
oid2in_addr(offset, IN_ADDR_SIZE, &addr->prefix);
- offset++;
+ offset += IN_ADDR_SIZE;
/* Prefix length. */
addr->prefixlen = *offset;
@@ -497,7 +497,7 @@ static struct bgp_path_info *bgp4PathAttrLookup(struct variable *v, oid name[],
offset = name + v->namelen;
oid_copy_in_addr(offset, &rn_p->u.prefix4);
- offset++;
+ offset += IN_ADDR_SIZE;
*offset = rn_p->prefixlen;
offset++;
oid_copy_in_addr(offset,
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 5b4c3be212..130f5ca749 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -76,6 +76,11 @@ struct bgp_dest {
STAILQ_ENTRY(bgp_dest) pq;
+ struct zebra_announce_item zai;
+ struct bgp_path_info *za_bgp_pi;
+ struct bgpevpn *za_vpn;
+ bool za_is_sync;
+
uint64_t version;
mpls_label_t local_label;
@@ -91,12 +96,16 @@ struct bgp_dest {
#define BGP_NODE_LABEL_REQUESTED (1 << 7)
#define BGP_NODE_SOFT_RECONFIG (1 << 8)
#define BGP_NODE_PROCESS_CLEAR (1 << 9)
+#define BGP_NODE_SCHEDULE_FOR_INSTALL (1 << 10)
+#define BGP_NODE_SCHEDULE_FOR_DELETE (1 << 11)
struct bgp_addpath_node_data tx_addpath;
enum bgp_path_selection_reason reason;
};
+DECLARE_LIST(zebra_announce, struct bgp_dest, zai);
+
extern void bgp_delete_listnode(struct bgp_dest *dest);
/*
* bgp_table_iter_t
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 989dbe43a3..0a852c75de 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -328,15 +328,16 @@ static void subgrp_show_adjq_vty(struct update_subgroup *subgrp,
}
if ((flags & UPDWALK_FLAGS_ADVQUEUE) && adj->adv &&
adj->adv->baa) {
- route_vty_out_tmp(
- vty, dest, dest_p, adj->adv->baa->attr,
- SUBGRP_SAFI(subgrp), 0, NULL, false);
+ route_vty_out_tmp(vty, bgp, dest, dest_p,
+ adj->adv->baa->attr,
+ SUBGRP_SAFI(subgrp), 0, NULL,
+ false);
output_count++;
}
if ((flags & UPDWALK_FLAGS_ADVERTISED) && adj->attr) {
- route_vty_out_tmp(vty, dest, dest_p, adj->attr,
- SUBGRP_SAFI(subgrp), 0, NULL,
- false);
+ route_vty_out_tmp(vty, bgp, dest, dest_p,
+ adj->attr, SUBGRP_SAFI(subgrp),
+ 0, NULL, false);
output_count++;
}
}
@@ -532,7 +533,7 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
struct peer *adv_peer;
struct peer_af *paf;
struct bgp *bgp;
- uint32_t attr_hash = attrhash_key_make(attr);
+ uint32_t attr_hash = 0;
peer = SUBGRP_PEER(subgrp);
afi = SUBGRP_AFI(subgrp);
@@ -567,9 +568,11 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
* the route wasn't changed actually.
* Do not suppress BGP UPDATES for route-refresh.
*/
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES)
- && !CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES)
- && adj->attr_hash == attr_hash) {
+ if (likely(CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES)))
+ attr_hash = attrhash_key_make(attr);
+
+ if (!CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES) &&
+ attr_hash && adj->attr_hash == attr_hash) {
if (BGP_DEBUG(update, UPDATE_OUT)) {
char attr_str[BUFSIZ] = {0};
diff --git a/bgpd/bgp_vpn.c b/bgpd/bgp_vpn.c
index 8fe24ebe20..2470fb8844 100644
--- a/bgpd/bgp_vpn.c
+++ b/bgpd/bgp_vpn.c
@@ -191,7 +191,7 @@ int show_adj_route_vpn(struct vty *vty, struct peer *peer,
}
rd_header = 0;
}
- route_vty_out_tmp(vty, rm, bgp_dest_get_prefix(rm),
+ route_vty_out_tmp(vty, bgp, rm, bgp_dest_get_prefix(rm),
attr, safi, use_json, json_routes,
false);
output_count++;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index cd0d6def7d..5aedd6b828 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -126,6 +126,10 @@ FRR_CFG_DEFAULT_BOOL(BGP_SOFT_VERSION_CAPABILITY,
{ .val_bool = true, .match_profile = "datacenter", },
{ .val_bool = false },
);
+FRR_CFG_DEFAULT_BOOL(BGP_DYNAMIC_CAPABILITY,
+ { .val_bool = true, .match_profile = "datacenter", },
+ { .val_bool = false },
+);
FRR_CFG_DEFAULT_BOOL(BGP_ENFORCE_FIRST_AS,
{ .val_bool = false, .match_version = "< 9.1", },
{ .val_bool = true },
@@ -623,6 +627,9 @@ int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
if (DFLT_BGP_SOFT_VERSION_CAPABILITY)
SET_FLAG((*bgp)->flags,
BGP_FLAG_SOFT_VERSION_CAPABILITY);
+ if (DFLT_BGP_DYNAMIC_CAPABILITY)
+ SET_FLAG((*bgp)->flags,
+ BGP_FLAG_DYNAMIC_CAPABILITY);
if (DFLT_BGP_ENFORCE_FIRST_AS)
SET_FLAG((*bgp)->flags, BGP_FLAG_ENFORCE_FIRST_AS);
@@ -3028,14 +3035,17 @@ DEFUN (bgp_graceful_restart,
VTY_DECLVAR_CONTEXT(bgp, bgp);
ret = bgp_gr_update_all(bgp, GLOBAL_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
+
return bgp_vty_return(vty, ret);
}
@@ -3055,14 +3065,16 @@ DEFUN (no_bgp_graceful_restart,
int ret = BGP_GR_FAILURE;
ret = bgp_gr_update_all(bgp, NO_GLOBAL_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3270,24 +3282,25 @@ DEFUN (bgp_graceful_restart_disable,
VTY_DECLVAR_CONTEXT(bgp, bgp);
ret = bgp_gr_update_all(bgp, GLOBAL_DISABLE_CMD);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
- bgp->peer, ret);
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_UNSET);
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_LLGR,
+ CAPABILITY_ACTION_UNSET);
+ }
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
-
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_RESTART,
- CAPABILITY_ACTION_UNSET);
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_LLGR,
- CAPABILITY_ACTION_UNSET);
- }
+ zlog_debug("[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
return bgp_vty_return(vty, ret);
}
@@ -3309,15 +3322,17 @@ DEFUN (no_bgp_graceful_restart_disable,
int ret = BGP_GR_FAILURE;
ret = bgp_gr_update_all(bgp, NO_GLOBAL_DISABLE_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_graceful_restart_disable_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3345,15 +3360,16 @@ DEFUN (bgp_neighbor_graceful_restart_set,
return CMD_WARNING_CONFIG_FAILED;
ret = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3382,15 +3398,16 @@ DEFUN (no_bgp_neighbor_graceful_restart,
"[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3420,15 +3437,16 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set,
ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3457,15 +3475,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper,
"[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3493,18 +3512,19 @@ DEFUN (bgp_neighbor_graceful_restart_disable_set,
return CMD_WARNING_CONFIG_FAILED;
ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD);
+ if (ret == BGP_GR_SUCCESS) {
+ if (peer->bgp->t_startup)
+ bgp_peer_gr_flags_update(peer);
- if (peer->bgp->t_startup)
- bgp_peer_gr_flags_update(peer);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR]bgp_neighbor_graceful_restart_disable_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3533,15 +3553,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_disable,
"[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -4298,6 +4319,24 @@ DEFPY (bgp_default_software_version_capability,
return CMD_SUCCESS;
}
+DEFPY (bgp_default_dynamic_capability,
+ bgp_default_dynamic_capability_cmd,
+ "[no] bgp default dynamic-capability",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Advertise dynamic capability for all neighbors\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (no)
+ UNSET_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY);
+ else
+ SET_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY);
+
+ return CMD_SUCCESS;
+}
+
/* "bgp network import-check" configuration. */
DEFUN (bgp_network_import_check,
bgp_network_import_check_cmd,
@@ -4315,6 +4354,9 @@ DEFUN (bgp_network_import_check,
return CMD_SUCCESS;
}
+#if CONFDATE > 20241013
+CPP_NOTICE("Drop `bgp network import-check exact` command")
+#endif
ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd,
"bgp network import-check exact",
BGP_STR
@@ -5077,6 +5119,8 @@ DEFUN (no_neighbor,
struct peer_group *group;
struct peer *peer;
struct peer *other;
+ afi_t afi;
+ int lr_count;
ret = str2sockunion(argv[idx_peer]->arg, &su);
if (ret < 0) {
@@ -5094,6 +5138,15 @@ DEFUN (no_neighbor,
group = peer_group_lookup(bgp, argv[idx_peer]->arg);
if (group) {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ lr_count = listcount(group->listen_range[afi]);
+ if (lr_count) {
+ vty_out(vty,
+ "%%Peer-group %s is attached to %d listen-range(s), delete them first\n",
+ group->name, lr_count);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
peer_group_notify_unconfig(group);
peer_group_delete(group);
} else {
@@ -5171,9 +5224,20 @@ DEFUN (no_neighbor_peer_group,
VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_word = 2;
struct peer_group *group;
+ afi_t afi;
+ int lr_count;
group = peer_group_lookup(bgp, argv[idx_word]->arg);
if (group) {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ lr_count = listcount(group->listen_range[afi]);
+ if (lr_count) {
+ vty_out(vty,
+ "%%Peer-group %s is attached to %d listen-range(s), delete them first\n",
+ group->name, lr_count);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
peer_group_notify_unconfig(group);
peer_group_delete(group);
} else {
@@ -7073,6 +7137,26 @@ DEFUN (no_neighbor_disable_connected_check,
PEER_FLAG_DISABLE_CONNECTED_CHECK);
}
+DEFPY(neighbor_extended_link_bw,
+ neighbor_extended_link_bw_cmd,
+ "[no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor extended-link-bandwidth",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Send Extended (64-bit) version of encoding for Link-Bandwidth\n")
+{
+ int ret;
+
+ if (no)
+ ret = peer_flag_unset_vty(vty, neighbor,
+ PEER_FLAG_EXTENDED_LINK_BANDWIDTH);
+ else
+ ret = peer_flag_set_vty(vty, neighbor,
+ PEER_FLAG_EXTENDED_LINK_BANDWIDTH);
+
+ return ret;
+}
+
/* disable-link-bw-encoding-ieee */
DEFUN(neighbor_disable_link_bw_encoding_ieee,
neighbor_disable_link_bw_encoding_ieee_cmd,
@@ -9669,8 +9753,6 @@ DEFPY (af_label_vpn_export,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
/* fetch a label */
bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
- bgp_lp_get(LP_TYPE_VRF, &bgp->vpn_policy[afi],
- vpn_leak_label_callback);
} else {
bgp->vpn_policy[afi].tovpn_label = label;
UNSET_FLAG(bgp->vpn_policy[afi].flags,
@@ -10713,7 +10795,10 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
if (rm_p->prefixlen == match.prefixlen) {
SET_FLAG(rm->flags,
BGP_NODE_USER_CLEAR);
- bgp_process(bgp, rm, afi, safi);
+ bgp_process(bgp, rm,
+ bgp_dest_get_bgp_path_info(
+ rm),
+ afi, safi);
}
bgp_dest_unlock_node(rm);
}
@@ -10725,7 +10810,9 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
if (dest_p->prefixlen == match.prefixlen) {
SET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest,
+ bgp_dest_get_bgp_path_info(dest),
+ afi, safi);
}
bgp_dest_unlock_node(dest);
}
@@ -12725,7 +12812,7 @@ static void bgp_show_neighbor_graceful_restart_remote_mode(struct vty *vty,
if (json)
json_object_string_add(json, "remoteGrMode", mode);
else
- vty_out(vty, "%s\n", mode);
+ vty_out(vty, "%s", mode);
}
static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
@@ -12757,7 +12844,7 @@ static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
if (json)
json_object_string_add(json, "localGrMode", mode);
else
- vty_out(vty, "%s\n", mode);
+ vty_out(vty, "%s", mode);
}
static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
@@ -17664,6 +17751,76 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
}
+DEFPY(bgp_redistribute_ipv6_table, bgp_redistribute_ipv6_table_cmd,
+ "redistribute table-direct (1-65535)$table_id [{metric$metric (0-4294967295)$metric_val|route-map WORD$rmap}]",
+ "Redistribute information from another routing protocol\n"
+ "Non-main Kernel Routing Table - Direct\n"
+ "Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bool changed = false;
+ struct route_map *route_map = NULL;
+ struct bgp_redist *red;
+
+ if (rmap)
+ route_map = route_map_lookup_warn_noexist(vty, rmap);
+
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use 'table-direct'\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (table_id == RT_TABLE_MAIN || table_id == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %lu routing table\n",
+ table_id);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ red = bgp_redist_add(bgp, AFI_IP6, ZEBRA_ROUTE_TABLE_DIRECT, table_id);
+ if (rmap)
+ changed = bgp_redistribute_rmap_set(red, rmap, route_map);
+ if (metric)
+ changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6,
+ ZEBRA_ROUTE_TABLE_DIRECT,
+ metric_val);
+ return bgp_redistribute_set(bgp, AFI_IP6, ZEBRA_ROUTE_TABLE_DIRECT,
+ table_id, changed);
+}
+
+DEFPY(no_bgp_redistribute_ipv6_table, no_bgp_redistribute_ipv6_table_cmd,
+ "no redistribute table-direct (1-65535)$table_id [{metric (0-4294967295)|route-map WORD}]",
+ NO_STR
+ "Redistribute information from another routing protocol\n"
+ "Non-main Kernel Routing Table - Direct\n"
+ "Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use 'table-direct'\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (table_id == RT_TABLE_MAIN || table_id == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %lu routing table\n",
+ table_id);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_redistribute_unset(bgp, AFI_IP6, ZEBRA_ROUTE_TABLE_DIRECT, table_id);
+ return CMD_SUCCESS;
+}
+
DEFUN (bgp_redistribute_ipv6_metric_rmap,
bgp_redistribute_ipv6_metric_rmap_cmd,
"redistribute " FRR_IP6_REDIST_STR_BGPD " metric (0-4294967295) route-map RMAP_NAME",
@@ -18324,6 +18481,9 @@ 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);
+ if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_LINK_BANDWIDTH))
+ vty_out(vty, " neighbor %s extended-link-bandwidth\n", addr);
+
/* extended-optional-parameters */
if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS))
vty_out(vty, " neighbor %s extended-optional-parameters\n",
@@ -18383,9 +18543,15 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " neighbor %s timers delayopen %u\n", addr,
peer->bgp->default_delayopen);
- /* capability dynamic */
- if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
- vty_out(vty, " neighbor %s capability dynamic\n", addr);
+ /* capability software-version */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY)) {
+ if (!peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
+ vty_out(vty, " no neighbor %s capability dynamic\n",
+ addr);
+ } else {
+ if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
+ vty_out(vty, " neighbor %s capability dynamic\n", addr);
+ }
/* capability extended-nexthop */
if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_ENHE)) {
@@ -19076,6 +19242,15 @@ int bgp_config_write(struct vty *vty)
? ""
: "no ");
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY) !=
+ SAVE_BGP_DYNAMIC_CAPABILITY)
+ vty_out(vty,
+ " %sbgp default dynamic-capability\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_DYNAMIC_CAPABILITY)
+ ? ""
+ : "no ");
+
/* BGP default subgroup-pkt-queue-max. */
if (bgp->default_subgroup_pkt_queue_max
!= BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
@@ -20124,6 +20299,9 @@ void bgp_vty_init(void)
/* bgp default software-version-capability */
install_element(BGP_NODE, &bgp_default_software_version_capability_cmd);
+ /* bgp default dynamic-capability */
+ install_element(BGP_NODE, &bgp_default_dynamic_capability_cmd);
+
/* "bgp default subgroup-pkt-queue-max" commands. */
install_element(BGP_NODE, &bgp_default_subgroup_pkt_queue_max_cmd);
install_element(BGP_NODE, &no_bgp_default_subgroup_pkt_queue_max_cmd);
@@ -20818,6 +20996,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE,
&no_neighbor_disable_link_bw_encoding_ieee_cmd);
+
+ install_element(BGP_NODE, &neighbor_extended_link_bw_cmd);
+
/* "neighbor extended-optional-parameters" commands. */
install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd);
install_element(BGP_NODE,
@@ -21144,6 +21325,15 @@ void bgp_vty_init(void)
install_element(BGP_VPNV6_NODE,
&neighbor_maximum_prefix_threshold_restart_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_EVPN_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_EVPN_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_maximum_prefix_cmd);
/* "neighbor allowas-in" */
install_element(BGP_NODE, &neighbor_allowas_in_hidden_cmd);
@@ -21294,6 +21484,8 @@ void bgp_vty_init(void)
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_cmd);
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_table_cmd);
+ install_element(BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_table_cmd);
/* import|export vpn [route-map RMAP_NAME] */
install_element(BGP_IPV4_NODE, &bgp_imexport_vpn_cmd);
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index 4955e4c3df..addd71757d 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -13,8 +13,6 @@ struct bgp;
#define BGP_INSTANCE_HELP_STR "BGP view\nBGP VRF\nView/VRF name\n"
#define BGP_INSTANCE_ALL_HELP_STR "BGP view\nBGP VRF\nAll Views/VRFs\n"
-#define BGP_AF_STR "Address Family\n"
-#define BGP_AF_MODIFIER_STR "Address Family modifier\n"
#define BGP_AFI_CMD_STR "<ipv4|ipv6>"
#define BGP_AFI_HELP_STR BGP_AF_STR BGP_AF_STR
#define BGP_SAFI_CMD_STR "<unicast|multicast|vpn>"
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 26194f8601..15ed98933e 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -1211,7 +1211,7 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
}
static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr,
- uint32_t *nh_weight)
+ uint64_t *nh_weight)
{
/* zero link-bandwidth and link-bandwidth not present are treated
* as the same situation.
@@ -1273,7 +1273,7 @@ static void bgp_zebra_announce_parse_nexthop(
for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) {
labels = NULL;
num_labels = 0;
- uint32_t nh_weight;
+ uint64_t nh_weight;
bool is_evpn;
bool is_parent_evpn;
@@ -1308,9 +1308,7 @@ static void bgp_zebra_announce_parse_nexthop(
else
api_nh = &api->backup_nexthops[*valid_nh_count];
- if (CHECK_FLAG(info->attr->flag,
- ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- api_nh->srte_color = bgp_attr_get_color(info->attr);
+ api_nh->srte_color = bgp_attr_get_color(info->attr);
if (bgp_debug_zebra(&api->prefix)) {
if (mpinfo->extra) {
@@ -1518,15 +1516,16 @@ static void bgp_debug_zebra_nh(struct zapi_route *api)
snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
prefix_mac2str(&api_nh->rmac, buf1,
sizeof(buf1)));
- zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s", i + 1,
- nh_buf, api_nh->ifindex, api_nh->vrf_id,
+ zlog_debug(" nhop [%d]: %s if %u VRF %u wt %" PRIu64
+ " %s %s %s",
+ i + 1, nh_buf, api_nh->ifindex, api_nh->vrf_id,
api_nh->weight, label_buf, segs_buf, eth_buf);
}
}
-void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
- struct bgp_path_info *info, struct bgp *bgp, afi_t afi,
- safi_t safi)
+static enum zclient_send_status
+bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp)
{
struct bgp_path_info *bpi_ultimate;
struct zapi_route api = { 0 };
@@ -1539,34 +1538,19 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
bool is_add;
uint32_t nhg_id = 0;
uint32_t recursion_flag = 0;
+ struct bgp_table *table = bgp_dest_table(dest);
+ const struct prefix *p = bgp_dest_get_prefix(dest);
- /*
- * BGP is installing this route and bgp has been configured
- * to suppress announcements until the route has been installed
- * let's set the fact that we expect this route to be installed
- */
- if (BGP_SUPPRESS_FIB_ENABLED(bgp))
- SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
- /* Don't try to install if we're not connected to Zebra or Zebra doesn't
- * know of this instance.
- */
- if (!bgp_install_info_to_zebra(bgp))
- return;
-
- if (bgp->main_zebra_update_hold)
- return;
-
- if (safi == SAFI_FLOWSPEC) {
- bgp_pbr_update_entry(bgp, bgp_dest_get_prefix(dest), info, afi,
- safi, true);
- return;
+ if (table->safi == SAFI_FLOWSPEC) {
+ bgp_pbr_update_entry(bgp, p, info, table->afi, table->safi,
+ true);
+ return ZCLIENT_SEND_SUCCESS;
}
/* Make Zebra API structure. */
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
- api.safi = safi;
+ api.safi = table->safi;
api.prefix = *p;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
@@ -1596,15 +1580,15 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api.tableid = info->attr->rmap_table_id;
}
- if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
+ if (info->attr->srte_color)
SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
/* Metric is currently based on the best-path only */
metric = info->attr->med;
bgp_zebra_announce_parse_nexthop(info, p, bgp, &api, &valid_nh_count,
- afi, safi, &nhg_id, &metric, &tag,
- &allow_recursion);
+ table->afi, table->safi, &nhg_id,
+ &metric, &tag, &allow_recursion);
is_add = (valid_nh_count || nhg_id) ? true : false;
@@ -1657,7 +1641,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api.tag = tag;
}
- distance = bgp_distance_apply(p, info, afi, safi, bgp);
+ distance = bgp_distance_apply(p, info, table->afi, table->safi, bgp);
if (distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = distance;
@@ -1677,10 +1661,11 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
zlog_debug("%s: %pFX: announcing to zebra (recursion %sset)",
__func__, p, (recursion_flag ? "" : "NOT "));
}
- zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
- zclient, &api);
+ return zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
+ zclient, &api);
}
+
/* Announce all routes of a table to zebra */
void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
{
@@ -1701,14 +1686,11 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
-
(pi->type == ZEBRA_ROUTE_BGP
&& (pi->sub_type == BGP_ROUTE_NORMAL
|| pi->sub_type == BGP_ROUTE_IMPORTED)))
-
- bgp_zebra_announce(dest,
- bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, true,
+ NULL, false);
}
/* Announce routes of any bgp subtype of a table to zebra */
@@ -1730,39 +1712,30 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
pi->type == ZEBRA_ROUTE_BGP)
- bgp_zebra_announce(dest,
- bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, true,
+ NULL, false);
}
-void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
- struct bgp *bgp, afi_t afi, safi_t safi)
+enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
+ struct bgp_path_info *info,
+ struct bgp *bgp)
{
struct zapi_route api;
struct peer *peer;
+ struct bgp_table *table = bgp_dest_table(dest);
+ const struct prefix *p = bgp_dest_get_prefix(dest);
- /*
- * If we are withdrawing the route, we don't need to have this
- * flag set. So unset it.
- */
- UNSET_FLAG(info->net->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
- /* Don't try to install if we're not connected to Zebra or Zebra doesn't
- * know of this instance.
- */
- if (!bgp_install_info_to_zebra(bgp))
- return;
-
- if (safi == SAFI_FLOWSPEC) {
+ if (table->safi == SAFI_FLOWSPEC) {
peer = info->peer;
- bgp_pbr_update_entry(peer->bgp, p, info, afi, safi, false);
- return;
+ bgp_pbr_update_entry(peer->bgp, p, info, table->afi,
+ table->safi, false);
+ return ZCLIENT_SEND_SUCCESS;
}
memset(&api, 0, sizeof(api));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
- api.safi = safi;
+ api.safi = table->safi;
api.prefix = *p;
if (info->attr->rmap_table_id) {
@@ -1774,7 +1747,206 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
zlog_debug("Tx route delete VRF %u %pFX", bgp->vrf_id,
&api.prefix);
- zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+ return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+}
+
+/*
+ * Walk the new Fifo list one by one and invoke bgp_zebra_announce/withdraw
+ * to install/withdraw the routes to zebra.
+ *
+ * If status = ZCLIENT_SEND_SUCCESS (Buffer empt)y i.e. Zebra is free to
+ * receive more incoming data, then pick the next item on the list and
+ * continue processing.
+ *
+ * If status = ZCLIENT_SEND_BUFFERED (Buffer pending) i.e. Zebra is busy,
+ * break and bail out of the function because once at some point when zebra
+ * is free, a callback is triggered which inturn call this same function and
+ * continue processing items on list.
+ */
+#define ZEBRA_ANNOUNCEMENTS_LIMIT 1000
+static void bgp_handle_route_announcements_to_zebra(struct event *e)
+{
+ bool is_evpn = false;
+ uint32_t count = 0;
+ struct bgp_dest *dest = NULL;
+ struct bgp_table *table = NULL;
+ enum zclient_send_status status = ZCLIENT_SEND_SUCCESS;
+ bool install;
+
+ while (count < ZEBRA_ANNOUNCEMENTS_LIMIT) {
+ dest = zebra_announce_pop(&bm->zebra_announce_head);
+
+ if (!dest)
+ break;
+
+ table = bgp_dest_table(dest);
+ install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ if (table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+ is_evpn = true;
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("BGP %s route %pBD(%s) with dest %p and flags 0x%x to zebra",
+ install ? "announcing" : "withdrawing", dest,
+ table->bgp->name_pretty, dest, dest->flags);
+
+ if (install) {
+ if (is_evpn)
+ status =
+ evpn_zebra_install(table->bgp,
+ dest->za_vpn,
+ (const struct prefix_evpn
+ *)
+ bgp_dest_get_prefix(
+ dest),
+ dest->za_bgp_pi);
+ else
+ status = bgp_zebra_announce_actual(dest,
+ dest->za_bgp_pi,
+ table->bgp);
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ } else {
+ if (is_evpn)
+ status = evpn_zebra_uninstall(
+ table->bgp, dest->za_vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(dest),
+ dest->za_bgp_pi, false);
+ else
+ status = bgp_zebra_withdraw_actual(dest,
+ dest->za_bgp_pi,
+ table->bgp);
+
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ }
+
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ dest->za_bgp_pi = NULL;
+ dest->za_vpn = NULL;
+ bgp_dest_unlock_node(dest);
+
+ if (status == ZCLIENT_SEND_BUFFERED)
+ break;
+
+ count++;
+ }
+
+ if (status != ZCLIENT_SEND_BUFFERED &&
+ zebra_announce_count(&bm->zebra_announce_head))
+ event_add_event(bm->master,
+ bgp_handle_route_announcements_to_zebra, NULL,
+ 0, &bm->t_bgp_zebra_route);
+}
+
+/*
+ * Callback function invoked when zclient_flush_data() receives a BUFFER_EMPTY
+ * i.e. zebra is free to receive more incoming data.
+ */
+static void bgp_zebra_buffer_write_ready(void)
+{
+ bgp_handle_route_announcements_to_zebra(NULL);
+}
+
+/*
+ * BGP is now keeping a list of dests with the dest having a pointer
+ * to the bgp_path_info that it will be working on.
+ * Here is the sequence of events that should happen:
+ *
+ * Current State New State Action
+ * ------------- --------- ------
+ * ---- Install Place dest on list, save pi, mark
+ * as going to be installed
+ * ---- Withdrawal Place dest on list, save pi, mark
+ * as going to be deleted
+ *
+ * Install Install Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * Installed
+ * Install Withdrawal Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * withdrawan, remove install flag
+ *
+ * Withdrawal Install Special case, send withdrawal immediately
+ * Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * installed. <see note about evpn
+ * in bgp_route.c in bgp_process_main_one>
+ * Withdrawal Withdrawal Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * withdrawn.
+ */
+void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp, bool install, struct bgpevpn *vpn,
+ bool is_sync)
+{
+ bool is_evpn = false;
+ struct bgp_table *table = NULL;
+
+ table = bgp_dest_table(dest);
+ if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+ is_evpn = true;
+
+ /*
+ * BGP is installing this route and bgp has been configured
+ * to suppress announcements until the route has been installed
+ * let's set the fact that we expect this route to be installed
+ */
+ if (install) {
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
+ if (bgp->main_zebra_update_hold && !is_evpn)
+ return;
+ } else {
+ UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+ }
+
+ /*
+ * Don't try to install if we're not connected to Zebra or Zebra doesn't
+ * know of this instance.
+ */
+ if (!bgp_install_info_to_zebra(bgp) && !is_evpn)
+ return;
+
+ if (!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL) &&
+ !CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
+ zebra_announce_add_tail(&bm->zebra_announce_head, dest);
+ /*
+ * If neither flag is set and za_bgp_pi is not set then it is a bug
+ */
+ assert(!dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ bgp_dest_lock_node(dest);
+ dest->za_bgp_pi = info;
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL)) {
+ assert(dest->za_bgp_pi);
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ dest->za_bgp_pi = info;
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
+ assert(dest->za_bgp_pi);
+ if (install & !is_evpn)
+ bgp_zebra_withdraw_actual(dest, dest->za_bgp_pi, bgp);
+
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ dest->za_bgp_pi = info;
+ }
+
+ if (is_evpn) {
+ dest->za_vpn = vpn;
+ dest->za_is_sync = is_sync;
+ }
+
+ if (install) {
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ } else {
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ }
+
+ event_add_event(bm->master, bgp_handle_route_announcements_to_zebra,
+ NULL, 0, &bm->t_bgp_zebra_route);
}
/* Withdraw all entries in a BGP instances RIB table from Zebra */
@@ -1795,8 +1967,8 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
&& (pi->type == ZEBRA_ROUTE_BGP))
- bgp_zebra_withdraw(bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, false,
+ NULL, false);
}
}
}
@@ -1981,7 +2153,7 @@ bool bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
bgp_path_info_set_flag(dest, pi,
BGP_PATH_ATTR_CHANGED);
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
}
}
}
@@ -2614,8 +2786,12 @@ static int bgp_zebra_route_notify_owner(int command, struct zclient *zclient,
/* Find the bgp route node */
dest = bgp_safi_node_lookup(bgp->rib[afi][safi], safi, &p,
&bgp->vrf_prd);
- if (!dest)
+ if (!dest) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: %pFX does not exist in the BGP table, nothing to do for %u",
+ __func__, &p, note);
return -1;
+ }
switch (note) {
case ZAPI_ROUTE_INSTALLED:
@@ -3471,6 +3647,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
zclient = zclient_new(master, &zclient_options_default, bgp_handlers,
array_size(bgp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
+ zclient->zebra_buffer_write_ready = bgp_zebra_buffer_write_ready;
zclient->zebra_connected = bgp_zebra_connected;
zclient->zebra_capabilities = bgp_zebra_capabilities;
zclient->nexthop_update = bgp_nexthop_update;
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 396c8335f8..ef296b963c 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -28,13 +28,11 @@ extern void bgp_zebra_destroy(void);
extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,
uint32_t *start, uint32_t *end);
extern int bgp_if_update_all(void);
-extern void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
- struct bgp_path_info *path, struct bgp *bgp,
- afi_t afi, safi_t safi);
+extern void bgp_zebra_route_install(struct bgp_dest *dest,
+ struct bgp_path_info *path, struct bgp *bgp,
+ bool install, struct bgpevpn *vpn,
+ bool is_sync);
extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi);
-extern void bgp_zebra_withdraw(const struct prefix *p,
- struct bgp_path_info *path, struct bgp *bgp,
- afi_t afi, safi_t safi);
/* Announce routes of any bgp subtype of a table to zebra */
extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
@@ -127,4 +125,7 @@ extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
bool label_auto);
extern void bgp_zebra_release_label_range(uint32_t start, uint32_t end);
+extern enum zclient_send_status
+bgp_zebra_withdraw_actual(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp);
#endif /* _QUAGGA_BGP_ZEBRA_H */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 2fc1f70bc2..a7564da8b3 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1377,7 +1377,7 @@ int bgp_global_gr_init(struct bgp *bgp)
/*GLOBAL_GR_cmd */ /*no_Global_GR_cmd*/
GLOBAL_GR, GLOBAL_INVALID,
/*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/
- GLOBAL_INVALID, GLOBAL_HELPER
+ GLOBAL_DISABLE, GLOBAL_HELPER
},
/* GLOBAL_INVALID Mode */
{
@@ -1411,13 +1411,13 @@ int bgp_peer_gr_init(struct peer *peer)
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
{PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL },
/* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
- { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT,
+ { PEER_HELPER, NULL }, {PEER_GLOBAL_INHERIT,
bgp_peer_gr_action }
},
{
/* PEER_GR Mode */
/* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
- { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
+ { PEER_GR, NULL }, { PEER_GLOBAL_INHERIT,
bgp_peer_gr_action },
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
{PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL },
@@ -1429,7 +1429,7 @@ int bgp_peer_gr_init(struct peer *peer)
/* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
{ PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL },
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
- { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
+ { PEER_DISABLE, NULL }, { PEER_GLOBAL_INHERIT,
bgp_peer_gr_action },
/* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
{ PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
@@ -1539,10 +1539,13 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->sflags, PEER_STATUS_CAPABILITY_OPEN);
if (CHECK_FLAG(bgp->flags, BGP_FLAG_ENFORCE_FIRST_AS))
- SET_FLAG(peer->flags, PEER_FLAG_ENFORCE_FIRST_AS);
+ peer_flag_set(peer, PEER_FLAG_ENFORCE_FIRST_AS);
if (CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY))
- SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_SOFT_VERSION);
+ peer_flag_set(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION);
+
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY))
+ peer_flag_set(peer, PEER_FLAG_DYNAMIC_CAPABILITY);
SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_FQDN);
SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN);
@@ -1850,21 +1853,31 @@ void bgp_peer_conf_if_to_su_update(struct peer_connection *connection)
void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct bgp_dest *dest, *ndest;
+ struct bgp_path_info *pi, *next;
struct bgp_table *table;
for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
- if (table != NULL) {
- /* Special handling for 2-level routing
- * tables. */
- if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
- || safi == SAFI_EVPN) {
- for (ndest = bgp_table_top(table); ndest;
- ndest = bgp_route_next(ndest))
- bgp_process(bgp, ndest, afi, safi);
- } else
- bgp_process(bgp, dest, afi, safi);
+
+ if (!table)
+ continue;
+
+ /* Special handling for 2-level routing
+ * tables. */
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
+ || safi == SAFI_EVPN) {
+ for (ndest = bgp_table_top(table); ndest;
+ ndest = bgp_route_next(ndest)) {
+ for (pi = bgp_dest_get_bgp_path_info(ndest);
+ (pi != NULL) && (next = pi->next, 1);
+ pi = next)
+ bgp_process(bgp, ndest, pi, afi, safi);
+ }
+ } else {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next)
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
}
@@ -2919,6 +2932,13 @@ static void peer_group2peer_config_copy(struct peer_group *group,
SET_FLAG(peer->flags,
PEER_FLAG_CAPABILITY_SOFT_VERSION);
+ /* capability dynamic apply */
+ if (!CHECK_FLAG(peer->flags_override,
+ PEER_FLAG_DYNAMIC_CAPABILITY))
+ if (CHECK_FLAG(conf->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
+ SET_FLAG(peer->flags,
+ PEER_FLAG_DYNAMIC_CAPABILITY);
+
/* password apply */
if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
PEER_STR_ATTR_INHERIT(peer, group, password,
@@ -3855,10 +3875,20 @@ int bgp_delete(struct bgp *bgp)
afi_t afi;
safi_t safi;
int i;
+ struct bgp_dest *dest = NULL;
struct graceful_restart_info *gr_info;
assert(bgp);
+ while (zebra_announce_count(&bm->zebra_announce_head)) {
+ dest = zebra_announce_pop(&bm->zebra_announce_head);
+ if (dest->za_bgp_pi->peer->bgp == bgp) {
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_dest_unlock_node(dest);
+ } else
+ zebra_announce_add_tail(&bm->zebra_announce_head, dest);
+ }
+
bgp_soft_reconfig_table_task_cancel(bgp, NULL, NULL);
/* make sure we withdraw any exported routes */
@@ -4569,7 +4599,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none},
{PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none},
{PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none},
- {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
+ {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_none},
{PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
{PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
{PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
@@ -4593,6 +4623,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none},
{PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
{PEER_FLAG_AS_LOOP_DETECTION, 0, peer_change_none},
+ {PEER_FLAG_EXTENDED_LINK_BANDWIDTH, 0, peer_change_none},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
@@ -8298,6 +8329,8 @@ void bgp_master_init(struct event_loop *master, const int buffer_size,
memset(&bgp_master, 0, sizeof(bgp_master));
bm = &bgp_master;
+
+ zebra_announce_init(&bm->zebra_announce_head);
bm->bgp = list_new();
bm->listen_sockets = list_new();
bm->port = BGP_PORT_DEFAULT;
@@ -8316,6 +8349,7 @@ void bgp_master_init(struct event_loop *master, const int buffer_size,
bm->outq_limit = BM_DEFAULT_Q_LIMIT;
bm->t_bgp_sync_label_manager = NULL;
bm->t_bgp_start_label_manager = NULL;
+ bm->t_bgp_zebra_route = NULL;
bgp_mac_init();
/* init the rd id space.
@@ -8566,6 +8600,7 @@ void bgp_terminate(void)
EVENT_OFF(bm->t_rmap_update);
EVENT_OFF(bm->t_bgp_sync_label_manager);
EVENT_OFF(bm->t_bgp_start_label_manager);
+ EVENT_OFF(bm->t_bgp_zebra_route);
bgp_mac_finish();
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 1c5f90c59b..f577a6e5f3 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -18,6 +18,8 @@
#include "iana_afi.h"
#include "asn.h"
+PREDECL_LIST(zebra_announce);
+
/* For union sockunion. */
#include "queue.h"
#include "sockunion.h"
@@ -173,8 +175,13 @@ struct bgp_master {
struct event *t_bgp_sync_label_manager;
struct event *t_bgp_start_label_manager;
+ struct event *t_bgp_zebra_route;
+
bool v6_with_v4_nexthops;
+ /* To preserve ordering of installations into zebra across all Vrfs */
+ struct zebra_announce_head zebra_announce_head;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp_master);
@@ -471,7 +478,7 @@ struct bgp {
* factor (e.g., number of multipaths for the prefix)
* Value is in Mbps
*/
- uint32_t lb_ref_bw;
+ uint64_t lb_ref_bw;
#define BGP_LINK_BW_REF_BW 1
/* BGP flags. */
@@ -522,6 +529,8 @@ struct bgp {
#define BGP_FLAG_LU_IPV6_EXPLICIT_NULL (1ULL << 34)
#define BGP_FLAG_SOFT_VERSION_CAPABILITY (1ULL << 35)
#define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)
+#define BGP_FLAG_DYNAMIC_CAPABILITY (1ULL << 37)
+#define BGP_FLAG_VNI_DOWN (1ULL << 38)
/* BGP default address-families.
* New peers inherit enabled afi/safis from bgp instance.
@@ -1471,6 +1480,7 @@ struct peer {
#define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36)
#define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */
#define PEER_FLAG_AS_LOOP_DETECTION (1ULL << 38) /* as path loop detection */
+#define PEER_FLAG_EXTENDED_LINK_BANDWIDTH (1ULL << 39)
/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
@@ -1658,6 +1668,8 @@ struct peer {
uint32_t stat_pfx_nh_invalid;
uint32_t stat_pfx_dup_withdraw;
uint32_t stat_upd_7606; /* RFC7606: treat-as-withdraw */
+ uint64_t stat_pfx_loc_rib; /* RFC7854 : Number of routes in Loc-RIB */
+ uint64_t stat_pfx_adj_rib_in; /* RFC7854 : Number of routes in Adj-RIBs-In */
/* BGP state count */
uint32_t established; /* Established */
@@ -1962,7 +1974,6 @@ struct bgp_nlri {
#define BGP_ATTR_LARGE_COMMUNITIES 32
#define BGP_ATTR_OTC 35
#define BGP_ATTR_PREFIX_SID 40
-#define BGP_ATTR_SRTE_COLOR 51
#ifdef ENABLE_BGP_VNC_ATTR
#define BGP_ATTR_VNC 255
#endif
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 382af05c24..ae899daf82 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -463,7 +463,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
} else {
vnc_zlog_debug_verbose(
"%s: Couldn't find route (safi=%d) at prefix %pFX",
@@ -1001,7 +1001,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
/* Process change. */
bgp_aggregate_increment(bgp, p, bpi, afi, safi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
bgp_dest_unlock_node(bn);
vnc_zlog_debug_any(
@@ -1046,7 +1046,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
}
bgp_dest_unlock_node(bn);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, new, afi, safi);
vnc_zlog_debug_any(
"%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)",
diff --git a/configure.ac b/configure.ac
index 9213bf0105..f11b345cf6 100644
--- a/configure.ac
+++ b/configure.ac
@@ -751,8 +751,6 @@ AC_ARG_ENABLE([snmp],
AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx]))
AC_ARG_ENABLE([config_rollbacks],
AS_HELP_STRING([--enable-config-rollbacks], [enable configuration rollbacks (requires sqlite3)]))
-AC_ARG_ENABLE([confd],
- AS_HELP_STRING([--enable-confd=ARG], [enable confd integration]))
AC_ARG_ENABLE([sysrepo],
AS_HELP_STRING([--enable-sysrepo], [enable sysrepo integration]))
AC_ARG_ENABLE([grpc],
@@ -2082,22 +2080,6 @@ if test "$enable_config_rollbacks" = "yes"; then
fi
dnl ---------------
-dnl confd
-dnl ---------------
-if test "$enable_confd" != "" -a "$enable_confd" != "no"; then
- AC_CHECK_PROG([CONFD], [confd], [confd], [/bin/false], "${enable_confd}/bin")
- if test "$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"
- AC_SUBST([CONFD_LIBS])
- AC_DEFINE([HAVE_CONFD], [1], [Enable confd integration])
-fi
-
-dnl ---------------
dnl sysrepo
dnl ---------------
if test "$enable_sysrepo" = "yes"; then
@@ -2766,7 +2748,6 @@ AM_CONDITIONAL([ENABLE_BGP_VNC], [test "$enable_bgp_vnc" != "no"])
AM_CONDITIONAL([BGP_BMP], [$bgpd_bmp])
dnl northbound
AM_CONDITIONAL([SQLITE3], [$SQLITE3])
-AM_CONDITIONAL([CONFD], [test "$enable_confd" != ""])
AM_CONDITIONAL([SYSREPO], [test "$enable_sysrepo" = "yes"])
AM_CONDITIONAL([GRPC], [test "$enable_grpc" = "yes"])
AM_CONDITIONAL([ZEROMQ], [test "$ZEROMQ" = "true"])
diff --git a/debian/changelog b/debian/changelog
index b3b086e019..96c66db89b 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,8 +1,14 @@
-frr (9.2~dev-1) UNRELEASED; urgency=medium
+frr (10.1~dev-1) UNRELEASED; urgency=medium
- * FRR Dev 9.2
+ * FRR Dev 10.1
- -- Donatas Abraitis <donatas@opensourcerouting.org> Tue, 10 Oct 2023 12:00:00 -0600
+ -- Jafar Al-Gharaibeh <jafar@atcorp.com> Tue, 26 Mar 2024 02:00:00 -0600
+
+frr (10.0-0) unstable; urgency=medium
+
+ * New upstream release FRR 10.0
+
+ -- Jafar Al-Gharaibeh <jafar@atcorp.com> Mon, 25 Mar 2024 02:00:00 -0600
frr (9.1-0) unstable; urgency=medium
diff --git a/debian/control b/debian/control
index fb8c2162da..e6d65133d3 100644
--- a/debian/control
+++ b/debian/control
@@ -23,7 +23,7 @@ Build-Depends: bison,
librtr-dev (>= 0.8.0~) <!pkg.frr.nortrlib>,
libsnmp-dev,
libssh-dev <!pkg.frr.nortrlib>,
- libyang2-dev (>= 2.1.80),
+ libyang2-dev (>= 2.1.128),
lsb-base,
pkg-config,
protobuf-c-compiler,
diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst
index a46c79376c..8d9876c21a 100644
--- a/doc/developer/building-libyang.rst
+++ b/doc/developer/building-libyang.rst
@@ -41,7 +41,7 @@ DEB packages are available as CI artifacts `here
cd libyang
git checkout v2.1.128
mkdir build; cd build
- cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr \
+ cmake --install-prefix /usr \
-D CMAKE_BUILD_TYPE:String="Release" ..
make
sudo make install
diff --git a/doc/developer/cross-compiling.rst b/doc/developer/cross-compiling.rst
index af99262c4f..c503487441 100644
--- a/doc/developer/cross-compiling.rst
+++ b/doc/developer/cross-compiling.rst
@@ -148,7 +148,7 @@ be built and installed generally like:
CC=${HOST_ARCH}-gcc \
CXX=${HOST_ARCH}-g++ \
cmake \
- -DCMAKE_INSTALL_PREFIX=/usr/${HOST_ARCH} \
+ --install-prefix /usr/${HOST_ARCH} \
..
make
make install
diff --git a/doc/developer/northbound/advanced-topics.rst b/doc/developer/northbound/advanced-topics.rst
index edfc10bcbd..eb756026e0 100644
--- a/doc/developer/northbound/advanced-topics.rst
+++ b/doc/developer/northbound/advanced-topics.rst
@@ -12,8 +12,7 @@ Auto-generated CLI commands
In order to have less code to maintain, it should be possible to write a
tool that auto-generates CLI commands based on the FRR YANG models. As a
matter of fact, there are already a number of NETCONF-based CLIs that do
-exactly that (e.g. `Clixon <https://github.com/clicon/clixon>`__,
-ConfD’s CLI).
+exactly that (e.g. `Clixon <https://github.com/clicon/clixon>`__).
The problem however is that there isn’t an exact one-to-one mapping
between the existing CLI commands and the corresponding YANG nodes from
@@ -27,11 +26,6 @@ command for each YANG leaf, (leaf-)list and presence-container. The
ripd’s ``timers basic`` command, for instance, would become three
different commands, which would be undesirable.
- This Tail-f’s®
- `document <http://info.tail-f.com/hubfs/Whitepapers/Tail-f_ConfD-CLI__Cfg_Mode_App_Note_Rev%20C.pdf>`__
- shows how to customize ConfD auto-generated CLI commands using YANG
- annotations.
-
The good news is that *libyang* allows users to create plugins to
implement their own YANG extensions, which can be used to implement CLI
annotations. If done properly, a CLI generator can save FRR developers
@@ -76,8 +70,8 @@ Example of how this feature could be provided in the CLI:
``commit confirmed [minutes <1-60>]``. The ability to do confirmed
commits should also be exposed in the northbound API so that the
northbound plugins can also take advantage of it (in the case of the
-Sysrepo and ConfD plugins, confirmed commits are implemented externally
-in the *netopeer2-server* and *confd* daemons, respectively).
+Sysrepo plugin, confirmed commit is implemented externally in the
+*netopeer2-server* daemon).
Proposed feature: enable/disable configuration commands/sections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/developer/northbound/architecture.rst b/doc/developer/northbound/architecture.rst
index 5fd89c32f1..4e84f1d6a4 100644
--- a/doc/developer/northbound/architecture.rst
+++ b/doc/developer/northbound/architecture.rst
@@ -116,7 +116,7 @@ multitude of different management APIs, all of them connected to the
northbound layer of the FRR daemons. By default, only the CLI interface
is compiled built-in in the FRR daemons. The other management interfaces
are provided as optional plugins and need to be loaded during the daemon
-initialization (e.g. *zebra -M confd*). This design makes it possible to
+initialization (e.g. *zebra -M grpc*). This design makes it possible to
integrate FRR with different NETCONF solutions without introducing
vendor lock-in. The [[Plugins - Writing Your Own]] page explains how to
write custom northbound plugins that can be tailored to all needs
diff --git a/doc/developer/northbound/demos.rst b/doc/developer/northbound/demos.rst
index 8a0f6ad6b2..7c5ae0c229 100644
--- a/doc/developer/northbound/demos.rst
+++ b/doc/developer/northbound/demos.rst
@@ -8,23 +8,3 @@ This short demo shows some of the capabilities of the new transactional
CLI:
|asciicast1|
-
-ConfD + NETCONF + Cisco YDK
----------------------------
-
-This is a very simple demo of *ripd* being configured by a python
-script. The script uses NETCONF to communicate with *ripd*, which has
-the ConfD plugin loaded. The most interesting part, however, is the fact
-that the python script is not using handcrafted XML payloads to
-configure *ripd*. Instead, the script is using python bindings generated
-using Cisco’s YANG Development Kit (YDK).
-
-- Script used in the demo:
- https://gist.github.com/rwestphal/defa9bd1ccf216ab082d4711ae402f95
-
-|asciicast2|
-
-.. |asciicast1| image:: https://asciinema.org/a/jL0BS5HfP2kS6N1HfgsZvfZk1.png
- :target: https://asciinema.org/a/jL0BS5HfP2kS6N1HfgsZvfZk1
-.. |asciicast2| image:: https://asciinema.org/a/VfMElNxsjLcdvV7484E6ChxWv.png
- :target: https://asciinema.org/a/VfMElNxsjLcdvV7484E6ChxWv
diff --git a/doc/developer/northbound/links.rst b/doc/developer/northbound/links.rst
index 6cec176f8b..e8fb327238 100644
--- a/doc/developer/northbound/links.rst
+++ b/doc/developer/northbound/links.rst
@@ -195,14 +195,6 @@ pyangbind
- GitHub page: https://github.com/robshakir/pyangbind
- Documentation: http://pynms.io/pyangbind/
-ConfD
-^^^^^
-
-- Official webpage (for ConfD Basic):
- http://www.tail-f.com/confd-basic/
-- Training Videos: http://www.tail-f.com/confd-training-videos/
-- Forum: http://discuss.tail-f.com/
-
Sysrepo
^^^^^^^
diff --git a/doc/developer/northbound/operational-data-rpcs-and-notifications.rst b/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
index 5cb70ca6f1..07f92c2ca0 100644
--- a/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
+++ b/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
@@ -10,10 +10,10 @@ Operational data
~~~~~~~~~~~~~~~~
Writing API-agnostic code for YANG-modeled operational data is
-challenging. ConfD and Sysrepo, for instance, have completely different
-APIs to fetch operational data. So how can we write API-agnostic
-callbacks that can be used by both the ConfD and Sysrepo plugins, and
-any other northbound client that might be written in the future?
+challenging. Sysrepo, for instance, has completely different API to
+fetch operational data. So how can we write API-agnostic callbacks
+that can be used by both the Sysrepo plugin, and any other northbound
+client that might be written in the future?
As an additional requirement, the callbacks must be designed in a way
that makes in-place XPath filtering possible. As an example, a
@@ -94,27 +94,18 @@ in the northbound architecture:
*/
void *(*lookup_entry)(struct yang_list_keys *keys);
-These callbacks were designed to provide maximum flexibility, and borrow
-a lot of ideas from the ConfD API. Each callback does one and only one
-task, they are indivisible primitives that can be combined in several
-different ways to iterate over operational data. The extra flexibility
-certainly has a performance cost, but it’s the price to pay if we want
-to expose FRR operational data using several different management
-interfaces (e.g. NETCONF via either ConfD or Sysrepo+Netopeer2). In the
+These callbacks were designed to provide maximum flexibility. Each
+callback does one and only one task, they are indivisible primitives
+that can be combined in several different ways to iterate over operational
+data. The extra flexibility certainly has a performance cost, but it’s the
+price to pay if we want to expose FRR operational data using several
+different management interfaces (e.g. Sysrepo+Netopeer2). In the
future it might be possible to introduce optional callbacks that do
things like returning multiple objects at once. They would provide
enhanced performance when iterating over large lists, but their use
would be limited by the northbound plugins that can be integrated with
them.
- NOTE: using the northbound callbacks as a base, the ConfD plugin can
- provide up to 100 objects between each round trip between FRR and the
- *confd* daemon. Preliminary tests showed FRR taking ~7 seconds
- (asynchronously, without blocking the main pthread) to return a RIP
- table containing 100k routes to a NETCONF client connected to *confd*
- (JSON was used as the encoding format). Work needs to be done to find
- the bottlenecks and optimize this operation.
-
The [[Plugins - Writing Your Own]] page explains how the northbound
plugins can fetch operational data using the aforementioned northbound
callbacks, and how in-place XPath filtering can be implemented.
@@ -351,10 +342,10 @@ are being iterated over. If that is not done, the list entry returned by
this callback can become a dangling pointer when used in another
callback.
-Currently the ConfD and Sysrepo plugins run only in the main pthread.
-The plan in the short-term is to introduce a separate pthread only for
-handling operational data, and use the main pthread only for handling
-configuration changes, RPCs and notifications.
+Currently the Sysrepo plugin runs only in the main pthread. The plan in the
+short-term is to introduce a separate pthread only for handling operational
+data, and use the main pthread only for handling configuration changes,
+RPCs and notifications.
RPCs and Actions
~~~~~~~~~~~~~~~~
@@ -396,8 +387,8 @@ some EXEC-level commands using YANG so that their functionality is
exposed to other management interfaces other than the CLI. As an
example, if the ``clear bgp`` command is modeled using a YANG RPC, and a
corresponding ``rpc`` callback is written, then it should be possible to
-clear BGP neighbors using NETCONF and RESTCONF with that RPC (the ConfD
-and Sysrepo plugins have full support for YANG RPCs and actions).
+clear BGP neighbors using NETCONF and RESTCONF with that RPC (the Sysrepo
+plugin has full support for YANG RPCs and actions).
Here’s an example of a very simple RPC modeled using YANG:
@@ -568,8 +559,7 @@ Now sending the *authentication-failure* YANG notification should be as
simple as calling the above function and provide the appropriate
interface name. The notification will be processed by all northbound
plugins that subscribed a callback to the ``nb_notification_send`` hook.
-The ConfD and Sysrepo plugins, for instance, use this hook to relay the
-notifications to the *confd*/*sysrepod* daemons, which can generate
-NETCONF notifications to subscribed clients. When no northbound plugin
-is loaded, ``nb_notification_send()`` doesn’t do anything and the
-notifications are ignored.
+The Sysrepo plugin, for instance, uses this hook to relay the notifications
+to the *sysrepod* daemon, which can generate NETCONF notifications to subscribed
+clients. When no northbound plugin is loaded, ``nb_notification_send()`` doesn’t
+do anything and the notifications are ignored.
diff --git a/doc/developer/northbound/plugins-sysrepo.rst b/doc/developer/northbound/plugins-sysrepo.rst
index 0cfdb825e5..f4df68ce3c 100644
--- a/doc/developer/northbound/plugins-sysrepo.rst
+++ b/doc/developer/northbound/plugins-sysrepo.rst
@@ -32,7 +32,7 @@ libyang
cd libyang
git checkout v2.1.148
mkdir build; cd build
- cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ cmake --install-prefix /usr \
-DCMAKE_BUILD_TYPE:String="Release" ..
make
sudo make install
@@ -51,7 +51,7 @@ Sysrepo
cd sysrepo/
git checkout v2.2.150
mkdir build; cd build
- cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ cmake --install-prefix /usr \
-DCMAKE_BUILD_TYPE:String="Release" ..
make
sudo make install
diff --git a/doc/developer/static-linking.rst b/doc/developer/static-linking.rst
index 5342fbfbf6..e9bb9281f8 100644
--- a/doc/developer/static-linking.rst
+++ b/doc/developer/static-linking.rst
@@ -44,7 +44,7 @@ when building libyang statically.
The resultant cmake command is::
cmake -DENABLE_STATIC=ON -DENABLE_LYD_PRIV=ON \
- -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ --install-prefix /usr \
-DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \
-DCMAKE_BUILD_TYPE:String="Release" ..
diff --git a/doc/developer/zebra.rst b/doc/developer/zebra.rst
index be2952e71a..482df96267 100644
--- a/doc/developer/zebra.rst
+++ b/doc/developer/zebra.rst
@@ -161,6 +161,21 @@ Zebra Protocol Commands
The definitions of zebra protocol commands can be found at ``lib/zclient.h``.
+
+Zebra Dataplane
+===============
+
+The zebra dataplane subsystem provides a framework for FIB
+programming. Zebra uses the dataplane to program the local kernel as
+it makes changes to objects such as IP routes, MPLS LSPs, and
+interface IP addresses. The dataplane runs in its own pthread, in
+order to off-load work from the main zebra pthread.
+
+The zebra dataplane API is versioned; the version number must be
+updated along with API changes. Plugins can test the current version
+number and confirm that they are compatible with the current version.
+
+
Dataplane batching
==================
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 9ae9508b02..1de6773922 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -425,6 +425,11 @@ Route Selection
Disabled by default.
+.. clicmd:: bgp bestpath med missing-as-worst
+
+ If the paths MED value is missing and this command is configured
+ then treat it as the worse possible value that it can be.
+
.. clicmd:: maximum-paths (1-128)
Sets the maximum-paths value used for ecmp calculations for this
@@ -1059,7 +1064,7 @@ BGP GR Global Mode Commands
This command will enable BGP graceful restart functionality at the global
level.
-.. clicmd:: bgp graceful-restart disable
+.. clicmd:: bgp graceful-restart-disable
This command will disable both the functionality graceful restart and helper
mode.
@@ -1329,7 +1334,14 @@ OSPFv3 into ``address-family ipv4 unicast`` as OSPFv3 supports IPv6.
.. clicmd:: redistribute <babel|connected|eigrp|isis|kernel|openfabric|ospf|ospf6|rip|ripng|sharp|static> [metric (0-4294967295)] [route-map WORD]
-Redistribute routes from other protocols into BGP.
+ Redistribute routes from other protocols into BGP.
+
+ Note - When redistributing a static route, or any better Admin Distance route,
+ into BGP for which the same path is learned dynamically from another BGP
+ speaker, if the redistribute path is more preferred from a BGP Best Path
+ standpoint than the dynamically learned path, then BGP will not export
+ the best path to Zebra(RIB) for installation into the routing table,
+ unless BGP receives the path before the static route is created.
.. clicmd:: redistribute <table|table-direct> (1-65535)] [metric (0-4294967295)] [route-map WORD]
@@ -1560,6 +1572,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-link-bandwidth
+
+ By default bandwidth in extended communities is carried encoded as IEEE
+ floating-point format, and is limited to maximum of 25 Gbps.
+
+ Enabling this parameter, you can use the bandwidth of to 4294967295 Mbps.
+
+ This is disabled by default.
+
.. clicmd:: neighbor PEER enforce-first-as
Discard updates received from the specified (eBGP) peer if the AS_PATH
@@ -1816,7 +1837,7 @@ Configuring Peers
This includes changing graceful-restart (LLGR also) timers,
enabling/disabling add-path, and other supported capabilities.
-.. clicmd:: neighbor PEER capability fqdn
+.. clicmd:: neighbor PEER capability fqdn
Allow BGP to negotiate the FQDN Capability with its peers.
@@ -1825,7 +1846,7 @@ Configuring Peers
This capability is activated by default. The ``no neighbor PEER capability
fqdn`` avoid negotiation of that capability. This is useful for peers who
- are not supporting this capability or supporting BGP Capabilities
+ are not supporting this capability or supporting BGP Capabilities
Negotiation RFC 2842.
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> accept-own
@@ -1949,6 +1970,13 @@ Configuring Peers
outputs. It's easier to troubleshoot if you have a number of BGP peers
and a number of routes to check.
+.. clicmd:: bgp default dynamic-capability
+
+ This command enables dynamic capability advertisement by default
+ for all the neighbors.
+
+ For ``datacenter`` profile, this is enabled by default.
+
.. clicmd:: bgp default software-version-capability
This command enables software version capability advertisement by default
@@ -3219,7 +3247,7 @@ that the 2001:db8:2:2:: prefix is valid.
.. code-block:: frr
- r1# show bgp nexthop detail
+ r1# show bgp nexthop detail
Current BGP nexthop cache:
2001:db8:2:2:: valid [IGP metric 0], #paths 4
gate 2001:db8:12::2, if eth0
diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst
index 0f46832059..14d0849b34 100644
--- a/doc/user/bmp.rst
+++ b/doc/user/bmp.rst
@@ -23,6 +23,8 @@ The `BMP` implementation in FRR has the following properties:
- 3: count of **prefixes** with loop in cluster id
- 4: count of **prefixes** with loop in AS-path
- 5: count of **prefixes** with loop in originator
+ - 7: count of **routes** in adj-rib-in
+ - 8: count of **routes** in Loc-RIB
- 11: count of updates subjected to :rfc:`7607` "treat as withdrawal"
handling due to errors
- 65531: *experimental* count of prefixes rejected due to invalid next-hop
@@ -146,6 +148,11 @@ associated with a particular ``bmp targets``:
Send BMP Statistics (counter) messages at the specified interval (in
milliseconds.)
+.. clicmd:: bmp stats send-experimental
+
+ Send BMP Statistics (counter) messages whose code is defined as
+ experimental (in the [65531-65534] range).
+
.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy|loc-rib>
Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index f07bade52c..d17112d8aa 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -326,11 +326,6 @@ options from the list below.
Build with configuration rollback support. Requires SQLite3.
-.. option:: --enable-confd=<dir>
-
- Build the ConfD northbound plugin. Look for the libconfd libs and headers
- in `dir`.
-
.. option:: --enable-sysrepo
Build the Sysrepo northbound plugin.
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index d442faf0c1..135d94004a 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -123,7 +123,7 @@ ISIS Timer
Set LSP refresh interval in seconds, globally, for an area (level-1) or a
domain (level-2).
-.. clicmd:: max-lsp-lifetime [level-1 | level-2] (360-65535)
+.. clicmd:: max-lsp-lifetime [level-1 | level-2] (350-65535)
Set LSP maximum LSP lifetime in seconds, globally, for an area (level-1) or
a domain (level-2).
@@ -301,7 +301,7 @@ Showing ISIS information
Show summary information about ISIS.
-.. clicmd:: show isis hostname
+.. clicmd:: show isis [vrf <NAME|all>] hostname
Show information about ISIS node.
@@ -320,17 +320,17 @@ Showing ISIS information
Show the ISIS database globally, for a specific LSP id without or with
details.
-.. clicmd:: show isis topology [level-1|level-2] [algorithm [(128-255)]]
+.. clicmd:: show isis [vrf <NAME|all>] topology [level-1|level-2] [algorithm [(128-255)]]
Show topology IS-IS paths to Intermediate Systems, globally, in area
(level-1) or domain (level-2).
-.. clicmd:: show isis route [level-1|level-2] [prefix-sid|backup] [algorithm [(128-255)]]
+.. clicmd:: show isis [vrf <NAME|all>] route [level-1|level-2] [prefix-sid|backup] [algorithm [(128-255)]]
Show the ISIS routing table, as determined by the most recent SPF
calculation.
-.. clicmd:: show isis fast-reroute summary [level-1|level-2]
+.. clicmd:: show isis [vrf <NAME|all>] fast-reroute summary [level-1|level-2]
Show information about the number of prefixes having LFA protection,
and network-wide LFA coverage.
@@ -634,26 +634,14 @@ Debugging ISIS
IS-IS Adjacency related packets.
-.. clicmd:: debug isis checksum-errors
-
- IS-IS LSP checksum errors.
-
.. clicmd:: debug isis events
IS-IS Events.
-.. clicmd:: debug isis local-updates
-
- IS-IS local update packets.
-
.. clicmd:: debug isis packet-dump
IS-IS packet dump.
-.. clicmd:: debug isis protocol-errors
-
- IS-IS LSP protocol errors.
-
.. clicmd:: debug isis route-events
IS-IS Route related events.
@@ -663,11 +651,8 @@ Debugging ISIS
IS-IS CSNP/PSNP packets.
.. clicmd:: debug isis spf-events
-.. clicmd:: debug isis spf-statistics
-.. clicmd:: debug isis spf-triggers
- IS-IS Shortest Path First Events, Timing and Statistic Data and triggering
- events.
+ IS-IS Shortest Path First Events.
.. clicmd:: debug isis update-packets
@@ -846,7 +831,7 @@ A simple vrf example:
!
interface eth0 vrf RED
- ip router isis FOO vrf RED
+ ip router isis FOO
isis network point-to-point
isis circuit-type level-2-only
!
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index ad5861051d..ea41ba53b3 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -494,11 +494,11 @@ Graceful Restart
Configure Graceful Restart (RFC 5187) helper support.
- By default, helper support is disabled for all neighbours.
+ By default, helper support is disabled for all neighbors.
This config enables/disables helper support on this router
- for all neighbours.
+ for all neighbors.
To enable/disable helper support for a specific
- neighbour, the router-id (A.B.C.D) has to be specified.
+ neighbor, the router-id (A.B.C.D) has to be specified.
.. clicmd:: graceful-restart helper strict-lsa-checking
diff --git a/doc/user/ospf_fundamentals.rst b/doc/user/ospf_fundamentals.rst
index c566059121..3032d2771e 100644
--- a/doc/user/ospf_fundamentals.rst
+++ b/doc/user/ospf_fundamentals.rst
@@ -12,7 +12,7 @@ OSPF Fundamentals
:term:`distance-vector` protocols, such as :abbr:`RIP` or :abbr:`BGP`, where
routers describe available `paths` (i.e. routes) to each other, in
:term:`link-state` protocols routers instead describe the state of their links
-to their immediate neighbouring routers.
+to their immediate neighboring routers.
.. index::
single: Link State Announcement
@@ -127,7 +127,7 @@ LSA Flooding
""""""""""""
OSPF defines several related mechanisms, used to manage synchronisation of
-:abbr:`LSDB` s between neighbours as neighbours form adjacencies and the
+:abbr:`LSDB` s between neighbors as neighbors form adjacencies and the
propagation, or `flooding` of new or updated :abbr:`LSA` s.
@@ -259,7 +259,7 @@ called `intra-area routes`.
LSA is originated for such a link.
Stub
- A link with no adjacent neighbours, or a host route.
+ A link with no adjacent neighbors, or a host route.
- Link ID and Data
@@ -339,8 +339,8 @@ The example below shows two :abbr:`LSA` s, both originated by the same router
of different LSA types.
The first LSA being the router LSA describing 192.168.0.49's links: 2 links
-to multi-access networks with fully-adjacent neighbours (i.e. Transit
-links) and 1 being a Stub link (no adjacent neighbours).
+to multi-access networks with fully-adjacent neighbors (i.e. Transit
+links) and 1 being a Stub link (no adjacent neighbors).
The second LSA being a Network LSA, for which 192.168.0.49 is the
:abbr:`DR`, listing the Router IDs of 4 routers on that network which
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 3bc4487f64..ad0b25aec4 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -28,6 +28,12 @@ Configuring OSPF
Enable the OSPF API server. This is required to use ``ospfclient``.
+.. option:: -l, --apiserver_addr <address>
+
+ Specify the local IPv4 address to which to bind the OSPF API server socket.
+ If unspecified, connections are accepted to any address. Specification of
+ 127.0.0.1 can be used to limit socket access to local applications.
+
*ospfd* must acquire interface information from *zebra* in order to function.
Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is
restarted then *ospfd* must be too.
@@ -239,6 +245,17 @@ To start OSPF process you have to specify the OSPF router.
This configuration setting MUST be consistent across all routers within the
OSPF domain.
+.. clicmd:: neighbor A.B.C.D [poll-interval (1-65535)] [priority (0-255)]
+
+
+ Configures OSPF neighbors for non-broadcast multi-access (NBMA) networks
+ and point-to-multipoint non-broadcast networks. The `poll-interval`
+ specifies the rate for sending hello packets to neighbors that are not
+ active. When the configured neighbor is discovered, hello packets will be
+ sent at the rate of the hello-interval. The default `poll-interval` is 60
+ seconds. The `priority` is used to for the Designated Router (DR) election
+ on non-broadcast multi-access networks.
+
.. clicmd:: network A.B.C.D/M area A.B.C.D
.. clicmd:: network A.B.C.D/M area (0-4294967295)
@@ -580,7 +597,7 @@ Interfaces
Note that OSPF MD5 authentication requires that time never go backwards
(correct time is NOT important, only that it never goes backwards), even
across resets, if ospfd is to be able to promptly reestablish adjacencies
- with its neighbours after restarts/reboots. The host should have system time
+ with its neighbors after restarts/reboots. The host should have system time
be set at boot from an external or non-volatile source (e.g. battery backed
clock, NTP, etc.) or else the system clock should be periodically saved to
non-volatile storage and restored at boot if MD5 authentication is to be
@@ -612,7 +629,7 @@ Interfaces
Note that OSPF HMAC cryptographic authentication requires that time never go backwards
(correct time is NOT important, only that it never goes backwards), even
across resets, if ospfd is to be able to promptly reestablish adjacencies
- with its neighbours after restarts/reboots. The host should have system time
+ with its neighbors after restarts/reboots. The host should have system time
be set at boot from an external or non-volatile source (e.g. battery backed
clock, NTP, etc.) or else the system clock should be periodically saved to
non-volatile storage and restored at boot if HMAC cryptographic authentication is to be
@@ -679,7 +696,7 @@ Interfaces
it's recommended to set the hello delay and hello interval with the same values.
The default value is 10 seconds.
-.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint [delay-reflood]|point-to-point [dmvpn])
+.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint [delay-reflood|non-broadcast]|point-to-point [dmvpn])
When configuring a point-to-point network on an interface and the interface
has a /32 address associated with then OSPF will treat the interface
@@ -691,6 +708,13 @@ Interfaces
point-to-point, but the HUB will be a point-to-multipoint. To make this
topology work, specify the optional 'dmvpn' parameter at the spoke.
+ When the network is configured as point-to-multipoint and `non-broadcast`
+ is specified, the network doesn't support broadcast or multicast delivery
+ and neighbors cannot be discovered from OSPF hello received from the
+ OSPFAllRouters (224.0.0.5). Rather, they must be explicitly configured
+ using the :clicmd:`neighbor A.B.C.D` configuration command as they are
+ on non-broadcast networks.
+
When the network is configured as point-to-multipoint and `delay-reflood`
is specified, LSAs received on the interface from neighbors on the
interface will not be flooded back out on the interface immediately.
@@ -739,6 +763,32 @@ Interfaces
optional IPv4 address is specified, the prefix suppression will apply
to the OSPF interface associated with the specified interface address.
+.. clicmd:: ip ospf neighbor-filter NAME [A.B.C.D]
+
+ Configure an IP prefix-list to use to filter packets received from
+ OSPF neighbors on the OSPF interface. The prefix-list should include rules
+ to permit or deny OSPF neighbors by IP source address. This is useful for
+ multi-access interfaces where adjacencies with only a subset of the
+ reachable neighbors are desired. Applications include testing partially
+ meshed topologies, OSPF Denial of Sevice (DoS) mitigation, and avoidance
+ of adjacencies with OSPF neighbors not meeting traffic engineering criteria.
+
+ Example:
+
+.. code-block:: frr
+
+ !
+ ! Prefix-list to block neighbor with source address 10.1.0.2
+ !
+ ip prefix-list nbr-filter seq 10 deny 10.1.0.2/32
+ ip prefix-list nbr-filter seq 200 permit any
+ !
+ ! Configure the neighbor filter prefix-list on interface eth0
+ !
+ interface eth0
+ ip ospf neighbor-filter nbr-filter
+ !
+
.. clicmd:: ip ospf area (A.B.C.D|(0-4294967295))
@@ -838,11 +888,11 @@ Graceful Restart
Configure Graceful Restart (RFC 3623) helper support.
- By default, helper support is disabled for all neighbours.
+ By default, helper support is disabled for all neighbors.
This config enables/disables helper support on this router
- for all neighbours.
+ for all neighbors.
To enable/disable helper support for a specific
- neighbour, the router-id (A.B.C.D) has to be specified.
+ neighbor, the router-id (A.B.C.D) has to be specified.
.. clicmd:: graceful-restart helper strict-lsa-checking
@@ -1082,7 +1132,7 @@ Router Information
respectively the PCE IP address, Autonomous System (AS) numbers of
controlled domains, neighbor ASs, flag and scope. For flag and scope, please
refer to :rfc`5088` for the BITPATTERN recognition. Multiple 'pce neighbor'
- command could be specified in order to specify all PCE neighbours.
+ command could be specified in order to specify all PCE neighbors.
.. clicmd:: show ip ospf router-info
diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst
index 76910ee7b9..fe9e407ca9 100644
--- a/doc/user/rpki.rst
+++ b/doc/user/rpki.rst
@@ -215,15 +215,18 @@ Displaying RPKI
Display RPKI configuration state including timers values.
-.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)] [vrf NAME] [json]
+.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASN] [vrf NAME] [json]
Display validated prefixes received from the cache servers filtered
- by the specified prefix.
+ by the specified prefix. The AS number space has been increased
+ to allow the choice of using AS 0 because RFC-7607 specifically
+ calls out the usage of 0 in a special case.
.. clicmd:: show rpki as-number ASN [vrf NAME] [json]
Display validated prefixes received from the cache servers filtered
- by ASN.
+ by ASN. The usage of AS 0 is allowed because RFC-76067 specifically
+ calls out the usage of 0 in a special case.
.. clicmd:: show rpki prefix-table [vrf NAME] [json]
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index cba1b91fae..7acd3a2b4e 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -687,7 +687,7 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
default:
continue;
}
- backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
+ backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)"
: "";
json_object_string_add(adj_sid_json, "nexthop",
@@ -862,7 +862,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
default:
continue;
}
- backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
+ backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)"
: "";
vty_out(vty, " %s %s%s: %u\n",
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c
index 6f21f4cea2..4eb57aefb0 100644
--- a/isisd/isis_lfa.c
+++ b/isisd/isis_lfa.c
@@ -916,9 +916,8 @@ int isis_tilfa_check(struct isis_spftree *spftree_pc,
adj = isis_adj_find(spftree_pc->area, spftree_pc->level,
vertex->N.id);
- if (adj
- && isis_sr_adj_sid_find(adj, spftree_pc->family,
- ISIS_SR_LAN_BACKUP)) {
+ if (adj && isis_sr_adj_sid_find(adj, spftree_pc->family,
+ ISIS_SR_ADJ_BACKUP)) {
if (IS_DEBUG_LFA)
zlog_debug(
"ISIS-LFA: %s %s already covered by node protection",
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 6f410d342e..5be317018e 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -2082,7 +2082,7 @@ static void send_hello_cb(struct event *thread)
circuit->u.p2p.t_send_p2p_hello = NULL;
send_hello(circuit, 1);
send_hello_sched(circuit, ISIS_LEVEL1,
- 1000 * circuit->hello_interval[1]);
+ 1000 * circuit->hello_interval[0]);
return;
}
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 36986a19c5..294c03def1 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -2908,7 +2908,7 @@ static void show_isis_route_common(struct vty *vty, int levels,
struct isis_spftree *spftree;
struct listnode *node;
struct isis_area *area;
- char key[8];
+ char key[18];
if (!isis->area_list || isis->area_list->count == 0)
return;
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index e8354fdf92..af22f56f8b 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -462,8 +462,7 @@ void isis_area_delete_backup_adj_sids(struct isis_area *area, int level)
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(area->srdb.adj_sids, node, nnode, sra))
- if (sra->type == ISIS_SR_LAN_BACKUP
- && (sra->adj->level & level))
+ if (sra->type == ISIS_SR_ADJ_BACKUP && (sra->adj->level & level))
sr_adj_sid_del(sra);
}
@@ -689,7 +688,7 @@ void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, bool backup,
circuit->ext = isis_alloc_ext_subtlvs();
sra = XCALLOC(MTYPE_ISIS_SR_INFO, sizeof(*sra));
- sra->type = backup ? ISIS_SR_LAN_BACKUP : ISIS_SR_ADJ_NORMAL;
+ sra->type = backup ? ISIS_SR_ADJ_BACKUP : ISIS_SR_ADJ_NORMAL;
sra->input_label = input_label;
sra->nexthop.family = family;
sra->nexthop.address = nexthop;
@@ -819,7 +818,7 @@ static void sr_adj_sid_del(struct sr_adjacency *sra)
exit(1);
}
- if (sra->type == ISIS_SR_LAN_BACKUP && sra->backup_nexthops) {
+ if (sra->type == ISIS_SR_ADJ_BACKUP && sra->backup_nexthops) {
sra->backup_nexthops->del =
(void (*)(void *))isis_nexthop_delete;
list_delete(&sra->backup_nexthops);
diff --git a/isisd/isis_sr.h b/isisd/isis_sr.h
index 4378760299..76f776825d 100644
--- a/isisd/isis_sr.h
+++ b/isisd/isis_sr.h
@@ -82,7 +82,7 @@ struct sr_local_block {
/* Segment Routing Adjacency-SID type. */
enum sr_adj_type {
ISIS_SR_ADJ_NORMAL = 0,
- ISIS_SR_LAN_BACKUP,
+ ISIS_SR_ADJ_BACKUP,
};
/* Segment Routing Adjacency. */
diff --git a/isisd/isis_srv6.c b/isisd/isis_srv6.c
index 1b0c706946..44fd599cbb 100644
--- a/isisd/isis_srv6.c
+++ b/isisd/isis_srv6.c
@@ -363,7 +363,7 @@ void isis_area_delete_backup_srv6_endx_sids(struct isis_area *area, int level)
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(area->srv6db.srv6_endx_sids, node, nnode, sra))
- if (sra->type == ISIS_SRV6_LAN_BACKUP &&
+ if (sra->type == ISIS_SRV6_ADJ_BACKUP &&
(sra->adj->level & level))
srv6_endx_sid_del(sra);
}
@@ -420,7 +420,7 @@ void srv6_endx_sid_add_single(struct isis_adjacency *adj, bool backup,
: SRV6_ENDPOINT_BEHAVIOR_END_X;
sra = XCALLOC(MTYPE_ISIS_SRV6_INFO, sizeof(*sra));
- sra->type = backup ? ISIS_SRV6_LAN_BACKUP : ISIS_SRV6_ADJ_NORMAL;
+ sra->type = backup ? ISIS_SRV6_ADJ_BACKUP : ISIS_SRV6_ADJ_NORMAL;
sra->behavior = behavior;
sra->locator = chunk;
sra->structure.loc_block_len = chunk->block_bits_length;
@@ -538,7 +538,7 @@ void srv6_endx_sid_del(struct srv6_adjacency *sra)
exit(1);
}
- if (sra->type == ISIS_SRV6_LAN_BACKUP && sra->backup_nexthops) {
+ if (sra->type == ISIS_SRV6_ADJ_BACKUP && sra->backup_nexthops) {
sra->backup_nexthops->del =
(void (*)(void *))isis_nexthop_delete;
list_delete(&sra->backup_nexthops);
diff --git a/isisd/isis_srv6.h b/isisd/isis_srv6.h
index 33864360c1..7f16712ae3 100644
--- a/isisd/isis_srv6.h
+++ b/isisd/isis_srv6.h
@@ -68,7 +68,7 @@ struct isis_srv6_locator {
/* SRv6 Adjacency-SID type */
enum srv6_adj_type {
ISIS_SRV6_ADJ_NORMAL = 0,
- ISIS_SRV6_LAN_BACKUP,
+ ISIS_SRV6_ADJ_BACKUP,
};
/* SRv6 Adjacency. */
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 18a0c49ceb..2412ec5e84 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -454,7 +454,7 @@ void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
/* Set backup nexthops. */
- if (sra->type == ISIS_SR_LAN_BACKUP) {
+ if (sra->type == ISIS_SR_ADJ_BACKUP) {
int count;
count = isis_zebra_add_nexthops(isis, sra->backup_nexthops,
diff --git a/lib/command.c b/lib/command.c
index 0288ab7599..51f2529e3e 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -1374,7 +1374,7 @@ DEFUN (disable,
}
/* Down vty node level. */
-DEFUN (config_exit,
+DEFUN_YANG (config_exit,
config_exit_cmd,
"exit",
"Exit current mode and down to previous mode\n")
diff --git a/lib/command.h b/lib/command.h
index ef1815c0bd..e4c575e8d7 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -462,6 +462,8 @@ struct cmd_node {
#define MPLS_LDP_SYNC_HOLDDOWN_STR \
"Time to wait for LDP-SYNC to occur before restoring if cost\n"
#define NO_MPLS_LDP_SYNC_HOLDDOWN_STR "holddown timer disable\n"
+#define BGP_AF_STR "Address Family\n"
+#define BGP_AF_MODIFIER_STR "Address Family modifier\n"
/* Command warnings. */
#define NO_PASSWD_CMD_WARNING \
diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c
index 1ffa5934aa..3a4bc712fc 100644
--- a/lib/frr_pthread.c
+++ b/lib/frr_pthread.c
@@ -92,9 +92,14 @@ struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr,
MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t));
fpt->running_cond = XCALLOC(MTYPE_PTHREAD_PRIM,
sizeof(pthread_cond_t));
+
pthread_mutex_init(fpt->running_cond_mtx, NULL);
pthread_cond_init(fpt->running_cond, NULL);
+ pthread_mutex_init(&fpt->startup_cond_mtx, NULL);
+ pthread_cond_init(&fpt->startup_cond, NULL);
+ fpt->started = false;
+
frr_with_mutex (&frr_pthread_list_mtx) {
listnode_add(frr_pthread_list, fpt);
}
@@ -108,6 +113,8 @@ static void frr_pthread_destroy_nolock(struct frr_pthread *fpt)
pthread_mutex_destroy(&fpt->mtx);
pthread_mutex_destroy(fpt->running_cond_mtx);
pthread_cond_destroy(fpt->running_cond);
+ pthread_mutex_destroy(&fpt->startup_cond_mtx);
+ pthread_cond_destroy(&fpt->startup_cond);
XFREE(MTYPE_FRR_PTHREAD, fpt->name);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond_mtx);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond);
@@ -140,11 +147,34 @@ int frr_pthread_set_name(struct frr_pthread *fpt)
return ret;
}
+/* New pthread waits before running */
+static void frr_pthread_wait_startup(struct frr_pthread *fpt)
+{
+ frr_with_mutex (&fpt->startup_cond_mtx) {
+ while (!fpt->started)
+ pthread_cond_wait(&fpt->startup_cond,
+ &fpt->startup_cond_mtx);
+ }
+}
+
+/* Parent pthread allows new pthread to start running */
+static void frr_pthread_notify_startup(struct frr_pthread *fpt)
+{
+ frr_with_mutex (&fpt->startup_cond_mtx) {
+ fpt->started = true;
+ pthread_cond_signal(&fpt->startup_cond);
+ }
+}
+
static void *frr_pthread_inner(void *arg)
{
struct frr_pthread *fpt = arg;
+ /* The new pthead waits until the parent allows it to continue. */
+ frr_pthread_wait_startup(fpt);
+
rcu_thread_start(fpt->rcu_thread);
+
return fpt->attr.start(fpt);
}
@@ -169,6 +199,9 @@ int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr)
/* Restore caller's signals */
pthread_sigmask(SIG_SETMASK, &oldsigs, NULL);
+ /* Allow new child pthread to start */
+ frr_pthread_notify_startup(fpt);
+
/*
* Per pthread_create(3), the contents of fpt->thread are undefined if
* pthread_create() did not succeed. Reset this value to zero.
@@ -250,6 +283,8 @@ int frr_pthread_non_controlled_startup(pthread_t thread, const char *name,
fpt->thread = thread;
fpt->rcu_thread = rcu_thread;
+ fpt->started = true;
+
frr_pthread_inner(fpt);
return 0;
diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h
index 1e1b8d7fd3..bb751b7071 100644
--- a/lib/frr_pthread.h
+++ b/lib/frr_pthread.h
@@ -47,6 +47,17 @@ struct frr_pthread {
struct frr_pthread_attr attr;
/*
+ * Startup serialization: newly-started pthreads wait at a point
+ * very early in life so that there isn't a race with the
+ * starting pthread. The OS 'start' apis don't make any guarantees
+ * about which pthread runs first - the existing pthread that has
+ * called the 'start' api, or the new pthread that is just starting.
+ */
+ pthread_cond_t startup_cond;
+ pthread_mutex_t startup_cond_mtx;
+ atomic_bool started;
+
+ /*
* Notification mechanism for allowing pthreads to notify their parents
* when they are ready to do work. This mechanism has two associated
* functions:
diff --git a/lib/keychain_nb.c b/lib/keychain_nb.c
index 6838268a93..57967b30a5 100644
--- a/lib/keychain_nb.c
+++ b/lib/keychain_nb.c
@@ -545,10 +545,6 @@ static int key_chains_key_chain_key_crypto_algorithm_modify(struct nb_cb_modify_
if (args->event != NB_EV_VALIDATE && args->event != NB_EV_APPLY)
return NB_OK;
- name = yang_dnode_get_string(args->dnode, "../../name");
- keychain = keychain_lookup(name);
- index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../key-id");
- key = key_lookup(keychain, index);
name = yang_dnode_get_string(args->dnode, NULL);
if (!strncmp(name, prefix, prefix_len))
name += prefix_len;
@@ -570,6 +566,10 @@ static int key_chains_key_chain_key_crypto_algorithm_modify(struct nb_cb_modify_
}
assert(args->event == NB_EV_APPLY);
+ name = yang_dnode_get_string(args->dnode, "../../name");
+ keychain = keychain_lookup(name);
+ index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../key-id");
+ key = key_lookup(keychain, index);
key->hash_algo = hash_algo;
keychain_touch(keychain);
diff --git a/lib/lib_errors.c b/lib/lib_errors.c
index a96fac9cd4..9d6c04325c 100644
--- a/lib/lib_errors.c
+++ b/lib/lib_errors.c
@@ -308,24 +308,6 @@ static struct log_ref ferr_lib_err[] = {
.suggestion = "Check if the FRR libyang plugins were installed correctly in the system",
},
{
- .code = EC_LIB_CONFD_INIT,
- .title = "ConfD initialization error",
- .description = "Upon startup FRR failed to properly initialize and startup the ConfD northbound plugin",
- .suggestion = "Check if ConfD is installed correctly in the system. Also, check if the confd daemon is running.",
- },
- {
- .code = EC_LIB_CONFD_DATA_CONVERT,
- .title = "ConfD data conversion error",
- .description = "An error has occurred while converting a ConfD data value (binary) to a string",
- .suggestion = "Open an Issue with all relevant log files and restart FRR"
- },
- {
- .code = EC_LIB_LIBCONFD,
- .title = "libconfd error",
- .description = "The northbound subsystem has detected that the libconfd library returned an error",
- .suggestion = "Open an Issue with all relevant log files and restart FRR"
- },
- {
.code = EC_LIB_SYSREPO_INIT,
.title = "Sysrepo initialization error",
.description = "Upon startup FRR failed to properly initialize and startup the Sysrepo northbound plugin",
diff --git a/lib/lib_errors.h b/lib/lib_errors.h
index 8cdfb166c7..9e0d539599 100644
--- a/lib/lib_errors.h
+++ b/lib/lib_errors.h
@@ -65,9 +65,6 @@ enum lib_log_refs {
EC_LIB_NB_TRANSACTION_RECORD_FAILED,
EC_LIB_LIBYANG,
EC_LIB_LIBYANG_PLUGIN_LOAD,
- EC_LIB_CONFD_INIT,
- EC_LIB_CONFD_DATA_CONVERT,
- EC_LIB_LIBCONFD,
EC_LIB_SYSREPO_INIT,
EC_LIB_SYSREPO_DATA_CONVERT,
EC_LIB_LIBSYSREPO,
diff --git a/lib/libfrr.c b/lib/libfrr.c
index c5c7e7837a..876efe23a8 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -59,7 +59,7 @@ char config_default[512];
char frr_zclientpath[512];
static char pidfile_default[1024];
#ifdef HAVE_SQLITE3
-static char dbfile_default[512];
+static char dbfile_default[1024];
#endif
static char vtypath_default[512];
@@ -1450,3 +1450,12 @@ void _libfrr_version(void)
write(1, banner, sizeof(banner) - 1);
_exit(0);
}
+
+/* Render simple version tuple to string */
+const char *frr_vers2str(uint32_t version, char *buf, int buflen)
+{
+ snprintf(buf, buflen, "%d.%d.%d", MAJOR_FRRVERSION(version),
+ MINOR_FRRVERSION(version), SUB_FRRVERSION(version));
+
+ return buf;
+}
diff --git a/lib/libfrr.h b/lib/libfrr.h
index ee436d9f8f..77d70448a9 100644
--- a/lib/libfrr.h
+++ b/lib/libfrr.h
@@ -233,6 +233,17 @@ extern bool frr_is_after_fork;
extern bool debug_memstats_at_exit;
+/*
+ * Version numbering: MAJOR (8) | MINOR (16) | SUB (8)
+ */
+#define MAKE_FRRVERSION(maj, min, sub) \
+ ((((maj) & 0xff) << 24) | (((min) & 0xffff) << 8) | ((sub) & 0xff))
+#define MAJOR_FRRVERSION(v) (((v) >> 24) & 0xff)
+#define MINOR_FRRVERSION(v) (((v) >> 8) & 0xffff)
+#define SUB_FRRVERSION(v) ((v) & 0xff)
+
+const char *frr_vers2str(uint32_t version, char *buf, int buflen);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libospf.h b/lib/libospf.h
index 45e7fb1870..0ac490a00e 100644
--- a/lib/libospf.h
+++ b/lib/libospf.h
@@ -69,6 +69,7 @@ extern "C" {
#define OSPF_MTU_IGNORE_DEFAULT 0
#define OSPF_FAST_HELLO_DEFAULT 0
#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
+#define OSPF_P2MP_NON_BROADCAST_DEFAULT false
#define OSPF_OPAQUE_CAPABLE_DEFAULT true
#define OSPF_PREFIX_SUPPRESSION_DEFAULT false
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c
index a107582bea..3345505213 100644
--- a/lib/mgmt_fe_client.c
+++ b/lib/mgmt_fe_client.c
@@ -329,6 +329,36 @@ int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
return ret;
}
+int mgmt_fe_send_edit_req(struct mgmt_fe_client *client, uint64_t session_id,
+ uint64_t req_id, uint8_t datastore,
+ LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath, const char *data)
+{
+ struct mgmt_msg_edit *msg;
+ int ret;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_edit, 0,
+ MTYPE_MSG_NATIVE_EDIT);
+ msg->refer_id = session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_EDIT;
+ msg->request_type = request_type;
+ msg->flags = flags;
+ msg->datastore = datastore;
+ msg->operation = operation;
+
+ mgmt_msg_native_xpath_encode(msg, xpath);
+ if (data)
+ mgmt_msg_native_append(msg, data, strlen(data) + 1);
+
+ debug_fe_client("Sending EDIT_REQ session-id %" PRIu64
+ " req-id %" PRIu64 " xpath: %s",
+ session_id, req_id, xpath);
+
+ ret = mgmt_msg_native_send_msg(&client->client.conn, msg, false);
+ mgmt_msg_native_free_msg(msg);
+ return ret;
+}
static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
Mgmtd__FeMessage *fe_msg)
@@ -503,7 +533,9 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
struct mgmt_fe_client_session *session = NULL;
struct mgmt_msg_notify_data *notify_msg;
struct mgmt_msg_tree_data *tree_msg;
+ struct mgmt_msg_edit_reply *edit_msg;
struct mgmt_msg_error *err_msg;
+ const char *xpath = NULL;
const char *data = NULL;
size_t dlen;
@@ -554,6 +586,28 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
msg_len - sizeof(*tree_msg),
tree_msg->partial_error);
break;
+ case MGMT_MSG_CODE_EDIT_REPLY:
+ if (!session->client->cbs.edit_notify)
+ return;
+
+ edit_msg = (typeof(edit_msg))msg;
+ if (msg_len < sizeof(*edit_msg)) {
+ log_err_fe_client("Corrupt edit-reply msg recv");
+ return;
+ }
+
+ xpath = mgmt_msg_native_xpath_decode(edit_msg, msg_len);
+ if (!xpath) {
+ log_err_fe_client("Corrupt edit-reply msg recv");
+ return;
+ }
+
+ session->client->cbs.edit_notify(client, client->user_data,
+ session->client_id,
+ msg->refer_id,
+ session->user_ctx, msg->req_id,
+ xpath);
+ break;
case MGMT_MSG_CODE_NOTIFY:
if (!session->client->cbs.async_notification)
return;
diff --git a/lib/mgmt_fe_client.h b/lib/mgmt_fe_client.h
index eee4594e17..9d569348ae 100644
--- a/lib/mgmt_fe_client.h
+++ b/lib/mgmt_fe_client.h
@@ -114,6 +114,12 @@ struct mgmt_fe_client_cbs {
LYD_FORMAT result_type, void *result, size_t len,
int partial_error);
+ /* Called when edit result is returned */
+ int (*edit_notify)(struct mgmt_fe_client *client, uintptr_t user_data,
+ uint64_t client_id, uint64_t session_id,
+ uintptr_t session_ctx, uint64_t req_id,
+ const char *xpath);
+
/* Called with asynchronous notifications from backends */
int (*async_notification)(struct mgmt_fe_client *client,
uintptr_t user_data, uint64_t client_id,
@@ -410,6 +416,45 @@ extern int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
const char *xpath);
/*
+ * Send EDIT to MGMTD daemon.
+ *
+ * client
+ * Client object.
+ *
+ * session_id
+ * Client session ID.
+ *
+ * req_id
+ * Client request ID.
+ *
+ * datastore
+ * Datastore for editing.
+ *
+ * request_type
+ * The LYD_FORMAT of the request.
+ *
+ * flags
+ * Flags to control the behavior of the request.
+ *
+ * operation
+ * NB_OP_* operation to perform.
+ *
+ * xpath
+ * the xpath to edit.
+ *
+ * data
+ * the data tree.
+ *
+ * Returns:
+ * 0 on success, otherwise msg_conn_send_msg() return values.
+ */
+extern int mgmt_fe_send_edit_req(struct mgmt_fe_client *client,
+ uint64_t session_id, uint64_t req_id,
+ uint8_t datastore, LYD_FORMAT request_type,
+ uint8_t flags, uint8_t operation,
+ const char *xpath, const char *data);
+
+/*
* Destroy library and cleanup everything.
*/
extern void mgmt_fe_client_destroy(struct mgmt_fe_client *client);
diff --git a/lib/mgmt_msg_native.c b/lib/mgmt_msg_native.c
index 98b7da45ce..09ea43ece0 100644
--- a/lib/mgmt_msg_native.c
+++ b/lib/mgmt_msg_native.c
@@ -14,6 +14,8 @@ DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_GET_TREE, "native get tree msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_TREE_DATA, "native tree data msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_GET_DATA, "native get data msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_NOTIFY, "native get data msg");
+DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT, "native edit msg");
+DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT_REPLY, "native edit reply msg");
int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id,
uint64_t req_id, bool short_circuit_ok,
diff --git a/lib/mgmt_msg_native.h b/lib/mgmt_msg_native.h
index 53bb81be28..b7c29862aa 100644
--- a/lib/mgmt_msg_native.h
+++ b/lib/mgmt_msg_native.h
@@ -21,6 +21,7 @@ extern "C" {
#include "memory.h"
#include "mgmt_msg.h"
#include "mgmt_defines.h"
+#include "northbound.h"
#include <stdalign.h>
@@ -149,6 +150,8 @@ DECLARE_MTYPE(MSG_NATIVE_GET_TREE);
DECLARE_MTYPE(MSG_NATIVE_TREE_DATA);
DECLARE_MTYPE(MSG_NATIVE_GET_DATA);
DECLARE_MTYPE(MSG_NATIVE_NOTIFY);
+DECLARE_MTYPE(MSG_NATIVE_EDIT);
+DECLARE_MTYPE(MSG_NATIVE_EDIT_REPLY);
/*
* Native message codes
@@ -158,6 +161,8 @@ DECLARE_MTYPE(MSG_NATIVE_NOTIFY);
#define MGMT_MSG_CODE_TREE_DATA 2
#define MGMT_MSG_CODE_GET_DATA 3
#define MGMT_MSG_CODE_NOTIFY 4
+#define MGMT_MSG_CODE_EDIT 5
+#define MGMT_MSG_CODE_EDIT_REPLY 6
/*
* Datastores
@@ -318,6 +323,60 @@ _Static_assert(sizeof(struct mgmt_msg_notify_data) ==
offsetof(struct mgmt_msg_notify_data, data),
"Size mismatch");
+#define EDIT_FLAG_IMPLICIT_LOCK 0x01
+#define EDIT_FLAG_IMPLICIT_COMMIT 0x02
+
+#define EDIT_OP_CREATE 0
+#define EDIT_OP_DELETE 4
+#define EDIT_OP_MERGE 2
+#define EDIT_OP_REPLACE 5
+#define EDIT_OP_REMOVE 3
+
+_Static_assert(EDIT_OP_CREATE == NB_OP_CREATE_EXCL, "Operation mismatch");
+_Static_assert(EDIT_OP_DELETE == NB_OP_DELETE, "Operation mismatch");
+_Static_assert(EDIT_OP_MERGE == NB_OP_MODIFY, "Operation mismatch");
+_Static_assert(EDIT_OP_REPLACE == NB_OP_REPLACE, "Operation mismatch");
+_Static_assert(EDIT_OP_REMOVE == NB_OP_DESTROY, "Operation mismatch");
+
+/**
+ * struct mgmt_msg_edit - frontend edit request.
+ *
+ * @request_type: ``LYD_FORMAT`` for the @data.
+ * @flags: combination of ``EDIT_FLAG_*`` flags.
+ * @datastore: the datastore to edit.
+ * @operation: one of ``EDIT_OP_*`` operations.
+ * @data: the xpath followed by the tree data for the operation.
+ * for CREATE, xpath points to the parent node.
+ */
+struct mgmt_msg_edit {
+ struct mgmt_msg_header;
+ uint8_t request_type;
+ uint8_t flags;
+ uint8_t datastore;
+ uint8_t operation;
+ uint8_t resv2[4];
+
+ alignas(8) char data[];
+};
+_Static_assert(sizeof(struct mgmt_msg_edit) ==
+ offsetof(struct mgmt_msg_edit, data),
+ "Size mismatch");
+
+/**
+ * struct mgmt_msg_edit_reply - frontend edit reply.
+ *
+ * @data: the xpath of the data node that was created.
+ */
+struct mgmt_msg_edit_reply {
+ struct mgmt_msg_header;
+ uint8_t resv2[8];
+
+ alignas(8) char data[];
+};
+_Static_assert(sizeof(struct mgmt_msg_edit_reply) ==
+ offsetof(struct mgmt_msg_edit_reply, data),
+ "Size mismatch");
+
/*
* Validate that the message ends in a NUL terminating byte
*/
@@ -504,13 +563,13 @@ extern int vmgmt_msg_native_send_error(struct msg_conn *conn,
* The xpath string or NULL if there was an error decoding (i.e., the
* message is corrupt).
*/
-#define mgmt_msg_native_xpath_data_decode(msg, msglen, data) \
+#define mgmt_msg_native_xpath_data_decode(msg, msglen, __data) \
({ \
size_t __len = (msglen) - sizeof(*msg); \
const char *__s = NULL; \
if (msg->vsplit && msg->vsplit <= __len && \
msg->data[msg->vsplit - 1] == 0) { \
- (data) = msg->data + msg->vsplit; \
+ (__data) = msg->data + msg->vsplit; \
__s = msg->data; \
} \
__s; \
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 4ddb53cd96..243b52d554 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -1150,11 +1150,7 @@ static ssize_t printfrr_nh(struct fbuf *buf, struct printfrr_eargs *ea,
return -1;
}
-bool nexthop_is_ifindex_type(const struct nexthop *nh)
+bool nexthop_is_blackhole(const struct nexthop *nh)
{
- if (nh->type == NEXTHOP_TYPE_IFINDEX ||
- nh->type == NEXTHOP_TYPE_IPV4_IFINDEX ||
- nh->type == NEXTHOP_TYPE_IPV6_IFINDEX)
- return true;
- return false;
+ return nh->type == NEXTHOP_TYPE_BLACKHOLE;
}
diff --git a/lib/nexthop.h b/lib/nexthop.h
index bed6447d49..958d06aa51 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -240,8 +240,8 @@ extern struct nexthop *nexthop_dup(const struct nexthop *nexthop,
extern struct nexthop *nexthop_dup_no_recurse(const struct nexthop *nexthop,
struct nexthop *rparent);
-/* Check nexthop of IFINDEX type */
-extern bool nexthop_is_ifindex_type(const struct nexthop *nh);
+/* Is this nexthop a blackhole? */
+extern bool nexthop_is_blackhole(const struct nexthop *nh);
/*
* Parse one or more backup index values, as comma-separated numbers,
diff --git a/lib/northbound.c b/lib/northbound.c
index 487f225913..9a5d67cd1b 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -813,6 +813,223 @@ int nb_candidate_edit(struct nb_config *candidate, const struct nb_node *nb_node
return NB_OK;
}
+static int nb_candidate_edit_tree_add(struct nb_config *candidate,
+ enum nb_operation operation,
+ LYD_FORMAT format, const char *xpath,
+ const char *data, char *xpath_created,
+ char *errmsg, size_t errmsg_len)
+{
+ struct lyd_node *tree = NULL;
+ struct lyd_node *parent = NULL;
+ struct lyd_node *dnode = NULL;
+ struct lyd_node *existing = NULL;
+ struct lyd_node *ex_parent = NULL;
+ char *parent_xpath = NULL;
+ struct ly_in *in;
+ LY_ERR err;
+ bool root;
+ int ret;
+
+ ly_in_new_memory(data, &in);
+
+ root = xpath[0] == 0 || (xpath[0] == '/' && xpath[1] == 0);
+
+ /* get parent xpath if xpath is not root */
+ if (!root) {
+ /* NB_OP_CREATE_EXCT already expects parent xpath */
+ parent_xpath = XSTRDUP(MTYPE_TMP, xpath);
+
+ /* for other operations - pop one level */
+ if (operation != NB_OP_CREATE_EXCL) {
+ ret = yang_xpath_pop_node(parent_xpath);
+ if (ret) {
+ snprintf(errmsg, errmsg_len, "Invalid xpath");
+ goto done;
+ }
+
+ /* root is not actually a parent */
+ if (parent_xpath[0] == 0)
+ XFREE(MTYPE_TMP, parent_xpath);
+ }
+ }
+
+ /*
+ * Create parent if it's not root. We're creating a new tree here to be
+ * merged later with candidate.
+ */
+ if (parent_xpath) {
+ err = lyd_new_path2(NULL, ly_native_ctx, parent_xpath, NULL, 0,
+ 0, 0, &tree, &parent);
+ if (err) {
+ yang_print_errors(ly_native_ctx, errmsg, errmsg_len);
+ ret = NB_ERR;
+ goto done;
+ }
+ assert(parent);
+ }
+
+ /* parse data */
+ err = yang_lyd_parse_data(ly_native_ctx, parent, in, format,
+ LYD_PARSE_ONLY | LYD_PARSE_STRICT |
+ LYD_PARSE_NO_STATE,
+ 0, &dnode);
+ if (err) {
+ yang_print_errors(ly_native_ctx, errmsg, errmsg_len);
+ ret = NB_ERR;
+ goto done;
+ }
+
+ /* set the tree if we created a top-level node */
+ if (!parent)
+ tree = dnode;
+
+ /* save xpath of the created node */
+ lyd_path(dnode, LYD_PATH_STD, xpath_created, XPATH_MAXLEN);
+
+ /* verify that list keys are the same in the xpath and the data tree */
+ if (!root && (operation == NB_OP_REPLACE || operation == NB_OP_MODIFY)) {
+ if (lyd_find_path(tree, xpath, 0, NULL)) {
+ snprintf(errmsg, errmsg_len,
+ "List keys in xpath and data tree are different");
+ ret = NB_ERR;
+ goto done;
+ }
+ }
+
+ /* check if the node already exists in candidate */
+ if (operation == NB_OP_CREATE_EXCL || operation == NB_OP_REPLACE) {
+ existing = yang_dnode_get(candidate->dnode, xpath_created);
+
+ /* if the existing node is implicit default, ignore */
+ if (existing && (existing->flags & LYD_DEFAULT))
+ existing = NULL;
+
+ if (existing) {
+ if (operation == NB_OP_CREATE_EXCL) {
+ snprintf(errmsg, errmsg_len,
+ "Data already exists");
+ ret = NB_ERR;
+ goto done;
+ }
+
+ if (root) {
+ candidate->dnode = NULL;
+ } else {
+ /* if it's the first top-level node, update candidate */
+ if (candidate->dnode == existing)
+ candidate->dnode =
+ candidate->dnode->next;
+
+ ex_parent = lyd_parent(existing);
+ lyd_unlink_tree(existing);
+ }
+ }
+ }
+
+ err = lyd_merge_siblings(&candidate->dnode, tree,
+ LYD_MERGE_DESTRUCT | LYD_MERGE_WITH_FLAGS);
+ if (err) {
+ /* if replace failed, restore the original node */
+ if (existing) {
+ if (root) {
+ candidate->dnode = existing;
+ } else {
+ if (ex_parent)
+ lyd_insert_child(ex_parent, existing);
+ else
+ lyd_insert_sibling(candidate->dnode,
+ existing,
+ &candidate->dnode);
+ }
+ }
+ yang_print_errors(ly_native_ctx, errmsg, errmsg_len);
+ ret = NB_ERR;
+ goto done;
+ } else {
+ /*
+ * Free existing node after replace.
+ * We're using `lyd_free_siblings` here to free the whole
+ * tree if we replaced the root node. It won't affect other
+ * siblings if it wasn't root, because the existing node
+ * was unlinked from the tree.
+ */
+ if (existing)
+ lyd_free_siblings(existing);
+
+ tree = NULL; /* LYD_MERGE_DESTRUCT deleted the tree */
+ }
+
+ ret = NB_OK;
+done:
+ if (tree)
+ lyd_free_all(tree);
+ XFREE(MTYPE_TMP, parent_xpath);
+ ly_in_free(in, 0);
+
+ return ret;
+}
+
+static int nb_candidate_edit_tree_del(struct nb_config *candidate,
+ enum nb_operation operation,
+ const char *xpath, char *errmsg,
+ size_t errmsg_len)
+{
+ struct lyd_node *dnode;
+
+ /* deleting root - remove the whole config */
+ if (xpath[0] == 0 || (xpath[0] == '/' && xpath[1] == 0)) {
+ lyd_free_all(candidate->dnode);
+ candidate->dnode = NULL;
+ return NB_OK;
+ }
+
+ dnode = yang_dnode_get(candidate->dnode, xpath);
+ if (!dnode || (dnode->flags & LYD_DEFAULT)) {
+ if (operation == NB_OP_DELETE) {
+ snprintf(errmsg, errmsg_len, "Data missing");
+ return NB_ERR;
+ } else
+ return NB_OK;
+ }
+
+ /* if it's the first top-level node, update candidate */
+ if (candidate->dnode == dnode)
+ candidate->dnode = candidate->dnode->next;
+
+ lyd_free_tree(dnode);
+
+ return NB_OK;
+}
+
+int nb_candidate_edit_tree(struct nb_config *candidate,
+ enum nb_operation operation, LYD_FORMAT format,
+ const char *xpath, const char *data,
+ char *xpath_created, char *errmsg, size_t errmsg_len)
+{
+ int ret = NB_ERR;
+
+ switch (operation) {
+ case NB_OP_CREATE_EXCL:
+ case NB_OP_CREATE:
+ case NB_OP_MODIFY:
+ case NB_OP_REPLACE:
+ ret = nb_candidate_edit_tree_add(candidate, operation, format,
+ xpath, data, xpath_created,
+ errmsg, errmsg_len);
+ break;
+ case NB_OP_DESTROY:
+ case NB_OP_DELETE:
+ ret = nb_candidate_edit_tree_del(candidate, operation, xpath,
+ errmsg, errmsg_len);
+ break;
+ case NB_OP_MOVE:
+ /* not supported yet */
+ break;
+ }
+
+ return ret;
+}
+
const char *nb_operation_name(enum nb_operation operation)
{
switch (operation) {
@@ -2403,8 +2620,6 @@ const char *nb_client_name(enum nb_client client)
switch (client) {
case NB_CLIENT_CLI:
return "CLI";
- case NB_CLIENT_CONFD:
- return "ConfD";
case NB_CLIENT_SYSREPO:
return "Sysrepo";
case NB_CLIENT_GRPC:
diff --git a/lib/northbound.h b/lib/northbound.h
index 5be111cf0a..3bf1eacd61 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -621,11 +621,6 @@ struct nb_node {
/* Flags. */
uint8_t flags;
-
-#ifdef HAVE_CONFD
- /* ConfD hash value corresponding to this YANG path. */
- int confd_hash;
-#endif
};
/* The YANG container or list contains only config data. */
#define F_NB_NODE_CONFIG_ONLY 0x01
@@ -700,7 +695,6 @@ enum nb_error {
enum nb_client {
NB_CLIENT_NONE = 0,
NB_CLIENT_CLI,
- NB_CLIENT_CONFD,
NB_CLIENT_SYSREPO,
NB_CLIENT_GRPC,
NB_CLIENT_PCEP,
@@ -1005,6 +999,44 @@ extern int nb_candidate_edit(struct nb_config *candidate,
const struct yang_data *data);
/*
+ * Edit a candidate configuration. Value is given as JSON/XML.
+ *
+ * candidate
+ * Candidate configuration to edit.
+ *
+ * operation
+ * Operation to apply.
+ *
+ * format
+ * LYD_FORMAT of the value.
+ *
+ * xpath
+ * XPath of the configuration node being edited.
+ * For create, it must be the parent.
+ *
+ * data
+ * New data tree for the node.
+ *
+ * xpath_created
+ * XPath of the created node if operation is "create".
+ *
+ * errmsg
+ * Buffer to store human-readable error message in case of error.
+ *
+ * errmsg_len
+ * Size of errmsg.
+ *
+ * Returns:
+ * - NB_OK on success.
+ * - NB_ERR for other errors.
+ */
+extern int nb_candidate_edit_tree(struct nb_config *candidate,
+ enum nb_operation operation,
+ LYD_FORMAT format, const char *xpath,
+ const char *data, char *xpath_created,
+ char *errmsg, size_t errmsg_len);
+
+/*
* Create diff for configuration.
*
* dnode
diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c
deleted file mode 100644
index 8503d18002..0000000000
--- a/lib/northbound_confd.c
+++ /dev/null
@@ -1,1494 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 NetDEF, Inc.
- * Renato Westphal
- */
-
-#include <zebra.h>
-
-#include "log.h"
-#include "lib_errors.h"
-#include "command.h"
-#include "debug.h"
-#include "libfrr.h"
-#include "lib/version.h"
-#include "northbound.h"
-
-#include <confd_lib.h>
-#include <confd_cdb.h>
-#include <confd_dp.h>
-#include <confd_maapi.h>
-
-DEFINE_MTYPE_STATIC(LIB, CONFD, "ConfD module");
-
-static struct debug nb_dbg_client_confd = {0, "Northbound client: ConfD"};
-
-static struct event_loop *master;
-static struct sockaddr confd_addr;
-static int cdb_sub_sock, dp_ctl_sock, dp_worker_sock;
-static struct event *t_cdb_sub, *t_dp_ctl, *t_dp_worker;
-static struct confd_daemon_ctx *dctx;
-static struct confd_notification_ctx *live_ctx;
-static bool confd_connected;
-static struct list *confd_spoints;
-static struct nb_transaction *transaction;
-
-static void frr_confd_finish_cdb(void);
-static void frr_confd_finish_dp(void);
-static int frr_confd_finish(void);
-
-#define flog_err_confd(funcname) \
- flog_err(EC_LIB_LIBCONFD, "%s: %s() failed: %s (%d): %s", __func__, \
- (funcname), confd_strerror(confd_errno), confd_errno, \
- confd_lasterr())
-
-
-/* ------------ Utils ------------ */
-
-/* Get XPath string from ConfD hashed keypath. */
-static void frr_confd_get_xpath(const confd_hkeypath_t *kp, char *xpath,
- size_t len)
-{
- char *p;
-
- confd_xpath_pp_kpath(xpath, len, 0, kp);
-
- /*
- * Replace double quotes by single quotes (the format accepted by the
- * northbound API).
- */
- p = xpath;
- while ((p = strchr(p, '"')) != NULL)
- *p++ = '\'';
-}
-
-/* Convert ConfD binary value to a string. */
-static int frr_confd_val2str(const char *xpath, const confd_value_t *value,
- char *string, size_t string_size)
-{
- struct confd_cs_node *csp;
-
- csp = confd_cs_node_cd(NULL, xpath);
- if (!csp) {
- flog_err_confd("confd_cs_node_cd");
- return -1;
- }
- if (confd_val2str(csp->info.type, value, string, string_size)
- == CONFD_ERR) {
- flog_err_confd("confd_val2str");
- return -1;
- }
-
- return 0;
-}
-
-/* Obtain list entry from ConfD hashed keypath. */
-static int frr_confd_hkeypath_get_list_entry(const confd_hkeypath_t *kp,
- struct nb_node *nb_node,
- const void **list_entry)
-{
- struct nb_node *nb_node_list;
- int parent_lists = 0;
- int curr_list = 0;
-
- *list_entry = NULL;
-
- /*
- * Count the number of YANG lists in the path, disconsidering the
- * last element.
- */
- nb_node_list = nb_node;
- while (nb_node_list->parent_list) {
- nb_node_list = nb_node_list->parent_list;
- parent_lists++;
- }
- if (nb_node->snode->nodetype != LYS_LIST && parent_lists == 0)
- return 0;
-
- /* Start from the beginning and move down the tree. */
- for (int i = kp->len; i >= 0; i--) {
- struct yang_list_keys keys;
-
- /* Not a YANG list. */
- if (kp->v[i][0].type != C_BUF)
- continue;
-
- /* Obtain list keys. */
- memset(&keys, 0, sizeof(keys));
- for (int j = 0; kp->v[i][j].type != C_NOEXISTS; j++) {
- strlcpy(keys.key[keys.num],
- (char *)kp->v[i][j].val.buf.ptr,
- sizeof(keys.key[keys.num]));
- keys.num++;
- }
-
- /* Obtain northbound node associated to the YANG list. */
- nb_node_list = nb_node;
- for (int j = curr_list; j < parent_lists; j++)
- nb_node_list = nb_node_list->parent_list;
-
- /* Obtain list entry. */
- if (!CHECK_FLAG(nb_node_list->flags, F_NB_NODE_KEYLESS_LIST)) {
- *list_entry = nb_callback_lookup_entry(
- nb_node, *list_entry, &keys);
- if (*list_entry == NULL)
- return -1;
- } else {
- unsigned long ptr_ulong;
-
- /* Retrieve list entry from pseudo-key (string). */
- if (sscanf(keys.key[0], "%lu", &ptr_ulong) != 1)
- return -1;
- *list_entry = (const void *)ptr_ulong;
- }
-
- curr_list++;
- }
-
- return 0;
-}
-
-/* Fill the current date and time into a confd_datetime structure. */
-static void getdatetime(struct confd_datetime *datetime)
-{
- struct tm tm;
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- gmtime_r(&tv.tv_sec, &tm);
-
- memset(datetime, 0, sizeof(*datetime));
- datetime->year = 1900 + tm.tm_year;
- datetime->month = tm.tm_mon + 1;
- datetime->day = tm.tm_mday;
- datetime->sec = tm.tm_sec;
- datetime->micro = tv.tv_usec;
- datetime->timezone = 0;
- datetime->timezone_minutes = 0;
- datetime->hour = tm.tm_hour;
- datetime->min = tm.tm_min;
-}
-
-/* ------------ CDB code ------------ */
-
-struct cdb_iter_args {
- struct nb_config *candidate;
- bool error;
-};
-
-static enum cdb_iter_ret
-frr_confd_cdb_diff_iter(confd_hkeypath_t *kp, enum cdb_iter_op cdb_op,
- confd_value_t *oldv, confd_value_t *newv, void *args)
-{
- char xpath[XPATH_MAXLEN];
- struct nb_node *nb_node;
- enum nb_operation nb_op;
- struct cdb_iter_args *iter_args = args;
- char value_str[YANG_VALUE_MAXLEN];
- struct yang_data *data;
- char *sb1, *sb2;
- int ret;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- /*
- * HACK: obtain value of leaf-list elements from the XPath due to
- * a bug in the ConfD API.
- */
- value_str[0] = '\0';
- sb1 = strrchr(xpath, '[');
- sb2 = strrchr(xpath, ']');
- if (sb1 && sb2 && !strchr(sb1, '=')) {
- *sb2 = '\0';
- strlcpy(value_str, sb1 + 1, sizeof(value_str));
- *sb1 = '\0';
- }
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- /* Map operation values. */
- switch (cdb_op) {
- case MOP_CREATED:
- nb_op = NB_OP_CREATE;
- break;
- case MOP_DELETED:
- nb_op = NB_OP_DESTROY;
- break;
- case MOP_VALUE_SET:
- if (nb_is_operation_allowed(nb_node, NB_OP_MODIFY))
- nb_op = NB_OP_MODIFY;
- else
- /* Ignore list keys modifications. */
- return ITER_RECURSE;
- break;
- case MOP_MOVED_AFTER:
- nb_op = NB_OP_MOVE;
- break;
- case MOP_MODIFIED:
- /* We're not interested on this. */
- return ITER_RECURSE;
- default:
- flog_err(EC_LIB_DEVELOPMENT,
- "%s: unexpected operation %u [xpath %s]", __func__,
- cdb_op, xpath);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- /* Convert ConfD value to a string. */
- if (nb_node->snode->nodetype != LYS_LEAFLIST && newv
- && frr_confd_val2str(nb_node->xpath, newv, value_str,
- sizeof(value_str))
- != 0) {
- flog_err(EC_LIB_CONFD_DATA_CONVERT,
- "%s: failed to convert ConfD value to a string",
- __func__);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- /* Edit the candidate configuration. */
- data = yang_data_new(xpath, value_str);
- ret = nb_candidate_edit(iter_args->candidate, nb_node, nb_op, xpath,
- NULL, data);
- yang_data_free(data);
- if (ret != NB_OK) {
- flog_warn(
- EC_LIB_NB_CANDIDATE_EDIT_ERROR,
- "%s: failed to edit candidate configuration: operation [%s] xpath [%s]",
- __func__, nb_operation_name(nb_op), xpath);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- return ITER_RECURSE;
-}
-
-static void frr_confd_cdb_read_cb_prepare(int fd, int *subp, int reslen)
-{
- struct nb_context context = {};
- struct nb_config *candidate;
- struct cdb_iter_args iter_args;
- char errmsg[BUFSIZ] = {0};
- int ret;
-
- candidate = nb_config_dup(running_config);
-
- /* Iterate over all configuration changes. */
- iter_args.candidate = candidate;
- iter_args.error = false;
- for (int i = 0; i < reslen; i++) {
- if (cdb_diff_iterate(fd, subp[i], frr_confd_cdb_diff_iter,
- ITER_WANT_PREV, &iter_args)
- != CONFD_OK) {
- flog_err_confd("cdb_diff_iterate");
- }
- }
- free(subp);
-
- if (iter_args.error) {
- nb_config_free(candidate);
-
- if (cdb_sub_abort_trans(
- cdb_sub_sock, CONFD_ERRCODE_APPLICATION_INTERNAL, 0,
- 0, "Couldn't apply configuration changes")
- != CONFD_OK) {
- flog_err_confd("cdb_sub_abort_trans");
- return;
- }
- return;
- }
-
- /*
- * Validate the configuration changes and allocate all resources
- * required to apply them.
- */
- transaction = NULL;
- context.client = NB_CLIENT_CONFD;
- ret = nb_candidate_commit_prepare(context, candidate, NULL,
- &transaction, false, false, errmsg,
- sizeof(errmsg));
- if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) {
- enum confd_errcode errcode;
-
- switch (ret) {
- case NB_ERR_LOCKED:
- errcode = CONFD_ERRCODE_IN_USE;
- break;
- case NB_ERR_RESOURCE:
- errcode = CONFD_ERRCODE_RESOURCE_DENIED;
- break;
- default:
- errcode = CONFD_ERRCODE_APPLICATION;
- break;
- }
-
- /* Reject the configuration changes. */
- if (cdb_sub_abort_trans(cdb_sub_sock, errcode, 0, 0, "%s",
- errmsg)
- != CONFD_OK) {
- flog_err_confd("cdb_sub_abort_trans");
- return;
- }
- } else {
- /* Acknowledge the notification. */
- if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY)
- != CONFD_OK) {
- flog_err_confd("cdb_sync_subscription_socket");
- return;
- }
-
- /* No configuration changes. */
- if (!transaction)
- nb_config_free(candidate);
- }
-}
-
-static void frr_confd_cdb_read_cb_commit(int fd, int *subp, int reslen)
-{
- /*
- * No need to process the configuration changes again as we're already
- * keeping track of them in the "transaction" variable.
- */
- free(subp);
-
- /* Apply the transaction. */
- if (transaction) {
- struct nb_config *candidate = transaction->config;
- char errmsg[BUFSIZ] = {0};
-
- nb_candidate_commit_apply(transaction, true, NULL, errmsg,
- sizeof(errmsg));
- nb_config_free(candidate);
- }
-
- /* Acknowledge the notification. */
- if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY) != CONFD_OK) {
- flog_err_confd("cdb_sync_subscription_socket");
- return;
- }
-}
-
-static int frr_confd_cdb_read_cb_abort(int fd, int *subp, int reslen)
-{
- /*
- * No need to process the configuration changes again as we're already
- * keeping track of them in the "transaction" variable.
- */
- free(subp);
-
- /* Abort the transaction. */
- if (transaction) {
- struct nb_config *candidate = transaction->config;
- char errmsg[BUFSIZ] = {0};
-
- nb_candidate_commit_abort(transaction, errmsg, sizeof(errmsg));
- nb_config_free(candidate);
- }
-
- /* Acknowledge the notification. */
- if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY) != CONFD_OK) {
- flog_err_confd("cdb_sync_subscription_socket");
- return -1;
- }
-
- return 0;
-}
-
-static void frr_confd_cdb_read_cb(struct event *thread)
-{
- int fd = EVENT_FD(thread);
- enum cdb_sub_notification cdb_ev;
- int flags;
- int *subp = NULL;
- int reslen = 0;
-
- event_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &t_cdb_sub);
-
- if (cdb_read_subscription_socket2(fd, &cdb_ev, &flags, &subp, &reslen)
- != CONFD_OK) {
- flog_err_confd("cdb_read_subscription_socket2");
- return;
- }
-
- switch (cdb_ev) {
- case CDB_SUB_PREPARE:
- frr_confd_cdb_read_cb_prepare(fd, subp, reslen);
- break;
- case CDB_SUB_COMMIT:
- frr_confd_cdb_read_cb_commit(fd, subp, reslen);
- break;
- case CDB_SUB_ABORT:
- frr_confd_cdb_read_cb_abort(fd, subp, reslen);
- break;
- default:
- flog_err_confd("unknown CDB event");
- break;
- }
-}
-
-/* Trigger CDB subscriptions to read the startup configuration. */
-static void *thread_cdb_trigger_subscriptions(void *data)
-{
- int sock;
- int *sub_points = NULL, len = 0;
- struct listnode *node;
- int *spoint;
- int i = 0;
-
- /* Create CDB data socket. */
- sock = socket(PF_INET, SOCK_STREAM, 0);
- if (sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- return NULL;
- }
-
- if (cdb_connect(sock, CDB_DATA_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("cdb_connect");
- return NULL;
- }
-
- /*
- * Fill array containing the subscription point of all loaded YANG
- * modules.
- */
- len = listcount(confd_spoints);
- sub_points = XCALLOC(MTYPE_CONFD, len * sizeof(int));
- for (ALL_LIST_ELEMENTS_RO(confd_spoints, node, spoint))
- sub_points[i++] = *spoint;
-
- if (cdb_trigger_subscriptions(sock, sub_points, len) != CONFD_OK) {
- flog_err_confd("cdb_trigger_subscriptions");
- return NULL;
- }
-
- /* Cleanup and exit thread. */
- XFREE(MTYPE_CONFD, sub_points);
- cdb_close(sock);
-
- 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;
- pthread_t cdb_trigger_thread;
-
- /* Create CDB subscription socket. */
- cdb_sub_sock = socket(PF_INET, SOCK_STREAM, 0);
- if (cdb_sub_sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- return -1;
- }
-
- if (cdb_connect(cdb_sub_sock, CDB_SUBSCRIPTION_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("cdb_connect");
- goto error;
- }
-
- /* Subscribe to all loaded YANG data modules. */
- confd_spoints = list_new();
- RB_FOREACH (module, yang_modules, &yang_modules) {
- module->confd_hash = confd_str2hash(module->info->ns);
- if (module->confd_hash == 0) {
- flog_err(
- EC_LIB_LIBCONFD,
- "%s: failed to find hash value for namespace %s",
- __func__, module->info->ns);
- goto error;
- }
-
- /*
- * The CDB API doesn't provide a mechanism to subscribe to an
- * entire YANG module. So we have to find the top level
- * nodes ourselves and subscribe to their paths.
- */
- yang_snodes_iterate(module->info, frr_confd_subscribe, 0,
- module);
- }
-
- if (cdb_subscribe_done(cdb_sub_sock) != CONFD_OK) {
- flog_err_confd("cdb_subscribe_done");
- goto error;
- }
-
- /* Create short lived pthread to trigger the CDB subscriptions. */
- if (pthread_create(&cdb_trigger_thread, NULL,
- thread_cdb_trigger_subscriptions, NULL)) {
- flog_err(EC_LIB_SYSTEM_CALL, "%s: error creating pthread: %s",
- __func__, safe_strerror(errno));
- goto error;
- }
- pthread_detach(cdb_trigger_thread);
-
- event_add_read(master, frr_confd_cdb_read_cb, NULL, cdb_sub_sock,
- &t_cdb_sub);
-
- return 0;
-
-error:
- frr_confd_finish_cdb();
-
- return -1;
-}
-
-static void frr_confd_finish_cdb(void)
-{
- if (cdb_sub_sock > 0) {
- EVENT_OFF(t_cdb_sub);
- cdb_close(cdb_sub_sock);
- }
-}
-
-/* ------------ DP code ------------ */
-
-static int frr_confd_transaction_init(struct confd_trans_ctx *tctx)
-{
- confd_trans_set_fd(tctx, dp_worker_sock);
-
- return CONFD_OK;
-}
-
-#define CONFD_MAX_CHILD_NODES 32
-
-static int frr_confd_data_get_elem(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp)
-{
- struct nb_node *nb_node;
- char xpath[XPATH_MAXLEN];
- struct yang_data *data;
- confd_value_t v;
- const void *list_entry = NULL;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_not_found(tctx);
- return CONFD_OK;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &list_entry) != 0) {
- confd_data_reply_not_found(tctx);
- return CONFD_OK;
- }
-
- data = nb_callback_get_elem(nb_node, xpath, list_entry);
- if (data) {
- if (data->value) {
- CONFD_SET_STR(&v, data->value);
- confd_data_reply_value(tctx, &v);
- } else
- confd_data_reply_found(tctx);
- yang_data_free(data);
- } else
- confd_data_reply_not_found(tctx);
-
- return CONFD_OK;
-}
-
-static int frr_confd_data_get_next(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp, long next)
-{
- struct nb_node *nb_node;
- char xpath[XPATH_MAXLEN];
- struct yang_data *data;
- const void *parent_list_entry, *nb_next;
- confd_value_t v[LIST_MAXKEYS];
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &parent_list_entry)
- != 0) {
- /* List entry doesn't exist anymore. */
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- nb_next = nb_callback_get_next(nb_node, parent_list_entry,
- (next == -1) ? NULL : (void *)next);
- if (!nb_next) {
- /* End of the list or leaf-list. */
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- switch (nb_node->snode->nodetype) {
- case LYS_LIST:
- if (!CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) {
- struct yang_list_keys keys;
-
- memset(&keys, 0, sizeof(keys));
- if (nb_callback_get_keys(nb_node, nb_next, &keys)
- != NB_OK) {
- flog_warn(EC_LIB_NB_CB_STATE,
- "%s: failed to get list keys",
- __func__);
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- /* Feed keys to ConfD. */
- for (size_t i = 0; i < keys.num; i++)
- CONFD_SET_STR(&v[i], keys.key[i]);
- confd_data_reply_next_key(tctx, v, keys.num,
- (long)nb_next);
- } else {
- char pointer_str[32];
-
- /*
- * ConfD 6.6 user guide, chapter 6.11 (Operational data
- * lists without keys):
- * "To support this without having completely separate
- * APIs, we use a "pseudo" key in the ConfD APIs for
- * this type of list. This key is not part of the data
- * model, and completely hidden in the northbound agent
- * interfaces, but is used with e.g. the get_next() and
- * get_elem() callbacks as if it were a normal key. This
- * "pseudo" key is always a single signed 64-bit
- * integer, i.e. the confd_value_t type is C_INT64. The
- * values can be chosen arbitrarily by the application,
- * as long as a key value returned by get_next() can be
- * used to get the data for the corresponding list entry
- * with get_elem() or get_object() as usual. It could
- * e.g. be an index into an array that holds the data,
- * or even a memory address in integer form".
- *
- * Since we're using the CONFD_DAEMON_FLAG_STRINGSONLY
- * option, we must convert our pseudo-key (a void
- * pointer) to a string before sending it to confd.
- */
- snprintf(pointer_str, sizeof(pointer_str), "%lu",
- (unsigned long)nb_next);
- CONFD_SET_STR(&v[0], pointer_str);
- confd_data_reply_next_key(tctx, v, 1, (long)nb_next);
- }
- break;
- case LYS_LEAFLIST:
- data = nb_callback_get_elem(nb_node, xpath, nb_next);
- if (data) {
- if (data->value) {
- CONFD_SET_STR(&v[0], data->value);
- confd_data_reply_next_key(tctx, v, 1,
- (long)nb_next);
- }
- yang_data_free(data);
- } else
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- break;
- default:
- break;
- }
-
- return CONFD_OK;
-}
-
-/*
- * Optional callback - implemented for performance reasons.
- */
-static int frr_confd_data_get_object(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp)
-{
- struct nb_node *nb_node;
- const struct lysc_node *child;
- char xpath[XPATH_MAXLEN];
- char xpath_child[XPATH_MAXLEN * 2];
- struct list *elements;
- struct yang_data *data;
- const void *list_entry;
- confd_value_t values[CONFD_MAX_CHILD_NODES];
- size_t nvalues = 0;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_not_found(tctx);
- return CONFD_ERR;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &list_entry) != 0) {
- confd_data_reply_not_found(tctx);
- return CONFD_OK;
- }
-
- elements = yang_data_list_new();
-
- /* Loop through list child nodes. */
- LY_LIST_FOR (lysc_node_child(nb_node->snode), child) {
- struct nb_node *nb_node_child = child->priv;
- confd_value_t *v;
-
- if (nvalues > CONFD_MAX_CHILD_NODES)
- break;
-
- v = &values[nvalues++];
-
- /* Non-presence containers, lists and leaf-lists. */
- if (!nb_node_child->cbs.get_elem) {
- CONFD_SET_NOEXISTS(v);
- continue;
- }
-
- snprintf(xpath_child, sizeof(xpath_child), "%s/%s", xpath,
- child->name);
- data = nb_callback_get_elem(nb_node_child, xpath_child,
- list_entry);
- if (data) {
- if (data->value)
- CONFD_SET_STR(v, data->value);
- else {
- /* Presence containers and empty leafs. */
- CONFD_SET_XMLTAG(
- v, nb_node_child->confd_hash,
- confd_str2hash(nb_node_child->snode
- ->module->ns));
- }
- listnode_add(elements, data);
- } else
- CONFD_SET_NOEXISTS(v);
- }
-
- confd_data_reply_value_array(tctx, values, nvalues);
-
- /* Release memory. */
- list_delete(&elements);
-
- return CONFD_OK;
-}
-
-/*
- * Optional callback - implemented for performance reasons.
- */
-static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp, long next)
-{
- char xpath[XPATH_MAXLEN];
- struct nb_node *nb_node;
- struct list *elements;
- const void *parent_list_entry;
- 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][32];
- int nobjects = 0;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_next_object_array(tctx, NULL, 0, 0);
- return CONFD_OK;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &parent_list_entry)
- != 0) {
- confd_data_reply_next_object_array(tctx, NULL, 0, 0);
- return CONFD_OK;
- }
-
- elements = yang_data_list_new();
- nb_next = (next == -1) ? NULL : (void *)next;
-
- memset(objects, 0, sizeof(objects));
- for (int j = 0; j < CONFD_OBJECTS_PER_TIME; j++) {
- struct confd_next_object *object;
- const struct lysc_node *child;
- struct yang_data *data;
- size_t nvalues = 0;
-
- object = &objects[j];
-
- nb_next = nb_callback_get_next(nb_node, parent_list_entry,
- nb_next);
- if (!nb_next)
- /* End of the list. */
- break;
-
- object->next = (long)nb_next;
-
- /* Leaf-lists require special handling. */
- if (nb_node->snode->nodetype == LYS_LEAFLIST) {
- object->v = XMALLOC(MTYPE_CONFD, sizeof(confd_value_t));
- data = nb_callback_get_elem(nb_node, xpath, nb_next);
- assert(data && data->value);
- CONFD_SET_STR(object->v, data->value);
- nvalues++;
- listnode_add(elements, data);
- goto next;
- }
-
- object->v =
- XMALLOC(MTYPE_CONFD,
- CONFD_MAX_CHILD_NODES * sizeof(confd_value_t));
-
- /*
- * ConfD 6.6 user guide, chapter 6.11 (Operational data lists
- * without keys):
- * "In the response to the get_next_object() callback, the data
- * provider is expected to provide the key values along with the
- * other leafs in an array that is populated according to the
- * data model. This must be done also for this type of list,
- * even though the key isn't actually in the data model. The
- * "pseudo" key must always be the first element in the array".
- */
- if (CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) {
- confd_value_t *v;
-
- snprintf(pseudo_keys[j], sizeof(pseudo_keys[j]), "%lu",
- (unsigned long)nb_next);
-
- v = &object->v[nvalues++];
- CONFD_SET_STR(v, pseudo_keys[j]);
- }
-
- /* Loop through list child nodes. */
- LY_LIST_FOR (lysc_node_child(nb_node->snode), child) {
- struct nb_node *nb_node_child = child->priv;
- char xpath_child[XPATH_MAXLEN * 2];
- confd_value_t *v;
-
- if (nvalues > CONFD_MAX_CHILD_NODES)
- break;
-
- v = &object->v[nvalues++];
-
- /* Non-presence containers, lists and leaf-lists. */
- if (!nb_node_child->cbs.get_elem) {
- CONFD_SET_NOEXISTS(v);
- continue;
- }
-
- snprintf(xpath_child, sizeof(xpath_child), "%s/%s",
- xpath, child->name);
- data = nb_callback_get_elem(nb_node_child, xpath_child,
- nb_next);
- if (data) {
- if (data->value)
- CONFD_SET_STR(v, data->value);
- else {
- /*
- * Presence containers and empty leafs.
- */
- CONFD_SET_XMLTAG(
- v, nb_node_child->confd_hash,
- confd_str2hash(
- nb_node_child->snode
- ->module->ns));
- }
- listnode_add(elements, data);
- } else
- CONFD_SET_NOEXISTS(v);
- }
- next:
- object->n = nvalues;
- nobjects++;
- }
-
- if (nobjects == 0) {
- confd_data_reply_next_object_array(tctx, NULL, 0, 0);
- list_delete(&elements);
- return CONFD_OK;
- }
-
- /* Detect end of the list. */
- if (!nb_next) {
- nobjects++;
- objects[nobjects].v = NULL;
- }
-
- /* Reply to ConfD. */
- confd_data_reply_next_object_arrays(tctx, objects, nobjects, 0);
- if (!nb_next)
- nobjects--;
-
- /* Release memory. */
- list_delete(&elements);
- for (int j = 0; j < nobjects; j++) {
- struct confd_next_object *object;
-
- object = &objects[j];
- XFREE(MTYPE_CONFD, object->v);
- }
-
- return CONFD_OK;
-}
-
-static int frr_confd_notification_send(const char *xpath,
- struct list *arguments)
-{
- struct nb_node *nb_node;
- struct yang_module *module;
- struct confd_datetime now;
- confd_tag_value_t *values;
- int nvalues;
- int i = 0;
- struct yang_data *data;
- struct listnode *node;
- int ret;
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- return -1;
- }
- module = yang_module_find(nb_node->snode->module->name);
- assert(module);
-
- nvalues = 2;
- if (arguments)
- nvalues += listcount(arguments);
-
- values = XMALLOC(MTYPE_CONFD, nvalues * sizeof(*values));
-
- CONFD_SET_TAG_XMLBEGIN(&values[i++], nb_node->confd_hash,
- module->confd_hash);
- for (ALL_LIST_ELEMENTS_RO(arguments, node, data)) {
- struct nb_node *nb_node_arg;
-
- nb_node_arg = nb_node_find(data->xpath);
- if (!nb_node_arg) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__,
- data->xpath);
- XFREE(MTYPE_CONFD, values);
- return NB_ERR;
- }
-
- CONFD_SET_TAG_STR(&values[i++], nb_node_arg->confd_hash,
- data->value);
- }
- CONFD_SET_TAG_XMLEND(&values[i++], nb_node->confd_hash,
- module->confd_hash);
-
- getdatetime(&now);
- ret = confd_notification_send(live_ctx, &now, values, nvalues);
-
- /* Release memory. */
- XFREE(MTYPE_CONFD, values);
-
- /* Map ConfD return code to northbound return code. */
- switch (ret) {
- case CONFD_OK:
- return NB_OK;
- default:
- return NB_ERR;
- }
-}
-
-static int frr_confd_action_init(struct confd_user_info *uinfo)
-{
- confd_action_set_fd(uinfo, dp_worker_sock);
-
- return CONFD_OK;
-}
-
-static int frr_confd_action_execute(struct confd_user_info *uinfo,
- struct xml_tag *name, confd_hkeypath_t *kp,
- confd_tag_value_t *params, int nparams)
-{
- char xpath[XPATH_MAXLEN];
- struct nb_node *nb_node;
- struct list *input;
- struct list *output;
- struct yang_data *data;
- confd_tag_value_t *reply;
- int ret = CONFD_OK;
- char errmsg[BUFSIZ] = {0};
-
- /* Getting the XPath is tricky. */
- if (kp) {
- /* This is a YANG RPC. */
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
- strlcat(xpath, "/", sizeof(xpath));
- strlcat(xpath, confd_hash2str(name->tag), sizeof(xpath));
- } else {
- /* This is a YANG action. */
- snprintf(xpath, sizeof(xpath), "/%s:%s",
- confd_ns2prefix(name->ns), confd_hash2str(name->tag));
- }
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- return CONFD_ERR;
- }
-
- input = yang_data_list_new();
- output = yang_data_list_new();
-
- /* Process input nodes. */
- for (int i = 0; i < nparams; i++) {
- char xpath_input[XPATH_MAXLEN * 2];
- char value_str[YANG_VALUE_MAXLEN];
-
- snprintf(xpath_input, sizeof(xpath_input), "%s/%s", xpath,
- confd_hash2str(params[i].tag.tag));
-
- if (frr_confd_val2str(xpath_input, &params[i].v, value_str,
- sizeof(value_str))
- != 0) {
- flog_err(
- EC_LIB_CONFD_DATA_CONVERT,
- "%s: failed to convert ConfD value to a string",
- __func__);
- ret = CONFD_ERR;
- goto exit;
- }
-
- data = yang_data_new(xpath_input, value_str);
- listnode_add(input, data);
- }
-
- /* Execute callback registered for this XPath. */
- if (nb_callback_rpc(nb_node, xpath, input, output, errmsg,
- sizeof(errmsg))
- != NB_OK) {
- flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s",
- __func__, xpath);
- ret = CONFD_ERR;
- goto exit;
- }
-
- /* Process output nodes. */
- if (listcount(output) > 0) {
- struct listnode *node;
- int i = 0;
-
- reply = XMALLOC(MTYPE_CONFD,
- listcount(output) * sizeof(*reply));
-
- for (ALL_LIST_ELEMENTS_RO(output, node, data)) {
- struct nb_node *nb_node_output;
- int hash;
-
- nb_node_output = nb_node_find(data->xpath);
- if (!nb_node_output) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__,
- data->xpath);
- goto exit;
- }
-
- hash = confd_str2hash(nb_node_output->snode->name);
- CONFD_SET_TAG_STR(&reply[i++], hash, data->value);
- }
- confd_action_reply_values(uinfo, reply, listcount(output));
- XFREE(MTYPE_CONFD, reply);
- }
-
-exit:
- /* Release memory. */
- list_delete(&input);
- list_delete(&output);
-
- return ret;
-}
-
-
-static int frr_confd_dp_read(struct confd_daemon_ctx *dctx, int fd)
-{
- int ret;
-
- ret = confd_fd_ready(dctx, fd);
- if (ret == CONFD_EOF) {
- flog_err_confd("confd_fd_ready");
- frr_confd_finish();
- return -1;
- } else if (ret == CONFD_ERR && confd_errno != CONFD_ERR_EXTERNAL) {
- flog_err_confd("confd_fd_ready");
- frr_confd_finish();
- return -1;
- }
-
- return 0;
-}
-
-static void frr_confd_dp_ctl_read(struct event *thread)
-{
- struct confd_daemon_ctx *dctx = EVENT_ARG(thread);
- int fd = EVENT_FD(thread);
-
- event_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl);
-
- frr_confd_dp_read(dctx, fd);
-}
-
-static void frr_confd_dp_worker_read(struct event *thread)
-{
- struct confd_daemon_ctx *dctx = EVENT_ARG(thread);
- int fd = EVENT_FD(thread);
-
- event_add_read(master, frr_confd_dp_worker_read, dctx, fd,
- &t_dp_worker);
-
- frr_confd_dp_read(dctx, fd);
-}
-
-static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg)
-{
- struct nb_node *nb_node = snode->priv;
- struct confd_data_cbs *data_cbs = arg;
-
- if (!nb_node || !CHECK_FLAG(snode->flags, LYS_CONFIG_R))
- return YANG_ITER_CONTINUE;
- /* We only need to subscribe to the root of the state subtrees. */
- if (snode->parent && CHECK_FLAG(snode->parent->flags, LYS_CONFIG_R))
- return YANG_ITER_CONTINUE;
-
- DEBUGD(&nb_dbg_client_confd,
- "%s: providing data to '%s' (callpoint %s)", __func__,
- nb_node->xpath, snode->name);
-
- strlcpy(data_cbs->callpoint, snode->name, sizeof(data_cbs->callpoint));
- if (confd_register_data_cb(dctx, data_cbs) != CONFD_OK)
- flog_err_confd("confd_register_data_cb");
-
- return YANG_ITER_CONTINUE;
-}
-
-static int frr_confd_init_dp(const char *program_name)
-{
- struct confd_trans_cbs trans_cbs;
- struct confd_data_cbs data_cbs;
- struct confd_notification_stream_cbs ncbs;
- struct confd_action_cbs acbs;
-
- /* Initialize daemon context. */
- dctx = confd_init_daemon(program_name);
- if (!dctx) {
- flog_err_confd("confd_init_daemon");
- goto error;
- }
-
- /*
- * Inform we want to receive YANG values as raw strings, and that we
- * want to provide only strings in the reply functions, regardless of
- * the YANG type.
- */
- confd_set_daemon_flags(dctx, CONFD_DAEMON_FLAG_STRINGSONLY);
-
- /* Establish a control socket. */
- dp_ctl_sock = socket(PF_INET, SOCK_STREAM, 0);
- if (dp_ctl_sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- goto error;
- }
-
- if (confd_connect(dctx, dp_ctl_sock, CONTROL_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("confd_connect");
- goto error;
- }
-
- /*
- * Establish a worker socket (only one since this plugin runs on a
- * single thread).
- */
- dp_worker_sock = socket(PF_INET, SOCK_STREAM, 0);
- if (dp_worker_sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- goto error;
- }
- if (confd_connect(dctx, dp_worker_sock, WORKER_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("confd_connect");
- goto error;
- }
-
- /* Register transaction callback functions. */
- memset(&trans_cbs, 0, sizeof(trans_cbs));
- trans_cbs.init = frr_confd_transaction_init;
- confd_register_trans_cb(dctx, &trans_cbs);
-
- /* Register our read/write callbacks. */
- memset(&data_cbs, 0, sizeof(data_cbs));
- data_cbs.get_elem = frr_confd_data_get_elem;
- data_cbs.exists_optional = frr_confd_data_get_elem;
- data_cbs.get_next = frr_confd_data_get_next;
- data_cbs.get_object = frr_confd_data_get_object;
- data_cbs.get_next_object = frr_confd_data_get_next_object;
-
- /*
- * Iterate over all loaded YANG modules and subscribe to the paths
- * referent to state data.
- */
- yang_snodes_iterate(NULL, frr_confd_subscribe_state, 0, &data_cbs);
-
- /* Register notification stream. */
- memset(&ncbs, 0, sizeof(ncbs));
- ncbs.fd = dp_worker_sock;
- /*
- * RFC 5277 - Section 3.2.3:
- * A NETCONF server implementation supporting the notification
- * capability MUST support the "NETCONF" notification event
- * stream. This stream contains all NETCONF XML event notifications
- * supported by the NETCONF server.
- */
- strlcpy(ncbs.streamname, "NETCONF", sizeof(ncbs.streamname));
- if (confd_register_notification_stream(dctx, &ncbs, &live_ctx)
- != CONFD_OK) {
- flog_err_confd("confd_register_notification_stream");
- goto error;
- }
-
- /* Register the action handler callback. */
- memset(&acbs, 0, sizeof(acbs));
- strlcpy(acbs.actionpoint, "actionpoint", sizeof(acbs.actionpoint));
- acbs.init = frr_confd_action_init;
- acbs.action = frr_confd_action_execute;
- if (confd_register_action_cbs(dctx, &acbs) != CONFD_OK) {
- flog_err_confd("confd_register_action_cbs");
- goto error;
- }
-
- /* Notify we registered all callbacks we wanted. */
- if (confd_register_done(dctx) != CONFD_OK) {
- flog_err_confd("confd_register_done");
- goto error;
- }
-
- event_add_read(master, frr_confd_dp_ctl_read, dctx, dp_ctl_sock,
- &t_dp_ctl);
- event_add_read(master, frr_confd_dp_worker_read, dctx, dp_worker_sock,
- &t_dp_worker);
-
- return 0;
-
-error:
- frr_confd_finish_dp();
-
- return -1;
-}
-
-static void frr_confd_finish_dp(void)
-{
- if (dp_worker_sock > 0) {
- EVENT_OFF(t_dp_worker);
- close(dp_worker_sock);
- }
- if (dp_ctl_sock > 0) {
- EVENT_OFF(t_dp_ctl);
- close(dp_ctl_sock);
- }
- if (dctx != NULL)
- confd_release_daemon(dctx);
-}
-
-/* ------------ CLI ------------ */
-
-DEFUN (debug_nb_confd,
- debug_nb_confd_cmd,
- "[no] debug northbound client confd",
- NO_STR
- DEBUG_STR
- "Northbound debugging\n"
- "Client\n"
- "ConfD\n")
-{
- uint32_t mode = DEBUG_NODE2MODE(vty->node);
- bool no = strmatch(argv[0]->text, "no");
-
- DEBUG_MODE_SET(&nb_dbg_client_confd, mode, !no);
-
- return CMD_SUCCESS;
-}
-
-static int frr_confd_debug_config_write(struct vty *vty)
-{
- if (DEBUG_MODE_CHECK(&nb_dbg_client_confd, DEBUG_MODE_CONF))
- vty_out(vty, "debug northbound client confd\n");
-
- return 0;
-}
-
-static int frr_confd_debug_set_all(uint32_t flags, bool set)
-{
- DEBUG_FLAGS_SET(&nb_dbg_client_confd, flags, set);
-
- /* If all modes have been turned off, don't preserve options. */
- if (!DEBUG_MODE_CHECK(&nb_dbg_client_confd, DEBUG_MODE_ALL))
- DEBUG_CLEAR(&nb_dbg_client_confd);
-
- return 0;
-}
-
-static void frr_confd_cli_init(void)
-{
- hook_register(nb_client_debug_config_write,
- frr_confd_debug_config_write);
- hook_register(nb_client_debug_set_all, frr_confd_debug_set_all);
-
- install_element(ENABLE_NODE, &debug_nb_confd_cmd);
- install_element(CONFIG_NODE, &debug_nb_confd_cmd);
-}
-
-/* ------------ Main ------------ */
-
-static int frr_confd_calculate_snode_hash(const struct lysc_node *snode,
- void *arg)
-{
- struct nb_node *nb_node = snode->priv;
-
- if (nb_node)
- nb_node->confd_hash = confd_str2hash(snode->name);
-
- return YANG_ITER_CONTINUE;
-}
-
-static int frr_confd_init(const char *program_name)
-{
- struct sockaddr_in *confd_addr4 = (struct sockaddr_in *)&confd_addr;
- int debuglevel = CONFD_SILENT;
- int ret = -1;
-
- /* Initialize ConfD library. */
- confd_init(program_name, stderr, debuglevel);
-
- confd_addr4->sin_family = AF_INET;
- confd_addr4->sin_addr.s_addr = inet_addr("127.0.0.1");
- confd_addr4->sin_port = htons(CONFD_PORT);
- if (confd_load_schemas(&confd_addr, sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("confd_load_schemas");
- return -1;
- }
-
- ret = frr_confd_init_cdb();
- if (ret != 0)
- goto error;
-
- ret = frr_confd_init_dp(program_name);
- if (ret != 0) {
- frr_confd_finish_cdb();
- goto error;
- }
-
- yang_snodes_iterate(NULL, frr_confd_calculate_snode_hash, 0, NULL);
-
- hook_register(nb_notification_send, frr_confd_notification_send);
-
- confd_connected = true;
- return 0;
-
-error:
- confd_free_schemas();
-
- return ret;
-}
-
-static int frr_confd_finish(void)
-{
- if (!confd_connected)
- return 0;
-
- frr_confd_finish_cdb();
- frr_confd_finish_dp();
-
- confd_free_schemas();
-
- confd_connected = false;
-
- return 0;
-}
-
-static int frr_confd_module_late_init(struct event_loop *tm)
-{
- master = tm;
-
- if (frr_confd_init(frr_get_progname()) < 0) {
- flog_err(EC_LIB_CONFD_INIT,
- "failed to initialize the ConfD module");
- return -1;
- }
-
- hook_register(frr_fini, frr_confd_finish);
- frr_confd_cli_init();
-
- return 0;
-}
-
-static int frr_confd_module_init(void)
-{
- hook_register(frr_late_init, frr_confd_module_late_init);
-
- return 0;
-}
-
-FRR_MODULE_SETUP(.name = "frr_confd", .version = FRR_VERSION,
- .description = "FRR ConfD integration module",
- .init = frr_confd_module_init,
-);
diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c
index 2394b5e865..7e7190f5a4 100644
--- a/lib/northbound_oper.c
+++ b/lib/northbound_oper.c
@@ -342,38 +342,6 @@ static void nb_op_resume_data_tree(struct nb_op_yield_state *ys)
/* ======================= */
/**
- * __xpath_pop_node() - remove the last node from xpath string
- * @xpath: an xpath string
- *
- * Return: NB_OK or NB_ERR_NOT_FOUND if nothing left to pop.
- */
-static int __xpath_pop_node(char *xpath)
-{
- int len = strlen(xpath);
- bool abs = xpath[0] == '/';
- char *slash;
-
- /* "//" or "/" => NULL */
- if (abs && (len == 1 || (len == 2 && xpath[1] == '/')))
- return NB_ERR_NOT_FOUND;
-
- slash = (char *)frrstr_back_to_char(xpath, '/');
- /* "/foo/bar/" or "/foo/bar//" => "/foo " */
- if (slash && slash == &xpath[len - 1]) {
- xpath[--len] = 0;
- slash = (char *)frrstr_back_to_char(xpath, '/');
- if (slash && slash == &xpath[len - 1]) {
- xpath[--len] = 0;
- slash = (char *)frrstr_back_to_char(xpath, '/');
- }
- }
- if (!slash)
- return NB_ERR_NOT_FOUND;
- *slash = 0;
- return NB_OK;
-}
-
-/**
* nb_op_xpath_to_trunk() - generate a lyd_node tree (trunk) using an xpath.
* @xpath_in: xpath query string to build trunk from.
* @dnode: resulting tree (trunk)
@@ -398,7 +366,7 @@ static enum nb_error nb_op_xpath_to_trunk(const char *xpath_in,
if (err == LY_SUCCESS)
break;
- ret = __xpath_pop_node(xpath);
+ ret = yang_xpath_pop_node(xpath);
if (ret != NB_OK)
break;
}
diff --git a/lib/plist.c b/lib/plist.c
index 618d92b549..2cfaa7d81d 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1073,17 +1073,13 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
struct prefix_master *master;
int64_t seqnum = 0;
json_object *json = NULL;
- json_object *json_proto = NULL;
master = prefix_master_get(afi, 0);
if (master == NULL)
return CMD_WARNING;
- if (uj) {
+ if (uj)
json = json_object_new_object();
- json_proto = json_object_new_object();
- json_object_object_add(json, frr_protoname, json_proto);
- }
if (seq)
seqnum = (int64_t)atol(seq);
@@ -1096,8 +1092,8 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
"%% Can't find specified prefix-list\n");
return CMD_WARNING;
}
- vty_show_prefix_entry(vty, json_proto, afi, plist, master,
- dtype, seqnum);
+ vty_show_prefix_entry(vty, json, afi, plist, master, dtype,
+ seqnum);
} else {
if (dtype == detail_display || dtype == summary_display) {
if (master->recent && !uj)
@@ -1107,8 +1103,8 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
}
frr_each (plist, &master->str, plist)
- vty_show_prefix_entry(vty, json_proto, afi, plist,
- master, dtype, seqnum);
+ vty_show_prefix_entry(vty, json, afi, plist, master,
+ dtype, seqnum);
}
return vty_json(vty, json);
@@ -1227,7 +1223,7 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
#include "lib/plist_clippy.c"
-DEFPY (show_ip_prefix_list,
+DEFPY_NOSH (show_ip_prefix_list,
show_ip_prefix_list_cmd,
"show ip prefix-list [PREFIXLIST4_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
SHOW_STR
@@ -1239,6 +1235,7 @@ DEFPY (show_ip_prefix_list,
JSON_STR)
{
enum display_type dtype = normal_display;
+
if (dseq)
dtype = sequential_display;
@@ -1258,6 +1255,7 @@ DEFPY (show_ip_prefix_list_prefix,
"First matched prefix\n")
{
enum display_type dtype = normal_display;
+
if (dl)
dtype = longer_display;
else if (dfm)
@@ -1267,7 +1265,7 @@ DEFPY (show_ip_prefix_list_prefix,
dtype);
}
-DEFPY (show_ip_prefix_list_summary,
+DEFPY_NOSH (show_ip_prefix_list_summary,
show_ip_prefix_list_summary_cmd,
"show ip prefix-list summary [PREFIXLIST4_NAME$name] [json$uj]",
SHOW_STR
@@ -1281,7 +1279,7 @@ DEFPY (show_ip_prefix_list_summary,
summary_display, !!uj);
}
-DEFPY (show_ip_prefix_list_detail,
+DEFPY_NOSH (show_ip_prefix_list_detail,
show_ip_prefix_list_detail_cmd,
"show ip prefix-list detail [PREFIXLIST4_NAME$name] [json$uj]",
SHOW_STR
@@ -1307,7 +1305,7 @@ DEFPY (clear_ip_prefix_list,
return vty_clear_prefix_list(vty, AFI_IP, name, prefix_str);
}
-DEFPY (show_ipv6_prefix_list,
+DEFPY_NOSH(show_ipv6_prefix_list,
show_ipv6_prefix_list_cmd,
"show ipv6 prefix-list [PREFIXLIST6_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
SHOW_STR
@@ -1319,6 +1317,7 @@ DEFPY (show_ipv6_prefix_list,
JSON_STR)
{
enum display_type dtype = normal_display;
+
if (dseq)
dtype = sequential_display;
@@ -1338,6 +1337,7 @@ DEFPY (show_ipv6_prefix_list_prefix,
"First matched prefix\n")
{
enum display_type dtype = normal_display;
+
if (dl)
dtype = longer_display;
else if (dfm)
@@ -1347,7 +1347,7 @@ DEFPY (show_ipv6_prefix_list_prefix,
prefix_str, dtype);
}
-DEFPY (show_ipv6_prefix_list_summary,
+DEFPY_NOSH (show_ipv6_prefix_list_summary,
show_ipv6_prefix_list_summary_cmd,
"show ipv6 prefix-list summary [PREFIXLIST6_NAME$name] [json$uj]",
SHOW_STR
@@ -1361,7 +1361,7 @@ DEFPY (show_ipv6_prefix_list_summary,
summary_display, !!uj);
}
-DEFPY (show_ipv6_prefix_list_detail,
+DEFPY_NOSH (show_ipv6_prefix_list_detail,
show_ipv6_prefix_list_detail_cmd,
"show ipv6 prefix-list detail [PREFIXLIST6_NAME$name] [json$uj]",
SHOW_STR
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index 88b341cac0..a12a07c14f 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -1252,14 +1252,14 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
} else if (IS_SET_EXTCOMMUNITY_LB(action)) {
enum ecommunity_lb_type lb_type;
char str[VTY_BUFSIZ];
- uint16_t bandwidth;
+ uint32_t bandwidth;
lb_type = yang_dnode_get_enum(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type");
switch (lb_type) {
case EXPLICIT_BANDWIDTH:
- bandwidth = yang_dnode_get_uint16(
+ bandwidth = yang_dnode_get_uint32(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth");
snprintf(str, sizeof(str), "%d", bandwidth);
diff --git a/lib/srv6.c b/lib/srv6.c
index dceb6ab48b..a82103e423 100644
--- a/lib/srv6.c
+++ b/lib/srv6.c
@@ -94,9 +94,11 @@ const char *seg6local_context2str(char *str, size_t size,
snprintf(str, size, "table %u", ctx->table);
return str;
- case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
+ snprintfrr(str, size, "nh6 %pI6", &ctx->nh6);
+ return str;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
case ZEBRA_SEG6_LOCAL_ACTION_END_S:
case ZEBRA_SEG6_LOCAL_ACTION_END_AS:
diff --git a/lib/stream.c b/lib/stream.c
index c6de3aefa1..fa20ebdbe7 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -1241,9 +1241,7 @@ void stream_fifo_init(struct stream_fifo *fifo)
/* Add new stream to fifo. */
void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
{
-#if defined DEV_BUILD
size_t max, curmax;
-#endif
if (fifo->tail)
fifo->tail->next = s;
@@ -1252,15 +1250,11 @@ void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
fifo->tail = s;
fifo->tail->next = NULL;
-#if !defined DEV_BUILD
- atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
-#else
max = atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
curmax = atomic_load_explicit(&fifo->max_count, memory_order_relaxed);
if (max > curmax)
atomic_store_explicit(&fifo->max_count, max,
memory_order_relaxed);
-#endif
}
void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s)
diff --git a/lib/stream.h b/lib/stream.h
index 85eebb47be..61eaa46c95 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -105,9 +105,7 @@ struct stream_fifo {
/* number of streams in this fifo */
atomic_size_t count;
-#if defined DEV_BUILD
atomic_size_t max_count;
-#endif
struct stream *head;
struct stream *tail;
diff --git a/lib/subdir.am b/lib/subdir.am
index c621ad0658..221c0b1e1d 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -153,6 +153,7 @@ nodist_lib_libfrr_la_SOURCES = \
yang/frr-nexthop.yang.c \
yang/ietf/frr-deviations-ietf-key-chain.yang.c \
yang/ietf/ietf-routing-types.yang.c \
+ yang/ietf/ietf-netconf-acm.yang.c \
yang/ietf/ietf-key-chain.yang.c \
yang/ietf/ietf-interfaces.yang.c \
yang/ietf/ietf-bgp-types.yang.c \
@@ -410,18 +411,6 @@ lib_libfrrzmq_la_SOURCES = \
#end
#
-# Tail-f's ConfD support
-#
-if CONFD
-module_LTLIBRARIES += lib/confd.la
-endif
-
-lib_confd_la_CFLAGS = $(AM_CFLAGS) $(CONFD_CFLAGS)
-lib_confd_la_LDFLAGS = $(MODULE_LDFLAGS)
-lib_confd_la_LIBADD = lib/libfrr.la $(CONFD_LIBS)
-lib_confd_la_SOURCES = lib/northbound_confd.c
-
-#
# Sysrepo support
#
if SYSREPO
diff --git a/lib/vrf.c b/lib/vrf.c
index e907626bae..31632a80d5 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -636,7 +636,7 @@ int vrf_configure_backend(enum vrf_backend_type backend)
}
/* vrf CLI commands */
-DEFUN_NOSH(vrf_exit,
+DEFUN_YANG_NOSH (vrf_exit,
vrf_exit_cmd,
"exit-vrf",
"Exit current mode and down to previous mode\n")
diff --git a/lib/vty.c b/lib/vty.c
index 912c893556..d69b5eebd2 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -3826,6 +3826,23 @@ static int vty_mgmt_get_tree_result_notified(
return 0;
}
+static int vty_mgmt_edit_result_notified(struct mgmt_fe_client *client,
+ uintptr_t user_data,
+ uint64_t client_id, uint64_t session_id,
+ uintptr_t session_ctx, uint64_t req_id,
+ const char *xpath)
+{
+ struct vty *vty = (struct vty *)session_ctx;
+
+ debug_fe_client("EDIT request for client 0x%" PRIx64 " req-id %" PRIu64
+ " was successful, xpath: %s",
+ client_id, req_id, xpath);
+
+ vty_mgmt_resume_response(vty, CMD_SUCCESS);
+
+ return 0;
+}
+
static int vty_mgmt_error_notified(struct mgmt_fe_client *client,
uintptr_t user_data, uint64_t client_id,
uint64_t session_id, uintptr_t session_ctx,
@@ -3867,6 +3884,7 @@ static struct mgmt_fe_client_cbs mgmt_cbs = {
.commit_config_notify = vty_mgmt_commit_config_result_notified,
.get_data_notify = vty_mgmt_get_data_result_notified,
.get_tree_notify = vty_mgmt_get_tree_result_notified,
+ .edit_notify = vty_mgmt_edit_result_notified,
.error_notify = vty_mgmt_error_notified,
};
@@ -4122,6 +4140,28 @@ int vty_mgmt_send_get_data_req(struct vty *vty, uint8_t datastore,
return 0;
}
+int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
+ LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath,
+ const char *data)
+{
+ vty->mgmt_req_id++;
+
+ if (mgmt_fe_send_edit_req(mgmt_fe_client, vty->mgmt_session_id,
+ vty->mgmt_req_id, datastore, request_type,
+ flags, operation, xpath, data)) {
+ zlog_err("Failed to send EDIT to MGMTD session-id: %" PRIu64
+ " req-id %" PRIu64 ".",
+ vty->mgmt_session_id, vty->mgmt_req_id);
+ vty_out(vty, "Failed to send EDIT to MGMTD!\n");
+ return -1;
+ }
+
+ vty->mgmt_req_pending_cmd = "MESSAGE_EDIT_REQ";
+
+ return 0;
+}
+
/* Install vty's own commands like `who' command. */
void vty_init(struct event_loop *master_thread, bool do_command_logging)
{
diff --git a/lib/vty.h b/lib/vty.h
index a59ac7a652..0e0c92c336 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -419,6 +419,10 @@ extern int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
extern int vty_mgmt_send_get_data_req(struct vty *vty, uint8_t datastore,
LYD_FORMAT result_type, uint8_t flags,
uint8_t defaults, const char *xpath);
+extern int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
+ LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath,
+ const char *data);
extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
bool lock, bool scok);
extern void vty_mgmt_resume_response(struct vty *vty, int ret);
diff --git a/lib/yang.c b/lib/yang.c
index d71cb2f498..013a762842 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -12,6 +12,7 @@
#include "yang.h"
#include "yang_translator.h"
#include "northbound.h"
+#include "frrstr.h"
#include "lib/config_paths.h"
@@ -1122,6 +1123,32 @@ int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys)
return NB_OK;
}
+int yang_xpath_pop_node(char *xpath)
+{
+ int len = strlen(xpath);
+ bool abs = xpath[0] == '/';
+ char *slash;
+
+ /* "//" or "/" => NULL */
+ if (abs && (len == 1 || (len == 2 && xpath[1] == '/')))
+ return NB_ERR_NOT_FOUND;
+
+ slash = (char *)frrstr_back_to_char(xpath, '/');
+ /* "/foo/bar/" or "/foo/bar//" => "/foo " */
+ if (slash && slash == &xpath[len - 1]) {
+ xpath[--len] = 0;
+ slash = (char *)frrstr_back_to_char(xpath, '/');
+ if (slash && slash == &xpath[len - 1]) {
+ xpath[--len] = 0;
+ slash = (char *)frrstr_back_to_char(xpath, '/');
+ }
+ }
+ if (!slash)
+ return NB_ERR_NOT_FOUND;
+ *slash = 0;
+ return NB_OK;
+}
+
/*
* ------------------------
* Libyang Future Functions
@@ -1275,6 +1302,42 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath)
#endif
}
+/* Can be replaced by `lyd_parse_data` with libyang >= 2.1.156 */
+LY_ERR yang_lyd_parse_data(const struct ly_ctx *ctx, struct lyd_node *parent,
+ struct ly_in *in, LYD_FORMAT format,
+ uint32_t parse_options, uint32_t validate_options,
+ struct lyd_node **tree)
+{
+ struct lyd_node *child;
+ LY_ERR err;
+
+ err = lyd_parse_data(ctx, parent, in, format, parse_options,
+ validate_options, tree);
+ if (err)
+ return err;
+
+ if (!parent || !(parse_options & LYD_PARSE_ONLY))
+ return LY_SUCCESS;
+
+ /*
+ * Versions prior to 2.1.156 don't return `tree` if `parent` is not NULL
+ * and validation is disabled (`LYD_PARSE_ONLY`). To work around this,
+ * go through the children and find the one with `LYD_NEW` flag set.
+ */
+ *tree = NULL;
+
+ LY_LIST_FOR (lyd_child_no_keys(parent), child) {
+ if (child->flags & LYD_NEW) {
+ *tree = child;
+ break;
+ }
+ }
+
+ assert(tree);
+
+ return LY_SUCCESS;
+}
+
/*
* Safe to remove after libyang v2.1.128 is required
*/
diff --git a/lib/yang.h b/lib/yang.h
index 65f6a73e0b..25703b1879 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -45,9 +45,6 @@ struct yang_module {
RB_ENTRY(yang_module) entry;
const char *name;
const struct lys_module *info;
-#ifdef HAVE_CONFD
- int confd_hash;
-#endif
#ifdef HAVE_SYSREPO
sr_subscription_ctx_t *sr_subscription;
struct event *sr_thread;
@@ -771,6 +768,14 @@ extern int yang_get_key_preds(char *s, const struct lysc_node *snode,
extern int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys);
/**
+ * yang_xpath_pop_node() - remove the last node from xpath string
+ * @xpath: an xpath string
+ *
+ * Return: NB_OK or NB_ERR_NOT_FOUND if nothing left to pop.
+ */
+extern int yang_xpath_pop_node(char *xpath);
+
+/**
* yang_resolve_snodes() - Resolve an XPath to matching schema nodes.
* @ly_ctx: libyang context to operate on.
* @xpath: the path or XPath to resolve.
@@ -800,6 +805,11 @@ extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
const struct yang_list_keys *keys,
struct lyd_node **nodes);
extern LY_ERR yang_lyd_trim_xpath(struct lyd_node **rootp, const char *xpath);
+extern LY_ERR yang_lyd_parse_data(const struct ly_ctx *ctx,
+ struct lyd_node *parent, struct ly_in *in,
+ LYD_FORMAT format, uint32_t parse_options,
+ uint32_t validate_options,
+ struct lyd_node **tree);
#ifdef __cplusplus
}
diff --git a/lib/zclient.c b/lib/zclient.c
index 51ebb56275..4cf3934502 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -282,6 +282,7 @@ static void zclient_flush_data(struct event *thread)
zclient->sock, &zclient->t_write);
break;
case BUFFER_EMPTY:
+ /* Currently only Sharpd and Bgpd has callbacks defined */
if (zclient->zebra_buffer_write_ready)
(*zclient->zebra_buffer_write_ready)();
break;
@@ -1039,7 +1040,7 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
}
if (api_nh->weight)
- stream_putl(s, api_nh->weight);
+ stream_putq(s, api_nh->weight);
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_EVPN))
@@ -1411,7 +1412,7 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
}
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
- STREAM_GETL(s, api_nh->weight);
+ STREAM_GETQ(s, api_nh->weight);
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
@@ -4669,21 +4670,25 @@ char *zclient_dump_route_flags(uint32_t flags, char *buf, size_t len)
return buf;
}
- snprintfrr(
- buf, len, "%s%s%s%s%s%s%s%s%s%s",
- CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion "
- : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance "
- : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED) ? "Offload Failed "
- : "");
+ snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s",
+ CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion "
+ : "",
+
+ CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance "
+ : "",
+
+ CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED)
+ ? "Offload Failed "
+ : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_OUTOFSYNC) ? "OutOfSync " : "");
+
return buf;
}
diff --git a/lib/zclient.h b/lib/zclient.h
index 1bf91064e2..3759f94542 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -441,7 +441,7 @@ struct zapi_nexthop {
struct ethaddr rmac;
- uint32_t weight;
+ uint64_t weight;
/* Backup nexthops, for IP-FRR, TI-LFA, etc */
uint8_t backup_num;
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c
index 62d1a0109a..ab0da64d8f 100644
--- a/mgmtd/mgmt_fe_adapter.c
+++ b/mgmtd/mgmt_fe_adapter.c
@@ -898,11 +898,13 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
/*
* Create COMMITConfig request under the transaction
*/
- if (mgmt_txn_send_commit_config_req(
- session->cfg_txn_id, commcfg_req->req_id,
- commcfg_req->src_ds_id, src_ds_ctx, commcfg_req->dst_ds_id,
- dst_ds_ctx, commcfg_req->validate_only, commcfg_req->abort,
- false) != 0) {
+ if (mgmt_txn_send_commit_config_req(session->cfg_txn_id,
+ commcfg_req->req_id,
+ commcfg_req->src_ds_id, src_ds_ctx,
+ commcfg_req->dst_ds_id, dst_ds_ctx,
+ commcfg_req->validate_only,
+ commcfg_req->abort, false,
+ NULL) != 0) {
fe_adapter_send_commit_cfg_reply(
session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
@@ -1099,6 +1101,33 @@ done:
return ret;
}
+static int fe_adapter_send_edit_reply(struct mgmt_fe_session_ctx *session,
+ uint64_t req_id, const char *xpath)
+{
+ struct mgmt_msg_edit_reply *msg;
+ int ret;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_edit_reply, 0,
+ MTYPE_MSG_NATIVE_EDIT_REPLY);
+ msg->refer_id = session->session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_EDIT_REPLY;
+
+ mgmt_msg_native_xpath_encode(msg, xpath);
+
+ __dbg("Sending edit-reply from adapter %s to session-id %" PRIu64
+ " req-id %" PRIu64 " len %u",
+ session->adapter->name, session->session_id, req_id,
+ mgmt_msg_native_get_msg_len(msg));
+
+ ret = fe_adapter_send_native_msg(session->adapter, msg,
+ mgmt_msg_native_get_msg_len(msg),
+ false);
+ mgmt_msg_native_free_msg(msg);
+
+ return ret;
+}
+
/**
* fe_adapter_handle_get_data() - Handle a get-tree message from a FE client.
* @session: the client session.
@@ -1224,6 +1253,112 @@ done:
darr_free(xpath_resolved);
}
+static void fe_adapter_handle_edit(struct mgmt_fe_session_ctx *session,
+ void *__msg, size_t msg_len)
+{
+ struct mgmt_msg_edit *msg = __msg;
+ Mgmtd__DatastoreId ds_id, rds_id;
+ struct mgmt_ds_ctx *ds_ctx, *rds_ctx;
+ const char *xpath, *data;
+ bool lock, commit;
+ int ret;
+
+ if (msg->datastore != MGMT_MSG_DATASTORE_CANDIDATE) {
+ fe_adapter_send_error(session, msg->req_id, false, -EINVAL,
+ "Unsupported datastore");
+ return;
+ }
+
+ xpath = mgmt_msg_native_xpath_data_decode(msg, msg_len, data);
+ if (!xpath || !data) {
+ fe_adapter_send_error(session, msg->req_id, false, -EINVAL,
+ "Invalid message");
+ return;
+ }
+
+ ds_id = MGMTD_DS_CANDIDATE;
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, ds_id);
+ assert(ds_ctx);
+
+ rds_id = MGMTD_DS_RUNNING;
+ rds_ctx = mgmt_ds_get_ctx_by_id(mm, rds_id);
+ assert(rds_ctx);
+
+ lock = CHECK_FLAG(msg->flags, EDIT_FLAG_IMPLICIT_LOCK);
+ commit = CHECK_FLAG(msg->flags, EDIT_FLAG_IMPLICIT_COMMIT);
+
+ if (lock) {
+ if (mgmt_fe_session_write_lock_ds(ds_id, ds_ctx, session)) {
+ fe_adapter_send_error(session, msg->req_id, false,
+ -EBUSY,
+ "Candidate DS is locked by another session");
+ return;
+ }
+
+ if (commit) {
+ if (mgmt_fe_session_write_lock_ds(rds_id, rds_ctx,
+ session)) {
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx,
+ session);
+ fe_adapter_send_error(
+ session, msg->req_id, false, -EBUSY,
+ "Running DS is locked by another session");
+ return;
+ }
+ }
+ } else {
+ if (!session->ds_locked[ds_id]) {
+ fe_adapter_send_error(session, msg->req_id, false,
+ -EBUSY,
+ "Candidate DS is not locked");
+ return;
+ }
+
+ if (commit) {
+ if (!session->ds_locked[rds_id]) {
+ fe_adapter_send_error(session, msg->req_id,
+ false, -EBUSY,
+ "Running DS is not locked");
+ return;
+ }
+ }
+ }
+
+ session->cfg_txn_id = mgmt_create_txn(session->session_id,
+ MGMTD_TXN_TYPE_CONFIG);
+ if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) {
+ if (lock) {
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx, session);
+ if (commit)
+ mgmt_fe_session_unlock_ds(rds_id, rds_ctx,
+ session);
+ }
+ fe_adapter_send_error(session, msg->req_id, false, -EBUSY,
+ "Failed to create a configuration transaction");
+ return;
+ }
+
+ __dbg("Created new config txn-id: %" PRIu64 " for session-id: %" PRIu64,
+ session->cfg_txn_id, session->session_id);
+
+ ret = mgmt_txn_send_edit(session->cfg_txn_id, msg->req_id, ds_id,
+ ds_ctx, rds_id, rds_ctx, lock, commit,
+ msg->request_type, msg->flags, msg->operation,
+ xpath, data);
+ if (ret) {
+ /* destroy the just created txn */
+ mgmt_destroy_txn(&session->cfg_txn_id);
+ if (lock) {
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx, session);
+ if (commit)
+ mgmt_fe_session_unlock_ds(rds_id, rds_ctx,
+ session);
+ }
+ fe_adapter_send_error(session, msg->req_id, false, -EBUSY,
+ "Failed to create a configuration transaction");
+ }
+}
+
/**
* Handle a native encoded message from the FE client.
*/
@@ -1245,6 +1380,9 @@ static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter,
case MGMT_MSG_CODE_GET_DATA:
fe_adapter_handle_get_data(session, msg, msg_len);
break;
+ case MGMT_MSG_CODE_EDIT:
+ fe_adapter_handle_edit(session, msg, msg_len);
+ break;
default:
__log_err("unknown native message session-id %" PRIu64
" req-id %" PRIu64 " code %u to FE adapter %s",
@@ -1484,6 +1622,52 @@ int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
return ret;
}
+int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,
+ uint64_t req_id, bool unlock, bool commit,
+ const char *xpath, int16_t error,
+ const char *errstr)
+{
+ struct mgmt_fe_session_ctx *session;
+ Mgmtd__DatastoreId ds_id, rds_id;
+ struct mgmt_ds_ctx *ds_ctx, *rds_ctx;
+ int ret;
+
+ session = mgmt_session_id2ctx(session_id);
+ if (!session || session->cfg_txn_id != txn_id)
+ return -1;
+
+ if (session->cfg_txn_id != MGMTD_TXN_ID_NONE && commit)
+ mgmt_fe_session_register_event(session,
+ MGMTD_FE_SESSION_CFG_TXN_CLNUP);
+
+ if (unlock) {
+ ds_id = MGMTD_DS_CANDIDATE;
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, ds_id);
+ assert(ds_ctx);
+
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx, session);
+
+ if (commit) {
+ rds_id = MGMTD_DS_RUNNING;
+ rds_ctx = mgmt_ds_get_ctx_by_id(mm, rds_id);
+ assert(rds_ctx);
+
+ mgmt_fe_session_unlock_ds(rds_id, rds_ctx, session);
+ }
+ }
+
+ if (error)
+ ret = fe_adapter_send_error(session, req_id, false, error, "%s",
+ errstr);
+ else
+ ret = fe_adapter_send_edit_reply(session, req_id, xpath);
+
+ if (session->cfg_txn_id != MGMTD_TXN_ID_NONE && !commit)
+ mgmt_destroy_txn(&session->cfg_txn_id);
+
+ return ret;
+}
+
/**
* Send an error back to the FE client and cleanup any in-progress txn.
*/
diff --git a/mgmtd/mgmt_fe_adapter.h b/mgmtd/mgmt_fe_adapter.h
index e768a3cca0..8d61ffe910 100644
--- a/mgmtd/mgmt_fe_adapter.h
+++ b/mgmtd/mgmt_fe_adapter.h
@@ -163,6 +163,26 @@ mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
int partial_error, bool short_circuit_ok);
/**
+ * Send edit reply back to client. If error is not 0, a native error is sent.
+ *
+ * This also cleans up and frees the transaction.
+ *
+ * Args:
+ * session_id: the session.
+ * txn_id: the txn_id this data pertains to
+ * req_id: the req id for the edit message
+ * unlock: implicit-lock flag was set in the request
+ * commit: implicit-commit flag was set in the request
+ * xpath: the xpath of the data node that was created
+ * error: the error code, zero for successful request
+ * errstr: the error string, if error is non-zero
+ */
+extern int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,
+ uint64_t req_id, bool unlock,
+ bool commit, const char *xpath,
+ int16_t error, const char *errstr);
+
+/**
* Send an error back to the FE client using native messaging.
*
* This also cleans up and frees the transaction.
diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c
index a4e0fa2169..901163c6e6 100644
--- a/mgmtd/mgmt_txn.c
+++ b/mgmtd/mgmt_txn.c
@@ -30,7 +30,6 @@ enum mgmt_txn_event {
MGMTD_TXN_PROC_GETCFG,
MGMTD_TXN_PROC_GETTREE,
MGMTD_TXN_COMMITCFG_TIMEOUT,
- MGMTD_TXN_GETTREE_TIMEOUT,
};
PREDECL_LIST(mgmt_txn_reqs);
@@ -92,6 +91,11 @@ DECLARE_LIST(mgmt_txn_batches, struct mgmt_txn_be_cfg_batch, list_linkage);
#define FOREACH_TXN_CFG_BATCH_IN_LIST(list, batch) \
frr_each_safe (mgmt_txn_batches, list, batch)
+struct mgmt_edit_req {
+ char xpath_created[XPATH_MAXLEN];
+ bool unlock;
+};
+
struct mgmt_commit_cfg_req {
Mgmtd__DatastoreId src_ds_id;
struct mgmt_ds_ctx *src_ds_ctx;
@@ -110,6 +114,12 @@ struct mgmt_commit_cfg_req {
enum mgmt_commit_phase be_phase[MGMTD_BE_CLIENT_ID_MAX];
/*
+ * Additional information when the commit is triggered by native edit
+ * request.
+ */
+ struct mgmt_edit_req *edit;
+
+ /*
* Set of config changes to commit. This is used only
* when changes are NOT to be determined by comparing
* candidate and running DSs. This is typically used
@@ -407,7 +417,6 @@ static struct mgmt_txn_req *mgmt_txn_req_alloc(struct mgmt_txn_ctx *txn,
txn_req->req_id, txn->txn_id, txn->session_id);
break;
case MGMTD_TXN_COMMITCFG_TIMEOUT:
- case MGMTD_TXN_GETTREE_TIMEOUT:
break;
}
@@ -446,6 +455,8 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req)
cleanup = (ccreq->phase >= MGMTD_COMMIT_PHASE_TXN_CREATE &&
ccreq->phase < MGMTD_COMMIT_PHASE_TXN_DELETE);
+ XFREE(MTYPE_MGMTD_TXN_REQ, ccreq->edit);
+
FOREACH_MGMTD_BE_CLIENT_ID (id) {
/*
* Send TXN_DELETE to cleanup state for this
@@ -496,7 +507,6 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req)
XFREE(MTYPE_MGMTD_TXN_GETTREE_REQ, (*txn_req)->req.get_tree);
break;
case MGMTD_TXN_COMMITCFG_TIMEOUT:
- case MGMTD_TXN_GETTREE_TIMEOUT:
break;
}
@@ -607,7 +617,8 @@ static void mgmt_txn_process_set_cfg(struct event *thread)
->dst_ds_id,
txn_req->req.set_cfg
->dst_ds_ctx,
- false, false, true);
+ false, false, true,
+ NULL);
if (mm->perf_stats_en)
gettimeofday(&cmt_stats->last_start, NULL);
@@ -658,7 +669,8 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
* b/c right now that is special cased.. that special casing should be
* removed; however...
*/
- if (!txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
+ if (!txn->commit_cfg_req->req.commit_cfg.edit &&
+ !txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
!txn->commit_cfg_req->req.commit_cfg.rollback &&
mgmt_fe_send_commit_cfg_reply(txn->session_id, txn->txn_id,
txn->commit_cfg_req->req.commit_cfg
@@ -674,7 +686,8 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
txn->txn_id, txn->session_id);
}
- if (txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
+ if (!txn->commit_cfg_req->req.commit_cfg.edit &&
+ txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
!txn->commit_cfg_req->req.commit_cfg.rollback &&
mgmt_fe_send_set_cfg_reply(txn->session_id, txn->txn_id,
txn->commit_cfg_req->req.commit_cfg
@@ -688,6 +701,21 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
txn->txn_id, txn->session_id);
}
+ if (txn->commit_cfg_req->req.commit_cfg.edit &&
+ mgmt_fe_adapter_send_edit_reply(txn->session_id, txn->txn_id,
+ txn->commit_cfg_req->req_id,
+ txn->commit_cfg_req->req.commit_cfg
+ .edit->unlock,
+ true,
+ txn->commit_cfg_req->req.commit_cfg
+ .edit->xpath_created,
+ success ? 0 : -1,
+ error_if_any) != 0) {
+ __log_err("Failed to send EDIT-REPLY txn-id: %" PRIu64
+ " session-id: %" PRIu64,
+ txn->txn_id, txn->session_id);
+ }
+
if (success) {
/* Stop the commit-timeout timer */
/* XXX why only on success? */
@@ -1488,7 +1516,6 @@ static void mgmt_txn_send_getcfg_reply_data(struct mgmt_txn_req *txn_req,
case MGMTD_TXN_PROC_SETCFG:
case MGMTD_TXN_PROC_COMMITCFG:
case MGMTD_TXN_PROC_GETTREE:
- case MGMTD_TXN_GETTREE_TIMEOUT:
case MGMTD_TXN_COMMITCFG_TIMEOUT:
__log_err("Invalid Txn-Req-Event %u", txn_req->req_event);
break;
@@ -1862,11 +1889,6 @@ static void mgmt_txn_register_event(struct mgmt_txn_ctx *txn,
MGMTD_TXN_CFG_COMMIT_MAX_DELAY_SEC,
&txn->comm_cfg_timeout);
break;
- case MGMTD_TXN_GETTREE_TIMEOUT:
- event_add_timer(mgmt_txn_tm, txn_get_tree_timeout, txn,
- MGMTD_TXN_GET_TREE_MAX_DELAY_SEC,
- &txn->get_tree_timeout);
- break;
case MGMTD_TXN_PROC_GETTREE:
assert(!"code bug do not register this event");
break;
@@ -2020,7 +2042,7 @@ int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
Mgmtd__DatastoreId dst_ds_id,
struct mgmt_ds_ctx *dst_ds_ctx,
bool validate_only, bool abort,
- bool implicit)
+ bool implicit, struct mgmt_edit_req *edit)
{
struct mgmt_txn_ctx *txn;
struct mgmt_txn_req *txn_req;
@@ -2044,6 +2066,7 @@ int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
txn_req->req.commit_cfg.validate_only = validate_only;
txn_req->req.commit_cfg.abort = abort;
txn_req->req.commit_cfg.implicit = implicit;
+ txn_req->req.commit_cfg.edit = edit;
txn_req->req.commit_cfg.cmt_stats =
mgmt_fe_get_session_commit_stats(txn->session_id);
@@ -2427,6 +2450,52 @@ state:
return 0;
}
+int mgmt_txn_send_edit(uint64_t txn_id, uint64_t req_id,
+ Mgmtd__DatastoreId ds_id, struct mgmt_ds_ctx *ds_ctx,
+ Mgmtd__DatastoreId commit_ds_id,
+ struct mgmt_ds_ctx *commit_ds_ctx, bool unlock,
+ bool commit, LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath, const char *data)
+{
+ struct mgmt_txn_ctx *txn;
+ struct mgmt_edit_req *edit;
+ struct nb_config *nb_config;
+ char errstr[BUFSIZ];
+ int ret;
+
+ txn = mgmt_txn_id2ctx(txn_id);
+ if (!txn)
+ return -1;
+
+ edit = XCALLOC(MTYPE_MGMTD_TXN_REQ, sizeof(struct mgmt_edit_req));
+
+ nb_config = mgmt_ds_get_nb_config(ds_ctx);
+ assert(nb_config);
+
+ ret = nb_candidate_edit_tree(nb_config, operation, request_type, xpath,
+ data, edit->xpath_created, errstr,
+ sizeof(errstr));
+ if (ret)
+ goto reply;
+
+ if (commit) {
+ edit->unlock = unlock;
+
+ mgmt_txn_send_commit_config_req(txn_id, req_id, ds_id, ds_ctx,
+ commit_ds_id, commit_ds_ctx,
+ false, false, true, edit);
+ return 0;
+ }
+reply:
+ mgmt_fe_adapter_send_edit_reply(txn->session_id, txn->txn_id, req_id,
+ unlock, commit, edit->xpath_created,
+ ret ? -1 : 0, errstr);
+
+ XFREE(MTYPE_MGMTD_TXN_REQ, edit);
+
+ return 0;
+}
+
/*
* Error reply from the backend client.
*/
@@ -2475,7 +2544,6 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter,
case MGMTD_TXN_PROC_COMMITCFG:
case MGMTD_TXN_PROC_GETCFG:
case MGMTD_TXN_COMMITCFG_TIMEOUT:
- case MGMTD_TXN_GETTREE_TIMEOUT:
default:
assert(!"non-native req event in native erorr path");
return -1;
diff --git a/mgmtd/mgmt_txn.h b/mgmtd/mgmt_txn.h
index b7198326da..aeb74469f1 100644
--- a/mgmtd/mgmt_txn.h
+++ b/mgmtd/mgmt_txn.h
@@ -43,6 +43,7 @@
PREDECL_LIST(mgmt_txns);
struct mgmt_master;
+struct mgmt_edit_req;
enum mgmt_txn_type {
MGMTD_TXN_TYPE_NONE = 0,
@@ -171,16 +172,17 @@ extern int mgmt_txn_send_set_config_req(uint64_t txn_id, uint64_t req_id,
* implicit
* TRUE if the commit is implicit, FALSE otherwise.
*
+ * edit
+ * Additional info when triggered from native edit request.
+ *
* Returns:
* 0 on success, -1 on failures.
*/
-extern int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
- Mgmtd__DatastoreId src_ds_id,
- struct mgmt_ds_ctx *dst_ds_ctx,
- Mgmtd__DatastoreId dst_ds_id,
- struct mgmt_ds_ctx *src_ds_ctx,
- bool validate_only, bool abort,
- bool implicit);
+extern int mgmt_txn_send_commit_config_req(
+ uint64_t txn_id, uint64_t req_id, Mgmtd__DatastoreId src_ds_id,
+ struct mgmt_ds_ctx *dst_ds_ctx, Mgmtd__DatastoreId dst_ds_id,
+ struct mgmt_ds_ctx *src_ds_ctx, bool validate_only, bool abort,
+ bool implicit, struct mgmt_edit_req *edit);
/*
* Send get-{cfg,data} request to be processed later in transaction.
@@ -219,6 +221,31 @@ extern int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id,
uint32_t wd_options, bool simple_xpath,
const char *xpath);
+/**
+ * Send edit request.
+ *
+ * Args:
+ * txn_id: Transaction identifier.
+ * req_id: FE client request identifier.
+ * ds_id: Datastore ID.
+ * ds_ctx: Datastore context.
+ * commit_ds_id: Commit datastore ID.
+ * commit_ds_ctx: Commit datastore context.
+ * unlock: Unlock datastores after the edit.
+ * commit: Commit the candidate datastore after the edit.
+ * request_type: LYD_FORMAT request type.
+ * flags: option flags for the request.
+ * operation: The operation to perform.
+ * xpath: The xpath of data node to edit.
+ * data: The data tree.
+ */
+extern int
+mgmt_txn_send_edit(uint64_t txn_id, uint64_t req_id, Mgmtd__DatastoreId ds_id,
+ struct mgmt_ds_ctx *ds_ctx, Mgmtd__DatastoreId commit_ds_id,
+ struct mgmt_ds_ctx *commit_ds_ctx, bool unlock, bool commit,
+ LYD_FORMAT request_type, uint8_t flags, uint8_t operation,
+ const char *xpath, const char *data);
+
/*
* Notifiy backend adapter on connection.
*/
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
index 2cd24719bc..61d0760e05 100644
--- a/mgmtd/mgmt_vty.c
+++ b/mgmtd/mgmt_vty.c
@@ -238,6 +238,64 @@ DEFPY(mgmt_replace_config_data, mgmt_replace_config_data_cmd,
return CMD_SUCCESS;
}
+DEFPY(mgmt_edit, mgmt_edit_cmd,
+ "mgmt edit {create|delete|merge|replace|remove}$op XPATH [json|xml]$fmt [lock$lock] [commit$commit] [DATA]",
+ MGMTD_STR
+ "Edit configuration data\n"
+ "Create data\n"
+ "Delete data\n"
+ "Merge data\n"
+ "Replace data\n"
+ "Remove data\n"
+ "XPath expression specifying the YANG data path\n"
+ "JSON input format (default)\n"
+ "XML input format\n"
+ "Lock the datastores automatically\n"
+ "Commit the changes automatically\n"
+ "Data tree\n")
+{
+ LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON;
+ uint8_t operation;
+ uint8_t flags = 0;
+
+ switch (op[2]) {
+ case 'e':
+ operation = NB_OP_CREATE_EXCL;
+ break;
+ case 'l':
+ operation = NB_OP_DELETE;
+ break;
+ case 'r':
+ operation = NB_OP_MODIFY;
+ break;
+ case 'p':
+ operation = NB_OP_REPLACE;
+ break;
+ case 'm':
+ operation = NB_OP_DESTROY;
+ break;
+ default:
+ vty_out(vty, "Invalid operation!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (!data && (operation == NB_OP_CREATE_EXCL ||
+ operation == NB_OP_MODIFY || operation == NB_OP_REPLACE)) {
+ vty_out(vty, "Data tree is missing!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (lock)
+ flags |= EDIT_FLAG_IMPLICIT_LOCK;
+
+ if (commit)
+ flags |= EDIT_FLAG_IMPLICIT_COMMIT;
+
+ vty_mgmt_send_edit_req(vty, MGMT_MSG_DATASTORE_CANDIDATE, format, flags,
+ operation, xpath, data);
+ return CMD_SUCCESS;
+}
+
DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
"show mgmt get-config [candidate|operational|running]$dsname WORD$path",
SHOW_STR MGMTD_STR
@@ -643,6 +701,7 @@ void mgmt_vty_init(void)
install_element(CONFIG_NODE, &mgmt_delete_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_remove_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_replace_config_data_cmd);
+ install_element(CONFIG_NODE, &mgmt_edit_cmd);
install_element(CONFIG_NODE, &mgmt_load_config_cmd);
install_element(CONFIG_NODE, &mgmt_save_config_cmd);
install_element(CONFIG_NODE, &mgmt_rollback_cmd);
diff --git a/mgmtd/subdir.am b/mgmtd/subdir.am
index 1624c6e4f9..5182c4a47d 100644
--- a/mgmtd/subdir.am
+++ b/mgmtd/subdir.am
@@ -61,7 +61,6 @@ mgmtd_mgmtd_SOURCES = \
nodist_mgmtd_mgmtd_SOURCES = \
yang/frr-zebra.yang.c \
yang/frr-zebra-route-map.yang.c \
- yang/ietf/ietf-netconf-acm.yang.c \
yang/ietf/ietf-netconf.yang.c \
yang/ietf/ietf-netconf-with-defaults.yang.c \
# nothing
diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c
index acd3b7df97..f779f93486 100644
--- a/nhrpd/nhrp_nhs.c
+++ b/nhrpd/nhrp_nhs.c
@@ -169,9 +169,15 @@ static void nhrp_reg_send_req(struct event *t)
struct nhrp_cie_header *cie;
if (!nhrp_peer_check(r->peer, 2)) {
- debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %pSU",
- &r->peer->vc->remote.nbma);
- event_add_timer(master, nhrp_reg_send_req, r, 120,
+ int renewtime = if_ad->holdtime / 4;
+ /* RFC 2332 5.2.0.1 says "a retry is sent after an appropriate
+ * interval." Using holdtime/4, to be shorter than
+ * recommended renew time (holdtime/3), see RFC2332 Sec 5.2.3
+ */
+ debugf(NHRP_DEBUG_COMMON,
+ "NHS: Waiting link for %pSU, retrying in %d seconds",
+ &r->peer->vc->remote.nbma, renewtime);
+ event_add_timer(master, nhrp_reg_send_req, r, renewtime,
&r->t_register);
return;
}
diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c
index be1042f260..229e0a4db8 100644
--- a/ospf6d/ospf6_gr_helper.c
+++ b/ospf6d/ospf6_gr_helper.c
@@ -938,15 +938,6 @@ static void show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6,
? "Enabled"
: "Disabled");
-#if CONFDATE > 20240401
- CPP_NOTICE("Remove deprecated json key: restartSupoort")
-#endif
- json_object_string_add(
- json, "restartSupoort",
- (ospf6->ospf6_helper_cfg.only_planned_restart)
- ? "Planned Restart only"
- : "Planned and Unplanned Restarts");
-
json_object_string_add(
json, "restartSupport",
(ospf6->ospf6_helper_cfg.only_planned_restart)
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index b9dace2fe8..a4f4e8fcab 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -1395,10 +1395,17 @@ static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
}
/* show interface */
-DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd,
+DEFUN(show_ipv6_ospf6_interface,
+ show_ipv6_ospf6_interface_ifname_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]",
- SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
- "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR)
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ VRF_CMD_HELP_STR
+ "All VRFs\n"
+ INTERFACE_STR
+ IFNAME_STR
+ JSON_STR)
{
int idx_ifname = 4;
int intf_idx = 5;
@@ -1598,11 +1605,18 @@ static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
}
/* show interface */
-DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd,
+DEFUN(show_ipv6_ospf6_interface_traffic,
+ show_ipv6_ospf6_interface_traffic_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]",
- SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
- "All VRFs\n" INTERFACE_STR
- "Protocol Packet counters\n" IFNAME_STR JSON_STR)
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ VRF_CMD_HELP_STR
+ "All VRFs\n"
+ INTERFACE_STR
+ "Protocol Packet counters\n"
+ IFNAME_STR
+ JSON_STR)
{
struct ospf6 *ospf6;
struct listnode *node;
@@ -1631,17 +1645,21 @@ DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd,
DEFUN(show_ipv6_ospf6_interface_ifname_prefix,
show_ipv6_ospf6_interface_ifname_prefix_cmd,
- "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\
- [<\
- detail\
- |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
- >] [json]",
- SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
- "All VRFs\n" INTERFACE_STR IFNAME_STR
+ "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix "
+ "[<detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]>] [json]",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ VRF_CMD_HELP_STR
+ "All VRFs\n"
+ INTERFACE_STR IFNAME_STR
"Display connected prefixes to advertise\n"
- "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
- OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
- "Display details of the prefixes\n" JSON_STR)
+ "Display details of the prefixes\n"
+ OSPF6_ROUTE_ADDRESS_STR
+ OSPF6_ROUTE_PREFIX_STR
+ OSPF6_ROUTE_MATCH_STR
+ "Display details of the prefixes\n"
+ JSON_STR)
{
int idx_ifname = 4;
int idx_prefix = 6;
@@ -1693,17 +1711,23 @@ DEFUN(show_ipv6_ospf6_interface_ifname_prefix,
return CMD_SUCCESS;
}
-DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd,
- "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\
- [<\
- detail\
- |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
- >] [json]",
- SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
- "All VRFs\n" INTERFACE_STR "Display connected prefixes to advertise\n"
- "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
- OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
- "Display details of the prefixes\n" JSON_STR)
+DEFUN(show_ipv6_ospf6_interface_prefix,
+ show_ipv6_ospf6_interface_prefix_cmd,
+ "show ipv6 ospf6 [vrf <NAME|all>] interface prefix "
+ "[<detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]>] [json]",
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ VRF_CMD_HELP_STR
+ "All VRFs\n"
+ INTERFACE_STR
+ "Display connected prefixes to advertise\n"
+ "Display details of the prefixes\n"
+ OSPF6_ROUTE_ADDRESS_STR
+ OSPF6_ROUTE_PREFIX_STR
+ OSPF6_ROUTE_MATCH_STR
+ "Display details of the prefixes\n"
+ JSON_STR)
{
struct vrf *vrf = NULL;
int idx_prefix = 5;
@@ -1802,11 +1826,14 @@ void ospf6_interface_stop(struct ospf6_interface *oi)
}
/* interface variable set command */
-DEFUN(ipv6_ospf6_area, ipv6_ospf6_area_cmd,
- "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
- IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- "OSPF6 area ID in decimal notation\n")
+DEFUN (ipv6_ospf6_area,
+ ipv6_ospf6_area_cmd,
+ "ipv6 ospf6 area <A.B.C.D|(0-4294967295)>",
+ IP6_STR
+ OSPF6_STR
+ "Specify the OSPF6 area ID\n"
+ "OSPF6 area ID in IPv4 address notation\n"
+ "OSPF6 area ID in decimal notation\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -1840,11 +1867,15 @@ DEFUN(ipv6_ospf6_area, ipv6_ospf6_area_cmd,
return CMD_SUCCESS;
}
-DEFUN(no_ipv6_ospf6_area, no_ipv6_ospf6_area_cmd,
- "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
- NO_STR IP6_STR OSPF6_STR "Specify the OSPF6 area ID\n"
- "OSPF6 area ID in IPv4 address notation\n"
- "OSPF6 area ID in decimal notation\n")
+DEFUN (no_ipv6_ospf6_area,
+ no_ipv6_ospf6_area_cmd,
+ "no ipv6 ospf6 area [<A.B.C.D|(0-4294967295)>]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Specify the OSPF6 area ID\n"
+ "OSPF6 area ID in IPv4 address notation\n"
+ "OSPF6 area ID in decimal notation\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -1864,9 +1895,14 @@ DEFUN(no_ipv6_ospf6_area, no_ipv6_ospf6_area_cmd,
return CMD_SUCCESS;
}
-DEFUN(ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)",
- IP6_STR OSPF6_STR "Interface MTU\n"
- "OSPFv3 Interface MTU\n")
+DEFUN (ipv6_ospf6_ifmtu,
+ ipv6_ospf6_ifmtu_cmd,
+ "ipv6 ospf6 ifmtu (1-65535)",
+ IP6_STR
+ OSPF6_STR
+ "Interface MTU\n"
+ "OSPFv3 Interface MTU\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -1915,10 +1951,15 @@ DEFUN(ipv6_ospf6_ifmtu, ipv6_ospf6_ifmtu_cmd, "ipv6 ospf6 ifmtu (1-65535)",
return CMD_SUCCESS;
}
-DEFUN(no_ipv6_ospf6_ifmtu, no_ipv6_ospf6_ifmtu_cmd,
- "no ipv6 ospf6 ifmtu [(1-65535)]",
- NO_STR IP6_STR OSPF6_STR "Interface MTU\n"
- "OSPFv3 Interface MTU\n")
+DEFUN (no_ipv6_ospf6_ifmtu,
+ no_ipv6_ospf6_ifmtu_cmd,
+ "no ipv6 ospf6 ifmtu [(1-65535)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Interface MTU\n"
+ "OSPFv3 Interface MTU\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -1956,9 +1997,13 @@ DEFUN(no_ipv6_ospf6_ifmtu, no_ipv6_ospf6_ifmtu_cmd,
return CMD_SUCCESS;
}
-DEFUN(ipv6_ospf6_cost, ipv6_ospf6_cost_cmd, "ipv6 ospf6 cost (1-65535)",
- IP6_STR OSPF6_STR "Interface cost\n"
- "Outgoing metric of this interface\n")
+DEFUN (ipv6_ospf6_cost,
+ ipv6_ospf6_cost_cmd,
+ "ipv6 ospf6 cost (1-65535)",
+ IP6_STR
+ OSPF6_STR
+ "Interface cost\n"
+ "Outgoing metric of this interface\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -1989,10 +2034,14 @@ DEFUN(ipv6_ospf6_cost, ipv6_ospf6_cost_cmd, "ipv6 ospf6 cost (1-65535)",
return CMD_SUCCESS;
}
-DEFUN(no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd,
- "no ipv6 ospf6 cost [(1-65535)]",
- NO_STR IP6_STR OSPF6_STR "Calculate interface cost from bandwidth\n"
- "Outgoing metric of this interface\n")
+DEFUN (no_ipv6_ospf6_cost,
+ no_ipv6_ospf6_cost_cmd,
+ "no ipv6 ospf6 cost [(1-65535)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Calculate interface cost from bandwidth\n"
+ "Outgoing metric of this interface\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2010,11 +2059,12 @@ DEFUN(no_ipv6_ospf6_cost, no_ipv6_ospf6_cost_cmd,
return CMD_SUCCESS;
}
-DEFUN(auto_cost_reference_bandwidth, auto_cost_reference_bandwidth_cmd,
- "auto-cost reference-bandwidth (1-4294967)",
- "Calculate OSPF interface cost according to bandwidth\n"
- "Use reference bandwidth method to assign OSPF cost\n"
- "The reference bandwidth in terms of Mbits per second\n")
+DEFUN (auto_cost_reference_bandwidth,
+ auto_cost_reference_bandwidth_cmd,
+ "auto-cost reference-bandwidth (1-4294967)",
+ "Calculate OSPF interface cost according to bandwidth\n"
+ "Use reference bandwidth method to assign OSPF cost\n"
+ "The reference bandwidth in terms of Mbits per second\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
int idx_number = 2;
@@ -2041,11 +2091,13 @@ DEFUN(auto_cost_reference_bandwidth, auto_cost_reference_bandwidth_cmd,
return CMD_SUCCESS;
}
-DEFUN(no_auto_cost_reference_bandwidth, no_auto_cost_reference_bandwidth_cmd,
- "no auto-cost reference-bandwidth [(1-4294967)]",
- NO_STR "Calculate OSPF interface cost according to bandwidth\n"
- "Use reference bandwidth method to assign OSPF cost\n"
- "The reference bandwidth in terms of Mbits per second\n")
+DEFUN (no_auto_cost_reference_bandwidth,
+ no_auto_cost_reference_bandwidth_cmd,
+ "no auto-cost reference-bandwidth [(1-4294967)]",
+ NO_STR
+ "Calculate OSPF interface cost according to bandwidth\n"
+ "Use reference bandwidth method to assign OSPF cost\n"
+ "The reference bandwidth in terms of Mbits per second\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
struct ospf6_area *oa;
@@ -2064,10 +2116,11 @@ DEFUN(no_auto_cost_reference_bandwidth, no_auto_cost_reference_bandwidth_cmd,
}
-DEFUN(ospf6_write_multiplier, ospf6_write_multiplier_cmd,
- "write-multiplier (1-100)",
- "Write multiplier\n"
- "Maximum number of interface serviced per write\n")
+DEFUN (ospf6_write_multiplier,
+ ospf6_write_multiplier_cmd,
+ "write-multiplier (1-100)",
+ "Write multiplier\n"
+ "Maximum number of interface serviced per write\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
uint32_t write_oi_count;
@@ -2082,10 +2135,12 @@ DEFUN(ospf6_write_multiplier, ospf6_write_multiplier_cmd,
return CMD_SUCCESS;
}
-DEFUN(no_ospf6_write_multiplier, no_ospf6_write_multiplier_cmd,
- "no write-multiplier (1-100)",
- NO_STR "Write multiplier\n"
- "Maximum number of interface serviced per write\n")
+DEFUN (no_ospf6_write_multiplier,
+ no_ospf6_write_multiplier_cmd,
+ "no write-multiplier (1-100)",
+ NO_STR
+ "Write multiplier\n"
+ "Maximum number of interface serviced per write\n")
{
VTY_DECLVAR_CONTEXT(ospf6, o);
@@ -2093,9 +2148,13 @@ DEFUN(no_ospf6_write_multiplier, no_ospf6_write_multiplier_cmd,
return CMD_SUCCESS;
}
-DEFUN(ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd,
- "ipv6 ospf6 hello-interval (1-65535)",
- IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR)
+DEFUN (ipv6_ospf6_hellointerval,
+ ipv6_ospf6_hellointerval_cmd,
+ "ipv6 ospf6 hello-interval (1-65535)",
+ IP6_STR
+ OSPF6_STR
+ "Time between HELLO packets\n"
+ SECONDS_STR)
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -2123,15 +2182,23 @@ DEFUN(ipv6_ospf6_hellointerval, ipv6_ospf6_hellointerval_cmd,
return CMD_SUCCESS;
}
-ALIAS(ipv6_ospf6_hellointerval, no_ipv6_ospf6_hellointerval_cmd,
- "no ipv6 ospf6 hello-interval [(1-65535)]",
- NO_STR IP6_STR OSPF6_STR "Time between HELLO packets\n" SECONDS_STR)
+ALIAS (ipv6_ospf6_hellointerval,
+ no_ipv6_ospf6_hellointerval_cmd,
+ "no ipv6 ospf6 hello-interval [(1-65535)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Time between HELLO packets\n"
+ SECONDS_STR)
/* interface variable set command */
-DEFUN(ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd,
- "ipv6 ospf6 dead-interval (1-65535)",
- IP6_STR OSPF6_STR
- "Interval time after which a neighbor is declared down\n" SECONDS_STR)
+DEFUN (ipv6_ospf6_deadinterval,
+ ipv6_ospf6_deadinterval_cmd,
+ "ipv6 ospf6 dead-interval (1-65535)",
+ IP6_STR
+ OSPF6_STR
+ "Interval time after which a neighbor is declared down\n"
+ SECONDS_STR)
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -2149,16 +2216,23 @@ DEFUN(ipv6_ospf6_deadinterval, ipv6_ospf6_deadinterval_cmd,
return CMD_SUCCESS;
}
-ALIAS(ipv6_ospf6_deadinterval, no_ipv6_ospf6_deadinterval_cmd,
- "no ipv6 ospf6 dead-interval [(1-65535)]",
- NO_STR IP6_STR OSPF6_STR
- "Interval time after which a neighbor is declared down\n" SECONDS_STR)
+ALIAS (ipv6_ospf6_deadinterval,
+ no_ipv6_ospf6_deadinterval_cmd,
+ "no ipv6 ospf6 dead-interval [(1-65535)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Interval time after which a neighbor is declared down\n"
+ SECONDS_STR)
-DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd,
+DEFPY(ipv6_ospf6_gr_hdelay,
+ ipv6_ospf6_gr_hdelay_cmd,
"ipv6 ospf6 graceful-restart hello-delay (1-1800)",
- IP6_STR OSPF6_STR "Graceful Restart parameters\n"
- "Delay the sending of the first hello packets.\n"
- "Delay in seconds\n")
+ IP6_STR
+ OSPF6_STR
+ "Graceful Restart parameters\n"
+ "Delay the sending of the first hello packets.\n"
+ "Delay in seconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2173,11 +2247,15 @@ DEFPY(ipv6_ospf6_gr_hdelay, ipv6_ospf6_gr_hdelay_cmd,
return CMD_SUCCESS;
}
-DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd,
+DEFPY(no_ipv6_ospf6_gr_hdelay,
+ no_ipv6_ospf6_gr_hdelay_cmd,
"no ipv6 ospf6 graceful-restart hello-delay [(1-1800)]",
- NO_STR IP6_STR OSPF6_STR "Graceful Restart parameters\n"
- "Delay the sending of the first hello packets.\n"
- "Delay in seconds\n")
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Graceful Restart parameters\n"
+ "Delay the sending of the first hello packets.\n"
+ "Delay in seconds\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2194,9 +2272,13 @@ DEFPY(no_ipv6_ospf6_gr_hdelay, no_ipv6_ospf6_gr_hdelay_cmd,
}
/* interface variable set command */
-DEFUN(ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd,
- "ipv6 ospf6 transmit-delay (1-3600)",
- IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR)
+DEFUN (ipv6_ospf6_transmitdelay,
+ ipv6_ospf6_transmitdelay_cmd,
+ "ipv6 ospf6 transmit-delay (1-3600)",
+ IP6_STR
+ OSPF6_STR
+ "Link state transmit delay\n"
+ SECONDS_STR)
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -2214,15 +2296,23 @@ DEFUN(ipv6_ospf6_transmitdelay, ipv6_ospf6_transmitdelay_cmd,
return CMD_SUCCESS;
}
-ALIAS(ipv6_ospf6_transmitdelay, no_ipv6_ospf6_transmitdelay_cmd,
- "no ipv6 ospf6 transmit-delay [(1-3600)]",
- NO_STR IP6_STR OSPF6_STR "Link state transmit delay\n" SECONDS_STR)
+ALIAS (ipv6_ospf6_transmitdelay,
+ no_ipv6_ospf6_transmitdelay_cmd,
+ "no ipv6 ospf6 transmit-delay [(1-3600)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Link state transmit delay\n"
+ SECONDS_STR)
/* interface variable set command */
-DEFUN(ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd,
- "ipv6 ospf6 retransmit-interval (1-65535)",
- IP6_STR OSPF6_STR
- "Time between retransmitting lost link state advertisements\n" SECONDS_STR)
+DEFUN (ipv6_ospf6_retransmitinterval,
+ ipv6_ospf6_retransmitinterval_cmd,
+ "ipv6 ospf6 retransmit-interval (1-65535)",
+ IP6_STR
+ OSPF6_STR
+ "Time between retransmitting lost link state advertisements\n"
+ SECONDS_STR)
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -2240,16 +2330,23 @@ DEFUN(ipv6_ospf6_retransmitinterval, ipv6_ospf6_retransmitinterval_cmd,
return CMD_SUCCESS;
}
-ALIAS(ipv6_ospf6_retransmitinterval, no_ipv6_ospf6_retransmitinterval_cmd,
- "no ipv6 ospf6 retransmit-interval [(1-65535)]",
- NO_STR IP6_STR OSPF6_STR
- "Time between retransmitting lost link state advertisements\n" SECONDS_STR)
+ALIAS (ipv6_ospf6_retransmitinterval,
+ no_ipv6_ospf6_retransmitinterval_cmd,
+ "no ipv6 ospf6 retransmit-interval [(1-65535)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Time between retransmitting lost link state advertisements\n"
+ SECONDS_STR)
/* interface variable set command */
-DEFUN(ipv6_ospf6_priority, ipv6_ospf6_priority_cmd,
- "ipv6 ospf6 priority (0-255)",
- IP6_STR OSPF6_STR "Router priority\n"
- "Priority value\n")
+DEFUN (ipv6_ospf6_priority,
+ ipv6_ospf6_priority_cmd,
+ "ipv6 ospf6 priority (0-255)",
+ IP6_STR
+ OSPF6_STR
+ "Router priority\n"
+ "Priority value\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -2275,15 +2372,22 @@ DEFUN(ipv6_ospf6_priority, ipv6_ospf6_priority_cmd,
return CMD_SUCCESS;
}
-ALIAS(ipv6_ospf6_priority, no_ipv6_ospf6_priority_cmd,
- "no ipv6 ospf6 priority [(0-255)]",
- NO_STR IP6_STR OSPF6_STR "Router priority\n"
- "Priority value\n")
+ALIAS (ipv6_ospf6_priority,
+ no_ipv6_ospf6_priority_cmd,
+ "no ipv6 ospf6 priority [(0-255)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Router priority\n"
+ "Priority value\n")
-DEFUN(ipv6_ospf6_instance, ipv6_ospf6_instance_cmd,
- "ipv6 ospf6 instance-id (0-255)",
- IP6_STR OSPF6_STR "Instance ID for this interface\n"
- "Instance ID value\n")
+DEFUN (ipv6_ospf6_instance,
+ ipv6_ospf6_instance_cmd,
+ "ipv6 ospf6 instance-id (0-255)",
+ IP6_STR
+ OSPF6_STR
+ "Instance ID for this interface\n"
+ "Instance ID value\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_number = 3;
@@ -2301,14 +2405,22 @@ DEFUN(ipv6_ospf6_instance, ipv6_ospf6_instance_cmd,
return CMD_SUCCESS;
}
-ALIAS(ipv6_ospf6_instance, no_ipv6_ospf6_instance_cmd,
- "no ipv6 ospf6 instance-id [(0-255)]",
- NO_STR IP6_STR OSPF6_STR "Instance ID for this interface\n"
- "Instance ID value\n")
+ALIAS (ipv6_ospf6_instance,
+ no_ipv6_ospf6_instance_cmd,
+ "no ipv6 ospf6 instance-id [(0-255)]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Instance ID for this interface\n"
+ "Instance ID value\n")
-DEFUN(ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive",
- IP6_STR OSPF6_STR
- "Passive interface; no adjacency will be formed on this interface\n")
+DEFUN (ipv6_ospf6_passive,
+ ipv6_ospf6_passive_cmd,
+ "ipv6 ospf6 passive",
+ IP6_STR
+ OSPF6_STR
+ "Passive interface; no adjacency will be formed on this interface\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2334,9 +2446,14 @@ DEFUN(ipv6_ospf6_passive, ipv6_ospf6_passive_cmd, "ipv6 ospf6 passive",
return CMD_SUCCESS;
}
-DEFUN(no_ipv6_ospf6_passive, no_ipv6_ospf6_passive_cmd, "no ipv6 ospf6 passive",
- NO_STR IP6_STR OSPF6_STR
- "passive interface: No Adjacency will be formed on this I/F\n")
+DEFUN (no_ipv6_ospf6_passive,
+ no_ipv6_ospf6_passive_cmd,
+ "no ipv6 ospf6 passive",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "passive interface: No Adjacency will be formed on this I/F\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2359,8 +2476,13 @@ DEFUN(no_ipv6_ospf6_passive, no_ipv6_ospf6_passive_cmd, "no ipv6 ospf6 passive",
return CMD_SUCCESS;
}
-DEFUN(ipv6_ospf6_mtu_ignore, ipv6_ospf6_mtu_ignore_cmd, "ipv6 ospf6 mtu-ignore",
- IP6_STR OSPF6_STR "Disable MTU mismatch detection on this interface\n")
+DEFUN (ipv6_ospf6_mtu_ignore,
+ ipv6_ospf6_mtu_ignore_cmd,
+ "ipv6 ospf6 mtu-ignore",
+ IP6_STR
+ OSPF6_STR
+ "Disable MTU mismatch detection on this interface\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2376,10 +2498,14 @@ DEFUN(ipv6_ospf6_mtu_ignore, ipv6_ospf6_mtu_ignore_cmd, "ipv6 ospf6 mtu-ignore",
return CMD_SUCCESS;
}
-DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd,
- "no ipv6 ospf6 mtu-ignore",
- NO_STR IP6_STR OSPF6_STR
- "Disable MTU mismatch detection on this interface\n")
+DEFUN (no_ipv6_ospf6_mtu_ignore,
+ no_ipv6_ospf6_mtu_ignore_cmd,
+ "no ipv6 ospf6 mtu-ignore",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Disable MTU mismatch detection on this interface\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2395,11 +2521,14 @@ DEFUN(no_ipv6_ospf6_mtu_ignore, no_ipv6_ospf6_mtu_ignore_cmd,
return CMD_SUCCESS;
}
-DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd,
+DEFUN(ipv6_ospf6_advertise_prefix_list,
+ ipv6_ospf6_advertise_prefix_list_cmd,
"ipv6 ospf6 advertise prefix-list PREFIXLIST6_NAME",
- IP6_STR OSPF6_STR "Advertising options\n"
- "Filter prefix using prefix-list\n"
- "Prefix list name\n")
+ IP6_STR
+ OSPF6_STR
+ "Advertising options\n"
+ "Filter prefix using prefix-list\n"
+ "Prefix list name\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_word = 4;
@@ -2432,9 +2561,12 @@ DEFUN(ipv6_ospf6_advertise_prefix_list, ipv6_ospf6_advertise_prefix_list_cmd,
DEFUN(no_ipv6_ospf6_advertise_prefix_list,
no_ipv6_ospf6_advertise_prefix_list_cmd,
"no ipv6 ospf6 advertise prefix-list [PREFIXLIST6_NAME]",
- NO_STR IP6_STR OSPF6_STR "Advertising options\n"
- "Filter prefix using prefix-list\n"
- "Prefix list name\n")
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Advertising options\n"
+ "Filter prefix using prefix-list\n"
+ "Prefix list name\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2462,12 +2594,16 @@ DEFUN(no_ipv6_ospf6_advertise_prefix_list,
return CMD_SUCCESS;
}
-DEFUN(ipv6_ospf6_network, ipv6_ospf6_network_cmd,
- "ipv6 ospf6 network <broadcast|point-to-point|point-to-multipoint>",
- IP6_STR OSPF6_STR "Network type\n"
- "Specify OSPF6 broadcast network\n"
- "Specify OSPF6 point-to-point network\n"
- "Specify OSPF6 point-to-multipoint network\n")
+DEFUN (ipv6_ospf6_network,
+ ipv6_ospf6_network_cmd,
+ "ipv6 ospf6 network <broadcast|point-to-point|point-to-multipoint>",
+ IP6_STR
+ OSPF6_STR
+ "Network type\n"
+ "Specify OSPF6 broadcast network\n"
+ "Specify OSPF6 point-to-point network\n"
+ "Specify OSPF6 point-to-multipoint network\n"
+ )
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int idx_network = 3;
@@ -2506,11 +2642,15 @@ DEFUN(ipv6_ospf6_network, ipv6_ospf6_network_cmd,
return CMD_SUCCESS;
}
-DEFUN(no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd,
- "no ipv6 ospf6 network [<broadcast|point-to-point>]",
- NO_STR IP6_STR OSPF6_STR "Set default network type\n"
- "Specify OSPF6 broadcast network\n"
- "Specify OSPF6 point-to-point network\n")
+DEFUN (no_ipv6_ospf6_network,
+ no_ipv6_ospf6_network_cmd,
+ "no ipv6 ospf6 network [<broadcast|point-to-point>]",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Set default network type\n"
+ "Specify OSPF6 broadcast network\n"
+ "Specify OSPF6 point-to-point network\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -2537,11 +2677,14 @@ DEFUN(no_ipv6_ospf6_network, no_ipv6_ospf6_network_cmd,
return CMD_SUCCESS;
}
-DEFPY(ipv6_ospf6_p2xp_only_cfg_neigh, ipv6_ospf6_p2xp_only_cfg_neigh_cmd,
- "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only",
- NO_STR IP6_STR OSPF6_STR
- "Point-to-point and Point-to-Multipoint parameters\n"
- "Only form adjacencies with explicitly configured neighbors\n")
+DEFPY (ipv6_ospf6_p2xp_only_cfg_neigh,
+ ipv6_ospf6_p2xp_only_cfg_neigh_cmd,
+ "[no] ipv6 ospf6 p2p-p2mp config-neighbors-only",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Point-to-point and Point-to-Multipoint parameters\n"
+ "Only form adjacencies with explicitly configured neighbors\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi = ifp->info;
@@ -2561,11 +2704,14 @@ DEFPY(ipv6_ospf6_p2xp_only_cfg_neigh, ipv6_ospf6_p2xp_only_cfg_neigh_cmd,
return CMD_SUCCESS;
}
-DEFPY(ipv6_ospf6_p2xp_no_multicast_hello, ipv6_ospf6_p2xp_no_multicast_hello_cmd,
- "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello",
- NO_STR IP6_STR OSPF6_STR
- "Point-to-point and Point-to-Multipoint parameters\n"
- "Do not send multicast hellos\n")
+DEFPY (ipv6_ospf6_p2xp_no_multicast_hello,
+ ipv6_ospf6_p2xp_no_multicast_hello_cmd,
+ "[no] ipv6 ospf6 p2p-p2mp disable-multicast-hello",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Point-to-point and Point-to-Multipoint parameters\n"
+ "Do not send multicast hellos\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi = ifp->info;
@@ -2585,13 +2731,16 @@ DEFPY(ipv6_ospf6_p2xp_no_multicast_hello, ipv6_ospf6_p2xp_no_multicast_hello_cmd
return CMD_SUCCESS;
}
-DEFPY(ipv6_ospf6_p2xp_connected_pfx, ipv6_ospf6_p2xp_connected_pfx_cmd,
- "[no] ipv6 ospf6 p2p-p2mp connected-prefixes <include$incl|exclude$excl>",
- NO_STR IP6_STR OSPF6_STR
- "Point-to-point and Point-to-Multipoint parameters\n"
- "Adjust handling of directly connected prefixes\n"
- "Advertise prefixes and own /128 (default for PtP)\n"
- "Ignore, only advertise own /128 (default for PtMP)\n")
+DEFPY (ipv6_ospf6_p2xp_connected_pfx,
+ ipv6_ospf6_p2xp_connected_pfx_cmd,
+ "[no] ipv6 ospf6 p2p-p2mp connected-prefixes <include$incl|exclude$excl>",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Point-to-point and Point-to-Multipoint parameters\n"
+ "Adjust handling of directly connected prefixes\n"
+ "Advertise prefixes and own /128 (default for PtP)\n"
+ "Ignore, only advertise own /128 (default for PtMP)\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi = ifp->info;
@@ -2619,11 +2768,14 @@ DEFPY(ipv6_ospf6_p2xp_connected_pfx, ipv6_ospf6_p2xp_connected_pfx_cmd,
return CMD_SUCCESS;
}
-ALIAS(ipv6_ospf6_p2xp_connected_pfx, no_ipv6_ospf6_p2xp_connected_pfx_cmd,
- "no ipv6 ospf6 p2p-p2mp connected-prefixes",
- NO_STR IP6_STR OSPF6_STR
- "Point-to-point and Point-to-Multipoint parameters\n"
- "Adjust handling of directly connected prefixes\n")
+ALIAS (ipv6_ospf6_p2xp_connected_pfx,
+ no_ipv6_ospf6_p2xp_connected_pfx_cmd,
+ "no ipv6 ospf6 p2p-p2mp connected-prefixes",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Point-to-point and Point-to-Multipoint parameters\n"
+ "Adjust handling of directly connected prefixes\n")
static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
@@ -2873,9 +3025,16 @@ void ospf6_interface_clear(struct interface *ifp)
}
/* Clear interface */
-DEFUN(clear_ipv6_ospf6_interface, clear_ipv6_ospf6_interface_cmd,
- "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]",
- CLEAR_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR INTERFACE_STR IFNAME_STR)
+DEFUN (clear_ipv6_ospf6_interface,
+ clear_ipv6_ospf6_interface_cmd,
+ "clear ipv6 ospf6 [vrf NAME] interface [IFNAME]",
+ CLEAR_STR
+ IP6_STR
+ OSPF6_STR
+ VRF_CMD_HELP_STR
+ INTERFACE_STR
+ IFNAME_STR
+ )
{
struct vrf *vrf;
int idx_vrf = 3;
@@ -2916,16 +3075,26 @@ void install_element_ospf6_clear_interface(void)
install_element(ENABLE_NODE, &clear_ipv6_ospf6_interface_cmd);
}
-DEFUN(debug_ospf6_interface, debug_ospf6_interface_cmd, "debug ospf6 interface",
- DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n")
+DEFUN (debug_ospf6_interface,
+ debug_ospf6_interface_cmd,
+ "debug ospf6 interface",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Interface\n"
+ )
{
OSPF6_DEBUG_INTERFACE_ON();
return CMD_SUCCESS;
}
-DEFUN(no_debug_ospf6_interface, no_debug_ospf6_interface_cmd,
- "no debug ospf6 interface",
- NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Interface\n")
+DEFUN (no_debug_ospf6_interface,
+ no_debug_ospf6_interface_cmd,
+ "no debug ospf6 interface",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Interface\n"
+ )
{
OSPF6_DEBUG_INTERFACE_OFF();
return CMD_SUCCESS;
@@ -2962,9 +3131,11 @@ void ospf6_auth_write_config(struct vty *vty, struct ospf6_auth_data *at_data)
DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,
ipv6_ospf6_intf_auth_trailer_keychain_cmd,
"ipv6 ospf6 authentication keychain KEYCHAIN_NAME",
- IP6_STR OSPF6_STR "Enable authentication on this interface\n"
- "Keychain\n"
- "Keychain name\n")
+ IP6_STR
+ OSPF6_STR
+ "Enable authentication on this interface\n"
+ "Keychain\n"
+ "Keychain name\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int keychain_idx = 4;
@@ -2994,9 +3165,12 @@ DEFUN(ipv6_ospf6_intf_auth_trailer_keychain,
DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,
no_ipv6_ospf6_intf_auth_trailer_keychain_cmd,
"no ipv6 ospf6 authentication keychain [KEYCHAIN_NAME]",
- NO_STR IP6_STR OSPF6_STR "Enable authentication on this interface\n"
- "Keychain\n"
- "Keychain name\n")
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Enable authentication on this interface\n"
+ "Keychain\n"
+ "Keychain name\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
@@ -3018,21 +3192,24 @@ DEFUN(no_ipv6_ospf6_intf_auth_trailer_keychain,
return CMD_SUCCESS;
}
-DEFUN(ipv6_ospf6_intf_auth_trailer_key, ipv6_ospf6_intf_auth_trailer_key_cmd,
+DEFUN(ipv6_ospf6_intf_auth_trailer_key,
+ ipv6_ospf6_intf_auth_trailer_key_cmd,
"ipv6 ospf6 authentication key-id (1-65535) hash-algo "
"<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
"key WORD",
- IP6_STR OSPF6_STR "Authentication\n"
- "Key ID\n"
- "Key ID value\n"
- "Cryptographic-algorithm\n"
- "Use MD5 algorithm\n"
- "Use HMAC-SHA-1 algorithm\n"
- "Use HMAC-SHA-256 algorithm\n"
- "Use HMAC-SHA-384 algorithm\n"
- "Use HMAC-SHA-512 algorithm\n"
- "Password\n"
- "Password string (key)\n")
+ IP6_STR
+ OSPF6_STR
+ "Authentication\n"
+ "Key ID\n"
+ "Key ID value\n"
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n"
+ "Password\n"
+ "Password string (key)\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
int key_id_idx = 4;
@@ -3077,17 +3254,20 @@ DEFUN(no_ipv6_ospf6_intf_auth_trailer_key,
"no ipv6 ospf6 authentication key-id [(1-65535) hash-algo "
"<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512> "
"key WORD]",
- NO_STR IP6_STR OSPF6_STR "Authentication\n"
- "Key ID\n"
- "Key ID value\n"
- "Cryptographic-algorithm\n"
- "Use MD5 algorithm\n"
- "Use HMAC-SHA-1 algorithm\n"
- "Use HMAC-SHA-256 algorithm\n"
- "Use HMAC-SHA-384 algorithm\n"
- "Use HMAC-SHA-512 algorithm\n"
- "Password\n"
- "Password string (key)\n")
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Authentication\n"
+ "Key ID\n"
+ "Key ID value\n"
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n"
+ "Password\n"
+ "Password string (key)\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi;
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index 8b7afd89a7..0e44f2a142 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -704,10 +704,14 @@ static void p2xp_neigh_refresh(struct ospf6_neighbor *on, uint32_t prev_cost)
#include "ospf6d/ospf6_neighbor_clippy.c"
#endif
-DEFPY(ipv6_ospf6_p2xp_neigh, ipv6_ospf6_p2xp_neigh_cmd,
- "[no] ipv6 ospf6 neighbor X:X::X:X",
- NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n"
- "Neighbor link-local address\n")
+DEFPY (ipv6_ospf6_p2xp_neigh,
+ ipv6_ospf6_p2xp_neigh_cmd,
+ "[no] ipv6 ospf6 neighbor X:X::X:X",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Configure static neighbor\n"
+ "Neighbor link-local address\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi = ifp->info;
@@ -745,12 +749,16 @@ DEFPY(ipv6_ospf6_p2xp_neigh, ipv6_ospf6_p2xp_neigh_cmd,
return CMD_SUCCESS;
}
-DEFPY(ipv6_ospf6_p2xp_neigh_cost, ipv6_ospf6_p2xp_neigh_cost_cmd,
- "[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)",
- NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n"
- "Neighbor link-local address\n"
- "Outgoing metric for this neighbor\n"
- "Outgoing metric for this neighbor\n")
+DEFPY (ipv6_ospf6_p2xp_neigh_cost,
+ ipv6_ospf6_p2xp_neigh_cost_cmd,
+ "[no] ipv6 ospf6 neighbor X:X::X:X cost (1-65535)",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Configure static neighbor\n"
+ "Neighbor link-local address\n"
+ "Outgoing metric for this neighbor\n"
+ "Outgoing metric for this neighbor\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi = ifp->info;
@@ -821,13 +829,16 @@ static void p2xp_unicast_hello_send(struct event *event)
ospf6_hello_send_addr(oi, &p2xp_cfg->addr);
}
-DEFPY(ipv6_ospf6_p2xp_neigh_poll_interval,
- ipv6_ospf6_p2xp_neigh_poll_interval_cmd,
- "[no] ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)",
- NO_STR IP6_STR OSPF6_STR "Configure static neighbor\n"
- "Neighbor link-local address\n"
- "Send unicast hellos to neighbor when down\n"
- "Unicast hello interval when down (seconds)\n")
+DEFPY (ipv6_ospf6_p2xp_neigh_poll_interval,
+ ipv6_ospf6_p2xp_neigh_poll_interval_cmd,
+ "[no] ipv6 ospf6 neighbor X:X::X:X poll-interval (1-65535)",
+ NO_STR
+ IP6_STR
+ OSPF6_STR
+ "Configure static neighbor\n"
+ "Neighbor link-local address\n"
+ "Send unicast hellos to neighbor when down\n"
+ "Unicast hello interval when down (seconds)\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct ospf6_interface *oi = ifp->info;
@@ -1340,13 +1351,18 @@ static void ospf6_neighbor_show_detail_common(struct vty *vty,
}
}
-DEFUN(show_ipv6_ospf6_neighbor, show_ipv6_ospf6_neighbor_cmd,
+DEFUN(show_ipv6_ospf6_neighbor,
+ show_ipv6_ospf6_neighbor_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] neighbor [<detail|drchoice>] [json]",
- SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ VRF_CMD_HELP_STR
"All VRFs\n"
"Neighbor list\n"
"Display details\n"
- "Display DR choices\n" JSON_STR)
+ "Display DR choices\n"
+ JSON_STR)
{
struct ospf6 *ospf6;
struct listnode *node;
@@ -1415,12 +1431,17 @@ static int ospf6_neighbor_show_common(struct vty *vty, int argc,
return CMD_SUCCESS;
}
-DEFUN(show_ipv6_ospf6_neighbor_one, show_ipv6_ospf6_neighbor_one_cmd,
+DEFUN(show_ipv6_ospf6_neighbor_one,
+ show_ipv6_ospf6_neighbor_one_cmd,
"show ipv6 ospf6 [vrf <NAME|all>] neighbor A.B.C.D [json]",
- SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+ SHOW_STR
+ IP6_STR
+ OSPF6_STR
+ VRF_CMD_HELP_STR
"All VRFs\n"
"Neighbor list\n"
- "Specify Router-ID as IPv4 address notation\n" JSON_STR)
+ "Specify Router-ID as IPv4 address notation\n"
+ JSON_STR)
{
int idx_ipv4 = 4;
struct ospf6 *ospf6;
@@ -1460,11 +1481,14 @@ void ospf6_neighbor_init(void)
&ipv6_ospf6_p2xp_neigh_poll_interval_cmd);
}
-DEFUN(debug_ospf6_neighbor, debug_ospf6_neighbor_cmd,
- "debug ospf6 neighbor [<state|event>]",
- DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n"
- "Debug OSPFv3 Neighbor State Change\n"
- "Debug OSPFv3 Neighbor Event\n")
+DEFUN (debug_ospf6_neighbor,
+ debug_ospf6_neighbor_cmd,
+ "debug ospf6 neighbor [<state|event>]",
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Neighbor\n"
+ "Debug OSPFv3 Neighbor State Change\n"
+ "Debug OSPFv3 Neighbor Event\n")
{
int idx_type = 3;
unsigned char level = 0;
@@ -1482,11 +1506,15 @@ DEFUN(debug_ospf6_neighbor, debug_ospf6_neighbor_cmd,
}
-DEFUN(no_debug_ospf6_neighbor, no_debug_ospf6_neighbor_cmd,
- "no debug ospf6 neighbor [<state|event>]",
- NO_STR DEBUG_STR OSPF6_STR "Debug OSPFv3 Neighbor\n"
- "Debug OSPFv3 Neighbor State Change\n"
- "Debug OSPFv3 Neighbor Event\n")
+DEFUN (no_debug_ospf6_neighbor,
+ no_debug_ospf6_neighbor_cmd,
+ "no debug ospf6 neighbor [<state|event>]",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR
+ "Debug OSPFv3 Neighbor\n"
+ "Debug OSPFv3 Neighbor State Change\n"
+ "Debug OSPFv3 Neighbor Event\n")
{
int idx_type = 4;
unsigned char level = 0;
@@ -1504,8 +1532,12 @@ DEFUN(no_debug_ospf6_neighbor, no_debug_ospf6_neighbor_cmd,
}
-DEFUN(no_debug_ospf6, no_debug_ospf6_cmd, "no debug ospf6",
- NO_STR DEBUG_STR OSPF6_STR)
+DEFUN (no_debug_ospf6,
+ no_debug_ospf6_cmd,
+ "no debug ospf6",
+ NO_STR
+ DEBUG_STR
+ OSPF6_STR)
{
unsigned int i;
diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c
index 419113e6d7..fcc28c6f9f 100644
--- a/ospfd/ospf_apiserver.c
+++ b/ospfd/ospf_apiserver.c
@@ -62,6 +62,11 @@ DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter");
/* List of all active connections. */
struct list *apiserver_list;
+/* Indicates that API the server socket local addresss has been
+ * specified.
+ */
+struct in_addr ospf_apiserver_addr;
+
/* -----------------------------------------------------------
* Functions to lookup interfaces
* -----------------------------------------------------------
@@ -109,7 +114,21 @@ struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp)
unsigned short ospf_apiserver_getport(void)
{
- struct servent *sp = getservbyname("ospfapi", "tcp");
+ struct servent *sp = NULL;
+ char sbuf[16];
+
+ /*
+ * Allow the OSPF API server port to be specified per-instance by
+ * including the instance ID in the /etc/services name. Use the
+ * prior name if no per-instance service is specified.
+ */
+ if (ospf_instance) {
+ snprintfrr(sbuf, sizeof(sbuf), "ospfapi-%d", ospf_instance);
+ sp = getservbyname(sbuf, "tcp");
+ }
+
+ if (!sp)
+ sp = getservbyname("ospfapi", "tcp");
return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT;
}
@@ -557,8 +576,10 @@ int ospf_apiserver_serv_sock_family(unsigned short port, int family)
sockopt_reuseaddr(accept_sock);
sockopt_reuseport(accept_sock);
- /* Bind socket to address and given port. */
- rc = sockunion_bind(accept_sock, &su, port, NULL);
+ /* Bind socket to optional lcoal address and port. */
+ if (ospf_apiserver_addr.s_addr)
+ sockunion2ip(&su) = ospf_apiserver_addr.s_addr;
+ rc = sockunion_bind(accept_sock, &su, port, &su);
if (rc < 0) {
close(accept_sock); /* Close socket */
return rc;
diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h
index 0aaf67c1f3..4341a9d380 100644
--- a/ospfd/ospf_apiserver.h
+++ b/ospfd/ospf_apiserver.h
@@ -67,6 +67,14 @@ enum ospf_apiserver_event {
};
/* -----------------------------------------------------------
+ * External definitions for OSPF API ospfd parameters.
+ * -----------------------------------------------------------
+ */
+
+extern int ospf_apiserver_enable;
+extern struct in_addr ospf_apiserver_addr;
+
+/* -----------------------------------------------------------
* Following are functions to manage client connections.
* -----------------------------------------------------------
*/
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 95a593ad4d..e15871ac81 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -765,8 +765,9 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
packets must be sent, as unicasts, to each adjacent neighbor
(i.e., those in state Exchange or greater). The destination
IP addresses for these packets are the neighbors' IP
- addresses. */
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ addresses. This behavior is extended to P2MP networks which
+ don't support broadcast. */
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_neighbor *nbr;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 17426d2615..11ac7af7c9 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -19,6 +19,7 @@
#include "zclient.h"
#include "bfd.h"
#include "ldp_sync.h"
+#include "plist.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_bfd.h"
@@ -67,6 +68,34 @@ int ospf_interface_neighbor_count(struct ospf_interface *oi)
return count;
}
+
+void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi)
+{
+ struct route_node *rn;
+ struct ospf_neighbor *nbr = NULL;
+ struct prefix nbr_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } };
+
+ if (!oi->nbr_filter)
+ return;
+
+ /*
+ * Kill neighbors that don't match the neighbor filter prefix-list
+ * excluding the neighbor for the router itself and any neighbors
+ * that are already down.
+ */
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+ if (nbr && nbr != oi->nbr_self && nbr->state != NSM_Down) {
+ nbr_src_prefix.u.prefix4 = nbr->src;
+ if (prefix_list_apply(oi->nbr_filter,
+ (struct prefix *)&(
+ nbr_src_prefix)) !=
+ PREFIX_PERMIT)
+ OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
+ }
+ }
+}
+
int ospf_if_get_output_cost(struct ospf_interface *oi)
{
/* If all else fails, use default OSPF cost */
@@ -147,17 +176,11 @@ void ospf_if_reset(struct interface *ifp)
}
}
-void ospf_if_reset_variables(struct ospf_interface *oi)
+static void ospf_if_default_variables(struct ospf_interface *oi)
{
/* Set default values. */
- /* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */
- if (oi->vl_data)
- oi->type = OSPF_IFTYPE_VIRTUALLINK;
- else
- /* preserve network-type */
- if (oi->type != OSPF_IFTYPE_NBMA)
- oi->type = OSPF_IFTYPE_BROADCAST;
+ oi->type = OSPF_IFTYPE_BROADCAST;
oi->state = ISM_Down;
@@ -254,7 +277,7 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
oi->ls_ack_direct.ls_ack = list_new();
/* Set default values. */
- ospf_if_reset_variables(oi);
+ ospf_if_default_variables(oi);
/* Set pseudo neighbor to Null */
oi->nbr_self = NULL;
@@ -532,6 +555,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
UNSET_IF_PARAM(oip, if_area);
UNSET_IF_PARAM(oip, opaque_capable);
UNSET_IF_PARAM(oip, keychain_name);
+ UNSET_IF_PARAM(oip, nbr_filter_name);
oip->auth_crypt = list_new();
@@ -550,6 +574,7 @@ static void ospf_del_if_params(struct interface *ifp,
{
list_delete(&oip->auth_crypt);
XFREE(MTYPE_OSPF_IF_PARAMS, oip->keychain_name);
+ XFREE(MTYPE_OSPF_IF_PARAMS, oip->nbr_filter_name);
ospf_interface_disable_bfd(ifp, oip);
ldp_sync_info_free(&(oip->ldp_sync_info));
XFREE(MTYPE_OSPF_IF_PARAMS, oip);
@@ -585,7 +610,8 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
!OSPF_IF_PARAM_CONFIGURED(oip, if_area) &&
!OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) &&
!OSPF_IF_PARAM_CONFIGURED(oip, prefix_suppression) &&
- !OSPF_IF_PARAM_CONFIGURED(oip, keychain_name) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, keychain_name) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, nbr_filter_name) &&
listcount(oip->auth_crypt) == 0) {
ospf_del_if_params(ifp, oip);
rn->info = NULL;
@@ -1388,7 +1414,8 @@ static int ospf_ifp_create(struct interface *ifp)
(!OSPF_IF_PARAM_CONFIGURED(IF_DEF_PARAMS(ifp), type) ||
if_is_loopback(ifp))) {
SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
- IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
+ if (!IF_DEF_PARAMS(ifp)->type_cfg)
+ IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
}
ospf = ifp->vrf->info;
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 08a2b11273..45d0b7943a 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -57,6 +57,7 @@ struct ospf_if_params {
DECLARE_IF_PARAM(struct in_addr, if_area);
uint32_t if_area_id_fmt;
+ bool type_cfg;
DECLARE_IF_PARAM(uint8_t, type); /* type of interface */
#define OSPF_IF_ACTIVE 0
#define OSPF_IF_PASSIVE 1
@@ -119,8 +120,14 @@ struct ospf_if_params {
/* point-to-multipoint delayed reflooding configuration */
bool p2mp_delay_reflood;
+ /* point-to-multipoint doesn't support broadcast */
+ bool p2mp_non_broadcast;
+
/* Opaque LSA capability at interface level (see RFC5250) */
DECLARE_IF_PARAM(bool, opaque_capable);
+
+ /* Name of prefix-list name for packet source address filtering. */
+ DECLARE_IF_PARAM(char *, nbr_filter_name);
};
enum { MEMBER_ALLROUTERS = 0,
@@ -185,6 +192,10 @@ struct ospf_interface {
/* OSPF Network Type. */
uint8_t type;
+#define OSPF_IF_NON_BROADCAST(O) \
+ (((O)->type == OSPF_IFTYPE_NBMA) || \
+ ((((O)->type == OSPF_IFTYPE_POINTOMULTIPOINT) && \
+ (O)->p2mp_non_broadcast)))
/* point-to-point DMVPN configuration */
uint8_t ptp_dmvpn;
@@ -192,6 +203,9 @@ struct ospf_interface {
/* point-to-multipoint delayed reflooding */
bool p2mp_delay_reflood;
+ /* point-to-multipoint doesn't support broadcast */
+ bool p2mp_non_broadcast;
+
/* State of Interface State Machine. */
uint8_t state;
@@ -232,6 +246,9 @@ struct ospf_interface {
/* List of configured NBMA neighbor. */
struct list *nbr_nbma;
+ /* Configured prefix-list for filtering neighbors. */
+ struct prefix_list *nbr_filter;
+
/* Graceful-Restart data. */
struct {
struct {
@@ -326,7 +343,6 @@ extern void ospf_if_update_params(struct interface *ifp, struct in_addr addr);
extern int ospf_if_new_hook(struct interface *ifp);
extern void ospf_if_init(void);
extern void ospf_if_stream_unset(struct ospf_interface *oi);
-extern void ospf_if_reset_variables(struct ospf_interface *oi);
extern int ospf_if_is_enable(struct ospf_interface *oi);
extern int ospf_if_get_output_cost(struct ospf_interface *oi);
extern void ospf_if_recalculate_output_cost(struct interface *ifp);
@@ -358,6 +374,7 @@ extern void ospf_crypt_key_add(struct list *list, struct crypt_key *key);
extern int ospf_crypt_key_delete(struct list *list, uint8_t key_id);
extern uint8_t ospf_default_iftype(struct interface *ifp);
extern int ospf_interface_neighbor_count(struct ospf_interface *oi);
+extern void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi);
/* Set all multicast memberships appropriately based on the type and
state of the interface. */
diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c
index 2516fa75db..878ab725bd 100644
--- a/ospfd/ospf_ism.c
+++ b/ospfd/ospf_ism.c
@@ -367,7 +367,7 @@ static int ism_interface_up(struct ospf_interface *oi)
/* Otherwise, the state transitions to Waiting. */
next_state = ISM_Waiting;
- if (oi->type == OSPF_IFTYPE_NBMA)
+ if (OSPF_IF_NON_BROADCAST(oi))
ospf_nbr_nbma_if_update(oi->ospf, oi);
/* ospf_ism_event (t); */
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index abad6c5b90..9e97abba1c 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -44,6 +44,7 @@
#include "ospfd/ospf_errors.h"
#include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_routemap_nb.h"
+#include "ospfd/ospf_apiserver.h"
#define OSPFD_STATE_NAME "%s/ospfd.json", frr_libstatedir
#define OSPFD_INST_STATE_NAME(i) "%s/ospfd-%d.json", frr_runstatedir, i
@@ -75,6 +76,7 @@ struct zebra_privs_t ospfd_privs = {
const struct option longopts[] = {
{"instance", required_argument, NULL, 'n'},
{"apiserver", no_argument, NULL, 'a'},
+ {"apiserver_addr", required_argument, NULL, 'l'},
{0}
};
@@ -83,10 +85,6 @@ const struct option longopts[] = {
/* Master of threads. */
struct event_loop *master;
-#ifdef SUPPORT_OSPF_API
-extern int ospf_apiserver_enable;
-#endif /* SUPPORT_OSPF_API */
-
/* SIGHUP handler. */
static void sighup(void)
{
@@ -193,15 +191,11 @@ static void ospf_config_end(void)
/* OSPFd main routine. */
int main(int argc, char **argv)
{
-#ifdef SUPPORT_OSPF_API
- /* OSPF apiserver is disabled by default. */
- ospf_apiserver_enable = 0;
-#endif /* SUPPORT_OSPF_API */
-
frr_preinit(&ospfd_di, argc, argv);
- frr_opt_add("n:a", longopts,
+ frr_opt_add("n:al:", longopts,
" -n, --instance Set the instance id\n"
- " -a, --apiserver Enable OSPF apiserver\n");
+ " -a, --apiserver Enable OSPF apiserver\n"
+ " -l, --apiserver_addr Set OSPF apiserver bind address\n");
while (1) {
int opt;
@@ -223,6 +217,14 @@ int main(int argc, char **argv)
case 'a':
ospf_apiserver_enable = 1;
break;
+ case 'l':
+ if (inet_pton(AF_INET, optarg, &ospf_apiserver_addr) <=
+ 0) {
+ zlog_err("OSPF: Invalid API Server IPv4 address %s specified",
+ optarg);
+ exit(0);
+ }
+ break;
#endif /* SUPPORT_OSPF_API */
default:
frr_help_exit(1);
diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c
index c238f051df..d47d581605 100644
--- a/ospfd/ospf_neighbor.c
+++ b/ospfd/ospf_neighbor.c
@@ -431,7 +431,7 @@ static struct ospf_neighbor *ospf_nbr_add(struct ospf_interface *oi,
memcpy(&nbr->address, p, sizeof(struct prefix));
nbr->nbr_nbma = NULL;
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_nbr_nbma *nbr_nbma;
struct listnode *node;
@@ -485,7 +485,7 @@ struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi,
route_unlock_node(rn);
nbr = rn->info;
- if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) {
+ if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->state == NSM_Attempt) {
nbr->src = iph->ip_src;
memcpy(&nbr->address, p, sizeof(struct prefix));
}
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index 08aa103686..c466ddcc6f 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -166,7 +166,7 @@ static int nsm_hello_received(struct ospf_neighbor *nbr)
OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer,
nbr->v_inactivity);
- if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
+ if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->nbr_nbma != NULL)
EVENT_OFF(nbr->nbr_nbma->t_poll);
/* Send proactive ARP requests */
@@ -377,7 +377,7 @@ static int nsm_kill_nbr(struct ospf_neighbor *nbr)
return 0;
}
- if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL) {
+ if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->nbr_nbma != NULL) {
struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
nbr_nbma->nbr = NULL;
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 861b4e022a..87aaccad92 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -23,6 +23,7 @@
#endif
#include "vrf.h"
#include "lib_errors.h"
+#include "plist.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_network.h"
@@ -2747,6 +2748,20 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf)
oi = ospf_if_lookup_recv_if(ospf, iph->ip_src, ifp);
/*
+ * If a neighbor filter prefix-list is configured, apply it to the IP
+ * source address and ignore the packet if it doesn't match.
+ */
+ if (oi && oi->nbr_filter) {
+ struct prefix ip_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } };
+
+ ip_src_prefix.u.prefix4 = iph->ip_src;
+ if (prefix_list_apply(oi->nbr_filter,
+ (struct prefix *)&(ip_src_prefix)) !=
+ PREFIX_PERMIT)
+ return OSPF_READ_CONTINUE;
+ }
+
+ /*
* ospf_verify_header() relies on a valid "oi" and thus can be called
* only after the passive/backbone/other checks below are passed.
* These checks in turn access the fields of unverified "ospfh"
@@ -3395,17 +3410,19 @@ static void ospf_poll_send(struct ospf_nbr_nbma *nbr_nbma)
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
return;
- if (oi->type != OSPF_IFTYPE_NBMA)
- return;
-
if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
return;
- if (PRIORITY(oi) == 0)
- return;
+ if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (PRIORITY(oi) == 0)
+ return;
+
+ if (nbr_nbma->priority == 0 && oi->state != ISM_DR &&
+ oi->state != ISM_Backup)
+ return;
- if (nbr_nbma->priority == 0 && oi->state != ISM_DR
- && oi->state != ISM_Backup)
+ } else if (oi->type != OSPF_IFTYPE_POINTOMULTIPOINT ||
+ !oi->p2mp_non_broadcast)
return;
ospf_hello_send_sub(oi, nbr_nbma->addr.s_addr);
@@ -3451,7 +3468,7 @@ void ospf_hello_send(struct ospf_interface *oi)
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
return;
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_neighbor *nbr;
struct route_node *rn;
@@ -3467,31 +3484,44 @@ void ospf_hello_send(struct ospf_interface *oi)
continue;
/*
- * RFC 2328 Section 9.5.1
- * If the router is not eligible to become Designated
- * Router, it must periodically send Hello Packets to
- * both the Designated Router and the Backup
- * Designated Router (if they exist).
+ * Always send to all neighbors on Point-to-Multipoint
+ * non-braodcast networks.
*/
- if (PRIORITY(oi) == 0 &&
- IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
- IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
- continue;
+ if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
+ ospf_hello_send_sub(oi, nbr->address.u.prefix4
+ .s_addr);
+ else {
+ /*
+ * RFC 2328 Section 9.5.1
+ * If the router is not eligible to become Designated
+ * Router, it must periodically send Hello Packets to
+ * both the Designated Router and the Backup
+ * Designated Router (if they exist).
+ */
+ if (PRIORITY(oi) == 0 &&
+ IPV4_ADDR_CMP(&DR(oi),
+ &nbr->address.u.prefix4) &&
+ IPV4_ADDR_CMP(&BDR(oi),
+ &nbr->address.u.prefix4))
+ continue;
- /*
- * If the router is eligible to become Designated
- * Router, it must periodically send Hello Packets to
- * all neighbors that are also eligible. In addition,
- * if the router is itself the Designated Router or
- * Backup Designated Router, it must also send periodic
- * Hello Packets to all other neighbors.
- */
- if (nbr->priority == 0 && oi->state == ISM_DROther)
- continue;
+ /*
+ * If the router is eligible to become Designated
+ * Router, it must periodically send Hello Packets to
+ * all neighbors that are also eligible. In addition,
+ * if the router is itself the Designated Router or
+ * Backup Designated Router, it must also send periodic
+ * Hello Packets to all other neighbors.
+ */
+ if (nbr->priority == 0 &&
+ oi->state == ISM_DROther)
+ continue;
- /* if oi->state == Waiting, send
- * hello to all neighbors */
- ospf_hello_send_sub(oi, nbr->address.u.prefix4.s_addr);
+ /* if oi->state == Waiting, send
+ * hello to all neighbors */
+ ospf_hello_send_sub(oi, nbr->address.u.prefix4
+ .s_addr);
+ }
}
} else {
/* Decide destination address. */
@@ -3848,11 +3878,10 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag,
else
p.prefix.s_addr = htonl(OSPF_ALLDROUTERS);
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
if (flag == OSPF_SEND_PACKET_INDIRECT)
- flog_warn(
- EC_OSPF_PACKET,
- "* LS-Update is directly sent on NBMA network.");
+ flog_warn(EC_OSPF_PACKET,
+ "* LS-Update is directly sent on non-broadcast network.");
if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix))
flog_warn(EC_OSPF_PACKET,
"* LS-Update is sent to myself.");
@@ -3910,7 +3939,8 @@ static void ospf_ls_ack_send_list(struct ospf_interface *oi, struct list *ack,
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
- oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
+ (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT &&
+ !oi->p2mp_non_broadcast))
op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS);
else
op->dst.s_addr = dst.s_addr;
@@ -3962,7 +3992,7 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi)
networks, delayed Link State Acknowledgment packets must be
unicast separately over each adjacency (i.e., neighbor whose
state is >= Exchange). */
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_neighbor *nbr;
struct route_node *rn;
diff --git a/ospfd/ospf_snmp.c b/ospfd/ospf_snmp.c
index fc0c143c28..4e1f15361e 100644
--- a/ospfd/ospf_snmp.c
+++ b/ospfd/ospf_snmp.c
@@ -906,7 +906,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name,
area = ospf_area_lookup_by_area_id(ospf, *area_id);
if (!area)
return NULL;
- offset++;
+ offset += IN_ADDR_SIZE;
/* Type. */
*type = *offset;
@@ -914,7 +914,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name,
/* LS ID. */
oid2in_addr(offset, IN_ADDR_SIZE, ls_id);
- offset++;
+ offset += IN_ADDR_SIZE;
/* Router ID. */
oid2in_addr(offset, IN_ADDR_SIZE, router_id);
@@ -971,7 +971,7 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name,
}
/* Router ID. */
- offset++;
+ offset += IN_ADDR_SIZE;
offsetlen -= IN_ADDR_SIZE;
len = offsetlen;
@@ -996,11 +996,11 @@ static struct ospf_lsa *ospfLsdbLookup(struct variable *v, oid *name,
/* Fill in value. */
offset = name + v->namelen;
oid_copy_in_addr(offset, area_id);
- offset++;
+ offset += IN_ADDR_SIZE;
*offset = lsa->data->type;
offset++;
oid_copy_in_addr(offset, &lsa->data->id);
- offset++;
+ offset += IN_ADDR_SIZE;
oid_copy_in_addr(offset,
&lsa->data->adv_router);
@@ -1106,7 +1106,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v,
if (!area)
return NULL;
- offset++;
+ offset += IN_ADDR_SIZE;
/* Lookup area range. */
oid2in_addr(offset, IN_ADDR_SIZE, range_net);
@@ -1135,7 +1135,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v,
return NULL;
do {
- offset++;
+ offset += IN_ADDR_SIZE;
offsetlen -= IN_ADDR_SIZE;
len = offsetlen;
@@ -1157,7 +1157,7 @@ static struct ospf_area_range *ospfAreaRangeLookup(struct variable *v,
/* Fill in value. */
offset = name + v->namelen;
oid_copy_in_addr(offset, area_id);
- offset++;
+ offset += IN_ADDR_SIZE;
oid_copy_in_addr(offset, range_net);
return range;
@@ -1559,7 +1559,7 @@ static struct ospf_interface *ospfIfLookup(struct variable *v, oid *name,
*length = v->namelen + IN_ADDR_SIZE + 1;
offset = name + v->namelen;
oid_copy_in_addr(offset, ifaddr);
- offset++;
+ offset += IN_ADDR_SIZE;
*offset = *ifindex;
return oi;
}
@@ -1703,7 +1703,7 @@ static struct ospf_interface *ospfIfMetricLookup(struct variable *v, oid *name,
*length = v->namelen + IN_ADDR_SIZE + 1 + 1;
offset = name + v->namelen;
oid_copy_in_addr(offset, ifaddr);
- offset++;
+ offset += IN_ADDR_SIZE;
*offset = *ifindex;
offset++;
*offset = OSPF_SNMP_METRIC_VALUE;
@@ -2241,7 +2241,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name,
/* LS ID. */
oid2in_addr(offset, IN_ADDR_SIZE, ls_id);
- offset++;
+ offset += IN_ADDR_SIZE;
/* Router ID. */
oid2in_addr(offset, IN_ADDR_SIZE, router_id);
@@ -2269,7 +2269,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name,
oid2in_addr(offset, len, ls_id);
- offset++;
+ offset += IN_ADDR_SIZE;
offsetlen -= IN_ADDR_SIZE;
/* Router ID. */
@@ -2292,7 +2292,7 @@ static struct ospf_lsa *ospfExtLsdbLookup(struct variable *v, oid *name,
*offset = OSPF_AS_EXTERNAL_LSA;
offset++;
oid_copy_in_addr(offset, &lsa->data->id);
- offset++;
+ offset += IN_ADDR_SIZE;
oid_copy_in_addr(offset, &lsa->data->adv_router);
return lsa;
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index e26fe6f53a..198309c1ef 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -2740,9 +2740,9 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
if (srn->algo[i] == SR_ALGORITHM_UNSET)
continue;
json_obj = json_object_new_object();
- char tmp[2];
+ char tmp[12];
- snprintf(tmp, sizeof(tmp), "%u", i);
+ snprintf(tmp, sizeof(tmp), "%d", i);
json_object_string_add(json_obj, tmp,
srn->algo[i] == SR_ALGORITHM_SPF
? "SPF"
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 93dd12ce49..3f8731f369 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2406,130 +2406,30 @@ DEFUN (no_ospf_timers_lsa_min_arrival,
return CMD_SUCCESS;
}
-DEFUN (ospf_neighbor,
- ospf_neighbor_cmd,
- "neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]",
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Neighbor Priority\n"
- "Priority\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 1;
- int idx_pri = 3;
- int idx_poll = 5;
- struct in_addr nbr_addr;
- unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
- unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT;
-
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (argc > 2)
- priority = strtoul(argv[idx_pri]->arg, NULL, 10);
-
- if (argc > 4)
- interval = strtoul(argv[idx_poll]->arg, NULL, 10);
-
- ospf_nbr_nbma_set(ospf, nbr_addr);
-
- if (argc > 2)
- ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority);
-
- if (argc > 4)
- ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ospf_neighbor_poll_interval,
- ospf_neighbor_poll_interval_cmd,
- "neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]",
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n"
- "OSPF priority of non-broadcast neighbor\n"
- "Priority\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 1;
- int idx_poll = 3;
- int idx_pri = 5;
- struct in_addr nbr_addr;
- unsigned int priority;
- unsigned int interval;
-
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- interval = strtoul(argv[idx_poll]->arg, NULL, 10);
-
- priority = argc > 4 ? strtoul(argv[idx_pri]->arg, NULL, 10)
- : OSPF_NEIGHBOR_PRIORITY_DEFAULT;
-
- ospf_nbr_nbma_set(ospf, nbr_addr);
- ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval);
-
- if (argc > 4)
- ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf_neighbor,
- no_ospf_neighbor_cmd,
- "no neighbor A.B.C.D [priority (0-255) [poll-interval (1-65525)]]",
- NO_STR
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Neighbor Priority\n"
- "Priority\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n")
+DEFPY(ospf_neighbor, ospf_neighbor_cmd,
+ "[no] neighbor A.B.C.D$nbr_address [{priority (0-255)$priority | poll-interval (1-65535)$interval}]",
+ NO_STR
+ NEIGHBOR_STR
+ "Neighbor IP address\n"
+ "Neighbor Priority\n"
+ "Priority\n"
+ "Dead Neighbor Polling interval\n"
+ "Seconds\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 2;
- struct in_addr nbr_addr;
-
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- (void)ospf_nbr_nbma_unset(ospf, nbr_addr);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf_neighbor_poll,
- no_ospf_neighbor_poll_cmd,
- "no neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]",
- NO_STR
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n"
- "Neighbor Priority\n"
- "Priority\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 2;
- struct in_addr nbr_addr;
+ if (no)
+ ospf_nbr_nbma_unset(ospf, nbr_address);
+ else {
+ ospf_nbr_nbma_set(ospf, nbr_address);
+ if (priority_str)
+ ospf_nbr_nbma_priority_set(ospf, nbr_address, priority);
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
+ if (interval_str)
+ ospf_nbr_nbma_poll_interval_set(ospf, nbr_address,
+ interval);
}
- (void)ospf_nbr_nbma_unset(ospf, nbr_addr);
-
return CMD_SUCCESS;
}
@@ -2680,7 +2580,7 @@ DEFUN (no_ospf_write_multiplier,
}
ALIAS(no_ospf_write_multiplier, no_write_multiplier_cmd,
- "no write-multiplier (1-100)", NO_STR
+ "no write-multiplier [(1-100)]", NO_STR
"Write multiplier\n"
"Maximum number of interface serviced per write\n")
@@ -2754,9 +2654,10 @@ DEFUN (ospf_max_multipath,
DEFUN (no_ospf_max_multipath,
no_ospf_max_multipath_cmd,
- "no maximum-paths",
+ "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]",
NO_STR
- "Max no of multiple paths for ECMP support\n")
+ "Max no of multiple paths for ECMP support\n"
+ "Number of paths\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
uint16_t maxpaths = MULTIPATH_NUM;
@@ -4148,6 +4049,8 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
ospf_interface_auth_show(vty, oi, json_interface_sub, use_json);
ospf_interface_auth_show(vty, oi, json_oi, use_json);
+
+ /* Point-to-Multipoint Interface options. */
if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
if (use_json) {
json_object_boolean_add(json_interface_sub,
@@ -4162,6 +4065,19 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
" %sDelay reflooding LSAs received on P2MP interface\n",
oi->p2mp_delay_reflood ? "" : "Don't ");
}
+ if (use_json) {
+ json_object_boolean_add(json_interface_sub,
+ "p2mpNonBroadcast",
+ oi->p2mp_non_broadcast);
+
+ json_object_boolean_add(json_oi,
+ "p2mpNonBroadcast",
+ oi->p2mp_non_broadcast);
+ } else {
+ vty_out(vty,
+ " P2MP interface does %ssupport broadcast\n",
+ oi->p2mp_non_broadcast ? "not " : "");
+ }
}
/* Add ospf_interface object to main json blob using SIP as key
@@ -4169,6 +4085,31 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
if (use_json)
json_object_object_addf(json_ois, json_oi, "%pI4",
&oi->address->u.prefix4);
+
+ if (oi->nbr_filter) {
+ if (use_json) {
+ json_object_string_add(json_interface_sub,
+ "nbrFilterPrefixList",
+ prefix_list_name(
+ oi->nbr_filter));
+ json_object_string_add(json_oi,
+ "nbrFilterPrefixList",
+ prefix_list_name(
+ oi->nbr_filter));
+ } else
+ vty_out(vty,
+ " Neighbor filter prefix-list: %s\n",
+ prefix_list_name(oi->nbr_filter));
+ } else {
+ if (use_json) {
+ json_object_string_add(json_interface_sub,
+ "nbrFilterPrefixList",
+ "N/A");
+ json_object_string_add(json_oi,
+ "nbrFilterPrefixList",
+ "N/A");
+ }
+ }
}
}
@@ -5970,7 +5911,7 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty,
prev_nbr = nbr;
}
- if (oi->type != OSPF_IFTYPE_NBMA)
+ if (!OSPF_IF_NON_BROADCAST(oi))
continue;
struct listnode *nd;
@@ -8548,7 +8489,7 @@ DEFUN_HIDDEN (no_ospf_hello_interval,
DEFUN(ip_ospf_network, ip_ospf_network_cmd,
"ip ospf network <broadcast|"
"non-broadcast|"
- "point-to-multipoint [delay-reflood]|"
+ "point-to-multipoint [delay-reflood|non-broadcast]|"
"point-to-point [dmvpn]>",
"IP Information\n"
"OSPF interface commands\n"
@@ -8557,6 +8498,7 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
"Specify OSPF NBMA network\n"
"Specify OSPF point-to-multipoint network\n"
"Specify OSPF delayed reflooding of LSAs received on P2MP interface\n"
+ "Specify OSPF point-to-multipoint network doesn't support broadcast\n"
"Specify OSPF point-to-point network\n"
"Specify OSPF point-to-point DMVPN network\n")
{
@@ -8565,6 +8507,7 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
int old_type = IF_DEF_PARAMS(ifp)->type;
uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
uint8_t old_p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
+ uint8_t old_p2mp_non_broadcast = IF_DEF_PARAMS(ifp)->p2mp_non_broadcast;
struct route_node *rn;
if (old_type == OSPF_IFTYPE_LOOPBACK) {
@@ -8576,24 +8519,30 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = OSPF_P2MP_NON_BROADCAST_DEFAULT;
if (argv_find(argv, argc, "broadcast", &idx))
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST;
- else if (argv_find(argv, argc, "non-broadcast", &idx))
- IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
else if (argv_find(argv, argc, "point-to-multipoint", &idx)) {
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
if (argv_find(argv, argc, "delay-reflood", &idx))
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = true;
- } else if (argv_find(argv, argc, "point-to-point", &idx)) {
+ if (argv_find(argv, argc, "non-broadcast", &idx))
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = true;
+ } else if (argv_find(argv, argc, "non-broadcast", &idx))
+ IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
+ else if (argv_find(argv, argc, "point-to-point", &idx)) {
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
if (argv_find(argv, argc, "dmvpn", &idx))
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
}
+ IF_DEF_PARAMS(ifp)->type_cfg = true;
+
if (IF_DEF_PARAMS(ifp)->type == old_type &&
IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn &&
- IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood)
+ IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood &&
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast == old_p2mp_non_broadcast)
return CMD_SUCCESS;
SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
@@ -8607,13 +8556,16 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
oi->type = IF_DEF_PARAMS(ifp)->type;
oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
+ oi->p2mp_non_broadcast = IF_DEF_PARAMS(ifp)->p2mp_non_broadcast;
/*
* The OSPF interface only needs to be flapped if the network
* type or DMVPN parameter changes.
*/
if (IF_DEF_PARAMS(ifp)->type != old_type ||
- IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn) {
+ IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn ||
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast !=
+ old_p2mp_non_broadcast) {
if (oi->state > ISM_Down) {
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
@@ -8654,9 +8606,11 @@ DEFUN (no_ip_ospf_network,
struct route_node *rn;
IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
+ IF_DEF_PARAMS(ifp)->type_cfg = false;
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = OSPF_P2MP_NON_BROADCAST_DEFAULT;
if (IF_DEF_PARAMS(ifp)->type == old_type)
return CMD_SUCCESS;
@@ -10011,6 +9965,58 @@ DEFPY(ip_ospf_prefix_suppression, ip_ospf_prefix_suppression_addr_cmd,
return CMD_SUCCESS;
}
+DEFPY(ip_ospf_neighbor_filter, ip_ospf_neighbor_filter_addr_cmd,
+ "[no] ip ospf neighbor-filter ![PREFIXLIST4_NAME]$prefix_list [A.B.C.D]$ip_addr", NO_STR
+ "IP Information\n"
+ "OSPF interface commands\n"
+ "Filter OSPF neighbor packets\n"
+ "Prefix-List used for filtering\n"
+ "Address of interface\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct ospf_if_params *params;
+ struct prefix_list *nbr_filter = NULL;
+ struct route_node *rn;
+
+ params = IF_DEF_PARAMS(ifp);
+
+ if (ip_addr.s_addr != INADDR_ANY) {
+ params = ospf_get_if_params(ifp, ip_addr);
+ ospf_if_update_params(ifp, ip_addr);
+ }
+
+ if (params->nbr_filter_name)
+ XFREE(MTYPE_OSPF_IF_PARAMS, params->nbr_filter_name);
+
+ if (no) {
+ UNSET_IF_PARAM(params, nbr_filter_name);
+ params->nbr_filter_name = NULL;
+ } else {
+ SET_IF_PARAM(params, nbr_filter_name);
+ params->nbr_filter_name = XSTRDUP(MTYPE_OSPF_IF_PARAMS,
+ prefix_list);
+ nbr_filter = prefix_list_lookup(AFI_IP, params->nbr_filter_name);
+ }
+
+ /*
+ * Determine if there is a change in neighbor filter prefix-list for the
+ * interface.
+ */
+ for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
+ struct ospf_interface *oi = rn->info;
+
+ if (oi &&
+ (ip_addr.s_addr == INADDR_ANY ||
+ IPV4_ADDR_SAME(&oi->address->u.prefix4, &ip_addr)) &&
+ oi->nbr_filter != nbr_filter) {
+ oi->nbr_filter = nbr_filter;
+ if (oi->nbr_filter)
+ ospf_intf_neighbor_filter_apply(oi);
+ }
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf_max_metric_router_lsa_admin,
ospf_max_metric_router_lsa_admin_cmd,
"max-metric router-lsa administrative",
@@ -10521,15 +10527,6 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
json_object_string_add(json_vrf, "strictLsaCheck",
(ospf->strict_lsa_check) ? "Enabled"
: "Disabled");
-#if CONFDATE > 20240401
- CPP_NOTICE("Remove deprecated json key: restartSupoort")
-#endif
- json_object_string_add(
- json_vrf, "restartSupoort",
- (ospf->only_planned_restart)
- ? "Planned Restart only"
- : "Planned and Unplanned Restarts");
-
json_object_string_add(
json_vrf, "restartSupport",
(ospf->only_planned_restart)
@@ -12211,25 +12208,25 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
do {
/* Interface Network print. */
- if (OSPF_IF_PARAM_CONFIGURED(params, type)
- && params->type != OSPF_IFTYPE_LOOPBACK) {
- if (params->type != ospf_default_iftype(ifp)) {
- vty_out(vty, " ip ospf network %s",
- ospf_int_type_str
- [params->type]);
- if (params->type
- == OSPF_IFTYPE_POINTOPOINT
- && params->ptp_dmvpn)
- vty_out(vty, " dmvpn");
- if (params->type ==
- OSPF_IFTYPE_POINTOMULTIPOINT &&
- params->p2mp_delay_reflood)
- vty_out(vty, " delay-reflood");
- if (params != IF_DEF_PARAMS(ifp) && rn)
- vty_out(vty, " %pI4",
- &rn->p.u.prefix4);
- vty_out(vty, "\n");
- }
+ if (OSPF_IF_PARAM_CONFIGURED(params, type) &&
+ params->type != OSPF_IFTYPE_LOOPBACK &&
+ params->type_cfg) {
+ vty_out(vty, " ip ospf network %s",
+ ospf_int_type_str[params->type]);
+ if (params->type == OSPF_IFTYPE_POINTOPOINT &&
+ params->ptp_dmvpn)
+ vty_out(vty, " dmvpn");
+ if (params->type ==
+ OSPF_IFTYPE_POINTOMULTIPOINT &&
+ params->p2mp_delay_reflood)
+ vty_out(vty, " delay-reflood");
+ if (params->type ==
+ OSPF_IFTYPE_POINTOMULTIPOINT &&
+ params->p2mp_non_broadcast)
+ vty_out(vty, " non-broadcast");
+ if (params != IF_DEF_PARAMS(ifp) && rn)
+ vty_out(vty, " %pI4", &rn->p.u.prefix4);
+ vty_out(vty, "\n");
}
/* OSPF interface authentication print */
@@ -12439,6 +12436,15 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
vty_out(vty, "\n");
}
+ /* neighbor-filter print. */
+ if (OSPF_IF_PARAM_CONFIGURED(params, nbr_filter_name)) {
+ vty_out(vty, " ip ospf neighbor-filter %s",
+ params->nbr_filter_name);
+ if (params != IF_DEF_PARAMS(ifp) && rn)
+ vty_out(vty, " %pI4", &rn->p.u.prefix4);
+ vty_out(vty, "\n");
+ }
+
while (1) {
if (rn == NULL)
rn = route_top(IF_OIFS_PARAMS(ifp));
@@ -13255,6 +13261,9 @@ static void ospf_vty_if_init(void)
/* "ip ospf prefix-suppression" commands. */
install_element(INTERFACE_NODE, &ip_ospf_prefix_suppression_addr_cmd);
+ /* "ip ospf neighbor-filter" commands. */
+ install_element(INTERFACE_NODE, &ip_ospf_neighbor_filter_addr_cmd);
+
/* These commands are compatibitliy for previous version. */
install_element(INTERFACE_NODE, &ospf_authentication_key_cmd);
install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd);
@@ -13753,11 +13762,8 @@ void ospf_vty_init(void)
install_element(OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd);
install_element(OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd);
- /* "neighbor" commands. */
+ /* "neighbor" command. */
install_element(OSPF_NODE, &ospf_neighbor_cmd);
- install_element(OSPF_NODE, &ospf_neighbor_poll_interval_cmd);
- install_element(OSPF_NODE, &no_ospf_neighbor_cmd);
- install_element(OSPF_NODE, &no_ospf_neighbor_poll_cmd);
/* write multiplier commands */
install_element(OSPF_NODE, &ospf_write_multiplier_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index bb6cc3a89c..2c518f2c9e 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1769,6 +1769,7 @@ static void ospf_prefix_list_update(struct prefix_list *plist)
int type;
int abr_inv = 0;
struct ospf_area *area;
+ struct ospf_interface *oi;
struct listnode *node, *n1;
/* If OSPF instatnce does not exist, return right now. */
@@ -1824,6 +1825,19 @@ static void ospf_prefix_list_update(struct prefix_list *plist)
}
}
+ /* Update interface neighbor-filter lists. */
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
+ if (OSPF_IF_PARAM(oi, nbr_filter_name) &&
+ strcmp(OSPF_IF_PARAM(oi, nbr_filter_name),
+ prefix_list_name(plist)) == 0) {
+ oi->nbr_filter = prefix_list_lookup(
+ AFI_IP,
+ OSPF_IF_PARAM(oi, nbr_filter_name));
+ if (oi->nbr_filter)
+ ospf_intf_neighbor_filter_apply(oi);
+ }
+ }
+
/* Schedule ABR task. */
if (IS_OSPF_ABR(ospf) && abr_inv)
ospf_schedule_abr_task(ospf);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 4c4666db52..1d013b260e 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -1096,6 +1096,7 @@ struct ospf_interface *add_ospf_interface(struct connected *co,
oi->type = IF_DEF_PARAMS(co->ifp)->type;
oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
oi->p2mp_delay_reflood = IF_DEF_PARAMS(co->ifp)->p2mp_delay_reflood;
+ oi->p2mp_non_broadcast = IF_DEF_PARAMS(co->ifp)->p2mp_non_broadcast;
/* Add pseudo neighbor. */
ospf_nbr_self_reset(oi, oi->ospf->router_id);
@@ -1989,7 +1990,7 @@ static void ospf_nbr_nbma_add(struct ospf_nbr_nbma *nbr_nbma,
struct route_node *rn;
struct prefix p;
- if (oi->type != OSPF_IFTYPE_NBMA)
+ if (!OSPF_IF_NON_BROADCAST(oi))
return;
if (nbr_nbma->nbr != NULL)
@@ -2036,7 +2037,7 @@ void ospf_nbr_nbma_if_update(struct ospf *ospf, struct ospf_interface *oi)
struct route_node *rn;
struct prefix_ipv4 p;
- if (oi->type != OSPF_IFTYPE_NBMA)
+ if (!OSPF_IF_NON_BROADCAST(oi))
return;
for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
@@ -2095,7 +2096,7 @@ int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr)
rn->info = nbr_nbma;
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
- if (oi->type == OSPF_IFTYPE_NBMA)
+ if (OSPF_IF_NON_BROADCAST(oi))
if (prefix_match(oi->address, (struct prefix *)&p)) {
ospf_nbr_nbma_add(nbr_nbma, oi);
break;
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index be36a07687..15d3904c37 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1941,12 +1941,15 @@ DEFUN (show_ip_pim_mlag_summary,
json_object *json_stat = NULL;
json = json_object_new_object();
- if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
- json_object_boolean_true_add(json, "mlagConnUp");
- if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
- json_object_boolean_true_add(json, "mlagPeerConnUp");
- if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
- json_object_boolean_true_add(json, "mlagPeerZebraUp");
+ json_object_boolean_add(json, "mlagConnUp",
+ CHECK_FLAG(router->mlag_flags,
+ PIM_MLAGF_LOCAL_CONN_UP));
+ json_object_boolean_add(json, "mlagPeerConnUp",
+ CHECK_FLAG(router->mlag_flags,
+ PIM_MLAGF_PEER_CONN_UP));
+ json_object_boolean_add(json, "mlagPeerZebraUp",
+ CHECK_FLAG(router->mlag_flags,
+ PIM_MLAGF_PEER_ZEBRA_UP));
json_object_string_add(json, "mlagRole",
mlag_role2str(router->mlag_role,
role_buf, sizeof(role_buf)));
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c
index ee318d45e3..5e50a09355 100644
--- a/pimd/pim_cmd_common.c
+++ b/pimd/pim_cmd_common.c
@@ -287,8 +287,15 @@ int pim_process_no_rp_kat_cmd(struct vty *vty)
sizeof(rs_timer_xpath));
/* RFC4601 */
- v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s",
- rs_timer_xpath);
+ /* Check if register suppress time is configured or assigned
+ * the default register suppress time.
+ */
+ if (yang_dnode_exists(vty->candidate_config->dnode, rs_timer_xpath))
+ v = yang_dnode_get_uint16(vty->candidate_config->dnode, "%s",
+ rs_timer_xpath);
+ else
+ v = PIM_REGISTER_SUPPRESSION_TIME_DEFAULT;
+
v = 3 * v + PIM_REGISTER_PROBE_TIME_DEFAULT;
if (v > UINT16_MAX)
v = UINT16_MAX;
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 5d7132c09a..dcb6116012 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1677,7 +1677,9 @@ static int pim_ifp_up(struct interface *ifp)
__func__, vrf->name);
return 0;
}
+
pim_zebra_interface_set_master(master, ifp);
+ break;
}
}
}
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 433aeacebb..f42079cd50 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -187,7 +187,7 @@ BuildRequires: make
BuildRequires: ncurses-devel
BuildRequires: readline-devel
BuildRequires: texinfo
-BuildRequires: libyang-devel >= 2.1.80
+BuildRequires: libyang-devel >= 2.1.128
%if 0%{?rhel} && 0%{?rhel} < 7
#python27-devel is available from ius community repo for RedHat/CentOS 6
BuildRequires: python27-devel
@@ -805,7 +805,21 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons
%changelog
-* Tue Oct 10 2023 Donatas Abraitis <donatas@opensourcerouting.org> - %{version}
+* Mon Mar 25 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - %{version}
+
+* Mon Mar 25 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - 10.0
+- Major highlights:
+- Introduce local host routes
+- Require libyang 2.1.128
+- Add suport to configire a log file per daemon
+- BGP BMP Loc-RIB (RFC9069) support
+- eBGP-OAD (One Administrative Domain) support
+- BGP RPKI VRF support
+- BGP SNMP traps for BGP4-MIBV2
+- Management (mgmtd) daemon "replace" operation support
+- BGP dynamic capabilities for addpath, fqdn, orf capabilities
+- SRv6 encapsulation source address feature
+- OSPFv3 Point-To-Multipoint mode
* Mon Oct 09 2023 Donatas Abraitis <donatas@opensourcerouting.org> - 9.1
- Major highlights:
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 07050ab93b..21c596bf71 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -448,6 +448,7 @@ DEFPY (install_seg6local_routes,
End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\
End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\
End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\
+ End_DX6$seg6l_enddx6 X:X::X:X$seg6l_enddx6_nh6|\
End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\
End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table|\
End_DT46$seg6l_enddt46 (1-4294967295)$seg6l_enddt46_table>\
@@ -467,6 +468,8 @@ DEFPY (install_seg6local_routes,
"Redirect table id to use\n"
"SRv6 End.DX4 function to use\n"
"V4 Nexthop address to use\n"
+ "SRv6 End.DX6 function to use\n"
+ "V6 Nexthop address to use\n"
"SRv6 End.DT6 function to use\n"
"Redirect table id to use\n"
"SRv6 End.DT4 function to use\n"
@@ -516,6 +519,9 @@ DEFPY (install_seg6local_routes,
if (seg6l_enddx4) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4;
ctx.nh4 = seg6l_enddx4_nh4;
+ } else if (seg6l_enddx6) {
+ action = ZEBRA_SEG6_LOCAL_ACTION_END_DX6;
+ ctx.nh6 = seg6l_enddx6_nh6;
} else if (seg6l_endx) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
ctx.nh6 = seg6l_endx_nh6;
diff --git a/snapcraft/snapcraft.yaml.in b/snapcraft/snapcraft.yaml.in
index cef02c3972..d90236f7a2 100644
--- a/snapcraft/snapcraft.yaml.in
+++ b/snapcraft/snapcraft.yaml.in
@@ -302,7 +302,7 @@ parts:
- libpcre2-8-0
source: https://github.com/CESNET/libyang.git
source-type: git
- source-tag: v2.1.80
+ source-tag: v2.1.128
plugin: cmake
configflags:
- -DCMAKE_INSTALL_PREFIX:PATH=/usr
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
index b2e8de5ce1..eb4e51a074 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
@@ -1,9 +1,9 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
index 7bee704182..8fe3ea41a6 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
@@ -1,9 +1,9 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0/24 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0/24 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
index 31071e760d..67b907131c 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
@@ -1,10 +1,10 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
Default local pref 100, local AS 100
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0/24 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0/24 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
index 53c4793bf4..4f21a5711b 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
@@ -1,7 +1,7 @@
BGP table version is 1, local router ID is 192.168.0.1
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
index fe3f0720d8..69e44e77ed 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
@@ -1,9 +1,9 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> fc00::/64 :: 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
index 363b4f5349..77aab38b0d 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
@@ -1,7 +1,7 @@
BGP table version is 1, local router ID is 192.168.0.1
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
- Network Next Hop Metric LocPrf Weight Path
- *> fc00::/64 :: 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
index 8c3229b45d..a99400a6b0 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
@@ -1,10 +1,10 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
Default local pref 100, local AS 100
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> fc00::/64 :: 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json b/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json
index 5cba71ef20..61be1df92a 100644
--- a/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json
+++ b/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json
@@ -4,51 +4,6 @@
"localAS": 101,
"routes":
{
- "2001:db8:6::/64": [
- {
- "stale": true,
- "valid": true,
- "bestpath": true,
- "pathFrom": "external",
- "prefix": "2001:db8:6::",
- "prefixLen": 64,
- "network": "2001:db8:6::\/64",
- "metric": 0,
- "weight": 0,
- "peerId": "2001:db8:4::1",
- "origin": "IGP",
- "nexthops": [
- { "ip": "2001:db8:4::1",
- "afi": "ipv6",
- "scope": "global",
- "used": true
- }
- ]
- }
- ],
- "2001:db8:7::/64": [
- {
- "stale": true,
- "valid": true,
- "bestpath": true,
- "pathFrom": "external",
- "prefix": "2001:db8:7::",
- "prefixLen": 64, "network":
- "2001:db8:7::\/64",
- "metric": 0,
- "weight": 0,
- "peerId": "2001:db8:4::1",
- "origin": "IGP",
- "nexthops": [
- {
- "ip": "2001:db8:4::1",
- "afi": "ipv6",
- "scope": "global",
- "used": true
- }
- ]
- }
- ],
"2001:db8:8::/64": [
{
"valid": true,
diff --git a/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json b/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json
index 8eea183285..36cdcc307d 100644
--- a/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json
+++ b/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json
@@ -32,49 +32,5 @@
}
]
}
- ],
- "2001:db8:6::/64": [{
- "distance": 20,
- "protocol": "bgp",
- "metric": 0,
- "selected": true,
- "destSelected": true,
- "prefix": "2001:db8:6::/64",
- "nexthops": [{
- "ip":"2001:db8:4::1",
- "active": true,
- "afi": "ipv6",
- "recursive":true
- },
- {
- "fib":true,
- "ip":"2001:db8:1::2",
- "afi": "ipv6",
- "interfaceName": "r1-eth0"
- }
- ]
- }
- ],
- "2001:db8:7::/64": [{
- "distance": 20,
- "protocol": "bgp",
- "metric": 0,
- "selected": true,
- "destSelected": true,
- "prefix": "2001:db8:7::/64",
- "nexthops": [{
- "ip":"2001:db8:4::1",
- "active": true,
- "afi": "ipv6",
- "recursive": true
- },
- {
- "fib":true,
- "ip":"2001:db8:1::2",
- "afi": "ipv6",
- "interfaceName":"r1-eth0"
- }
- ]
- }
]
}
diff --git a/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py
index 906687d1cd..d478e9902f 100644
--- a/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py
+++ b/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py
@@ -122,21 +122,23 @@ def test_bfd_connection():
def test_bfd_loss_intermediate():
"""
- Assert that BFD notices the bfd link down failure.
- but BGP entries should still be present
+ Assert that BGP notices the BFD link down failure.
+ The BGP entries should be flushed as the C-bit is set in both directions.
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
- expected = { "as":101, "peers":{ "2001:db8:4::1": { "state":"Established" } } }
- test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv6 uni summ json", expected)
+ expected = {"as": 101, "peers": {"2001:db8:4::1": {"state": "Established"}}}
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show bgp ipv6 uni summ json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
- assertmsg ='"r1" has not established bgp peering yet'
+ assertmsg = '"r1" has not established bgp peering yet'
assert result is None, assertmsg
- #assert False
+ # assert False
logger.info("removing IPv6 address from r2 to simulate loss of connectivity")
# Disable r2-eth0 ipv6 address
cmd = 'vtysh -c "configure terminal" -c "interface r2-eth1" -c "no ipv6 address 2001:db8:4::2/64"'
@@ -160,7 +162,7 @@ def test_bfd_loss_intermediate():
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
- logger.info("waiting for BGP entries to become stale")
+ logger.info("waiting for BGP entries to be removed")
for router in tgen.routers().values():
if router.name == "r2":
continue
diff --git a/tests/topotests/bfd_topo3/test_bfd_topo3.py b/tests/topotests/bfd_topo3/test_bfd_topo3.py
index f767b0e7b9..d7b2542f9f 100644
--- a/tests/topotests/bfd_topo3/test_bfd_topo3.py
+++ b/tests/topotests/bfd_topo3/test_bfd_topo3.py
@@ -189,7 +189,7 @@ def test_wait_bfd_convergence():
"show bfd peers json",
bfd_config,
)
- _, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=200, wait=1)
assertmsg = '"{}" BFD configuration failure'.format(router)
assert result is None, assertmsg
diff --git a/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
index 30f4a2f9b5..fee5f2d536 100644
--- a/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
+++ b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
@@ -81,8 +81,7 @@ def setup_module(mod):
for rname, router in router_list.items():
router.load_config(
- TopoRouter.RD_ZEBRA,
- os.path.join(CWD, "{}/zebra.conf".format(rname))
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
@@ -114,8 +113,8 @@ def test_bfd_connection():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("waiting for bfd peers to go up")
- router = tgen.gears['r1']
- json_file = "{}/{}/bfd_peers_status.json".format(CWD, 'r1')
+ router = tgen.gears["r1"]
+ json_file = "{}/{}/bfd_peers_status.json".format(CWD, "r1")
expected = json.loads(open(json_file).read())
test_func = partial(
diff --git a/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json
index e3703bf953..39ed61f718 100644
--- a/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json
+++ b/tests/topotests/bgp_asdot_regex/r1/show_bgp_ipv4.json
@@ -1,7 +1,6 @@
{
"vrfId": 0,
"vrfName": "default",
- "tableVersion": 3,
"routerId": "192.168.255.1",
"defaultLocPrf": 100,
"localAS": "1.1",
diff --git a/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json
index 1af4ff7e3d..30133175e2 100644
--- a/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json
+++ b/tests/topotests/bgp_asdot_regex/r2/show_bgp_ipv4.json
@@ -1,7 +1,6 @@
{
"vrfId": 0,
"vrfName": "default",
- "tableVersion": 3,
"routerId": "192.168.255.2",
"defaultLocPrf": 100,
"localAS": 65538,
diff --git a/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py
index 5d5f1659e9..4883e847c9 100644
--- a/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py
+++ b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py
@@ -44,8 +44,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py
index 6d17cdb4d9..e0c1b4953e 100644
--- a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py
+++ b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py
@@ -117,7 +117,9 @@ def test_bgp_color_extended_communities():
test_func = functools.partial(_bgp_check_route, r2, True)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
- assert result is None, "10.10.10.0/24 ext community is correctly not installed, but SHOULD be"
+ assert (
+ result is None
+ ), "10.10.10.0/24 ext community is correctly not installed, but SHOULD be"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py
index 000ea6075b..fdae9a3aa7 100644
--- a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py
+++ b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py
@@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../"))
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):
diff --git a/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py b/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py
index 4180bfcdf6..e9114bdbab 100644
--- a/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py
+++ b/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2"), "s2": ("r2", "r3")}
diff --git a/tests/topotests/bgp_confed1/test_bgp_confed1.py b/tests/topotests/bgp_confed1/test_bgp_confed1.py
index 57a8522020..7b37f4f6c7 100644
--- a/tests/topotests/bgp_confed1/test_bgp_confed1.py
+++ b/tests/topotests/bgp_confed1/test_bgp_confed1.py
@@ -32,7 +32,7 @@ pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
- for routern in range(1, 5):
+ for routern in range(1, 5):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s1")
@@ -47,8 +47,8 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r3"])
-def setup_module(mod):
+def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
@@ -67,6 +67,7 @@ def setup_module(mod):
# Initialize all routers.
tgen.start_router()
+
def teardown_module(_mod):
"Teardown the pytest environment"
tgen = get_topogen()
diff --git a/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py b/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py
index 5310d3b595..7bc0050109 100644
--- a/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py
+++ b/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py
@@ -18,7 +18,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r3")}
diff --git a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
index a0014c72e6..05e07486ae 100644
--- a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
+++ b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
@@ -30,8 +30,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 5):
diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py
index 6156968ded..50a1938ae3 100644
--- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py
+++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py
@@ -325,12 +325,14 @@ def teardown_module():
)
logger.info("=" * 40)
+
#####################################################
#
# Testcases
#
#####################################################
+
def test_verify_bgp_default_originate_in_IBGP_p0(request):
"""
Verify BGP default-originate route with IBGP peer
@@ -396,7 +398,9 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
step("After changing the BGP AS Path Verify the BGP Convergence")
BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, " Complete Convergence is expected after changing the ASN but failed to converge --> :Failed \n Error: {}".format(
+ assert (
+ BGP_CONVERGENCE is True
+ ), " Complete Convergence is expected after changing the ASN but failed to converge --> :Failed \n Error: {}".format(
BGP_CONVERGENCE
)
@@ -413,8 +417,10 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Failed to configure the static routes {} on router R1 \n Error: {}".format(
- tc_name,static_routes_input, result
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the static routes {} on router R1 \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step("verify IPv4 and IPv6 static route are configured and up on R1")
for addr_type in ADDR_TYPES:
@@ -429,8 +435,10 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r1", static_routes_input)
- assert result is True, "Testcase {} : Failed \n After configuring the static routes {} , the routes are not found in FIB \n Error: {}".format(
- tc_name,static_routes_input, result
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n After configuring the static routes {} , the routes are not found in FIB \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -483,7 +491,11 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
},
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure the redistribute static configuration \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the redistribute static configuration \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring redistribute command , verify static and connected routes ( loopback connected routes) are advertised on R2"
@@ -517,13 +529,17 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : After redistributing static routes the routes {} expected in FIB but NOT FOUND ......! \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : After redistributing static routes the routes {} expected in FIB but NOT FOUND ......! \n Error: {}".format(
+ tc_name, static_routes_input, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : After redistributing static routes the routes {} expected in RIB but NOT FOUND ......! \n Error: {}".format(
- tc_name, static_routes_input , result
+ assert (
+ result is True
+ ), "Testcase {} : After redistributing static routes the routes {} expected in RIB but NOT FOUND ......! \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -547,7 +563,11 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed Configuring default originate configuration. \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed Configuring default originate configuration. \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring default-originate command , verify default routes are advertised on R2 "
@@ -574,12 +594,16 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : post configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on FIB .......! FAILED \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : post configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on FIB .......! FAILED \n Error: {}".format(
tc_name, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : Failedpost configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on RIB......! FAILED \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failedpost configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on RIB......! FAILED \n Error: {}".format(
tc_name, result
)
step(
@@ -686,7 +710,9 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
step("After changing the BGP AS Path Verify the BGP Convergence")
BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, "Complete convergence is expeceted after changing the ASN os the routes ..! :Failed \n Error: {}".format(
+ assert (
+ BGP_CONVERGENCE is True
+ ), "Complete convergence is expeceted after changing the ASN os the routes ..! :Failed \n Error: {}".format(
BGP_CONVERGENCE
)
@@ -703,7 +729,9 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Failed to configure the static routes ....! Failed \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the static routes ....! Failed \n Error: {}".format(
tc_name, result
)
step("verify IPv4 and IPv6 static route are configured and up on R1")
@@ -719,8 +747,10 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input)
- assert result is True, "Testcase {} : Route is not found in {} in FIB ......! Failed \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : Route is not found in {} in FIB ......! Failed \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -773,7 +803,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
},
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure redistribute configuratin \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure redistribute configuratin \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring redistribute command , verify static and connected routes ( loopback connected routes) are advertised on R2"
@@ -806,11 +840,15 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static & and connected routes are expected but not found in FIB .... ! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : static & and connected routes are expected but not found in FIB .... ! \n Error: {}".format(
tc_name, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static & and connected routes are expected but not found in RIB .... ! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : static & and connected routes are expected but not found in RIB .... ! \n Error: {}".format(
tc_name, result
)
snapshot1 = get_prefix_count_route(tgen, topo, dut="r2", peer="r3")
@@ -830,7 +868,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure the default originate configuration \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the default originate configuration \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring default-originate command , verify default routes are advertised on R2 on both BGP RIB and FIB"
@@ -853,13 +895,17 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 FIB .....! NOT FOUND \n Error: {}".format(
- tc_name, NETWORK1_1,result
+ assert (
+ result is True
+ ), "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 FIB .....! NOT FOUND \n Error: {}".format(
+ tc_name, NETWORK1_1, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 RIB .....! NOT FOUND \n Error: {}".format(
- tc_name,NETWORK1_1, result
+ assert (
+ result is True
+ ), "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 RIB .....! NOT FOUND \n Error: {}".format(
+ tc_name, NETWORK1_1, result
)
step(
@@ -875,7 +921,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
metric=0,
expected_aspath="4000",
)
- assert result is True, "Testcase {} : Default route from R3 is expected with attributes in R2 RIB .....! NOT FOUND Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Default route from R3 is expected with attributes in R2 RIB .....! NOT FOUND Error: {}".format(
+ tc_name, result
+ )
step(
"Taking the snapshot2 of the prefix count after configuring the default originate"
@@ -968,7 +1018,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
step("After changing the BGP AS Path Verify the BGP Convergence")
BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, "Complete convergence is expected after changing ASN ....! ERROR :Failed \n Error: {}".format(
+ assert (
+ BGP_CONVERGENCE is True
+ ), "Complete convergence is expected after changing ASN ....! ERROR :Failed \n Error: {}".format(
BGP_CONVERGENCE
)
@@ -989,7 +1041,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Static Configuration is Failed \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Static Configuration is Failed \n Error: {}".format(
tc_name, result
)
@@ -1010,8 +1064,10 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r0", static_routes_input)
- assert result is True, "Testcase {} : routes {} unable is not found in R0 FIB \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : routes {} unable is not found in R0 FIB \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -1028,7 +1084,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure redistribute static configuration....! \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure redistribute static configuration....! \n Error: {}".format(
+ tc_name, result
+ )
step("verify IPv4 and IPv6 static route are configured and up on R1")
for addr_type in ADDR_TYPES:
@@ -1047,13 +1107,17 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r1", static_routes_input)
- assert result is True, "Testcase {} : Failed... Routes {} expected in r0 FIB after configuring the redistribute config \n Error: {}".format(
- tc_name,static_routes_input, result
+ assert (
+ result is True
+ ), "Testcase {} : Failed... Routes {} expected in r0 FIB after configuring the redistribute config \n Error: {}".format(
+ tc_name, static_routes_input, result
)
result = verify_bgp_rib(tgen, addr_type, "r1", static_routes_input)
- assert result is True, "Testcase {} : Failed... Routes {} expected in r0 RIB after configuring the redistribute config \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : Failed... Routes {} expected in r0 RIB after configuring the redistribute config \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -1094,7 +1158,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix list \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix list \n Error: {}".format(
+ tc_name, result
+ )
step(
"Configure IPV4 and IPv6 route-map (RMv4 and RMv6 ) matching prefix-list (Pv4 and Pv6) respectively on R1"
@@ -1120,7 +1188,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the route map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the route map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Configure default-originate with route-map (RMv4 and RMv6) on R1, on BGP IPv4 and IPv6 address family "
@@ -1142,7 +1214,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure the default originate \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the default originate \n Error: {}".format(
+ tc_name, result
+ )
step("Verify the default route is received in BGP RIB and FIB")
step(
@@ -1167,7 +1243,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed...! Expected default route from R1 not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed...! Expected default route from R1 not found in FIB \n Error: {}".format(
tc_name, result
)
@@ -1178,7 +1256,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed...! Expected default route from R1 not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed...! Expected default route from R1 not found in RIB \n Error: {}".format(
tc_name, result
)
step("Remove route-map RMv4 and RMv6 from default-originate command in R1")
@@ -1196,7 +1276,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to remove the default originate conditional route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to remove the default originate conditional route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Verify BGP RIB and FIB After removing route-map , default route still present on R2"
@@ -1221,7 +1305,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default route from R1 is not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is not found in FIB \n Error: {}".format(
tc_name, result
)
@@ -1232,7 +1318,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default route from R1 is not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is not found in RIB \n Error: {}".format(
tc_name, result
)
@@ -1266,7 +1354,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure the Default originate route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the Default originate route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring default-originate command , verify default routes are advertised on R2 "
@@ -1290,7 +1382,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default Route from R1 is not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default Route from R1 is not found in FIB \n Error: {}".format(
tc_name, result
)
@@ -1301,7 +1395,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default Route from R1 is not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default Route from R1 is not found in RIB \n Error: {}".format(
tc_name, result
)
@@ -1345,7 +1441,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to delete the prefix list Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to delete the prefix list Error: {}".format(
+ tc_name, result
+ )
step(
"Verify BGP RIB and FIB After deleting prefix-list , verify IPv4 and IPv6 default route got removed from DUT "
@@ -1426,7 +1526,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix lists Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix lists Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring the Prefixlist cross checking the BGP Default route is configured again , before deleting the route map"
@@ -1452,7 +1556,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
expected=True,
)
- assert result is True, "Testcase {} : Failed Default route from R1 is expected in FIB but not found \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is expected in FIB but not found \n Error: {}".format(
tc_name, result
)
@@ -1464,14 +1570,20 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
expected=True,
)
- assert result is True, "Testcase {} : Failed Default route from R1 is expected in RIB but not found \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is expected in RIB but not found \n Error: {}".format(
tc_name, result
)
step("Deleting the routemap")
input_dict = {"r1": {"route_maps": ["RMv4", "RMv6"]}}
result = delete_route_maps(tgen, input_dict)
- assert result is True, "Testcase {} : Failed to delete the Route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to delete the Route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Verify BGP RIB and FIB ,After deleting route-map , verify IPv4 and IPv6 default route got removed from DUT"
@@ -1605,7 +1717,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Failed to configure the static routes \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the static routes \n Error: {}".format(
tc_name, result
)
step("verify IPv4 and IPv6 static route are configured and up on R4")
@@ -1625,8 +1739,10 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input)
- assert result is True, "Testcase {} : Failed Static route {} is not found in R4 FIB \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : Failed Static route {} is not found in R4 FIB \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -1643,7 +1759,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure the redistribute static \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the redistribute static \n Error: {}".format(
+ tc_name, result
+ )
step("verify IPv4 and IPv6 static route are configured and up on R3")
for addr_type in ADDR_TYPES:
@@ -1662,11 +1782,15 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input)
- assert result is True, "Testcase {} : Failed static routes from R1 and R3 is not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed static routes from R1 and R3 is not found in FIB \n Error: {}".format(
tc_name, result
)
result = verify_bgp_rib(tgen, addr_type, "r3", static_routes_input)
- assert result is True, "Testcase {} : Failed static routes from R1 and R3 is not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed static routes from R1 and R3 is not found in RIB \n Error: {}".format(
tc_name, result
)
@@ -1698,12 +1822,20 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix lists \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix lists \n Error: {}".format(
+ tc_name, result
+ )
step("verify IPv4 and IPv6 Prefix list got configured on R3")
input_dict = {"r3": {"prefix_lists": ["Pv4", "Pv6"]}}
result = verify_prefix_lists(tgen, input_dict)
- assert result is True, "Testcase {} : Failed ..! configured prefix lists {} are not found \n Error: {}".format(tc_name,input_dict, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed ..! configured prefix lists {} are not found \n Error: {}".format(
+ tc_name, input_dict, result
+ )
step(
"Configure IPv4 and IPv6 route-map ( RMv4 and RMv6 ) matching prefix-list (Pv4 and Pv6 ) respectively on R3"
@@ -1729,7 +1861,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Taking the snapshot of the prefix count before configuring the default originate"
)
@@ -1754,7 +1890,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure default-originate \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure default-originate \n Error: {}".format(
+ tc_name, result
+ )
step("Verify the default route is NOT received in BGP RIB and FIB on R2 ")
step(
@@ -1836,7 +1976,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix lists Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix lists Error: {}".format(
+ tc_name, result
+ )
step("Verify BGP default route for IPv4 and IPv6 is received on R2")
@@ -1859,7 +2003,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R3[addr_type],
)
- assert result is True, "Testcase {} : Failed Default routes are expected in R2 FIB from R3 but not found ....! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default routes are expected in R2 FIB from R3 but not found ....! \n Error: {}".format(
tc_name, result
)
@@ -1870,7 +2016,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R3[addr_type],
)
- assert result is True, "Testcase {} : Failed Default routes are expected in R2 RIB from R3 but not found ....! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default routes are expected in R2 RIB from R3 but not found ....! \n Error: {}".format(
tc_name, result
)
@@ -1914,7 +2062,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to remove prefix-lists from R3 Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to remove prefix-lists from R3 Error: {}".format(
+ tc_name, result
+ )
step(
"After Removing route BGP default route for IPv4 and IPv6 is NOT received on R2"
diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py
index 59f833b93c..4e8bda55cf 100644
--- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py
+++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py
@@ -955,6 +955,7 @@ def test_verify_bgp_default_originate_route_map_in_OUT_p1(request):
write_test_footer(tc_name)
+
def test_verify_bgp_default_originate_route_map_in_IN_p1(request):
"""Verify BGP default originate route-map with IN route-map"""
tgen = get_topogen()
@@ -1472,6 +1473,7 @@ def test_verify_bgp_default_originate_route_map_in_IN_p1(request):
)
write_test_footer(tc_name)
+
def test_verify_default_originate_after_removing_default_originate_p1(request):
"""Verify BGP default route after removing default-originate"""
@@ -2232,9 +2234,9 @@ def test_verify_default_originate_after_removing_default_originate_p1(request):
)
write_test_footer(tc_name)
+
def test_verify_default_originate_route_with_GR_p1(request):
- """ "Verify default-originate route with GR "
- """
+ """ "Verify default-originate route with GR " """
tgen = get_topogen()
global BGP_CONVERGENCE
global topo
@@ -2250,14 +2252,13 @@ def test_verify_default_originate_route_with_GR_p1(request):
if BGP_CONVERGENCE != True:
pytest.skip("skipped because of BGP Convergence failure")
-
step("Configure IPV4 and IPV6 IBGP between R1 and R2 ")
step("Configure IPV4 and IPV6 EBGP between R2 to R3 ")
- r0_local_as = topo['routers']['r0']['bgp']['local_as']
- r1_local_as = topo['routers']['r1']['bgp']['local_as']
- r2_local_as = topo['routers']['r2']['bgp']['local_as']
- r3_local_as = topo['routers']['r3']['bgp']['local_as']
- r4_local_as = topo['routers']['r4']['bgp']['local_as']
+ r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"]
+ r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"]
+ r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"]
+ r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"]
+ r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"]
input_dict = {
"r0": {
"bgp": {
@@ -2336,33 +2337,14 @@ def test_verify_default_originate_route_with_GR_p1(request):
"bgp": {
"local_as": local_as,
"address_family": {
- "ipv4": {
- "unicast": {
- "default_originate":{
- "r2":{
-
- }
-
- }
-
- }
- }, "ipv6": {
- "unicast": {
- "default_originate":{
- "r2":{
-
- }
-
- }
- }
- }
- }
+ "ipv4": {"unicast": {"default_originate": {"r2": {}}}},
+ "ipv6": {"unicast": {"default_originate": {"r2": {}}}},
+ },
}
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step(
"R2 received default-originate routes and advertised it to R3 , verify on R2 and R3"
@@ -2383,17 +2365,28 @@ def test_verify_default_originate_route_with_GR_p1(request):
}
}
- result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_fib_routes(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_bgp_rib(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
-
step(" Kill BGPd session on R2")
kill_router_daemons(tgen, "r2", ["bgpd"])
start_router_daemons(tgen, "r2", ["bgpd"])
@@ -2411,17 +2404,30 @@ def test_verify_default_originate_route_with_GR_p1(request):
}
}
- result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_fib_routes(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_bgp_rib(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
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_default_originate/test_default_originate_conditional_routemap.py b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py
index 82c4e7e0ab..f67a431c7e 100644
--- a/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py
+++ b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py
@@ -75,6 +75,7 @@ NETWORK1_1 = {"ipv4": "198.51.1.1/32", "ipv6": "2001:DB8::1:1/128"}
DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"}
NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
+
def setup_module(mod):
"""
Sets up the pytest environment
@@ -818,11 +819,11 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
step("Configure IPv4 and IPv6 , EBGP neighbor between R3 and R2")
step("Configure IPv4 and IPv6 IBGP neighbor between R3 and R4")
- r0_local_as = topo['routers']['r0']['bgp']['local_as']
- r1_local_as = topo['routers']['r1']['bgp']['local_as']
- r2_local_as = topo['routers']['r2']['bgp']['local_as']
- r3_local_as = topo['routers']['r3']['bgp']['local_as']
- r4_local_as = topo['routers']['r4']['bgp']['local_as']
+ r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"]
+ r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"]
+ r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"]
+ r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"]
+ r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"]
input_dict = {
"r0": {
"bgp": {
@@ -1026,22 +1027,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "200",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "200",
+ "as_action": "prepend",
}
-
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "300",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "300",
+ "as_action": "prepend",
}
+ },
},
],
"RMv6": [
@@ -1049,21 +1049,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "200",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "200",
+ "as_action": "prepend",
}
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "300",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "300",
+ "as_action": "prepend",
}
+ },
},
],
}
@@ -1122,22 +1122,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "500",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "500",
+ "as_action": "prepend",
}
-
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "600",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "600",
+ "as_action": "prepend",
}
+ },
},
],
"RMv6": [
@@ -1145,21 +1144,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "500",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "500",
+ "as_action": "prepend",
}
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "600",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "600",
+ "as_action": "prepend",
}
+ },
},
],
}
@@ -1170,7 +1169,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
-
step("As path 500 added to IPv4 and IPv6 default -originate route received on R2")
result = verify_rib_default_route(
tgen,
@@ -1232,7 +1230,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes "
)
-
DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"}
result = verify_rib_default_route(
tgen,
@@ -1244,7 +1241,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
expected_aspath="4000 500",
)
-
step(
"Modify route-map seq1 configure metric 50 and route-map seq2 configure metric 100 IPv4 and IPv6 route-map "
)
@@ -1294,7 +1290,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes "
)
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1314,7 +1309,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
{
"action": "permit",
"seq_id": "1",
-
"set": {
"path": {
"as_num": "500",
@@ -1374,9 +1368,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify AS-prepend is deleted from default originate route and metric value only present on R2 for IPv4 and IPv6 default routes "
)
-
-
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1388,7 +1379,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
-
step("Delete metric value from IP4 and IPv6 route-map configured on R3 ")
route_map = {
"r3": {
@@ -1428,8 +1418,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Metric value deleted from IPv4 and IPv6 default route on R2 ,verify default routes "
)
-
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1443,11 +1431,11 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
step("Change IPv4 and IPv6 , EBGP to IBGP neighbor between R3 and R2")
step("Change IPv4 and IPv6 IBGP to EBGP neighbor between R3 and R4")
- r0_local_as = topo['routers']['r0']['bgp']['local_as']
- r1_local_as = topo['routers']['r1']['bgp']['local_as']
- r2_local_as = topo['routers']['r2']['bgp']['local_as']
- r3_local_as = topo['routers']['r3']['bgp']['local_as']
- r4_local_as = topo['routers']['r4']['bgp']['local_as']
+ r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"]
+ r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"]
+ r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"]
+ r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"]
+ r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"]
input_dict = {
"r0": {
"bgp": {
@@ -1459,7 +1447,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"local_as": r1_local_as,
}
},
-
"r2": {
"bgp": {
"local_as": 1111,
@@ -1645,8 +1632,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes "
)
-
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1656,7 +1641,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
locPrf=50,
)
-
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
step(
@@ -1708,9 +1692,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Modified local-preference value received on R2 for IPv4 and IPv6 default routes "
)
-
-
-
DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"}
result = verify_rib_default_route(
tgen,
@@ -1724,13 +1705,15 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
# updating the topology with the updated AS-Number to avoid conflict in con configuring the AS
updated_topo = topo
- updated_topo['routers']['r0']['bgp']['local_as']=get_dut_as_number(tgen,"r0")
- updated_topo['routers']['r1']['bgp']['local_as']=get_dut_as_number(tgen,"r1")
- updated_topo['routers']['r2']['bgp']['local_as']=get_dut_as_number(tgen,"r2")
- updated_topo['routers']['r3']['bgp']['local_as']=get_dut_as_number(tgen,"r3")
- updated_topo['routers']['r4']['bgp']['local_as']=get_dut_as_number(tgen,"r4")
+ updated_topo["routers"]["r0"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r0")
+ updated_topo["routers"]["r1"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r1")
+ updated_topo["routers"]["r2"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r2")
+ updated_topo["routers"]["r3"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r3")
+ updated_topo["routers"]["r4"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r4")
- step("Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ")
+ step(
+ "Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command "
+ )
local_as = get_dut_as_number(tgen, dut="r4")
shut_neighbor = {
"r4": {
@@ -1740,46 +1723,41 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"ipv4": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":True}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": True}}}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":True}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": True}}}
}
}
- }
- }
+ },
+ },
}
}
}
result = create_router_bgp(tgen, updated_topo, shut_neighbor)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- interface = topo['routers']['r3']['links']['r4']['interface']
- input_dict = {
- "r1": {
- "interface_list": [interface],
- "status": "down"
- }
- }
+ interface = topo["routers"]["r3"]["links"]["r4"]["interface"]
+ input_dict = {"r1": {"interface_list": [interface], "status": "down"}}
result = interface_status(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Shut down the interface failed ! \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Shut down the interface failed ! \n Error: {}".format(
+ tc_name, result
+ )
step("After shutting the interface verify the BGP convergence")
- result = verify_bgp_convergence(tgen,topo,expected=False)
- assert result is not True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result)
+ result = verify_bgp_convergence(tgen, topo, expected=False)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(
+ tc_name, result
+ )
step("verify default route deleted from R2 ")
result = verify_rib_default_route(
@@ -1788,8 +1766,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in RIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1797,11 +1780,17 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in FIB -> {}".format( tc_name, result)
-
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in FIB -> {}".format(
+ tc_name, result
+ )
- step("no Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ")
+ step(
+ "no Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command "
+ )
local_as = get_dut_as_number(tgen, dut="r4")
shut_neighbor = {
"r4": {
@@ -1811,46 +1800,39 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"ipv4": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":False}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": False}}}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":False}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": False}}}
}
}
- }
- }
+ },
+ },
}
}
}
result = create_router_bgp(tgen, updated_topo, shut_neighbor)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- interface = topo['routers']['r3']['links']['r4']['interface']
- input_dict = {
- "r1": {
- "interface_list": [interface],
- "status": "up"
- }
- }
+ interface = topo["routers"]["r3"]["links"]["r4"]["interface"]
+ input_dict = {"r1": {"interface_list": [interface], "status": "up"}}
result = interface_status(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Bring up interface failed ! \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Bring up interface failed ! \n Error: {}".format(tc_name, result)
step("After no shutting the interface verify the BGP convergence")
- result = verify_bgp_convergence(tgen,topo,expected=True)
- assert result is True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result)
+ result = verify_bgp_convergence(tgen, topo, expected=True)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(
+ tc_name, result
+ )
step("After no shut neighbor , verify default route relearn on R2")
result = verify_rib_default_route(
@@ -1859,8 +1841,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=True)
- assert result is True, "Testcase {} : Failed \n Error: After no Shut down interface the default route is expected but found in RIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After no Shut down interface the default route is expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1868,10 +1855,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=True)
- assert result is True, "Testcase {} : Failed \n Error: After Shut down interface the default route is expected but found in FIB -> {}".format( tc_name, result)
-
-
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After Shut down interface the default route is expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Remove IPv4/IPv6 static route configure on R4")
for addr_type in ADDR_TYPES:
@@ -1881,7 +1871,7 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
{
"network": [NETWORK1_1[addr_type]],
"next_hop": NEXT_HOP_IP[addr_type],
- "delete": True
+ "delete": True,
}
]
}
@@ -1902,12 +1892,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
]
}
}
- result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_fib_routes(
+ tgen, addr_type, "r4", static_routes_input, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_bgp_rib(
+ tgen, addr_type, "r4", static_routes_input, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
@@ -1918,8 +1912,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in RIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1927,9 +1926,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in FIB -> {}".format( tc_name, result)
-
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Configuring the static route back in r4")
for addr_type in ADDR_TYPES:
@@ -1959,12 +1962,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
]
}
}
- result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=True)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_fib_routes(
+ tgen, addr_type, "r4", static_routes_input, expected=True
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=True)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_bgp_rib(
+ tgen, addr_type, "r4", static_routes_input, expected=True
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
@@ -1975,8 +1982,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in RIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1984,8 +1996,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in FIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Deactivate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)")
@@ -1999,15 +2016,14 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"r3": {"dest_link": {"r4": {"deactivate": "ipv4"}}}
}
},
-
- },"ipv6": {
+ },
+ "ipv6": {
"unicast": {
"neighbor": {
"r3": {"dest_link": {"r4": {"deactivate": "ipv6"}}}
}
},
-
- }
+ },
}
}
}
@@ -2022,8 +2038,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in RIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -2031,8 +2052,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in FIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Activate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)")
@@ -2046,15 +2072,14 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"r3": {"dest_link": {"r4": {"activate": "ipv4"}}}
}
},
-
- },"ipv6": {
+ },
+ "ipv6": {
"unicast": {
"neighbor": {
"r3": {"dest_link": {"r4": {"activate": "ipv6"}}}
}
},
-
- }
+ },
}
}
}
@@ -2064,7 +2089,7 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
step("Verify bgp convergence.")
bgp_convergence = verify_bgp_convergence(tgen, updated_topo)
- assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+ assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, bgp_convergence
)
step("After Activating the BGP neighbor , verify default route learned on R2")
@@ -2074,8 +2099,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in RIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -2083,10 +2113,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in FIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in FIB -> {}".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_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
index 9a0f5621dc..8269322215 100644
--- a/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
+++ b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
@@ -194,6 +192,7 @@ def test_bgp_check_fqdn():
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "FQDN capability disabled, but we still have a hostname"
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py
index 7511d57e3e..4d7d46c3e8 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py
@@ -20,7 +20,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -29,8 +29,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py
index 338886d5f4..26fae17c5e 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py
index 4644ef3293..d67bfea45e 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py
@@ -18,7 +18,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -28,8 +28,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py
index ba95bd1614..9e1f26f21e 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
index aa9ad5f0e8..f6c1e25fd6 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
index 737e694701..128283bbc3 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
index 34f7dc8cd4..d9ccd6979c 100644
--- a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
+++ b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
@@ -35,8 +35,6 @@ sys.path.append(os.path.join(CWD, "../"))
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):
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/__init__.py b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf
new file mode 100644
index 0000000000..7476a3723d
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf
@@ -0,0 +1,4 @@
+!
+int c1-eth0
+ ip address 192.168.0.1/24
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf
new file mode 100644
index 0000000000..a203daae05
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf
@@ -0,0 +1,4 @@
+!
+int c2-eth0
+ ip address 192.168.0.2/24
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf
new file mode 100644
index 0000000000..0534518cfb
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf
@@ -0,0 +1,30 @@
+!
+!debug bgp neighbor
+!debug route-map detail
+!
+vni 10
+!
+int lo
+ ip address 10.10.10.1/32
+!
+int r1-eth1
+ ip address 192.168.1.1/24
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ network 10.10.10.10/32
+ exit-address-family
+ !
+ address-family l2vpn evpn
+ neighbor 192.168.1.2 activate
+ advertise-all-vni
+ advertise ipv4 unicast
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf
new file mode 100644
index 0000000000..353302b9e7
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf
@@ -0,0 +1,25 @@
+!
+!debug bgp neighbor
+!
+int lo
+ ip address 10.10.10.2/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ !
+ address-family l2vpn evpn
+ neighbor 192.168.1.1 activate
+ neighbor 192.168.1.1 maximum-prefix 2
+ advertise-all-vni
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py
new file mode 100644
index 0000000000..5469eff144
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+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": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ tgen.net["r1"].cmd(
+ """
+ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.1 nolearning
+ip link add name br10 type bridge
+ip link set dev vxlan10 master br10
+ip link set dev r1-eth0 master br10
+ip link set up dev br10
+ip link set up dev vxlan10"""
+ )
+
+ tgen.net["r2"].cmd(
+ """
+ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.2 nolearning
+ip link add name br10 type bridge
+ip link set dev vxlan10 master br10
+ip link set dev r2-eth1 master br10
+ip link set up dev br10
+ip link set up dev vxlan10"""
+ )
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_evpn_maximum_prefix():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp l2vpn evpn summary failed json"))
+ expected = {
+ "peers": {
+ "192.168.1.1": {
+ "lastNotificationReason": "Cease/Maximum Number of Prefixes Reached",
+ "lastResetDueTo": "BGP Notification send",
+ }
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert result is None, "Can't limit maximum-prefixes for EVPN routes"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
index 33b6d08aba..d246517898 100644
--- a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65101
+ timers bgp 3 10
bgp router-id 192.168.100.13
no bgp ebgp-requires-policy
neighbor 192.168.50.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
index 428998b0fe..6855a436d4 100644
--- a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65101
+ timers bgp 3 10
bgp router-id 192.168.100.14
no bgp ebgp-requires-policy
neighbor 192.168.61.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
index b9fce46ea4..7d6fef699d 100644
--- a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65001
+ timers bgp 3 10
bgp router-id 192.168.100.13
no bgp ebgp-requires-policy
neighbor 192.168.50.2 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
index 1430e10b68..c651ada686 100644
--- a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65001
+ timers bgp 3 10
bgp router-id 192.168.100.14
no bgp ebgp-requires-policy
neighbor 192.168.60.2 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py
index 7d8ddac4c8..b033e9c2eb 100644
--- a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py
+++ b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py
@@ -37,8 +37,6 @@ from lib import topotest
# Required to instantiate the topology builder class.
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd, pytest.mark.pimd]
-
#####################################################
##
## Network Topology Definition
diff --git a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
index 2c1c695a18..62b7ec5855 100644
--- a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65002
+ timers bgp 3 10
bgp router-id 192.168.100.15
no bgp ebgp-requires-policy
neighbor 192.168.1.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
index 8b0ce1d98f..3ceb974c47 100644
--- a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65003
+ timers bgp 3 10
bgp router-id 192.168.100.16
no bgp ebgp-requires-policy
neighbor 192.168.2.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
index 5247dc1ebd..ecaf85ddb7 100644
--- a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65004
+ timers bgp 3 10
bgp router-id 192.168.100.17
no bgp ebgp-requires-policy
neighbor 192.168.3.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
index ec56360176..c7e152498c 100644
--- a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
@@ -6,6 +6,7 @@ frr defaults datacenter
! debug bgp zebra
!
router bgp 65005
+ timers bgp 3 10
bgp router-id 192.168.100.18
no bgp ebgp-requires-policy
neighbor 192.168.4.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
index 2041a4091d..603f069fe3 100755
--- a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
+++ b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
@@ -179,7 +179,7 @@ def setup_module(mod):
pe.cmd_raises("sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept))
# For all registered routers, load the zebra configuration file
- for (name, router) in tgen.routers().items():
+ for name, router in tgen.routers().items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(name))
)
@@ -230,11 +230,11 @@ def evpn_gateway_ip_show_op_check(trigger=" "):
"zebra_vrf_ipv6": "show ipv6 route vrf vrf-blue json",
}
- for (name, pe) in tgen.gears.items():
+ for name, pe in tgen.gears.items():
if name not in PES:
continue
- for (cmd_key, command) in show_commands.items():
+ for cmd_key, command in show_commands.items():
expected_op_file = "{0}/{1}/{2}_{3}.json".format(
CWD, name, cmd_key, trigger
)
diff --git a/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py b/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py
index 5781684a88..2df0fd0e6c 100644
--- a/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py
+++ b/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")}
diff --git a/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py b/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py
index eb05986fe1..a5e5bdcee9 100644
--- a/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py
+++ b/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py
@@ -124,7 +124,8 @@ def test_rt_extcomm_list_delete():
# check for the deletion of the extended community
test_func = functools.partial(
- _bgp_extcomm_list_del_check, r2, "10.10.10.1/32", r"1.1.1.1:1")
+ _bgp_extcomm_list_del_check, r2, "10.10.10.1/32", r"1.1.1.1:1"
+ )
_, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5)
assert result, "RT extended community 1.1.1.1:1 was not stripped."
@@ -138,7 +139,8 @@ def test_soo_extcomm_list_delete():
# check for the deletion of the extended community
test_func = functools.partial(
- _bgp_extcomm_list_del_check, r2, "10.10.10.2/32", r"2.2.2.2:2")
+ _bgp_extcomm_list_del_check, r2, "10.10.10.2/32", r"2.2.2.2:2"
+ )
_, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5)
assert result, "SoO extended community 2.2.2.2:2 was not stripped."
@@ -152,7 +154,8 @@ def test_nt_extcomm_list_delete():
# check for the deletion of the extended community
test_func = functools.partial(
- _bgp_extcomm_list_del_check, r2, "10.10.10.3/32", r"3.3.3.3")
+ _bgp_extcomm_list_del_check, r2, "10.10.10.3/32", r"3.3.3.3"
+ )
_, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5)
assert result, "NT extended community 3.3.3.3:0 was not stripped."
diff --git a/tests/topotests/bgp_extended_link_bandwidth/__init__.py b/tests/topotests/bgp_extended_link_bandwidth/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_extended_link_bandwidth/__init__.py
diff --git a/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf
new file mode 100644
index 0000000000..d0c0813e84
--- /dev/null
+++ b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf
@@ -0,0 +1,32 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+router bgp 65000
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.1.2 remote-as internal
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ neighbor 192.168.1.2 extended-link-bandwidth
+ address-family ipv4 unicast
+ network 10.10.10.40/32
+ network 10.10.10.100/32
+ network 10.10.10.200/32
+ neighbor 192.168.1.2 route-map r2 out
+ exit-address-family
+!
+ip prefix-list p40 seq 5 permit 10.10.10.40/32
+ip prefix-list p100 seq 5 permit 10.10.10.100/32
+ip prefix-list p200 seq 5 permit 10.10.10.200/32
+!
+route-map r2 permit 10
+ match ip address prefix-list p40
+ set extcommunity bandwidth 40000
+route-map r2 permit 20
+ match ip address prefix-list p100
+ set extcommunity bandwidth 100000
+route-map r2 permit 30
+ match ip address prefix-list p200
+ set extcommunity bandwidth 200000
+exit
diff --git a/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf
new file mode 100644
index 0000000000..5cad150aef
--- /dev/null
+++ b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf
@@ -0,0 +1,10 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65000
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as internal
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+!
diff --git a/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py
new file mode 100644
index 0000000000..e7058f5392
--- /dev/null
+++ b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+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 _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_dynamic_capability_role():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json detail"))
+ expected = {
+ "routes": {
+ "10.10.10.40/32": {
+ "paths": [
+ {
+ "extendedIpv6Community": {
+ "string": "LB:65000:5000000000 (40.000 Gbps)",
+ }
+ }
+ ]
+ },
+ "10.10.10.100/32": {
+ "paths": [
+ {
+ "extendedIpv6Community": {
+ "string": "LB:65000:12500000000 (100.000 Gbps)",
+ }
+ }
+ ]
+ },
+ "10.10.10.200/32": {
+ "paths": [
+ {
+ "extendedIpv6Community": {
+ "string": "LB:65000:25000000000 (200.000 Gbps)",
+ }
+ }
+ ]
+ },
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see link bandwidths as expected"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
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
index eef122b369..a5db20e474 100644
--- 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
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf
index 50d1583873..3d4d3a8ee5 100644
--- a/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf
@@ -1,3 +1,10 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
router bgp 65001
no bgp ebgp-requires-policy
bgp graceful-restart
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf
deleted file mode 100644
index e65bfb2c3a..0000000000
--- a/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-!
-interface lo
- ip address 172.16.255.1/32
-!
-interface r1-eth0
- ip address 192.168.255.1/24
-!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf
index 97418ca9a0..f5ba4eae05 100644
--- a/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf
@@ -1,3 +1,8 @@
+no zebra nexthop kernel enable
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
router bgp 65002
no bgp ebgp-requires-policy
bgp graceful-restart
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf
deleted file mode 100644
index 758d797ad6..0000000000
--- a/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-no zebra nexthop kernel enable
-!
-interface r2-eth0
- ip address 192.168.255.2/24
-!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf b/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf
new file mode 100644
index 0000000000..1d84ec6eee
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf
@@ -0,0 +1,19 @@
+no zebra nexthop kernel enable
+!
+interface lo
+ ip address 172.16.255.3/32
+!
+interface r3-eth0
+ ip address 192.168.34.3/24
+!
+router bgp 65003
+ no bgp ebgp-requires-policy
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.34.4 remote-as external
+ neighbor 192.168.34.4 timers 1 3
+ neighbor 192.168.34.4 timers connect 1
+ neighbor 192.168.34.4 graceful-restart
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf b/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf
new file mode 100644
index 0000000000..58907916f4
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf
@@ -0,0 +1,13 @@
+no zebra nexthop kernel enable
+!
+interface r4-eth0
+ ip address 192.168.34.4/24
+!
+router bgp 65004
+ no bgp ebgp-requires-policy
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.34.3 remote-as external
+ neighbor 192.168.34.3 timers 1 3
+ neighbor 192.168.34.3 timers connect 1
+ neighbor 192.168.34.3 graceful-restart
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py
new file mode 100644
index 0000000000..2354c0cd3d
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+"""
+Test if routes are retained during BGP restarts using
+ Graceful Restart per-neighbor.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step, stop_router
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 5):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_gr_restart_retain_routes():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r4 = tgen.gears["r4"]
+
+ def _bgp_converge():
+ output = json.loads(r4.vtysh_cmd("show bgp ipv4 neighbors 192.168.34.3 json"))
+ expected = {
+ "192.168.34.3": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_bgp_retained_routes():
+ output = json.loads(r4.vtysh_cmd("show bgp ipv4 unicast 172.16.255.3/32 json"))
+ expected = {"paths": [{"stale": True}]}
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_kernel_retained_routes():
+ output = json.loads(
+ r4.cmd("ip -j route show 172.16.255.3/32 proto bgp dev r4-eth0")
+ )
+ expected = [{"dst": "172.16.255.3", "gateway": "192.168.34.3", "metric": 20}]
+ return topotest.json_cmp(output, expected)
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R4"
+
+ step("Restart R3")
+ stop_router(tgen, "r3")
+
+ step("Check if routes (BGP) are retained at R4")
+ test_func = functools.partial(_bgp_check_bgp_retained_routes)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP retained routes on R4"
+
+ step("Check if routes (Kernel) are retained at R4")
+ assert (
+ _bgp_check_kernel_retained_routes() is None
+ ), "Failed to retain BGP routes in kernel on R4"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
index a820b4b221..abf737ff34 100644
--- a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
+++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
@@ -42,13 +42,8 @@ def setup_module(mod):
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))
- )
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
tgen.start_router()
@@ -83,8 +78,10 @@ def test_bgp_gr_restart_retain_routes():
return topotest.json_cmp(output, expected)
def _bgp_check_kernel_retained_routes():
- output = json.loads(r2.cmd("ip -j route show 172.16.255.1/32 proto bgp dev r2-eth0"))
- expected = [{"dst":"172.16.255.1","gateway":"192.168.255.1","metric":20}]
+ output = json.loads(
+ r2.cmd("ip -j route show 172.16.255.1/32 proto bgp dev r2-eth0")
+ )
+ expected = [{"dst": "172.16.255.1", "gateway": "192.168.255.1", "metric": 20}]
return topotest.json_cmp(output, expected)
step("Initial BGP converge")
@@ -101,7 +98,9 @@ def test_bgp_gr_restart_retain_routes():
assert result is None, "Failed to see BGP retained routes on R2"
step("Check if routes (Kernel) are retained at R2")
- assert _bgp_check_kernel_retained_routes() is None, "Failed to retain BGP routes in kernel on R2"
+ assert (
+ _bgp_check_kernel_retained_routes() is None
+ ), "Failed to retain BGP routes in kernel on R2"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py
index 0deb181f3e..489c59fa40 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py
@@ -1,17 +1,17 @@
from lib.lutil import luCommand
luCommand(
- "r1", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH"
+ "r1", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH"
)
luCommand(
- "r3", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH"
+ "r3", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH"
)
luCommand(
- "r4", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH"
+ "r4", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH"
)
-luCommand("r1", 'vtysh -c "show bgp ipv4 uni"', "i5.*i5", "wait", "See CE routes")
-luCommand("r3", 'vtysh -c "show bgp ipv4 uni"', "i5.*i5", "wait", "See CE routes")
-luCommand("r4", 'vtysh -c "show bgp ipv4 uni"', "i5.*i5", "wait", "See CE routes")
+luCommand("r1", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes")
+luCommand("r3", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes")
+luCommand("r4", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes")
luCommand("ce1", 'vtysh -c "show bgp ipv4 uni 5.1.0.0/24"', "", "none", "See CE routes")
luCommand("r1", 'vtysh -c "show bgp ipv4 uni 5.1.0.0/24"', "", "none", "See CE routes")
luCommand("ce2", 'vtysh -c "show bgp ipv4 uni 5.1.0.0/24"', "", "none", "See CE routes")
@@ -39,22 +39,22 @@ luCommand(
luCommand(
"r3",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.1/32",
+ "i 99.0.0.1/32",
"wait",
"See R1s static address",
)
luCommand(
"r4",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.1/32",
+ "i 99.0.0.1/32",
"wait",
"See R1s static address",
)
luCommand(
- "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i5.*i5", "wait", "See R1s imports"
+ "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i 5.*i 5", "wait", "See R1s imports"
)
luCommand(
- "r4", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i5.*i5", "wait", "See R1s imports"
+ "r4", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i 5.*i 5", "wait", "See R1s imports"
)
luCommand(
@@ -86,14 +86,14 @@ if have2ndImports:
luCommand(
"r1",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.2/32",
+ "i 99.0.0.2/32",
"wait",
"See R3s static address",
)
luCommand(
"r4",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.2/32",
+ "i 99.0.0.2/32",
"wait",
"See R3s static address",
)
@@ -101,14 +101,14 @@ if have2ndImports:
luCommand(
"r1",
'vtysh -c "show bgp ipv4 vpn rd 10:3"',
- "i5.*i5",
+ "i 5.*i 5",
"none",
"See R3s imports",
)
luCommand(
"r4",
'vtysh -c "show bgp ipv4 vpn rd 10:3"',
- "i5.*i5",
+ "i 5.*i 5",
"none",
"See R3s imports",
)
@@ -133,22 +133,22 @@ luCommand(
luCommand(
"r1",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.3/32",
+ "i 99.0.0.3/32",
"wait",
"See R4s static address",
)
luCommand(
"r3",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.3/32",
+ "i 99.0.0.3/32",
"wait",
"See R4s static address",
)
luCommand(
- "r1", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i5.*i5", "wait", "See R4s imports"
+ "r1", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i 5.*i 5", "wait", "See R4s imports"
)
luCommand(
- "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i5.*i5", "wait", "See R4s imports"
+ "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i 5.*i 5", "wait", "See R4s imports"
)
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
index 6cd92e293d..c9666601aa 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
@@ -7,18 +7,36 @@ luCommand("ce1", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up
luCommand("ce2", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)
luCommand("ce3", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)
luCommand(
- "r1", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+ "r1",
+ 'vtysh -c "show ip route ospf"',
+ "2.2.2.2",
+ "wait",
+ "OSPF Route has Arrived",
+ 60,
+)
luCommand(
"r1", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
luCommand(
- "r3", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+ "r3",
+ 'vtysh -c "show ip route ospf"',
+ "2.2.2.2",
+ "wait",
+ "OSPF Route has Arrived",
+ 60,
+)
luCommand(
"r3", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
luCommand(
- "r4", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+ "r4",
+ 'vtysh -c "show ip route ospf"',
+ "2.2.2.2",
+ "wait",
+ "OSPF Route has Arrived",
+ 60,
+)
luCommand(
"r4", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
index e05bf21ea9..2ce4bc59be 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
@@ -70,7 +70,7 @@ else:
"See all sharp routes in rib on ce1",
wait,
wait_time=10,
- )
+ )
luCommand(
"ce2",
'vtysh -c "show ip route summ" | grep "sharp" | cut -d " " -f 33',
@@ -79,7 +79,7 @@ else:
"See all sharp routes in rib on ce2",
wait,
wait_time=10,
- )
+ )
rtrs = ["ce1", "ce2", "ce3"]
for rtr in rtrs:
diff --git a/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
index 483c048d25..7023e3a503 100644
--- a/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
+++ b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
@@ -137,7 +137,9 @@ def test_bgp_large_comm_list_match_any():
step("BGP filtering check with large-community-list on R3")
test_func = functools.partial(_bgp_converge)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
- assert result is None, "Failed to filter BGP UPDATES with large-community-list on R3"
+ assert (
+ result is None
+ ), "Failed to filter BGP UPDATES with large-community-list on R3"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
index dfc4171bad..6289a2eea3 100644
--- a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
+++ b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
@@ -4,7 +4,7 @@
{
"valid":true,
"multipath":true,
- "extendedCommunity":{
+ "extendedIpv6Community":{
"string":"LB:65302:125000 (1.000 Mbps)"
},
"nexthops":[
diff --git a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
index 4014bfbc8b..e4ed92db1d 100644
--- a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
+++ b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
@@ -13,6 +13,7 @@ router bgp 65302
bgp bestpath as-path multipath-relax
no bgp ebgp-requires-policy
neighbor 11.1.2.5 remote-as external
+ neighbor 11.1.2.5 extended-link-bandwidth
neighbor 11.1.2.5 timers 3 10
neighbor 11.1.5.2 remote-as external
neighbor 11.1.5.2 timers 3 10
diff --git a/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
index af6976b5a6..fd67b2ecdd 100644
--- a/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
+++ b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
@@ -53,7 +53,39 @@ anycast IP (VIP) addresses via BGP.
def build_topo(tgen):
- "Build function"
+ """
+ Build function
+
+ +------+
+ | |
+ /| r7 |---
+ / | 65351|
+ / +------+
+ /
+ +------+ / +------+
+ | |/ | |
+ /| r4 | | r8 |---
+ / | 65301|------| 65352|
+ / +------+ +------+
+ /
+ +------+ / +------+ +------+
+ | |/ | | | |
+ | r2 | | r5 | | r9 |---
+ | 65201|------| 65302|------| 65353|
+ +------+ +------+ +------+
+ |
+ +------+ |
+ | |----------
+ | r1 |
+ | 65101|----------
+ +------+ |
+ |
+ +------+ +------+ +------+
+ | | | | | |
+ | r3 |------| r6 |------| r10 |---
+ | 65202| | 65303| | 65354|
+ +------+ +------+ +------+
+ """
# Create 10 routers - 1 super-spine, 2 spines, 3 leafs
# and 4 servers
diff --git a/tests/topotests/bgp_llgr/test_bgp_llgr.py b/tests/topotests/bgp_llgr/test_bgp_llgr.py
index d604871303..d7897cfcb9 100644
--- a/tests/topotests/bgp_llgr/test_bgp_llgr.py
+++ b/tests/topotests/bgp_llgr/test_bgp_llgr.py
@@ -36,8 +36,6 @@ from lib.common_config import (
step,
)
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(0, 6):
diff --git a/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py b/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py
index 26e8fe9701..c84fce6a9d 100644
--- a/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py
+++ b/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py
@@ -35,7 +35,7 @@ from lib.common_config import (
verify_rib,
step,
check_address_types,
- check_router_status
+ check_router_status,
)
from lib.topolog import logger
diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py
index cb8fa1e9f9..cfaab9bbe2 100644
--- a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py
+++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py
@@ -48,7 +48,7 @@ from lib.common_config import (
verify_rib,
step,
check_address_types,
- check_router_status
+ check_router_status,
)
from lib.topolog import logger
@@ -163,7 +163,9 @@ def test_verify_bgp_local_as_agg_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -190,7 +192,9 @@ def test_verify_bgp_local_as_agg_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py
index e9234f5172..bacef47664 100644
--- a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py
+++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py
@@ -229,7 +229,9 @@ def test_verify_bgp_local_as_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -256,7 +258,9 @@ def test_verify_bgp_local_as_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -832,7 +836,9 @@ def test_verify_bgp_local_as_GR_EBGP_p0(request):
"neighbor": {
"r2": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -861,7 +867,9 @@ def test_verify_bgp_local_as_GR_EBGP_p0(request):
"neighbor": {
"r4": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -1395,7 +1403,9 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -1422,7 +1432,9 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -1593,7 +1605,10 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request):
{
"action": "permit",
"set": {
- "path": {"as_num": "1.1000 1.1000", "as_action": "prepend"}
+ "path": {
+ "as_num": "1.1000 1.1000",
+ "as_action": "prepend",
+ }
},
}
]
@@ -1778,7 +1793,9 @@ def test_verify_bgp_local_as_in_iBGP_p0(request):
"neighbor": {
"r4": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2137,7 +2154,9 @@ def test_verify_bgp_local_as_allow_as_in_iBGP_p0(request):
"neighbor": {
"r2": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2166,7 +2185,9 @@ def test_verify_bgp_local_as_allow_as_in_iBGP_p0(request):
"neighbor": {
"r4": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2484,7 +2505,9 @@ def test_verify_bgp_local_as_in_EBGP_port_reset_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2511,7 +2534,9 @@ def test_verify_bgp_local_as_in_EBGP_port_reset_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -2824,7 +2849,9 @@ def test_verify_bgp_local_as_in_EBGP_negative2_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2851,7 +2878,9 @@ def test_verify_bgp_local_as_in_EBGP_negative2_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -3164,7 +3193,9 @@ def test_verify_bgp_local_as_in_EBGP_negative3_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -3191,7 +3222,9 @@ def test_verify_bgp_local_as_in_EBGP_negative3_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -3354,7 +3387,9 @@ def test_verify_bgp_local_as_in_EBGP_restart_daemons_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -3381,7 +3416,9 @@ def test_verify_bgp_local_as_in_EBGP_restart_daemons_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
diff --git a/tests/topotests/bgp_oad/test_bgp_oad.py b/tests/topotests/bgp_oad/test_bgp_oad.py
index b26c548357..a2ca37a2b7 100644
--- a/tests/topotests/bgp_oad/test_bgp_oad.py
+++ b/tests/topotests/bgp_oad/test_bgp_oad.py
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2", "r4"), "s2": ("r2", "r3"), "s3": ("r4", "r5")}
diff --git a/tests/topotests/bgp_orf/test_bgp_orf.py b/tests/topotests/bgp_orf/test_bgp_orf.py
index 7f45a242c9..47c0556884 100644
--- a/tests/topotests/bgp_orf/test_bgp_orf.py
+++ b/tests/topotests/bgp_orf/test_bgp_orf.py
@@ -20,7 +20,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -29,8 +29,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py
index df390327d4..8504737d82 100644
--- a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py
+++ b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py
@@ -78,6 +78,7 @@ pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
# Address read from env variables
ADDR_TYPES = check_address_types()
+
####
def setup_module(mod):
"""
diff --git a/tests/topotests/bgp_path_selection/test_bgp_path_selection.py b/tests/topotests/bgp_path_selection/test_bgp_path_selection.py
index bf5737b660..30083b4de2 100644
--- a/tests/topotests/bgp_path_selection/test_bgp_path_selection.py
+++ b/tests/topotests/bgp_path_selection/test_bgp_path_selection.py
@@ -49,7 +49,11 @@ def setup_module(mod):
for routern in range(1, 4):
tgen.gears["r{}".format(routern)].cmd("ip link add vrf1 type vrf table 10")
tgen.gears["r{}".format(routern)].cmd("ip link set vrf1 up")
- tgen.gears["r{}".format(routern)].cmd("ip address add dev vrf1 {}.{}.{}.{}/32".format(routern, routern, routern,routern))
+ tgen.gears["r{}".format(routern)].cmd(
+ "ip address add dev vrf1 {}.{}.{}.{}/32".format(
+ routern, routern, routern, routern
+ )
+ )
tgen.gears["r2"].cmd("ip address add dev vrf1 192.0.2.8/32")
tgen.gears["r3"].cmd("ip address add dev vrf1 192.0.2.8/32")
@@ -74,6 +78,7 @@ def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
+
def test_bgp_path_selection_ecmp():
tgen = get_topogen()
@@ -97,7 +102,7 @@ def test_bgp_path_selection_ecmp():
"aspath": {"string": "65002"},
"multipath": True,
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
@@ -117,7 +122,9 @@ def test_bgp_path_selection_vpn_ecmp():
def _bgp_check_path_selection_vpn_ecmp():
output = json.loads(
- tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json")
+ tgen.gears["r1"].vtysh_cmd(
+ "show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json"
+ )
)
expected = {
"paths": [
@@ -132,7 +139,7 @@ def test_bgp_path_selection_vpn_ecmp():
"aspath": {"string": "65002"},
"multipath": True,
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
@@ -160,13 +167,13 @@ def test_bgp_path_selection_metric():
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.2", "metric": 10}],
- "bestpath":{ "selectionReason":"IGP Metric"},
+ "bestpath": {"selectionReason": "IGP Metric"},
},
{
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
@@ -189,7 +196,9 @@ def test_bgp_path_selection_vpn_metric():
def _bgp_check_path_selection_vpn_metric():
output = json.loads(
- tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json")
+ tgen.gears["r1"].vtysh_cmd(
+ "show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json"
+ )
)
expected = {
"paths": [
@@ -197,13 +206,13 @@ def test_bgp_path_selection_vpn_metric():
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.2", "metric": 10}],
- "bestpath":{ "selectionReason":"IGP Metric"},
+ "bestpath": {"selectionReason": "IGP Metric"},
},
{
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
diff --git a/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py b/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py
index 2eb936aaa0..9269826233 100644
--- a/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py
+++ b/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2"), "s2": ("r2", "r3")}
diff --git a/tests/topotests/bgp_peer_group/r1/bgpd.conf b/tests/topotests/bgp_peer_group/r1/bgpd.conf
index 19b490a359..68d8e61a59 100644
--- a/tests/topotests/bgp_peer_group/r1/bgpd.conf
+++ b/tests/topotests/bgp_peer_group/r1/bgpd.conf
@@ -5,4 +5,8 @@ router bgp 65001
neighbor PG timers 3 10
neighbor 192.168.255.3 peer-group PG
neighbor r1-eth0 interface peer-group PG
+ neighbor PG1 peer-group
+ neighbor PG1 remote-as external
+ neighbor PG1 timers 3 20
+ neighbor 192.168.251.2 peer-group PG1
!
diff --git a/tests/topotests/bgp_peer_group/r1/zebra.conf b/tests/topotests/bgp_peer_group/r1/zebra.conf
index e2c399e536..16fd8c538c 100644
--- a/tests/topotests/bgp_peer_group/r1/zebra.conf
+++ b/tests/topotests/bgp_peer_group/r1/zebra.conf
@@ -2,5 +2,8 @@
interface r1-eth0
ip address 192.168.255.1/24
!
+interface r1-eth1
+ ip address 192.168.251.1/30
+!
ip forwarding
!
diff --git a/tests/topotests/bgp_peer_group/r2/bgpd.conf b/tests/topotests/bgp_peer_group/r2/bgpd.conf
index 0880ee9fae..d0e8f017d1 100644
--- a/tests/topotests/bgp_peer_group/r2/bgpd.conf
+++ b/tests/topotests/bgp_peer_group/r2/bgpd.conf
@@ -4,4 +4,8 @@ router bgp 65002
neighbor PG remote-as external
neighbor PG timers 3 10
neighbor r2-eth0 interface peer-group PG
+ neighbor PG1 peer-group
+ neighbor PG1 remote-as external
+ neighbor PG1 timers 3 20
+ neighbor 192.168.251.1 peer-group PG1
!
diff --git a/tests/topotests/bgp_peer_group/r2/zebra.conf b/tests/topotests/bgp_peer_group/r2/zebra.conf
index 606c17bec9..c2ad956c9c 100644
--- a/tests/topotests/bgp_peer_group/r2/zebra.conf
+++ b/tests/topotests/bgp_peer_group/r2/zebra.conf
@@ -2,5 +2,8 @@
interface r2-eth0
ip address 192.168.255.2/24
!
+interface r2-eth1
+ ip address 192.168.251.2/30
+!
ip forwarding
!
diff --git a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
index a91fade049..5cbcd19be9 100644
--- a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
+++ b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
@@ -22,7 +22,7 @@ sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-
+from lib.topolog import logger
pytestmark = [pytest.mark.bgpd]
@@ -36,6 +36,10 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r3"])
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
@@ -70,6 +74,7 @@ def test_bgp_peer_group():
expected = {
"r1-eth0": {"peerGroup": "PG", "bgpState": "Established"},
"192.168.255.3": {"peerGroup": "PG", "bgpState": "Established"},
+ "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Established"},
}
return topotest.json_cmp(output, expected)
@@ -96,6 +101,48 @@ def test_bgp_peer_group():
assert result is None, "Failed checking advertised routes from r3"
+def test_bgp_peer_group_remote_as_del_readd():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ logger.info("Remove bgp peer-group PG1 remote-as neighbor should be retained")
+ r1.cmd(
+ 'vtysh -c "config t" -c "router bgp 65001" '
+ + ' -c "no neighbor PG1 remote-as external" '
+ )
+
+ def _bgp_peer_group_remoteas_del():
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Active"},
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_peer_group_remoteas_del)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed bgp convergence in r1"
+
+ logger.info("Re-add bgp peer-group PG1 remote-as neighbor should be established")
+ r1.cmd(
+ 'vtysh -c "config t" -c "router bgp 65001" '
+ + ' -c "neighbor PG1 remote-as external" '
+ )
+
+ def _bgp_peer_group_remoteas_add():
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Established"},
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_peer_group_remoteas_add)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed bgp convergence in r1"
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py b/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py
index 0eb244717e..5d6440ce6a 100644
--- a/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py
+++ b/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py b/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py
index 2ae6f7fc9e..d9402f2743 100644
--- a/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py
+++ b/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../"))
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):
diff --git a/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py b/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py
index 5c7cc8eae3..ef7c94bbab 100644
--- a/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py
+++ b/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py
@@ -18,7 +18,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ sys.path.append(os.path.join(CWD, "../"))
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):
diff --git a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py
index 412ecc12ef..d50d67b60e 100644
--- a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py
+++ b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py
@@ -403,7 +403,6 @@ def test_route_summarisation_with_summary_only_p1(request):
)
for action, value in zip(["removed", "add"], [True, False]):
-
step(
"{} static routes as below: "
"(no) ip route 10.1.1.0/24 and (no) ip route 10.1.2.0/24"
@@ -815,7 +814,11 @@ def test_route_summarisation_with_as_set_p1(request):
)
for addr_type in ADDR_TYPES:
- for pfx, seq_id, network, in zip(
+ for (
+ pfx,
+ seq_id,
+ network,
+ ) in zip(
[1, 2, 3, 4, 5],
[10, 20, 30, 40, 50],
[NETWORK_1_1, NETWORK_1_2, NETWORK_1_3, NETWORK_1_4, NETWORK_1_5],
diff --git a/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py b/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py
index 15a077da2e..f7a66fdad1 100644
--- a/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py
+++ b/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py
@@ -15,7 +15,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
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
index a06e3edc44..93a514bf6a 100644
--- 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
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../"))
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):
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
index 23cf041b68..18b7831a4a 100644
--- 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
@@ -15,7 +15,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../"))
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):
diff --git a/tests/topotests/bgp_software_version/test_bgp_software_version.py b/tests/topotests/bgp_software_version/test_bgp_software_version.py
index 25e646cf42..c867208d39 100644
--- a/tests/topotests/bgp_software_version/test_bgp_software_version.py
+++ b/tests/topotests/bgp_software_version/test_bgp_software_version.py
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py
index 900d0c296e..f0c9144248 100755
--- a/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py
+++ b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py
@@ -37,10 +37,12 @@ def setup_module(mod):
tgen.start_topology()
for rname, router in tgen.routers().items():
- 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)))
+ 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.gears["pe1"].run("ip link add vrf10 type vrf table 10")
tgen.gears["pe1"].run("ip link set vrf10 up")
@@ -62,7 +64,7 @@ def open_json_file(path):
return json.load(f)
except IOError:
assert False, "Could not read file {}".format(path)
-
+
def check(name, command, checker):
tgen = get_topogen()
@@ -80,25 +82,25 @@ def check(name, command, checker):
def check_vrf10_bgp_rib(output):
- expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_default_bgp_vpn_rib(output):
- expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
+ expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_vrf20_bgp_rib(output):
- expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_vrf20_rib(output):
- expected = open_json_file("%s/pe1/results/vrf20_ipv4.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf20_ipv4.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json
index 6fc43e194d..f054fab48f 100644
--- a/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r1/vpnv6_rib.json
@@ -1,6 +1,5 @@
{
"vrfName": "default",
- "tableVersion": 2,
"routerId": "192.0.2.1",
"defaultLocPrf": 100,
"localAS": 1,
diff --git a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json
index 538e8955ef..60bcb7565f 100644
--- a/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json
+++ b/tests/topotests/bgp_srv6l3vpn_sid/r2/vpnv6_rib.json
@@ -1,6 +1,5 @@
{
"vrfName": "default",
- "tableVersion": 2,
"routerId": "192.0.2.2",
"defaultLocPrf": 100,
"localAS": 2,
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json
index 25b7a8616f..0fdd3d6dc0 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r1/vpnv6_rib.json
@@ -1,7 +1,6 @@
{
"vrfId": 0,
"vrfName": "default",
- "tableVersion": 2,
"routerId": "1.1.1.1",
"defaultLocPrf": 100,
"localAS": 1,
diff --git a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json
index 2cd47b9ce5..03bbcc008d 100644
--- a/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json
+++ b/tests/topotests/bgp_srv6l3vpn_to_bgp_vrf/r2/vpnv6_rib.json
@@ -1,7 +1,6 @@
{
"vrfId": 0,
"vrfName": "default",
- "tableVersion": 2,
"routerId": "2.2.2.2",
"defaultLocPrf": 100,
"localAS": 2,
diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
index fd8a78b485..ec14ef065f 100644
--- a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
+++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
@@ -217,6 +217,7 @@ def test_bgp_allow_as_in():
assertmsg = '"r2" 192.168.1.1/32 route should be gone'
assert result is None, assertmsg
+
def test_local_vs_non_local():
tgen = get_topogen()
@@ -229,7 +230,7 @@ def test_local_vs_non_local():
paths = output["paths"]
for i in range(len(paths)):
if "fibPending" in paths[i]:
- assert(False), "Route 60.0.0.0/24 should not have fibPending"
+ assert False, "Route 60.0.0.0/24 should not have fibPending"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py
index e7948eaaac..4855d5c7d2 100644
--- a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py
+++ b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py
@@ -36,8 +36,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
index 6fe044fcea..aeb9bf529d 100644
--- a/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
+++ b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
@@ -46,7 +46,7 @@ from lib.bgp import (
verify_bgp_rib,
verify_bgp_timers_and_functionality,
verify_router_id,
- verify_tcp_mss
+ verify_tcp_mss,
)
from lib.common_config import (
kill_router_daemons,
@@ -54,6 +54,7 @@ from lib.common_config import (
addKernelRoute,
apply_raw_config,
check_address_types,
+ check_router_status,
create_prefix_lists,
create_route_maps,
create_static_routes,
@@ -66,10 +67,9 @@ from lib.common_config import (
verify_fib_routes,
verify_rib,
write_test_footer,
- write_test_header
+ write_test_header,
)
-pytestmark = [pytest.mark.bgpd]
# Global variables
NETWORK1_1 = {"ipv4": "1.1.1.1/32", "ipv6": "1::1/128"}
NETWORK1_2 = {"ipv4": "1.1.1.2/32", "ipv6": "1::2/128"}
@@ -85,7 +85,8 @@ NETWORK5_2 = {"ipv4": "5.1.1.2/32", "ipv6": "5::2/128"}
NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
## File name
-TCPDUMP_FILE="test_tcp_packet_test.txt"
+TCPDUMP_FILE = "test_tcp_packet_test.txt"
+
def setup_module(mod):
"""
@@ -93,7 +94,7 @@ def setup_module(mod):
* `mod`: module name
"""
- global topo,TCPDUMP_FILE
+ global topo, TCPDUMP_FILE
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.15")
@@ -128,6 +129,7 @@ def setup_module(mod):
step("Running setup_module() done")
+
def teardown_module():
"""Teardown the pytest environment"""
@@ -138,9 +140,7 @@ def teardown_module():
# Stop toplogy and Remove tmp files
tgen.stop_topology()
- step(
- "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
- )
+ step("Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))))
step("=" * 40)
@@ -150,6 +150,7 @@ def teardown_module():
#
#####################################################
+
def test_bgp_vrf_tcp_mss(request):
tgen = get_topogen()
tc_name = request.node.name
@@ -280,34 +281,34 @@ def test_bgp_vrf_tcp_mss(request):
step("Verify the static Routes in R2 on RED VRF")
for addr_type in ADDR_TYPES:
static_routes_input = {
- "r3": {
- "static_routes": [
- {
- "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- ]
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ ]
}
}
dut = "r2"
@@ -317,34 +318,34 @@ def test_bgp_vrf_tcp_mss(request):
step("Verify the static Routes in R1 on RED VRF")
for addr_type in ADDR_TYPES:
static_routes_input = {
- "r3": {
- "static_routes": [
- {
- "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- ]
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ ]
}
}
dut = "r1"
@@ -404,9 +405,6 @@ def test_bgp_vrf_tcp_mss(request):
tcp_mss_result
)
-
-
-
step("Enabling tcp-mss 500 between R2 and R3 of VRF Default")
TCP_MSS = 500
raw_config = {
@@ -440,8 +438,6 @@ def test_bgp_vrf_tcp_mss(request):
result = apply_raw_config(tgen, raw_config)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
-
-
step("Clear BGP at router R2 and R3")
for addr_type in ADDR_TYPES:
clear_bgp(tgen, topo, "r2", addr_type)
@@ -550,7 +546,6 @@ def test_bgp_vrf_tcp_mss(request):
tcp_mss_result is not True
), " TCP-MSS mismatch :Failed \n Error: {}".format(tcp_mss_result)
-
step("Removing tcp-mss 500 between R2 and R3 of VRF Default ")
TCP_MSS = 500
raw_config = {
diff --git a/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
index 6f313be628..31743c8a6d 100644
--- a/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
+++ b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
@@ -52,30 +52,32 @@ def build_topo(tgen):
switch = tgen.add_switch("s3")
switch.add_link(tgen.gears["r2"])
+
def _populate_iface():
tgen = get_topogen()
cmds_list = [
- 'ip link add vrf1 type vrf table 10',
- 'echo 10 > /proc/sys/net/mpls/platform_labels',
- 'ip link set dev vrf1 up',
- 'ip link set dev {0}-eth1 master vrf1',
- 'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input',
- 'ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}',
- 'ip link set dev {0}-gre0 up',
- 'echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input',
+ "ip link add vrf1 type vrf table 10",
+ "echo 10 > /proc/sys/net/mpls/platform_labels",
+ "ip link set dev vrf1 up",
+ "ip link set dev {0}-eth1 master vrf1",
+ "echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input",
+ "ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}",
+ "ip link set dev {0}-gre0 up",
+ "echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input",
]
for cmd in cmds_list:
- input = cmd.format('r1', '1', '2')
- logger.info('input: ' + cmd)
- output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2'))
- logger.info('output: ' + output)
+ input = cmd.format("r1", "1", "2")
+ logger.info("input: " + cmd)
+ output = tgen.net["r1"].cmd(cmd.format("r1", "1", "2"))
+ logger.info("output: " + output)
for cmd in cmds_list:
- input = cmd.format('r2', '2', '1')
- logger.info('input: ' + cmd)
- output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
- logger.info('output: ' + output)
+ input = cmd.format("r2", "2", "1")
+ logger.info("input: " + cmd)
+ output = tgen.net["r2"].cmd(cmd.format("r2", "2", "1"))
+ logger.info("output: " + output)
+
def setup_module(mod):
"Sets up the pytest environment"
@@ -113,13 +115,13 @@ def test_protocols_convergence():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- router = tgen.gears['r1']
+ router = tgen.gears["r1"]
logger.info("Dump some context for r1")
router.vtysh_cmd("show bgp ipv4 vpn")
router.vtysh_cmd("show bgp summary")
router.vtysh_cmd("show bgp vrf vrf1 ipv4")
router.vtysh_cmd("show running-config")
- router = tgen.gears['r2']
+ router = tgen.gears["r2"]
logger.info("Dump some context for r2")
router.vtysh_cmd("show bgp ipv4 vpn")
router.vtysh_cmd("show bgp summary")
@@ -128,11 +130,11 @@ def test_protocols_convergence():
# Check IPv4 routing tables on r1
logger.info("Checking IPv4 routes for convergence on r1")
- router = tgen.gears['r1']
+ router = tgen.gears["r1"]
json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
logger.info("skipping file {}".format(json_file))
- assert 0, 'ipv4_routes.json file not found'
+ assert 0, "ipv4_routes.json file not found"
return
expected = json.loads(open(json_file).read())
@@ -148,10 +150,10 @@ def test_protocols_convergence():
# Check BGP IPv4 routing tables on r2 not installed
logger.info("Checking BGP IPv4 routes for convergence on r2")
- router = tgen.gears['r2']
+ router = tgen.gears["r2"]
json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
- assert 0, 'bgp_ipv4_routes.json file not found'
+ assert 0, "bgp_ipv4_routes.json file not found"
expected = json.loads(open(json_file).read())
test_func = partial(
@@ -163,7 +165,8 @@ def test_protocols_convergence():
_, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
-
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py
index 1787021ebc..726afcb6ae 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py
@@ -851,23 +851,25 @@ def test_dynamic_imported_matching_prefix_based_on_community_list_p0(request):
result = verify_bgp_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
@@ -924,23 +926,25 @@ def test_dynamic_imported_matching_prefix_based_on_community_list_p0(request):
result = verify_bgp_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
@@ -1153,23 +1157,25 @@ def test_dynamic_import_routes_delete_static_route_p1(request):
result = verify_bgp_rib(
tgen, addr_type, "r2", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r2"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r2"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r2", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
step("Delete static routes from vrf BLUE")
@@ -1209,21 +1215,23 @@ def test_dynamic_import_routes_delete_static_route_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
step("Delete static routes from vrf default")
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
index c7fbc01eb1..45d7b0309e 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
@@ -320,7 +320,6 @@ def test_dynamic_import_recursive_import_tenant_vrf_p1(request):
for dut, vrf_name, vrf_import, as_num in zip(
["r2", "r4"], ["GREEN", "BLUE"], ["RED", "default"], [2, 4]
):
-
for action, value in zip(["Delete", "Re-add"], [True, False]):
step("{} the import command on {} router".format(action, dut))
temp = {}
@@ -357,23 +356,25 @@ def test_dynamic_import_recursive_import_tenant_vrf_p1(request):
result = verify_bgp_rib(
tgen, addr_type, "r4", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r4"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r4"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r4", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes["r4"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes["r4"]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, "r4", static_routes)
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
index 02950eb3d2..d29edf59b8 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
@@ -495,23 +495,25 @@ def test_dynamic_import_routes_between_two_tenant_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
@@ -882,23 +884,25 @@ def test_dynamic_import_routes_between_two_tenant_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
index 4b18903429..c118ffc090 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
@@ -356,23 +356,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
@@ -503,23 +505,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
@@ -882,23 +886,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
diff --git a/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py b/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py
index 244db6c46a..b20819264d 100755
--- a/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py
+++ b/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py
@@ -37,10 +37,12 @@ def setup_module(mod):
tgen.start_topology()
for rname, router in tgen.routers().items():
- 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)))
+ 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.gears["pe1"].run("ip link add vrf10 type vrf table 10")
tgen.gears["pe1"].run("ip link set vrf10 up")
@@ -62,22 +64,22 @@ def open_json_file(path):
return json.load(f)
except IOError:
assert False, "Could not read file {}".format(path)
-
+
def check_vrf10_rib(output):
- expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_default_vpn_rib(output):
- expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
+ expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_vrf20_rib(output):
- expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
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
index 5d93964380..3cb31809fe 100644
--- 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
@@ -43,7 +43,7 @@ from lib.common_config import (
step,
create_static_routes,
check_router_status,
- apply_raw_config
+ apply_raw_config,
)
from lib.topolog import logger
@@ -51,7 +51,7 @@ from lib.bgp import (
verify_bgp_convergence,
create_router_bgp,
verify_bgp_rib,
- verify_bgp_bestpath
+ verify_bgp_bestpath,
)
from lib.topojson import build_config_from_json
@@ -84,10 +84,8 @@ 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": "::"
-}
+BESTPATH = {"ipv4": "0.0.0.0", "ipv6": "::"}
+
def setup_module(mod):
"""
@@ -158,6 +156,7 @@ def teardown_module():
#
#####################################################
+
def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
"""
Verify ECMP for imported routes from different VRFs.
@@ -170,136 +169,130 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
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")
+ 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]
+ 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]
+ 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
+ "vrf": vrf_name,
}
]
}
}
result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ 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"
- }]
- }
- }
- })
+ temp.update(
+ {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
+ )
- redist_dict = {"r3": {"bgp": [{
- "vrf": vrf_name, "local_as": 3, "address_family": temp
- }]}}
+ 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)
+ 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")
+ 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]
+ 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]
+ 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
- }
+ {"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_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)
+ 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
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "import": {"vrf": vrf_name},
+ "maximum_paths": {"ebgp": 2},
}
}
}
- })
+ )
- bgp_val.append({
- "local_as": 3, "address_family": temp
- })
+ 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)
+ 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"
- ]
- }
+ "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)
+ 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.")
+ 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]
- ]
+ 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": [
@@ -310,54 +303,61 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
}
}
- 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_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)
+ 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")
+ 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]
+ 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"
+ "vrf": "RED",
},
{
"network": [NETWORK1_1[addr_type]],
- "next_hop": topo["routers"]["r2"]["links"][
- "r3-link1"][addr_type].split("/")[0],
+ "next_hop": topo["routers"]["r2"]["links"]["r3-link1"][
+ addr_type
+ ].split("/")[0],
"vrf": "RED",
- "delete": True
- }
+ "delete": True,
+ },
]
}
}
result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ 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")
+ 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]
- ]
+ 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": [
@@ -368,20 +368,24 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
}
}
- 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_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)
+ 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):
+def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0(
+ request,
+):
"""
Verify ECMP for imported routes from different VRFs.
"""
@@ -393,13 +397,15 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
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]]):
+ 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))
+ step("Configure static route for VRF : {} on {}".format(vrf_name, dut))
for addr_type in ADDR_TYPES:
static_routes = {
dut: {
@@ -407,44 +413,50 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": [network_vrf[addr_type]],
"next_hop": "blackhole",
- "vrf": vrf_name
+ "vrf": vrf_name,
}
]
}
}
result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ 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"
- }]
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
}
}
- })
+ )
- redist_dict = {dut: {"bgp": [{
- "vrf": vrf_name, "local_as": as_num, "address_family": temp
- }]}}
+ 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]]):
+ 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 = {
@@ -453,38 +465,32 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": [network_vrf[addr_type]],
"next_hop": "blackhole",
- "vrf": vrf_name
+ "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)
+ 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"
- }
- }
- }
- })
+ temp.update({addr_type: {"unicast": {"import": {"vrf": "RED"}}}})
- import_dict = {"r3": {"bgp": [{
- "vrf": "GREEN", "local_as": 3, "address_family": temp
- }]}}
+ 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)
+ 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")
+ 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": {
@@ -492,7 +498,7 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": [NETWORK1_2[addr_type]],
"next_hop": "blackhole",
- "vrf": "GREEN"
+ "vrf": "GREEN",
}
]
}
@@ -504,19 +510,21 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": NETWORK1_2[addr_type],
"bestpath": BESTPATH[addr_type],
- "vrf": "GREEN"
+ "vrf": "GREEN",
}
]
}
}
result = verify_bgp_bestpath(tgen, addr_type, input_routes)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ 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)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
write_test_footer(tc_name)
diff --git a/tests/topotests/config_timing/test_config_timing.py b/tests/topotests/config_timing/test_config_timing.py
index 5c1b97262c..52d196f12a 100644
--- a/tests/topotests/config_timing/test_config_timing.py
+++ b/tests/topotests/config_timing/test_config_timing.py
@@ -97,8 +97,8 @@ def test_static_timing():
optype = "adding" if add else "removing"
iptype = "IPv6" if do_ipv6 else "IPv4"
if super_prefix is None:
- super_prefix = u"2001::/48" if do_ipv6 else u"10.0.0.0/8"
- via = u"lo"
+ super_prefix = "2001::/48" if do_ipv6 else "10.0.0.0/8"
+ via = "lo"
optyped = "added" if add else "removed"
for rname, router in router_list.items():
@@ -161,8 +161,8 @@ def test_static_timing():
prefix_count = 50
prefix_base = [
- [u"10.0.0.0/8", u"11.0.0.0/8"],
- [u"2100:1111:2220::/44", u"2100:3333:4440::/44"],
+ ["10.0.0.0/8", "11.0.0.0/8"],
+ ["2100:1111:2220::/44", "2100:3333:4440::/44"],
]
# This apparently needed to allow for various mgmtd/staticd/zebra connections to form
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index c6f038b7f6..a2315138cc 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -496,7 +496,7 @@ def setup_coverage(config):
os.environ["GCOV_PREFIX"] = str(gcdadir)
if is_main_runner():
- commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+rw {{}} +")
+ commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+r {{}} +")
commander.cmd_raises(f"mkdir -p {gcdadir}")
commander.cmd_raises(f"chown -R root:frr {gcdadir}")
commander.cmd_raises(f"chmod 2775 {gcdadir}")
@@ -767,18 +767,25 @@ def coverage_finish(terminalreporter, config):
bdir = Path(os.environ["FRR_BUILD_DIR"])
gcdadir = Path(os.environ["GCOV_PREFIX"])
- # Get the data files into the build directory
- logger.info("Copying gcda files from '%s' to '%s'", gcdadir, bdir)
- user = os.environ.get("SUDO_USER", os.environ["USER"])
- commander.cmd_raises(f"chmod -R ugo+r {gcdadir}")
+ logger.info("Creating .gcno ssymlink from '%s' to '%s'", gcdadir, bdir)
commander.cmd_raises(
- f"tar -C {gcdadir} -cf - . | su {user} -c 'tar -C {bdir} -xf -'"
+ f"cd {gcdadir}; bdir={bdir}"
+ + """
+for f in $(find . -name '*.gcda'); do
+ f=${f#./};
+ f=${f%.gcda}.gcno;
+ ln -fs $bdir/$f $f;
+ touch -h -r $bdir/$f $f;
+ echo $f;
+done"""
)
# Get the results into a summary file
data_file = rundir / "coverage.info"
logger.info("Gathering coverage data into: %s", data_file)
- commander.cmd_raises(f"lcov --directory {bdir} --capture --output-file {data_file}")
+ commander.cmd_raises(
+ f"lcov --directory {gcdadir} --capture --output-file {data_file}"
+ )
# Get coverage info filtered to a specific set of files
report_file = rundir / "coverage.info"
diff --git a/tests/topotests/eigrp_topo1/test_eigrp_topo1.py b/tests/topotests/eigrp_topo1/test_eigrp_topo1.py
index 3c9392c3f5..b3152f43bc 100644
--- a/tests/topotests/eigrp_topo1/test_eigrp_topo1.py
+++ b/tests/topotests/eigrp_topo1/test_eigrp_topo1.py
@@ -193,6 +193,7 @@ if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
+
#
# Auxiliary Functions
#
diff --git a/tests/topotests/evpn_pim_1/spine/bgp.summ.json b/tests/topotests/evpn_pim_1/spine/bgp.summ.json
index 7f37cedb2b..b5b03e86b4 100644
--- a/tests/topotests/evpn_pim_1/spine/bgp.summ.json
+++ b/tests/topotests/evpn_pim_1/spine/bgp.summ.json
@@ -2,7 +2,6 @@
"routerId":"192.168.100.1",
"as":65001,
"vrfName":"default",
- "tableVersion":7,
"peerCount":2,
"peers":{
"192.168.1.2":{
diff --git a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py
index c0621d75a5..cfcd4a18ea 100644
--- a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py
+++ b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py
@@ -20,7 +20,7 @@ import pytest
import json
from functools import partial
-pytestmark = [pytest.mark.pimd]
+pytestmark = [pytest.mark.pimd, pytest.mark.bgpd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -32,10 +32,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-# Required to instantiate the topology builder class.
-
-pytestmark = [pytest.mark.bgpd, pytest.mark.bgpd]
-
#####################################################
##
diff --git a/tests/topotests/example_test/test_template.py b/tests/topotests/example_test/test_template.py
index 27975483a8..5728ebaea2 100644
--- a/tests/topotests/example_test/test_template.py
+++ b/tests/topotests/example_test/test_template.py
@@ -41,6 +41,7 @@ pytestmark = [
# pytest.mark.vrrpd,
]
+
# Function we pass to Topogen to create the topology
def build_topo(tgen):
"Build function"
diff --git a/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
index bb4d02d342..22fc50b914 100644
--- a/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
+++ b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
@@ -65,7 +65,8 @@ def setup_module(module):
TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
)
router.load_config(
- TopoRouter.RD_FPM_LISTENER, os.path.join(CWD, "{}/fpm_stub.conf".format(rname))
+ TopoRouter.RD_FPM_LISTENER,
+ os.path.join(CWD, "{}/fpm_stub.conf".format(rname)),
)
tgen.start_router()
diff --git a/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py b/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py
index 6a5f81def6..6689cf4c5e 100755
--- a/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py
+++ b/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py
@@ -118,11 +118,19 @@ def setup_module(mod):
# For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
- router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)))
- router.load_config( TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
if rname in ["rt0", "rt9"]:
- router.load_config( TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)))
- router.load_config( TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname)))
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname))
+ )
router.run("ip link add dum0 type dummy")
router.run("ip link set dum0 up")
if rname == "rt0":
@@ -145,6 +153,7 @@ def setup_testcase(msg):
pytest.skip(tgen.errors)
return tgen
+
def open_json_file(filename):
try:
with open(filename, "r") as f:
@@ -162,7 +171,7 @@ def check_rib(name, cmd, expected_file):
expected = open_json_file("{}/{}".format(CWD, expected_file))
return topotest.json_cmp(output, expected)
- logger.info("[+] check {} \"{}\" {}".format(name, cmd, expected_file))
+ logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file))
tgen = get_topogen()
func = partial(_check, name, cmd, expected_file)
success, result = topotest.run_and_expect(func, None, count=120, wait=0.5)
diff --git a/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py b/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py
index 892f6e1d0e..1a7505dd12 100644
--- a/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py
+++ b/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py
@@ -197,13 +197,16 @@ def setup_module(mod):
# For all registered routers, load the zebra and isis configuration files
for rname, router in tgen.routers().items():
- router.load_config(TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname)))
- router.load_config(TopoRouter.RD_ISIS,
- os.path.join(CWD, '{}/isisd.conf'.format(rname)))
- if (os.path.exists('{}/sharpd.conf'.format(rname))):
- router.load_config(TopoRouter.RD_SHARP,
- os.path.join(CWD, '{}/sharpd.conf'.format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+ if os.path.exists("{}/sharpd.conf".format(rname)):
+ router.load_config(
+ TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
+ )
# Start routers
tgen.start_router()
@@ -227,7 +230,9 @@ def router_compare_json_output(rname, command, reference):
expected = json.loads(open(filename).read())
# Run test function until we get an result. Wait at most 60 seconds.
- test_func = functools.partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
+ test_func = functools.partial(
+ topotest.router_json_cmp, tgen.gears[rname], command, expected
+ )
_, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
assert diff is None, assertmsg
@@ -308,8 +313,10 @@ def test_srv6_locator_step1():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step1/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step1/show_srv6_locator_table.ref",
+ )
def test_ping_step1():
@@ -326,10 +333,16 @@ def test_ping_step1():
pytest.skip(tgen.errors)
# Setup encap route on rt1, decap route on rt2
- tgen.gears["rt1"].vtysh_cmd("sharp install seg6-routes fc00:0:9::1 nexthop-seg6 2001:db8:1::2 encap fc00:0:1:2:6:f00d:: 1")
- tgen.gears["rt6"].vtysh_cmd("sharp install seg6local-routes fc00:0:f00d:: nexthop-seg6local eth-dst End_DT6 254 1")
- tgen.gears["dst"].vtysh_cmd("sharp install route 2001:db8:1::1 nexthop 2001:db8:10::1 1")
-
+ tgen.gears["rt1"].vtysh_cmd(
+ "sharp install seg6-routes fc00:0:9::1 nexthop-seg6 2001:db8:1::2 encap fc00:0:1:2:6:f00d:: 1"
+ )
+ tgen.gears["rt6"].vtysh_cmd(
+ "sharp install seg6local-routes fc00:0:f00d:: nexthop-seg6local eth-dst End_DT6 254 1"
+ )
+ tgen.gears["dst"].vtysh_cmd(
+ "sharp install route 2001:db8:1::1 nexthop 2001:db8:10::1 1"
+ )
+
# Try to ping dst from rt1
check_ping6("rt1", "fc00:0:9::1", True)
@@ -412,8 +425,10 @@ def test_srv6_locator_step2():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step2/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step2/show_srv6_locator_table.ref",
+ )
def test_ping_step2():
@@ -428,7 +443,7 @@ def test_ping_step2():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -512,8 +527,10 @@ def test_srv6_locator_step3():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step3/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step3/show_srv6_locator_table.ref",
+ )
def test_ping_step3():
@@ -528,7 +545,7 @@ def test_ping_step3():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
@@ -608,8 +625,10 @@ def test_srv6_locator_step4():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step4/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step4/show_srv6_locator_table.ref",
+ )
def test_ping_step4():
@@ -624,7 +643,7 @@ def test_ping_step4():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -704,8 +723,10 @@ def test_srv6_locator_step5():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step5/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step5/show_srv6_locator_table.ref",
+ )
def test_ping_step5():
@@ -720,7 +741,7 @@ def test_ping_step5():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
@@ -799,8 +820,10 @@ def test_srv6_locator_step6():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step6/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step6/show_srv6_locator_table.ref",
+ )
def test_ping_step6():
@@ -815,7 +838,7 @@ def test_ping_step6():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -895,8 +918,10 @@ def test_srv6_locator_step7():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step7/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step7/show_srv6_locator_table.ref",
+ )
def test_ping_step7():
@@ -911,7 +936,7 @@ def test_ping_step7():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
@@ -990,8 +1015,10 @@ def test_srv6_locator_step8():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step8/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step8/show_srv6_locator_table.ref",
+ )
def test_ping_step8():
@@ -1006,7 +1033,7 @@ def test_ping_step8():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -1089,8 +1116,10 @@ def test_srv6_locator_step9():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step9/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step9/show_srv6_locator_table.ref",
+ )
def test_ping_step9():
@@ -1105,7 +1134,7 @@ def test_ping_step9():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
diff --git a/tests/topotests/isis_te_topo1/test_isis_te_topo1.py b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
index 9c70e05784..eb4f31012b 100644
--- a/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
+++ b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
@@ -189,10 +189,18 @@ def test_step3():
tgen = setup_testcase("Step3: Add IPv6 on r1 and r2 interfaces")
- tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"')
- tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"')
- tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"')
- tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"')
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"'
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"'
+ )
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step3.json")
@@ -202,8 +210,12 @@ def test_step4():
tgen = setup_testcase("Step4: Modify Prefix SID on router r4")
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"')
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"')
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"'
+ )
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step4.json")
@@ -229,9 +241,15 @@ def test_step6():
tgen = setup_testcase("Step6: Modify link parameters on r2 & r4")
- tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"')
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"')
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"')
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"'
+ )
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step6.json")
diff --git a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py
index 6c814ee9aa..e1e6b51f64 100644
--- a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py
+++ b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py
@@ -8,27 +8,29 @@ import struct
class BGPOpen:
- UNPACK_STR = '!16sHBBHH4sB'
+ UNPACK_STR = "!16sHBBHH4sB"
@classmethod
def dissect(cls, data):
- (marker,
- length,
- open_type,
- version,
- my_as,
- hold_time,
- bgp_id,
- optional_params_len) = struct.unpack_from(cls.UNPACK_STR, data)
+ (
+ marker,
+ length,
+ open_type,
+ version,
+ my_as,
+ hold_time,
+ bgp_id,
+ optional_params_len,
+ ) = struct.unpack_from(cls.UNPACK_STR, data)
- data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len:]
+ data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len :]
# XXX: parse optional parameters
return data, {
- 'version': version,
- 'my_as': my_as,
- 'hold_time': hold_time,
- 'bgp_id': ipaddress.ip_address(bgp_id),
- 'optional_params_len': optional_params_len,
+ "version": version,
+ "my_as": my_as,
+ "hold_time": hold_time,
+ "bgp_id": ipaddress.ip_address(bgp_id),
+ "optional_params_len": optional_params_len,
}
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py
index d079b35113..629e175364 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py
@@ -10,45 +10,47 @@ from .nlri import NlriIPv4Unicast
from .path_attributes import PathAttribute
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BGPUpdate:
- UNPACK_STR = '!16sHBH'
+ UNPACK_STR = "!16sHBH"
STATIC_SIZE = 23
@classmethod
def dissect(cls, data):
- msg = {'bmp_log_type': 'update'}
+ msg = {"bmp_log_type": "update"}
common_size = struct.calcsize(cls.UNPACK_STR)
- (marker,
- length,
- update_type,
- withdrawn_routes_len) = struct.unpack_from(cls.UNPACK_STR, data)
+ (marker, length, update_type, withdrawn_routes_len) = struct.unpack_from(
+ cls.UNPACK_STR, data
+ )
# get withdrawn routes
- withdrawn_routes = ''
+ withdrawn_routes = ""
if withdrawn_routes_len:
withdrawn_routes = NlriIPv4Unicast.parse(
- data[common_size:common_size + withdrawn_routes_len]
+ data[common_size : common_size + withdrawn_routes_len]
)
- msg['bmp_log_type'] = 'withdraw'
+ msg["bmp_log_type"] = "withdraw"
msg.update(withdrawn_routes)
# get path attributes
(total_path_attrs_len,) = struct.unpack_from(
- '!H', data[common_size+withdrawn_routes_len:])
+ "!H", data[common_size + withdrawn_routes_len :]
+ )
if total_path_attrs_len:
offset = cls.STATIC_SIZE + withdrawn_routes_len
- path_attrs_data = data[offset:offset + total_path_attrs_len]
+ path_attrs_data = data[offset : offset + total_path_attrs_len]
while path_attrs_data:
path_attrs_data, pattr = PathAttribute.dissect(path_attrs_data)
if pattr:
msg = {**msg, **pattr}
# get nlri
- nlri_len = length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len
+ nlri_len = (
+ length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len
+ )
if nlri_len > 0:
- nlri = NlriIPv4Unicast.parse(data[length - nlri_len:length])
+ nlri = NlriIPv4Unicast.parse(data[length - nlri_len : length])
msg.update(nlri)
return data[length:], msg
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/af.py b/tests/topotests/lib/bmp_collector/bgp/update/af.py
index 01af1ae2be..200b15a05d 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/af.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/af.py
@@ -19,7 +19,7 @@ SAFI_IP_FLOWSPEC = 133
SAFI_VPN_FLOWSPEC = 134
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class AddressFamily:
def __init__(self, afi, safi):
self.afi = afi
@@ -31,13 +31,13 @@ class AddressFamily:
return (self.afi, self.safi) == (other.afi, other.safi)
def __str__(self):
- return f'afi: {self.afi}, safi: {self.safi}'
+ return f"afi: {self.afi}, safi: {self.safi}"
def __hash__(self):
return hash((self.afi, self.safi))
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class AF:
IPv4_UNICAST = AddressFamily(AFI_IP, SAFI_UNICAST)
IPv6_UNICAST = AddressFamily(AFI_IP6, SAFI_UNICAST)
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py
index c1720f126c..b3625201f4 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py
@@ -13,7 +13,8 @@ from .rd import RouteDistinguisher
def decode_label(label):
# from frr
# frr encode just one label
- return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xf0) >> 4
+ return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xF0) >> 4
+
def padding(databin, len_):
"""
@@ -23,7 +24,8 @@ def padding(databin, len_):
"""
if len(databin) >= len_:
return databin
- return databin + b'\0' * (len_ - len(databin))
+ return databin + b"\0" * (len_ - len(databin))
+
def dissect_nlri(nlri_data, afi, safi):
"""
@@ -37,35 +39,34 @@ def dissect_nlri(nlri_data, afi, safi):
elif addr_family == AF.IPv6_UNICAST:
return NlriIPv6Unicast.parse(nlri_data)
- return {'ip_prefix': 'Unknown'}
+ return {"ip_prefix": "Unknown"}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4Unicast:
-
@staticmethod
def parse(data):
"""parses prefixes from withdrawn_routes or nrli data"""
- (prefix_len,) = struct.unpack_from('!B', data)
+ (prefix_len,) = struct.unpack_from("!B", data)
prefix = padding(data[1:], 4)
- return {'ip_prefix': f'{ipaddress.IPv4Address(prefix)}/{prefix_len}'}
+ return {"ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}"}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6Unicast:
@staticmethod
def parse(data):
"""parses prefixes from withdrawn_routes or nrli data"""
- (prefix_len,) = struct.unpack_from('!B', data)
+ (prefix_len,) = struct.unpack_from("!B", data)
prefix = padding(data[1:], 16)
- return {'ip_prefix': f'{ipaddress.IPv6Address(prefix)}/{prefix_len}'}
+ return {"ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}"}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4Vpn:
- UNPACK_STR = '!B3s8s'
+ UNPACK_STR = "!B3s8s"
@classmethod
def parse(cls, data):
@@ -74,17 +75,17 @@ class NlriIPv4Vpn:
ipv4 = padding(data[offset:], 4)
# prefix_len = total_bits_len - label_bits_len - rd_bits_len
- prefix_len = bit_len - 3*8 - 8*8
+ prefix_len = bit_len - 3 * 8 - 8 * 8
return {
- 'label': decode_label(label),
- 'rd': str(RouteDistinguisher(rd)),
- 'ip_prefix': f'{ipaddress.IPv4Address(ipv4)}/{prefix_len}',
+ "label": decode_label(label),
+ "rd": str(RouteDistinguisher(rd)),
+ "ip_prefix": f"{ipaddress.IPv4Address(ipv4)}/{prefix_len}",
}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6Vpn:
- UNPACK_STR = '!B3s8s'
+ UNPACK_STR = "!B3s8s"
@classmethod
def parse(cls, data):
@@ -93,48 +94,49 @@ class NlriIPv6Vpn:
offset = struct.calcsize(cls.UNPACK_STR)
ipv6 = padding(data[offset:], 16)
- prefix_len = bit_len - 3*8 - 8*8
+ prefix_len = bit_len - 3 * 8 - 8 * 8
return {
- 'label': decode_label(label),
- 'rd': str(RouteDistinguisher(rd)),
- 'ip_prefix': f'{ipaddress.IPv6Address(ipv6)}/{prefix_len}',
+ "label": decode_label(label),
+ "rd": str(RouteDistinguisher(rd)),
+ "ip_prefix": f"{ipaddress.IPv6Address(ipv6)}/{prefix_len}",
}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4Mpls:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6Mpls:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriVpn4FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriVpn6FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriL2EVPN:
pass
-#------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
class NlriL2VPNFlowSpec:
pass
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
index 6e82e9c170..3694cb4fe3 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
@@ -38,17 +38,18 @@ ORIGIN_EGP = 0x01
ORIGIN_INCOMPLETE = 0x02
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttribute:
PATH_ATTRS = {}
UNKNOWN_ATTR = None
- UNPACK_STR = '!BB'
+ UNPACK_STR = "!BB"
@classmethod
def register_path_attr(cls, path_attr):
def _register_path_attr(subcls):
cls.PATH_ATTRS[path_attr] = subcls
return subcls
+
return _register_path_attr
@classmethod
@@ -61,7 +62,7 @@ class PathAttribute:
offset = struct.calcsize(cls.UNPACK_STR)
# get attribute length
- attr_len_str = '!H' if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else '!B'
+ attr_len_str = "!H" if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else "!B"
(attr_len,) = struct.unpack_from(attr_len_str, data[offset:])
@@ -69,32 +70,34 @@ class PathAttribute:
path_attr_cls = cls.lookup_path_attr(type_code)
if path_attr_cls == cls.UNKNOWN_ATTR:
- return data[offset + attr_len:], None
+ return data[offset + attr_len :], None
- return data[offset+attr_len:], path_attr_cls.dissect(data[offset:offset+attr_len])
+ return data[offset + attr_len :], path_attr_cls.dissect(
+ data[offset : offset + attr_len]
+ )
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_ORIGIN)
class PathAttrOrigin:
ORIGIN_STR = {
- ORIGIN_IGP: 'IGP',
- ORIGIN_EGP: 'EGP',
- ORIGIN_INCOMPLETE: 'INCOMPLETE',
+ ORIGIN_IGP: "IGP",
+ ORIGIN_EGP: "EGP",
+ ORIGIN_INCOMPLETE: "INCOMPLETE",
}
@classmethod
def dissect(cls, data):
- (origin,) = struct.unpack_from('!B', data)
+ (origin,) = struct.unpack_from("!B", data)
- return {'origin': cls.ORIGIN_STR.get(origin, 'UNKNOWN')}
+ return {"origin": cls.ORIGIN_STR.get(origin, "UNKNOWN")}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_AS_PATH)
class PathAttrAsPath:
AS_PATH_TYPE_SET = 0x01
- AS_PATH_TYPE_SEQUENCE= 0x02
+ AS_PATH_TYPE_SEQUENCE = 0x02
@staticmethod
def get_asn_len(asns):
@@ -103,34 +106,34 @@ class PathAttrAsPath:
@classmethod
def dissect(cls, data):
- (_type, _len) = struct.unpack_from('!BB', data)
+ (_type, _len) = struct.unpack_from("!BB", data)
data = data[2:]
- _type_str = 'Ordred' if _type == cls.AS_PATH_TYPE_SEQUENCE else 'Raw'
+ _type_str = "Ordred" if _type == cls.AS_PATH_TYPE_SEQUENCE else "Raw"
segment = []
while data:
- (asn,) = struct.unpack_from('!I', data)
+ (asn,) = struct.unpack_from("!I", data)
segment.append(asn)
data = data[4:]
- return {'as_path': ' '.join(str(a) for a in segment)}
+ return {"as_path": " ".join(str(a) for a in segment)}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_NEXT_HOP)
class PathAttrNextHop:
@classmethod
def dissect(cls, data):
- (nexthop,) = struct.unpack_from('!4s', data)
- return {'bgp_nexthop': str(ipaddress.IPv4Address(nexthop))}
+ (nexthop,) = struct.unpack_from("!4s", data)
+ return {"bgp_nexthop": str(ipaddress.IPv4Address(nexthop))}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrMultiExitDisc:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_REACH_NLRI)
class PathAttrMpReachNLRI:
"""
@@ -162,7 +165,8 @@ class PathAttrMpReachNLRI:
| Network Layer Reachability Information (variable) |
+---------------------------------------------------------+
"""
- UNPACK_STR = '!HBB'
+
+ UNPACK_STR = "!HBB"
NLRI_RESERVED_LEN = 1
@staticmethod
@@ -170,35 +174,35 @@ class PathAttrMpReachNLRI:
msg = {}
if nexthop_len == 4:
# IPv4
- (ipv4,) = struct.unpack_from('!4s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4))
+ (ipv4,) = struct.unpack_from("!4s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4))
elif nexthop_len == 12:
# RD + IPv4
- (rd, ipv4) = struct.unpack_from('!8s4s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4))
- msg['nxhp_rd'] = str(RouteDistinguisher(rd))
+ (rd, ipv4) = struct.unpack_from("!8s4s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4))
+ msg["nxhp_rd"] = str(RouteDistinguisher(rd))
elif nexthop_len == 16:
# IPv6
- (ipv6,) = struct.unpack_from('!16s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
+ (ipv6,) = struct.unpack_from("!16s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
elif nexthop_len == 24:
# RD + IPv6
- (rd, ipv6) = struct.unpack_from('!8s16s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
- msg['nxhp_rd'] = str(RouteDistinguisher(rd))
+ (rd, ipv6) = struct.unpack_from("!8s16s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
+ msg["nxhp_rd"] = str(RouteDistinguisher(rd))
elif nexthop_len == 32:
# IPv6 + IPv6 link-local
- (ipv6, link_local)= struct.unpack_from('!16s16s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
- msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local))
+ (ipv6, link_local) = struct.unpack_from("!16s16s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
+ msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local))
elif nexthop_len == 48:
# RD + IPv6 + RD + IPv6 link-local
- u_str = '!8s16s8s16s'
- (rd1, ipv6, rd2, link_local)= struct.unpack_from(u_str, nexthop_data)
- msg['nxhp_rd1'] = str(RouteDistinguisher(rd1))
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
- msg['nxhp_rd2'] = str(RouteDistinguisher(rd2))
- msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local))
+ u_str = "!8s16s8s16s"
+ (rd1, ipv6, rd2, link_local) = struct.unpack_from(u_str, nexthop_data)
+ msg["nxhp_rd1"] = str(RouteDistinguisher(rd1))
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
+ msg["nxhp_rd2"] = str(RouteDistinguisher(rd2))
+ msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local))
return msg
@@ -210,10 +214,10 @@ class PathAttrMpReachNLRI:
def dissect(cls, data):
(afi, safi, nexthop_len) = struct.unpack_from(cls.UNPACK_STR, data)
offset = struct.calcsize(cls.UNPACK_STR)
- msg = {'afi': afi, 'safi': safi}
+ msg = {"afi": afi, "safi": safi}
# dissect nexthop
- nexthop_data = data[offset: offset + nexthop_len]
+ nexthop_data = data[offset : offset + nexthop_len]
nexthop = cls.dissect_nexthop(nexthop_data, nexthop_len)
msg.update(nexthop)
@@ -227,7 +231,7 @@ class PathAttrMpReachNLRI:
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_UNREACH_NLRI)
class PathAttrMpUnReachNLRI:
"""
@@ -239,13 +243,14 @@ class PathAttrMpUnReachNLRI:
| Withdrawn Routes (variable) |
+---------------------------------------------------------+
"""
- UNPACK_STR = '!HB'
+
+ UNPACK_STR = "!HB"
@classmethod
def dissect(cls, data):
(afi, safi) = struct.unpack_from(cls.UNPACK_STR, data)
offset = struct.calcsize(cls.UNPACK_STR)
- msg = {'bmp_log_type': 'withdraw','afi': afi, 'safi': safi}
+ msg = {"bmp_log_type": "withdraw", "afi": afi, "safi": safi}
if data[offset:]:
# dissect withdrawn_routes
@@ -254,51 +259,51 @@ class PathAttrMpUnReachNLRI:
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrLocalPref:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrAtomicAgregate:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrAggregator:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrCommunities:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrOriginatorID:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrClusterList:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrExtendedCommunities:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrPMSITunnel:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrLinkState:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrLargeCommunities:
pass
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/rd.py b/tests/topotests/lib/bmp_collector/bgp/update/rd.py
index c382fa8340..3f08de5ae9 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/rd.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/rd.py
@@ -7,7 +7,7 @@ import ipaddress
import struct
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class RouteDistinguisher:
"""
type 0:
@@ -28,32 +28,32 @@ class RouteDistinguisher:
+ | 4-bytes AS number (4 bytes)| Service Provider 2 bytes)|
+-------------------------------------------------------------------------+
"""
+
def __init__(self, rd):
self.rd = rd
self.as_number = None
self.admin_ipv4 = None
self.four_bytes_as = None
self.assigned_sp = None
- self.repr_str = ''
+ self.repr_str = ""
self.dissect()
def dissect(self):
- (rd_type,) = struct.unpack_from('!H', self.rd)
+ (rd_type,) = struct.unpack_from("!H", self.rd)
if rd_type == 0:
- (self.as_number,
- self.assigned_sp) = struct.unpack_from('!HI', self.rd[2:])
- self.repr_str = f'{self.as_number}:{self.assigned_sp}'
+ (self.as_number, self.assigned_sp) = struct.unpack_from("!HI", self.rd[2:])
+ self.repr_str = f"{self.as_number}:{self.assigned_sp}"
elif rd_type == 1:
- (self.admin_ipv4,
- self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:])
+ (self.admin_ipv4, self.assigned_sp) = struct.unpack_from("!IH", self.rd[2:])
ipv4 = str(ipaddress.IPv4Address(self.admin_ipv4))
- self.repr_str = f'{self.as_number}:{self.assigned_sp}'
+ self.repr_str = f"{self.as_number}:{self.assigned_sp}"
elif rd_type == 2:
- (self.four_bytes_as,
- self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:])
- self.repr_str = f'{self.four_bytes_as}:{self.assigned_sp}'
+ (self.four_bytes_as, self.assigned_sp) = struct.unpack_from(
+ "!IH", self.rd[2:]
+ )
+ self.repr_str = f"{self.four_bytes_as}:{self.assigned_sp}"
def __str__(self):
return self.repr_str
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 598db84e63..7787b6f74b 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -936,14 +936,26 @@ def generate_support_bundle():
"""
tgen = get_topogen()
+ if tgen is None:
+ logger.warn(
+ "Support bundle attempted to be generated, but topogen is not being used"
+ )
+ return True
+
router_list = tgen.routers()
test_name = os.environ.get("PYTEST_CURRENT_TEST").split(":")[-1].split(" ")[0]
bundle_procs = {}
for rname, rnode in router_list.items():
logger.info("Spawn collection of support bundle for %s", rname)
- dst_bundle = "{}/{}/support_bundles/{}".format(tgen.logdir, rname, test_name)
- rnode.run("mkdir -p " + dst_bundle)
+ try:
+ dst_bundle = "{}/{}/support_bundles/{}".format(
+ tgen.logdir, rname, test_name
+ )
+ rnode.run("mkdir -p " + dst_bundle)
+ except Exception as err:
+ logger.error("Generation of Support bundle failed {}".format(err))
+ return True
gen_sup_cmd = [
"/usr/lib/frr/generate_support_bundle.py",
diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py
index 814813f7f4..8e2e76d154 100644
--- a/tests/topotests/lib/snmptest.py
+++ b/tests/topotests/lib/snmptest.py
@@ -85,15 +85,18 @@ class SnmpTester(object):
return out_dict, out_list
def get(self, oid):
- cmd = "snmpget {0} {1}".format(self._snmp_config(), oid)
-
+ cmd = "snmpget {0} {1} 2>&1 | grep -v SNMPv2-PDU".format(
+ self._snmp_config(), oid
+ )
result = self.router.cmd(cmd)
if "not found" in result:
return None
return self._get_snmp_value(result)
def get_next(self, oid):
- cmd = "snmpgetnext {0} {1}".format(self._snmp_config(), oid)
+ cmd = "snmpgetnext {0} {1} 2>&1 | grep -v SNMPv2-PDU".format(
+ self._snmp_config(), oid
+ )
result = self.router.cmd(cmd)
print("get_next: {}".format(result))
@@ -102,7 +105,9 @@ class SnmpTester(object):
return self._get_snmp_value(result)
def walk(self, oid):
- cmd = "snmpwalk {0} {1}".format(self._snmp_config(), oid)
+ cmd = "snmpwalk {0} {1} 2>&1 | grep -v SNMPv2-PDU".format(
+ self._snmp_config(), oid
+ )
result = self.router.cmd(cmd)
return self._parse_multiline(result)
diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py
index 901e4f623a..148fb04fe5 100644
--- a/tests/topotests/lib/topojson.py
+++ b/tests/topotests/lib/topojson.py
@@ -227,13 +227,17 @@ def build_topo_from_json(tgen, topo=None):
topo["routers"][destRouter]["links"][curSwitch][
"interface"
] = "{}-{}-eth{}".format(
- destRouter, curSwitch, topo["routers"][destRouter]["nextIfname"]
+ destRouter,
+ curSwitch,
+ topo["routers"][destRouter]["nextIfname"],
)
topo["switches"][curSwitch]["links"][destRouter][
"interface"
] = "{}-{}-eth{}".format(
- curSwitch, destRouter, topo["routers"][destRouter]["nextIfname"]
+ curSwitch,
+ destRouter,
+ topo["routers"][destRouter]["nextIfname"],
)
topo["routers"][destRouter]["nextIfname"] += 1
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 2f69f7364b..087d8454fc 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -1296,6 +1296,8 @@ def fix_netns_limits(ns):
sysctl_assure(ns, "net.ipv4.conf.all.ignore_routes_with_linkdown", 1)
sysctl_assure(ns, "net.ipv6.conf.all.ignore_routes_with_linkdown", 1)
+ sysctl_assure(ns, "net.ipv4.conf.default.ignore_routes_with_linkdown", 1)
+ sysctl_assure(ns, "net.ipv6.conf.default.ignore_routes_with_linkdown", 1)
# igmp
sysctl_atleast(ns, "net.ipv4.igmp_max_memberships", 1000)
@@ -2181,12 +2183,16 @@ class Router(Node):
daemon,
error.returncode,
error.cmd,
- '\n:stdout: "{}"'.format(error.stdout.strip())
- if error.stdout
- else "",
- '\n:stderr: "{}"'.format(error.stderr.strip())
- if error.stderr
- else "",
+ (
+ '\n:stdout: "{}"'.format(error.stdout.strip())
+ if error.stdout
+ else ""
+ ),
+ (
+ '\n:stderr: "{}"'.format(error.stderr.strip())
+ if error.stderr
+ else ""
+ ),
)
else:
logger.debug("%s: %s %s started", self, self.routertype, daemon)
diff --git a/tests/topotests/mgmt_fe_client/mgmt_pb2.py b/tests/topotests/mgmt_fe_client/mgmt_pb2.py
index 0aa8803f7f..44dd2f6688 100644
--- a/tests/topotests/mgmt_fe_client/mgmt_pb2.py
+++ b/tests/topotests/mgmt_fe_client/mgmt_pb2.py
@@ -7,90 +7,113 @@ from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
+
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
-
-
DESCRIPTOR = _descriptor.FileDescriptor(
- name='mgmt.proto',
- package='mgmtd',
- syntax='proto2',
- serialized_options=None,
- create_key=_descriptor._internal_create_key,
- serialized_pb=b'\n\nmgmt.proto\x12\x05mgmtd\"\x1e\n\rYangDataXPath\x12\r\n\x05xpath\x18\x01 \x02(\t\"3\n\rYangDataValue\x12\x19\n\x0f\x65ncoded_str_val\x18\x64 \x01(\tH\x00\x42\x07\n\x05value\">\n\x08YangData\x12\r\n\x05xpath\x18\x01 \x02(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.mgmtd.YangDataValue\"X\n\x0eYangCfgDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\'\n\x08req_type\x18\x02 \x02(\x0e\x32\x15.mgmtd.CfgDataReqType\"B\n\x0eYangGetDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03\"R\n\x0e\x42\x65SubscribeReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\x12\x18\n\x10subscribe_xpaths\x18\x02 \x02(\x08\x12\x11\n\txpath_reg\x18\x03 \x03(\t\"#\n\x10\x42\x65SubscribeReply\x12\x0f\n\x07success\x18\x01 \x02(\x08\"*\n\x08\x42\x65TxnReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\"=\n\nBeTxnReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\x12\x0f\n\x07success\x18\x03 \x02(\x08\"b\n\x12\x42\x65\x43\x66gDataCreateReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\'\n\x08\x64\x61ta_req\x18\x02 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x13\n\x0b\x65nd_of_data\x18\x03 \x02(\x08\"M\n\x14\x42\x65\x43\x66gDataCreateReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t\"#\n\x11\x42\x65\x43\x66gDataApplyReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\"L\n\x13\x42\x65\x43\x66gDataApplyReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t\"A\n\rYangDataReply\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03\"\x94\x03\n\tBeMessage\x12+\n\nsubscr_req\x18\x02 \x01(\x0b\x32\x15.mgmtd.BeSubscribeReqH\x00\x12/\n\x0csubscr_reply\x18\x03 \x01(\x0b\x32\x17.mgmtd.BeSubscribeReplyH\x00\x12\"\n\x07txn_req\x18\x04 \x01(\x0b\x32\x0f.mgmtd.BeTxnReqH\x00\x12&\n\ttxn_reply\x18\x05 \x01(\x0b\x32\x11.mgmtd.BeTxnReplyH\x00\x12\x31\n\x0c\x63\x66g_data_req\x18\x06 \x01(\x0b\x32\x19.mgmtd.BeCfgDataCreateReqH\x00\x12\x35\n\x0e\x63\x66g_data_reply\x18\x07 \x01(\x0b\x32\x1b.mgmtd.BeCfgDataCreateReplyH\x00\x12\x31\n\rcfg_apply_req\x18\x08 \x01(\x0b\x32\x18.mgmtd.BeCfgDataApplyReqH\x00\x12\x35\n\x0f\x63\x66g_apply_reply\x18\t \x01(\x0b\x32\x1a.mgmtd.BeCfgDataApplyReplyH\x00\x42\t\n\x07message\"$\n\rFeRegisterReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\"T\n\x0c\x46\x65SessionReq\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x18\n\x0e\x63lient_conn_id\x18\x02 \x01(\x04H\x00\x12\x14\n\nsession_id\x18\x03 \x01(\x04H\x00\x42\x04\n\x02id\"]\n\x0e\x46\x65SessionReply\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x16\n\x0e\x63lient_conn_id\x18\x03 \x01(\x04\x12\x12\n\nsession_id\x18\x04 \x02(\x04\"b\n\x0b\x46\x65LockDsReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\"\x8b\x01\n\rFeLockDsReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\"\xbf\x01\n\x0e\x46\x65SetConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12(\n\x0c\x63ommit_ds_id\x18\x06 \x02(\x0e\x32\x12.mgmtd.DatastoreId\"\x99\x01\n\x10\x46\x65SetConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12\x0f\n\x07success\x18\x04 \x02(\x08\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\"\xab\x01\n\x11\x46\x65\x43ommitConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x06 \x02(\x08\"\xd4\x01\n\x13\x46\x65\x43ommitConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\x0f\n\x07success\x18\x06 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x07 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x08 \x01(\t\"\x86\x01\n\x08\x46\x65GetReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x15.mgmtd.YangGetDataReq\"\xae\x01\n\nFeGetReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\x12\"\n\x04\x64\x61ta\x18\x07 \x01(\x0b\x32\x14.mgmtd.YangDataReply\"0\n\x0f\x46\x65NotifyDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\"\x9c\x01\n\x13\x46\x65RegisterNotifyReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x14\n\x0cregister_req\x18\x03 \x02(\x08\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12(\n\ndata_xpath\x18\x05 \x03(\x0b\x32\x14.mgmtd.YangDataXPath\"\xf0\x04\n\tFeMessage\x12,\n\x0cregister_req\x18\x02 \x01(\x0b\x32\x14.mgmtd.FeRegisterReqH\x00\x12*\n\x0bsession_req\x18\x03 \x01(\x0b\x32\x13.mgmtd.FeSessionReqH\x00\x12.\n\rsession_reply\x18\x04 \x01(\x0b\x32\x15.mgmtd.FeSessionReplyH\x00\x12(\n\nlockds_req\x18\x05 \x01(\x0b\x32\x12.mgmtd.FeLockDsReqH\x00\x12,\n\x0clockds_reply\x18\x06 \x01(\x0b\x32\x14.mgmtd.FeLockDsReplyH\x00\x12+\n\nsetcfg_req\x18\x07 \x01(\x0b\x32\x15.mgmtd.FeSetConfigReqH\x00\x12/\n\x0csetcfg_reply\x18\x08 \x01(\x0b\x32\x17.mgmtd.FeSetConfigReplyH\x00\x12/\n\x0b\x63ommcfg_req\x18\t \x01(\x0b\x32\x18.mgmtd.FeCommitConfigReqH\x00\x12\x33\n\rcommcfg_reply\x18\n \x01(\x0b\x32\x1a.mgmtd.FeCommitConfigReplyH\x00\x12\"\n\x07get_req\x18\x0b \x01(\x0b\x32\x0f.mgmtd.FeGetReqH\x00\x12&\n\tget_reply\x18\x0c \x01(\x0b\x32\x11.mgmtd.FeGetReplyH\x00\x12\x31\n\x0fnotify_data_req\x18\x0f \x01(\x0b\x32\x16.mgmtd.FeNotifyDataReqH\x00\x12\x33\n\rregnotify_req\x18\x10 \x01(\x0b\x32\x1a.mgmtd.FeRegisterNotifyReqH\x00\x42\t\n\x07message*B\n\x0e\x43\x66gDataReqType\x12\x11\n\rREQ_TYPE_NONE\x10\x00\x12\x0c\n\x08SET_DATA\x10\x01\x12\x0f\n\x0b\x44\x45LETE_DATA\x10\x02*`\n\x0b\x44\x61tastoreId\x12\x0b\n\x07\x44S_NONE\x10\x00\x12\x0e\n\nRUNNING_DS\x10\x01\x12\x10\n\x0c\x43\x41NDIDATE_DS\x10\x02\x12\x12\n\x0eOPERATIONAL_DS\x10\x03\x12\x0e\n\nSTARTUP_DS\x10\x04'
+ name="mgmt.proto",
+ package="mgmtd",
+ syntax="proto2",
+ serialized_options=None,
+ create_key=_descriptor._internal_create_key,
+ serialized_pb=b'\n\nmgmt.proto\x12\x05mgmtd"\x1e\n\rYangDataXPath\x12\r\n\x05xpath\x18\x01 \x02(\t"3\n\rYangDataValue\x12\x19\n\x0f\x65ncoded_str_val\x18\x64 \x01(\tH\x00\x42\x07\n\x05value">\n\x08YangData\x12\r\n\x05xpath\x18\x01 \x02(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.mgmtd.YangDataValue"X\n\x0eYangCfgDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\'\n\x08req_type\x18\x02 \x02(\x0e\x32\x15.mgmtd.CfgDataReqType"B\n\x0eYangGetDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03"R\n\x0e\x42\x65SubscribeReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\x12\x18\n\x10subscribe_xpaths\x18\x02 \x02(\x08\x12\x11\n\txpath_reg\x18\x03 \x03(\t"#\n\x10\x42\x65SubscribeReply\x12\x0f\n\x07success\x18\x01 \x02(\x08"*\n\x08\x42\x65TxnReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08"=\n\nBeTxnReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\x12\x0f\n\x07success\x18\x03 \x02(\x08"b\n\x12\x42\x65\x43\x66gDataCreateReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\'\n\x08\x64\x61ta_req\x18\x02 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x13\n\x0b\x65nd_of_data\x18\x03 \x02(\x08"M\n\x14\x42\x65\x43\x66gDataCreateReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t"#\n\x11\x42\x65\x43\x66gDataApplyReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04"L\n\x13\x42\x65\x43\x66gDataApplyReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t"A\n\rYangDataReply\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03"\x94\x03\n\tBeMessage\x12+\n\nsubscr_req\x18\x02 \x01(\x0b\x32\x15.mgmtd.BeSubscribeReqH\x00\x12/\n\x0csubscr_reply\x18\x03 \x01(\x0b\x32\x17.mgmtd.BeSubscribeReplyH\x00\x12"\n\x07txn_req\x18\x04 \x01(\x0b\x32\x0f.mgmtd.BeTxnReqH\x00\x12&\n\ttxn_reply\x18\x05 \x01(\x0b\x32\x11.mgmtd.BeTxnReplyH\x00\x12\x31\n\x0c\x63\x66g_data_req\x18\x06 \x01(\x0b\x32\x19.mgmtd.BeCfgDataCreateReqH\x00\x12\x35\n\x0e\x63\x66g_data_reply\x18\x07 \x01(\x0b\x32\x1b.mgmtd.BeCfgDataCreateReplyH\x00\x12\x31\n\rcfg_apply_req\x18\x08 \x01(\x0b\x32\x18.mgmtd.BeCfgDataApplyReqH\x00\x12\x35\n\x0f\x63\x66g_apply_reply\x18\t \x01(\x0b\x32\x1a.mgmtd.BeCfgDataApplyReplyH\x00\x42\t\n\x07message"$\n\rFeRegisterReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t"T\n\x0c\x46\x65SessionReq\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x18\n\x0e\x63lient_conn_id\x18\x02 \x01(\x04H\x00\x12\x14\n\nsession_id\x18\x03 \x01(\x04H\x00\x42\x04\n\x02id"]\n\x0e\x46\x65SessionReply\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x16\n\x0e\x63lient_conn_id\x18\x03 \x01(\x04\x12\x12\n\nsession_id\x18\x04 \x02(\x04"b\n\x0b\x46\x65LockDsReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08"\x8b\x01\n\rFeLockDsReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t"\xbf\x01\n\x0e\x46\x65SetConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12(\n\x0c\x63ommit_ds_id\x18\x06 \x02(\x0e\x32\x12.mgmtd.DatastoreId"\x99\x01\n\x10\x46\x65SetConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12\x0f\n\x07success\x18\x04 \x02(\x08\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t"\xab\x01\n\x11\x46\x65\x43ommitConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x06 \x02(\x08"\xd4\x01\n\x13\x46\x65\x43ommitConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\x0f\n\x07success\x18\x06 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x07 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x08 \x01(\t"\x86\x01\n\x08\x46\x65GetReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x15.mgmtd.YangGetDataReq"\xae\x01\n\nFeGetReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\x12"\n\x04\x64\x61ta\x18\x07 \x01(\x0b\x32\x14.mgmtd.YangDataReply"0\n\x0f\x46\x65NotifyDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData"\x9c\x01\n\x13\x46\x65RegisterNotifyReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x14\n\x0cregister_req\x18\x03 \x02(\x08\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12(\n\ndata_xpath\x18\x05 \x03(\x0b\x32\x14.mgmtd.YangDataXPath"\xf0\x04\n\tFeMessage\x12,\n\x0cregister_req\x18\x02 \x01(\x0b\x32\x14.mgmtd.FeRegisterReqH\x00\x12*\n\x0bsession_req\x18\x03 \x01(\x0b\x32\x13.mgmtd.FeSessionReqH\x00\x12.\n\rsession_reply\x18\x04 \x01(\x0b\x32\x15.mgmtd.FeSessionReplyH\x00\x12(\n\nlockds_req\x18\x05 \x01(\x0b\x32\x12.mgmtd.FeLockDsReqH\x00\x12,\n\x0clockds_reply\x18\x06 \x01(\x0b\x32\x14.mgmtd.FeLockDsReplyH\x00\x12+\n\nsetcfg_req\x18\x07 \x01(\x0b\x32\x15.mgmtd.FeSetConfigReqH\x00\x12/\n\x0csetcfg_reply\x18\x08 \x01(\x0b\x32\x17.mgmtd.FeSetConfigReplyH\x00\x12/\n\x0b\x63ommcfg_req\x18\t \x01(\x0b\x32\x18.mgmtd.FeCommitConfigReqH\x00\x12\x33\n\rcommcfg_reply\x18\n \x01(\x0b\x32\x1a.mgmtd.FeCommitConfigReplyH\x00\x12"\n\x07get_req\x18\x0b \x01(\x0b\x32\x0f.mgmtd.FeGetReqH\x00\x12&\n\tget_reply\x18\x0c \x01(\x0b\x32\x11.mgmtd.FeGetReplyH\x00\x12\x31\n\x0fnotify_data_req\x18\x0f \x01(\x0b\x32\x16.mgmtd.FeNotifyDataReqH\x00\x12\x33\n\rregnotify_req\x18\x10 \x01(\x0b\x32\x1a.mgmtd.FeRegisterNotifyReqH\x00\x42\t\n\x07message*B\n\x0e\x43\x66gDataReqType\x12\x11\n\rREQ_TYPE_NONE\x10\x00\x12\x0c\n\x08SET_DATA\x10\x01\x12\x0f\n\x0b\x44\x45LETE_DATA\x10\x02*`\n\x0b\x44\x61tastoreId\x12\x0b\n\x07\x44S_NONE\x10\x00\x12\x0e\n\nRUNNING_DS\x10\x01\x12\x10\n\x0c\x43\x41NDIDATE_DS\x10\x02\x12\x12\n\x0eOPERATIONAL_DS\x10\x03\x12\x0e\n\nSTARTUP_DS\x10\x04',
)
_CFGDATAREQTYPE = _descriptor.EnumDescriptor(
- name='CfgDataReqType',
- full_name='mgmtd.CfgDataReqType',
- filename=None,
- file=DESCRIPTOR,
- create_key=_descriptor._internal_create_key,
- values=[
- _descriptor.EnumValueDescriptor(
- name='REQ_TYPE_NONE', index=0, number=0,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='SET_DATA', index=1, number=1,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='DELETE_DATA', index=2, number=2,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=3674,
- serialized_end=3740,
+ name="CfgDataReqType",
+ full_name="mgmtd.CfgDataReqType",
+ filename=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name="REQ_TYPE_NONE",
+ index=0,
+ number=0,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="SET_DATA",
+ index=1,
+ number=1,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="DELETE_DATA",
+ index=2,
+ number=2,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ containing_type=None,
+ serialized_options=None,
+ serialized_start=3674,
+ serialized_end=3740,
)
_sym_db.RegisterEnumDescriptor(_CFGDATAREQTYPE)
CfgDataReqType = enum_type_wrapper.EnumTypeWrapper(_CFGDATAREQTYPE)
_DATASTOREID = _descriptor.EnumDescriptor(
- name='DatastoreId',
- full_name='mgmtd.DatastoreId',
- filename=None,
- file=DESCRIPTOR,
- create_key=_descriptor._internal_create_key,
- values=[
- _descriptor.EnumValueDescriptor(
- name='DS_NONE', index=0, number=0,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='RUNNING_DS', index=1, number=1,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='CANDIDATE_DS', index=2, number=2,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='OPERATIONAL_DS', index=3, number=3,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='STARTUP_DS', index=4, number=4,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=3742,
- serialized_end=3838,
+ name="DatastoreId",
+ full_name="mgmtd.DatastoreId",
+ filename=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name="DS_NONE",
+ index=0,
+ number=0,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="RUNNING_DS",
+ index=1,
+ number=1,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="CANDIDATE_DS",
+ index=2,
+ number=2,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="OPERATIONAL_DS",
+ index=3,
+ number=3,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="STARTUP_DS",
+ index=4,
+ number=4,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ containing_type=None,
+ serialized_options=None,
+ serialized_start=3742,
+ serialized_end=3838,
)
_sym_db.RegisterEnumDescriptor(_DATASTOREID)
@@ -105,1885 +128,3341 @@ OPERATIONAL_DS = 3
STARTUP_DS = 4
-
_YANGDATAXPATH = _descriptor.Descriptor(
- name='YangDataXPath',
- full_name='mgmtd.YangDataXPath',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='xpath', full_name='mgmtd.YangDataXPath.xpath', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=21,
- serialized_end=51,
+ name="YangDataXPath",
+ full_name="mgmtd.YangDataXPath",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="xpath",
+ full_name="mgmtd.YangDataXPath.xpath",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=21,
+ serialized_end=51,
)
_YANGDATAVALUE = _descriptor.Descriptor(
- name='YangDataValue',
- full_name='mgmtd.YangDataValue',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='encoded_str_val', full_name='mgmtd.YangDataValue.encoded_str_val', index=0,
- number=100, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='value', full_name='mgmtd.YangDataValue.value',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=53,
- serialized_end=104,
+ name="YangDataValue",
+ full_name="mgmtd.YangDataValue",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="encoded_str_val",
+ full_name="mgmtd.YangDataValue.encoded_str_val",
+ index=0,
+ number=100,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="value",
+ full_name="mgmtd.YangDataValue.value",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=53,
+ serialized_end=104,
)
_YANGDATA = _descriptor.Descriptor(
- name='YangData',
- full_name='mgmtd.YangData',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='xpath', full_name='mgmtd.YangData.xpath', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='value', full_name='mgmtd.YangData.value', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=106,
- serialized_end=168,
+ name="YangData",
+ full_name="mgmtd.YangData",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="xpath",
+ full_name="mgmtd.YangData.xpath",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="value",
+ full_name="mgmtd.YangData.value",
+ index=1,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=106,
+ serialized_end=168,
)
_YANGCFGDATAREQ = _descriptor.Descriptor(
- name='YangCfgDataReq',
- full_name='mgmtd.YangCfgDataReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.YangCfgDataReq.data', index=0,
- number=1, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_type', full_name='mgmtd.YangCfgDataReq.req_type', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=170,
- serialized_end=258,
+ name="YangCfgDataReq",
+ full_name="mgmtd.YangCfgDataReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.YangCfgDataReq.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=2,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_type",
+ full_name="mgmtd.YangCfgDataReq.req_type",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=170,
+ serialized_end=258,
)
_YANGGETDATAREQ = _descriptor.Descriptor(
- name='YangGetDataReq',
- full_name='mgmtd.YangGetDataReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.YangGetDataReq.data', index=0,
- number=1, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='next_indx', full_name='mgmtd.YangGetDataReq.next_indx', index=1,
- number=2, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=260,
- serialized_end=326,
+ name="YangGetDataReq",
+ full_name="mgmtd.YangGetDataReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.YangGetDataReq.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=2,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="next_indx",
+ full_name="mgmtd.YangGetDataReq.next_indx",
+ index=1,
+ number=2,
+ type=3,
+ cpp_type=2,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=260,
+ serialized_end=326,
)
_BESUBSCRIBEREQ = _descriptor.Descriptor(
- name='BeSubscribeReq',
- full_name='mgmtd.BeSubscribeReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='client_name', full_name='mgmtd.BeSubscribeReq.client_name', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='subscribe_xpaths', full_name='mgmtd.BeSubscribeReq.subscribe_xpaths', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='xpath_reg', full_name='mgmtd.BeSubscribeReq.xpath_reg', index=2,
- number=3, type=9, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=328,
- serialized_end=410,
+ name="BeSubscribeReq",
+ full_name="mgmtd.BeSubscribeReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="client_name",
+ full_name="mgmtd.BeSubscribeReq.client_name",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="subscribe_xpaths",
+ full_name="mgmtd.BeSubscribeReq.subscribe_xpaths",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="xpath_reg",
+ full_name="mgmtd.BeSubscribeReq.xpath_reg",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=328,
+ serialized_end=410,
)
_BESUBSCRIBEREPLY = _descriptor.Descriptor(
- name='BeSubscribeReply',
- full_name='mgmtd.BeSubscribeReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeSubscribeReply.success', index=0,
- number=1, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=412,
- serialized_end=447,
+ name="BeSubscribeReply",
+ full_name="mgmtd.BeSubscribeReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeSubscribeReply.success",
+ index=0,
+ number=1,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=412,
+ serialized_end=447,
)
_BETXNREQ = _descriptor.Descriptor(
- name='BeTxnReq',
- full_name='mgmtd.BeTxnReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeTxnReq.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.BeTxnReq.create', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=449,
- serialized_end=491,
+ name="BeTxnReq",
+ full_name="mgmtd.BeTxnReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeTxnReq.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.BeTxnReq.create",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=449,
+ serialized_end=491,
)
_BETXNREPLY = _descriptor.Descriptor(
- name='BeTxnReply',
- full_name='mgmtd.BeTxnReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeTxnReply.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.BeTxnReply.create', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeTxnReply.success', index=2,
- number=3, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=493,
- serialized_end=554,
+ name="BeTxnReply",
+ full_name="mgmtd.BeTxnReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeTxnReply.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.BeTxnReply.create",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeTxnReply.success",
+ index=2,
+ number=3,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=493,
+ serialized_end=554,
)
_BECFGDATACREATEREQ = _descriptor.Descriptor(
- name='BeCfgDataCreateReq',
- full_name='mgmtd.BeCfgDataCreateReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataCreateReq.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data_req', full_name='mgmtd.BeCfgDataCreateReq.data_req', index=1,
- number=2, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='end_of_data', full_name='mgmtd.BeCfgDataCreateReq.end_of_data', index=2,
- number=3, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=556,
- serialized_end=654,
+ name="BeCfgDataCreateReq",
+ full_name="mgmtd.BeCfgDataCreateReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataCreateReq.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data_req",
+ full_name="mgmtd.BeCfgDataCreateReq.data_req",
+ index=1,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="end_of_data",
+ full_name="mgmtd.BeCfgDataCreateReq.end_of_data",
+ index=2,
+ number=3,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=556,
+ serialized_end=654,
)
_BECFGDATACREATEREPLY = _descriptor.Descriptor(
- name='BeCfgDataCreateReply',
- full_name='mgmtd.BeCfgDataCreateReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataCreateReply.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeCfgDataCreateReply.success', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.BeCfgDataCreateReply.error_if_any', index=2,
- number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=656,
- serialized_end=733,
+ name="BeCfgDataCreateReply",
+ full_name="mgmtd.BeCfgDataCreateReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataCreateReply.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeCfgDataCreateReply.success",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.BeCfgDataCreateReply.error_if_any",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=656,
+ serialized_end=733,
)
_BECFGDATAAPPLYREQ = _descriptor.Descriptor(
- name='BeCfgDataApplyReq',
- full_name='mgmtd.BeCfgDataApplyReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataApplyReq.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=735,
- serialized_end=770,
+ name="BeCfgDataApplyReq",
+ full_name="mgmtd.BeCfgDataApplyReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataApplyReq.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=735,
+ serialized_end=770,
)
_BECFGDATAAPPLYREPLY = _descriptor.Descriptor(
- name='BeCfgDataApplyReply',
- full_name='mgmtd.BeCfgDataApplyReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataApplyReply.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeCfgDataApplyReply.success', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.BeCfgDataApplyReply.error_if_any', index=2,
- number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=772,
- serialized_end=848,
+ name="BeCfgDataApplyReply",
+ full_name="mgmtd.BeCfgDataApplyReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataApplyReply.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeCfgDataApplyReply.success",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.BeCfgDataApplyReply.error_if_any",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=772,
+ serialized_end=848,
)
_YANGDATAREPLY = _descriptor.Descriptor(
- name='YangDataReply',
- full_name='mgmtd.YangDataReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.YangDataReply.data', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='next_indx', full_name='mgmtd.YangDataReply.next_indx', index=1,
- number=2, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=850,
- serialized_end=915,
+ name="YangDataReply",
+ full_name="mgmtd.YangDataReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.YangDataReply.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="next_indx",
+ full_name="mgmtd.YangDataReply.next_indx",
+ index=1,
+ number=2,
+ type=3,
+ cpp_type=2,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=850,
+ serialized_end=915,
)
_BEMESSAGE = _descriptor.Descriptor(
- name='BeMessage',
- full_name='mgmtd.BeMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='subscr_req', full_name='mgmtd.BeMessage.subscr_req', index=0,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='subscr_reply', full_name='mgmtd.BeMessage.subscr_reply', index=1,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='txn_req', full_name='mgmtd.BeMessage.txn_req', index=2,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='txn_reply', full_name='mgmtd.BeMessage.txn_reply', index=3,
- number=5, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_data_req', full_name='mgmtd.BeMessage.cfg_data_req', index=4,
- number=6, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_data_reply', full_name='mgmtd.BeMessage.cfg_data_reply', index=5,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_apply_req', full_name='mgmtd.BeMessage.cfg_apply_req', index=6,
- number=8, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_apply_reply', full_name='mgmtd.BeMessage.cfg_apply_reply', index=7,
- number=9, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='message', full_name='mgmtd.BeMessage.message',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=918,
- serialized_end=1322,
+ name="BeMessage",
+ full_name="mgmtd.BeMessage",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="subscr_req",
+ full_name="mgmtd.BeMessage.subscr_req",
+ index=0,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="subscr_reply",
+ full_name="mgmtd.BeMessage.subscr_reply",
+ index=1,
+ number=3,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="txn_req",
+ full_name="mgmtd.BeMessage.txn_req",
+ index=2,
+ number=4,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="txn_reply",
+ full_name="mgmtd.BeMessage.txn_reply",
+ index=3,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_data_req",
+ full_name="mgmtd.BeMessage.cfg_data_req",
+ index=4,
+ number=6,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_data_reply",
+ full_name="mgmtd.BeMessage.cfg_data_reply",
+ index=5,
+ number=7,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_apply_req",
+ full_name="mgmtd.BeMessage.cfg_apply_req",
+ index=6,
+ number=8,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_apply_reply",
+ full_name="mgmtd.BeMessage.cfg_apply_reply",
+ index=7,
+ number=9,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="message",
+ full_name="mgmtd.BeMessage.message",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=918,
+ serialized_end=1322,
)
_FEREGISTERREQ = _descriptor.Descriptor(
- name='FeRegisterReq',
- full_name='mgmtd.FeRegisterReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='client_name', full_name='mgmtd.FeRegisterReq.client_name', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1324,
- serialized_end=1360,
+ name="FeRegisterReq",
+ full_name="mgmtd.FeRegisterReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="client_name",
+ full_name="mgmtd.FeRegisterReq.client_name",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1324,
+ serialized_end=1360,
)
_FESESSIONREQ = _descriptor.Descriptor(
- name='FeSessionReq',
- full_name='mgmtd.FeSessionReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.FeSessionReq.create', index=0,
- number=1, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='client_conn_id', full_name='mgmtd.FeSessionReq.client_conn_id', index=1,
- number=2, type=4, cpp_type=4, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSessionReq.session_id', index=2,
- number=3, type=4, cpp_type=4, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='id', full_name='mgmtd.FeSessionReq.id',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=1362,
- serialized_end=1446,
+ name="FeSessionReq",
+ full_name="mgmtd.FeSessionReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.FeSessionReq.create",
+ index=0,
+ number=1,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="client_conn_id",
+ full_name="mgmtd.FeSessionReq.client_conn_id",
+ index=1,
+ number=2,
+ type=4,
+ cpp_type=4,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSessionReq.session_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="id",
+ full_name="mgmtd.FeSessionReq.id",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=1362,
+ serialized_end=1446,
)
_FESESSIONREPLY = _descriptor.Descriptor(
- name='FeSessionReply',
- full_name='mgmtd.FeSessionReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.FeSessionReply.create', index=0,
- number=1, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeSessionReply.success', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='client_conn_id', full_name='mgmtd.FeSessionReply.client_conn_id', index=2,
- number=3, type=4, cpp_type=4, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSessionReply.session_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1448,
- serialized_end=1541,
+ name="FeSessionReply",
+ full_name="mgmtd.FeSessionReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.FeSessionReply.create",
+ index=0,
+ number=1,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeSessionReply.success",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="client_conn_id",
+ full_name="mgmtd.FeSessionReply.client_conn_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSessionReply.session_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1448,
+ serialized_end=1541,
)
_FELOCKDSREQ = _descriptor.Descriptor(
- name='FeLockDsReq',
- full_name='mgmtd.FeLockDsReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeLockDsReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeLockDsReq.req_id', index=1,
- number=2, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeLockDsReq.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lock', full_name='mgmtd.FeLockDsReq.lock', index=3,
- number=4, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1543,
- serialized_end=1641,
+ name="FeLockDsReq",
+ full_name="mgmtd.FeLockDsReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeLockDsReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeLockDsReq.req_id",
+ index=1,
+ number=2,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeLockDsReq.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lock",
+ full_name="mgmtd.FeLockDsReq.lock",
+ index=3,
+ number=4,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1543,
+ serialized_end=1641,
)
_FELOCKDSREPLY = _descriptor.Descriptor(
- name='FeLockDsReply',
- full_name='mgmtd.FeLockDsReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeLockDsReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeLockDsReply.req_id', index=1,
- number=2, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeLockDsReply.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lock', full_name='mgmtd.FeLockDsReply.lock', index=3,
- number=4, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeLockDsReply.success', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeLockDsReply.error_if_any', index=5,
- number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1644,
- serialized_end=1783,
+ name="FeLockDsReply",
+ full_name="mgmtd.FeLockDsReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeLockDsReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeLockDsReply.req_id",
+ index=1,
+ number=2,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeLockDsReply.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lock",
+ full_name="mgmtd.FeLockDsReply.lock",
+ index=3,
+ number=4,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeLockDsReply.success",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeLockDsReply.error_if_any",
+ index=5,
+ number=6,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1644,
+ serialized_end=1783,
)
_FESETCONFIGREQ = _descriptor.Descriptor(
- name='FeSetConfigReq',
- full_name='mgmtd.FeSetConfigReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSetConfigReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeSetConfigReq.ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeSetConfigReq.req_id', index=2,
- number=3, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeSetConfigReq.data', index=3,
- number=4, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='implicit_commit', full_name='mgmtd.FeSetConfigReq.implicit_commit', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='commit_ds_id', full_name='mgmtd.FeSetConfigReq.commit_ds_id', index=5,
- number=6, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1786,
- serialized_end=1977,
+ name="FeSetConfigReq",
+ full_name="mgmtd.FeSetConfigReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSetConfigReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeSetConfigReq.ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeSetConfigReq.req_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeSetConfigReq.data",
+ index=3,
+ number=4,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="implicit_commit",
+ full_name="mgmtd.FeSetConfigReq.implicit_commit",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="commit_ds_id",
+ full_name="mgmtd.FeSetConfigReq.commit_ds_id",
+ index=5,
+ number=6,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1786,
+ serialized_end=1977,
)
_FESETCONFIGREPLY = _descriptor.Descriptor(
- name='FeSetConfigReply',
- full_name='mgmtd.FeSetConfigReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSetConfigReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeSetConfigReply.ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeSetConfigReply.req_id', index=2,
- number=3, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeSetConfigReply.success', index=3,
- number=4, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='implicit_commit', full_name='mgmtd.FeSetConfigReply.implicit_commit', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeSetConfigReply.error_if_any', index=5,
- number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1980,
- serialized_end=2133,
+ name="FeSetConfigReply",
+ full_name="mgmtd.FeSetConfigReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSetConfigReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeSetConfigReply.ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeSetConfigReply.req_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeSetConfigReply.success",
+ index=3,
+ number=4,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="implicit_commit",
+ full_name="mgmtd.FeSetConfigReply.implicit_commit",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeSetConfigReply.error_if_any",
+ index=5,
+ number=6,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1980,
+ serialized_end=2133,
)
_FECOMMITCONFIGREQ = _descriptor.Descriptor(
- name='FeCommitConfigReq',
- full_name='mgmtd.FeCommitConfigReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeCommitConfigReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='src_ds_id', full_name='mgmtd.FeCommitConfigReq.src_ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='dst_ds_id', full_name='mgmtd.FeCommitConfigReq.dst_ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeCommitConfigReq.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='validate_only', full_name='mgmtd.FeCommitConfigReq.validate_only', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='abort', full_name='mgmtd.FeCommitConfigReq.abort', index=5,
- number=6, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2136,
- serialized_end=2307,
+ name="FeCommitConfigReq",
+ full_name="mgmtd.FeCommitConfigReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeCommitConfigReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="src_ds_id",
+ full_name="mgmtd.FeCommitConfigReq.src_ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="dst_ds_id",
+ full_name="mgmtd.FeCommitConfigReq.dst_ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeCommitConfigReq.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="validate_only",
+ full_name="mgmtd.FeCommitConfigReq.validate_only",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="abort",
+ full_name="mgmtd.FeCommitConfigReq.abort",
+ index=5,
+ number=6,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2136,
+ serialized_end=2307,
)
_FECOMMITCONFIGREPLY = _descriptor.Descriptor(
- name='FeCommitConfigReply',
- full_name='mgmtd.FeCommitConfigReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeCommitConfigReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='src_ds_id', full_name='mgmtd.FeCommitConfigReply.src_ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='dst_ds_id', full_name='mgmtd.FeCommitConfigReply.dst_ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeCommitConfigReply.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='validate_only', full_name='mgmtd.FeCommitConfigReply.validate_only', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeCommitConfigReply.success', index=5,
- number=6, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='abort', full_name='mgmtd.FeCommitConfigReply.abort', index=6,
- number=7, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeCommitConfigReply.error_if_any', index=7,
- number=8, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2310,
- serialized_end=2522,
+ name="FeCommitConfigReply",
+ full_name="mgmtd.FeCommitConfigReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeCommitConfigReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="src_ds_id",
+ full_name="mgmtd.FeCommitConfigReply.src_ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="dst_ds_id",
+ full_name="mgmtd.FeCommitConfigReply.dst_ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeCommitConfigReply.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="validate_only",
+ full_name="mgmtd.FeCommitConfigReply.validate_only",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeCommitConfigReply.success",
+ index=5,
+ number=6,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="abort",
+ full_name="mgmtd.FeCommitConfigReply.abort",
+ index=6,
+ number=7,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeCommitConfigReply.error_if_any",
+ index=7,
+ number=8,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2310,
+ serialized_end=2522,
)
_FEGETREQ = _descriptor.Descriptor(
- name='FeGetReq',
- full_name='mgmtd.FeGetReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeGetReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='config', full_name='mgmtd.FeGetReq.config', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeGetReq.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeGetReq.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeGetReq.data', index=4,
- number=5, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2525,
- serialized_end=2659,
+ name="FeGetReq",
+ full_name="mgmtd.FeGetReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeGetReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="config",
+ full_name="mgmtd.FeGetReq.config",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeGetReq.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeGetReq.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeGetReq.data",
+ index=4,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2525,
+ serialized_end=2659,
)
_FEGETREPLY = _descriptor.Descriptor(
- name='FeGetReply',
- full_name='mgmtd.FeGetReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeGetReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='config', full_name='mgmtd.FeGetReply.config', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeGetReply.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeGetReply.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeGetReply.success', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeGetReply.error_if_any', index=5,
- number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeGetReply.data', index=6,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2662,
- serialized_end=2836,
+ name="FeGetReply",
+ full_name="mgmtd.FeGetReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeGetReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="config",
+ full_name="mgmtd.FeGetReply.config",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeGetReply.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeGetReply.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeGetReply.success",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeGetReply.error_if_any",
+ index=5,
+ number=6,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeGetReply.data",
+ index=6,
+ number=7,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2662,
+ serialized_end=2836,
)
_FENOTIFYDATAREQ = _descriptor.Descriptor(
- name='FeNotifyDataReq',
- full_name='mgmtd.FeNotifyDataReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeNotifyDataReq.data', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2838,
- serialized_end=2886,
+ name="FeNotifyDataReq",
+ full_name="mgmtd.FeNotifyDataReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeNotifyDataReq.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2838,
+ serialized_end=2886,
)
_FEREGISTERNOTIFYREQ = _descriptor.Descriptor(
- name='FeRegisterNotifyReq',
- full_name='mgmtd.FeRegisterNotifyReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeRegisterNotifyReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeRegisterNotifyReq.ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='register_req', full_name='mgmtd.FeRegisterNotifyReq.register_req', index=2,
- number=3, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeRegisterNotifyReq.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data_xpath', full_name='mgmtd.FeRegisterNotifyReq.data_xpath', index=4,
- number=5, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2889,
- serialized_end=3045,
+ name="FeRegisterNotifyReq",
+ full_name="mgmtd.FeRegisterNotifyReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeRegisterNotifyReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeRegisterNotifyReq.ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="register_req",
+ full_name="mgmtd.FeRegisterNotifyReq.register_req",
+ index=2,
+ number=3,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeRegisterNotifyReq.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data_xpath",
+ full_name="mgmtd.FeRegisterNotifyReq.data_xpath",
+ index=4,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2889,
+ serialized_end=3045,
)
_FEMESSAGE = _descriptor.Descriptor(
- name='FeMessage',
- full_name='mgmtd.FeMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='register_req', full_name='mgmtd.FeMessage.register_req', index=0,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_req', full_name='mgmtd.FeMessage.session_req', index=1,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_reply', full_name='mgmtd.FeMessage.session_reply', index=2,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lockds_req', full_name='mgmtd.FeMessage.lockds_req', index=3,
- number=5, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lockds_reply', full_name='mgmtd.FeMessage.lockds_reply', index=4,
- number=6, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='setcfg_req', full_name='mgmtd.FeMessage.setcfg_req', index=5,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='setcfg_reply', full_name='mgmtd.FeMessage.setcfg_reply', index=6,
- number=8, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='commcfg_req', full_name='mgmtd.FeMessage.commcfg_req', index=7,
- number=9, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='commcfg_reply', full_name='mgmtd.FeMessage.commcfg_reply', index=8,
- number=10, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='get_req', full_name='mgmtd.FeMessage.get_req', index=9,
- number=11, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='get_reply', full_name='mgmtd.FeMessage.get_reply', index=10,
- number=12, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='notify_data_req', full_name='mgmtd.FeMessage.notify_data_req', index=11,
- number=15, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='regnotify_req', full_name='mgmtd.FeMessage.regnotify_req', index=12,
- number=16, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='message', full_name='mgmtd.FeMessage.message',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=3048,
- serialized_end=3672,
-)
-
-_YANGDATAVALUE.oneofs_by_name['value'].fields.append(
- _YANGDATAVALUE.fields_by_name['encoded_str_val'])
-_YANGDATAVALUE.fields_by_name['encoded_str_val'].containing_oneof = _YANGDATAVALUE.oneofs_by_name['value']
-_YANGDATA.fields_by_name['value'].message_type = _YANGDATAVALUE
-_YANGCFGDATAREQ.fields_by_name['data'].message_type = _YANGDATA
-_YANGCFGDATAREQ.fields_by_name['req_type'].enum_type = _CFGDATAREQTYPE
-_YANGGETDATAREQ.fields_by_name['data'].message_type = _YANGDATA
-_BECFGDATACREATEREQ.fields_by_name['data_req'].message_type = _YANGCFGDATAREQ
-_YANGDATAREPLY.fields_by_name['data'].message_type = _YANGDATA
-_BEMESSAGE.fields_by_name['subscr_req'].message_type = _BESUBSCRIBEREQ
-_BEMESSAGE.fields_by_name['subscr_reply'].message_type = _BESUBSCRIBEREPLY
-_BEMESSAGE.fields_by_name['txn_req'].message_type = _BETXNREQ
-_BEMESSAGE.fields_by_name['txn_reply'].message_type = _BETXNREPLY
-_BEMESSAGE.fields_by_name['cfg_data_req'].message_type = _BECFGDATACREATEREQ
-_BEMESSAGE.fields_by_name['cfg_data_reply'].message_type = _BECFGDATACREATEREPLY
-_BEMESSAGE.fields_by_name['cfg_apply_req'].message_type = _BECFGDATAAPPLYREQ
-_BEMESSAGE.fields_by_name['cfg_apply_reply'].message_type = _BECFGDATAAPPLYREPLY
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['subscr_req'])
-_BEMESSAGE.fields_by_name['subscr_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['subscr_reply'])
-_BEMESSAGE.fields_by_name['subscr_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['txn_req'])
-_BEMESSAGE.fields_by_name['txn_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['txn_reply'])
-_BEMESSAGE.fields_by_name['txn_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_data_req'])
-_BEMESSAGE.fields_by_name['cfg_data_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_data_reply'])
-_BEMESSAGE.fields_by_name['cfg_data_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_apply_req'])
-_BEMESSAGE.fields_by_name['cfg_apply_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_apply_reply'])
-_BEMESSAGE.fields_by_name['cfg_apply_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_FESESSIONREQ.oneofs_by_name['id'].fields.append(
- _FESESSIONREQ.fields_by_name['client_conn_id'])
-_FESESSIONREQ.fields_by_name['client_conn_id'].containing_oneof = _FESESSIONREQ.oneofs_by_name['id']
-_FESESSIONREQ.oneofs_by_name['id'].fields.append(
- _FESESSIONREQ.fields_by_name['session_id'])
-_FESESSIONREQ.fields_by_name['session_id'].containing_oneof = _FESESSIONREQ.oneofs_by_name['id']
-_FELOCKDSREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FELOCKDSREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FESETCONFIGREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FESETCONFIGREQ.fields_by_name['data'].message_type = _YANGCFGDATAREQ
-_FESETCONFIGREQ.fields_by_name['commit_ds_id'].enum_type = _DATASTOREID
-_FESETCONFIGREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREQ.fields_by_name['src_ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREQ.fields_by_name['dst_ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREPLY.fields_by_name['src_ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREPLY.fields_by_name['dst_ds_id'].enum_type = _DATASTOREID
-_FEGETREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FEGETREQ.fields_by_name['data'].message_type = _YANGGETDATAREQ
-_FEGETREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FEGETREPLY.fields_by_name['data'].message_type = _YANGDATAREPLY
-_FENOTIFYDATAREQ.fields_by_name['data'].message_type = _YANGDATA
-_FEREGISTERNOTIFYREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FEREGISTERNOTIFYREQ.fields_by_name['data_xpath'].message_type = _YANGDATAXPATH
-_FEMESSAGE.fields_by_name['register_req'].message_type = _FEREGISTERREQ
-_FEMESSAGE.fields_by_name['session_req'].message_type = _FESESSIONREQ
-_FEMESSAGE.fields_by_name['session_reply'].message_type = _FESESSIONREPLY
-_FEMESSAGE.fields_by_name['lockds_req'].message_type = _FELOCKDSREQ
-_FEMESSAGE.fields_by_name['lockds_reply'].message_type = _FELOCKDSREPLY
-_FEMESSAGE.fields_by_name['setcfg_req'].message_type = _FESETCONFIGREQ
-_FEMESSAGE.fields_by_name['setcfg_reply'].message_type = _FESETCONFIGREPLY
-_FEMESSAGE.fields_by_name['commcfg_req'].message_type = _FECOMMITCONFIGREQ
-_FEMESSAGE.fields_by_name['commcfg_reply'].message_type = _FECOMMITCONFIGREPLY
-_FEMESSAGE.fields_by_name['get_req'].message_type = _FEGETREQ
-_FEMESSAGE.fields_by_name['get_reply'].message_type = _FEGETREPLY
-_FEMESSAGE.fields_by_name['notify_data_req'].message_type = _FENOTIFYDATAREQ
-_FEMESSAGE.fields_by_name['regnotify_req'].message_type = _FEREGISTERNOTIFYREQ
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['register_req'])
-_FEMESSAGE.fields_by_name['register_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['session_req'])
-_FEMESSAGE.fields_by_name['session_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['session_reply'])
-_FEMESSAGE.fields_by_name['session_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['lockds_req'])
-_FEMESSAGE.fields_by_name['lockds_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['lockds_reply'])
-_FEMESSAGE.fields_by_name['lockds_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['setcfg_req'])
-_FEMESSAGE.fields_by_name['setcfg_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['setcfg_reply'])
-_FEMESSAGE.fields_by_name['setcfg_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['commcfg_req'])
-_FEMESSAGE.fields_by_name['commcfg_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['commcfg_reply'])
-_FEMESSAGE.fields_by_name['commcfg_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['get_req'])
-_FEMESSAGE.fields_by_name['get_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['get_reply'])
-_FEMESSAGE.fields_by_name['get_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['notify_data_req'])
-_FEMESSAGE.fields_by_name['notify_data_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['regnotify_req'])
-_FEMESSAGE.fields_by_name['regnotify_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-DESCRIPTOR.message_types_by_name['YangDataXPath'] = _YANGDATAXPATH
-DESCRIPTOR.message_types_by_name['YangDataValue'] = _YANGDATAVALUE
-DESCRIPTOR.message_types_by_name['YangData'] = _YANGDATA
-DESCRIPTOR.message_types_by_name['YangCfgDataReq'] = _YANGCFGDATAREQ
-DESCRIPTOR.message_types_by_name['YangGetDataReq'] = _YANGGETDATAREQ
-DESCRIPTOR.message_types_by_name['BeSubscribeReq'] = _BESUBSCRIBEREQ
-DESCRIPTOR.message_types_by_name['BeSubscribeReply'] = _BESUBSCRIBEREPLY
-DESCRIPTOR.message_types_by_name['BeTxnReq'] = _BETXNREQ
-DESCRIPTOR.message_types_by_name['BeTxnReply'] = _BETXNREPLY
-DESCRIPTOR.message_types_by_name['BeCfgDataCreateReq'] = _BECFGDATACREATEREQ
-DESCRIPTOR.message_types_by_name['BeCfgDataCreateReply'] = _BECFGDATACREATEREPLY
-DESCRIPTOR.message_types_by_name['BeCfgDataApplyReq'] = _BECFGDATAAPPLYREQ
-DESCRIPTOR.message_types_by_name['BeCfgDataApplyReply'] = _BECFGDATAAPPLYREPLY
-DESCRIPTOR.message_types_by_name['YangDataReply'] = _YANGDATAREPLY
-DESCRIPTOR.message_types_by_name['BeMessage'] = _BEMESSAGE
-DESCRIPTOR.message_types_by_name['FeRegisterReq'] = _FEREGISTERREQ
-DESCRIPTOR.message_types_by_name['FeSessionReq'] = _FESESSIONREQ
-DESCRIPTOR.message_types_by_name['FeSessionReply'] = _FESESSIONREPLY
-DESCRIPTOR.message_types_by_name['FeLockDsReq'] = _FELOCKDSREQ
-DESCRIPTOR.message_types_by_name['FeLockDsReply'] = _FELOCKDSREPLY
-DESCRIPTOR.message_types_by_name['FeSetConfigReq'] = _FESETCONFIGREQ
-DESCRIPTOR.message_types_by_name['FeSetConfigReply'] = _FESETCONFIGREPLY
-DESCRIPTOR.message_types_by_name['FeCommitConfigReq'] = _FECOMMITCONFIGREQ
-DESCRIPTOR.message_types_by_name['FeCommitConfigReply'] = _FECOMMITCONFIGREPLY
-DESCRIPTOR.message_types_by_name['FeGetReq'] = _FEGETREQ
-DESCRIPTOR.message_types_by_name['FeGetReply'] = _FEGETREPLY
-DESCRIPTOR.message_types_by_name['FeNotifyDataReq'] = _FENOTIFYDATAREQ
-DESCRIPTOR.message_types_by_name['FeRegisterNotifyReq'] = _FEREGISTERNOTIFYREQ
-DESCRIPTOR.message_types_by_name['FeMessage'] = _FEMESSAGE
-DESCRIPTOR.enum_types_by_name['CfgDataReqType'] = _CFGDATAREQTYPE
-DESCRIPTOR.enum_types_by_name['DatastoreId'] = _DATASTOREID
+ name="FeMessage",
+ full_name="mgmtd.FeMessage",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="register_req",
+ full_name="mgmtd.FeMessage.register_req",
+ index=0,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_req",
+ full_name="mgmtd.FeMessage.session_req",
+ index=1,
+ number=3,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_reply",
+ full_name="mgmtd.FeMessage.session_reply",
+ index=2,
+ number=4,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lockds_req",
+ full_name="mgmtd.FeMessage.lockds_req",
+ index=3,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lockds_reply",
+ full_name="mgmtd.FeMessage.lockds_reply",
+ index=4,
+ number=6,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="setcfg_req",
+ full_name="mgmtd.FeMessage.setcfg_req",
+ index=5,
+ number=7,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="setcfg_reply",
+ full_name="mgmtd.FeMessage.setcfg_reply",
+ index=6,
+ number=8,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="commcfg_req",
+ full_name="mgmtd.FeMessage.commcfg_req",
+ index=7,
+ number=9,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="commcfg_reply",
+ full_name="mgmtd.FeMessage.commcfg_reply",
+ index=8,
+ number=10,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="get_req",
+ full_name="mgmtd.FeMessage.get_req",
+ index=9,
+ number=11,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="get_reply",
+ full_name="mgmtd.FeMessage.get_reply",
+ index=10,
+ number=12,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="notify_data_req",
+ full_name="mgmtd.FeMessage.notify_data_req",
+ index=11,
+ number=15,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="regnotify_req",
+ full_name="mgmtd.FeMessage.regnotify_req",
+ index=12,
+ number=16,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="message",
+ full_name="mgmtd.FeMessage.message",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=3048,
+ serialized_end=3672,
+)
+
+_YANGDATAVALUE.oneofs_by_name["value"].fields.append(
+ _YANGDATAVALUE.fields_by_name["encoded_str_val"]
+)
+_YANGDATAVALUE.fields_by_name[
+ "encoded_str_val"
+].containing_oneof = _YANGDATAVALUE.oneofs_by_name["value"]
+_YANGDATA.fields_by_name["value"].message_type = _YANGDATAVALUE
+_YANGCFGDATAREQ.fields_by_name["data"].message_type = _YANGDATA
+_YANGCFGDATAREQ.fields_by_name["req_type"].enum_type = _CFGDATAREQTYPE
+_YANGGETDATAREQ.fields_by_name["data"].message_type = _YANGDATA
+_BECFGDATACREATEREQ.fields_by_name["data_req"].message_type = _YANGCFGDATAREQ
+_YANGDATAREPLY.fields_by_name["data"].message_type = _YANGDATA
+_BEMESSAGE.fields_by_name["subscr_req"].message_type = _BESUBSCRIBEREQ
+_BEMESSAGE.fields_by_name["subscr_reply"].message_type = _BESUBSCRIBEREPLY
+_BEMESSAGE.fields_by_name["txn_req"].message_type = _BETXNREQ
+_BEMESSAGE.fields_by_name["txn_reply"].message_type = _BETXNREPLY
+_BEMESSAGE.fields_by_name["cfg_data_req"].message_type = _BECFGDATACREATEREQ
+_BEMESSAGE.fields_by_name["cfg_data_reply"].message_type = _BECFGDATACREATEREPLY
+_BEMESSAGE.fields_by_name["cfg_apply_req"].message_type = _BECFGDATAAPPLYREQ
+_BEMESSAGE.fields_by_name["cfg_apply_reply"].message_type = _BECFGDATAAPPLYREPLY
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["subscr_req"]
+)
+_BEMESSAGE.fields_by_name["subscr_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["subscr_reply"]
+)
+_BEMESSAGE.fields_by_name["subscr_reply"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(_BEMESSAGE.fields_by_name["txn_req"])
+_BEMESSAGE.fields_by_name["txn_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["txn_reply"]
+)
+_BEMESSAGE.fields_by_name["txn_reply"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_data_req"]
+)
+_BEMESSAGE.fields_by_name["cfg_data_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_data_reply"]
+)
+_BEMESSAGE.fields_by_name[
+ "cfg_data_reply"
+].containing_oneof = _BEMESSAGE.oneofs_by_name["message"]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_apply_req"]
+)
+_BEMESSAGE.fields_by_name["cfg_apply_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_apply_reply"]
+)
+_BEMESSAGE.fields_by_name[
+ "cfg_apply_reply"
+].containing_oneof = _BEMESSAGE.oneofs_by_name["message"]
+_FESESSIONREQ.oneofs_by_name["id"].fields.append(
+ _FESESSIONREQ.fields_by_name["client_conn_id"]
+)
+_FESESSIONREQ.fields_by_name[
+ "client_conn_id"
+].containing_oneof = _FESESSIONREQ.oneofs_by_name["id"]
+_FESESSIONREQ.oneofs_by_name["id"].fields.append(
+ _FESESSIONREQ.fields_by_name["session_id"]
+)
+_FESESSIONREQ.fields_by_name[
+ "session_id"
+].containing_oneof = _FESESSIONREQ.oneofs_by_name["id"]
+_FELOCKDSREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FELOCKDSREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FESETCONFIGREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FESETCONFIGREQ.fields_by_name["data"].message_type = _YANGCFGDATAREQ
+_FESETCONFIGREQ.fields_by_name["commit_ds_id"].enum_type = _DATASTOREID
+_FESETCONFIGREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREQ.fields_by_name["src_ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREQ.fields_by_name["dst_ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREPLY.fields_by_name["src_ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREPLY.fields_by_name["dst_ds_id"].enum_type = _DATASTOREID
+_FEGETREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FEGETREQ.fields_by_name["data"].message_type = _YANGGETDATAREQ
+_FEGETREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FEGETREPLY.fields_by_name["data"].message_type = _YANGDATAREPLY
+_FENOTIFYDATAREQ.fields_by_name["data"].message_type = _YANGDATA
+_FEREGISTERNOTIFYREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FEREGISTERNOTIFYREQ.fields_by_name["data_xpath"].message_type = _YANGDATAXPATH
+_FEMESSAGE.fields_by_name["register_req"].message_type = _FEREGISTERREQ
+_FEMESSAGE.fields_by_name["session_req"].message_type = _FESESSIONREQ
+_FEMESSAGE.fields_by_name["session_reply"].message_type = _FESESSIONREPLY
+_FEMESSAGE.fields_by_name["lockds_req"].message_type = _FELOCKDSREQ
+_FEMESSAGE.fields_by_name["lockds_reply"].message_type = _FELOCKDSREPLY
+_FEMESSAGE.fields_by_name["setcfg_req"].message_type = _FESETCONFIGREQ
+_FEMESSAGE.fields_by_name["setcfg_reply"].message_type = _FESETCONFIGREPLY
+_FEMESSAGE.fields_by_name["commcfg_req"].message_type = _FECOMMITCONFIGREQ
+_FEMESSAGE.fields_by_name["commcfg_reply"].message_type = _FECOMMITCONFIGREPLY
+_FEMESSAGE.fields_by_name["get_req"].message_type = _FEGETREQ
+_FEMESSAGE.fields_by_name["get_reply"].message_type = _FEGETREPLY
+_FEMESSAGE.fields_by_name["notify_data_req"].message_type = _FENOTIFYDATAREQ
+_FEMESSAGE.fields_by_name["regnotify_req"].message_type = _FEREGISTERNOTIFYREQ
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["register_req"]
+)
+_FEMESSAGE.fields_by_name["register_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["session_req"]
+)
+_FEMESSAGE.fields_by_name["session_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["session_reply"]
+)
+_FEMESSAGE.fields_by_name["session_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["lockds_req"]
+)
+_FEMESSAGE.fields_by_name["lockds_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["lockds_reply"]
+)
+_FEMESSAGE.fields_by_name["lockds_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["setcfg_req"]
+)
+_FEMESSAGE.fields_by_name["setcfg_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["setcfg_reply"]
+)
+_FEMESSAGE.fields_by_name["setcfg_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["commcfg_req"]
+)
+_FEMESSAGE.fields_by_name["commcfg_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["commcfg_reply"]
+)
+_FEMESSAGE.fields_by_name["commcfg_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(_FEMESSAGE.fields_by_name["get_req"])
+_FEMESSAGE.fields_by_name["get_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["get_reply"]
+)
+_FEMESSAGE.fields_by_name["get_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["notify_data_req"]
+)
+_FEMESSAGE.fields_by_name[
+ "notify_data_req"
+].containing_oneof = _FEMESSAGE.oneofs_by_name["message"]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["regnotify_req"]
+)
+_FEMESSAGE.fields_by_name["regnotify_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+DESCRIPTOR.message_types_by_name["YangDataXPath"] = _YANGDATAXPATH
+DESCRIPTOR.message_types_by_name["YangDataValue"] = _YANGDATAVALUE
+DESCRIPTOR.message_types_by_name["YangData"] = _YANGDATA
+DESCRIPTOR.message_types_by_name["YangCfgDataReq"] = _YANGCFGDATAREQ
+DESCRIPTOR.message_types_by_name["YangGetDataReq"] = _YANGGETDATAREQ
+DESCRIPTOR.message_types_by_name["BeSubscribeReq"] = _BESUBSCRIBEREQ
+DESCRIPTOR.message_types_by_name["BeSubscribeReply"] = _BESUBSCRIBEREPLY
+DESCRIPTOR.message_types_by_name["BeTxnReq"] = _BETXNREQ
+DESCRIPTOR.message_types_by_name["BeTxnReply"] = _BETXNREPLY
+DESCRIPTOR.message_types_by_name["BeCfgDataCreateReq"] = _BECFGDATACREATEREQ
+DESCRIPTOR.message_types_by_name["BeCfgDataCreateReply"] = _BECFGDATACREATEREPLY
+DESCRIPTOR.message_types_by_name["BeCfgDataApplyReq"] = _BECFGDATAAPPLYREQ
+DESCRIPTOR.message_types_by_name["BeCfgDataApplyReply"] = _BECFGDATAAPPLYREPLY
+DESCRIPTOR.message_types_by_name["YangDataReply"] = _YANGDATAREPLY
+DESCRIPTOR.message_types_by_name["BeMessage"] = _BEMESSAGE
+DESCRIPTOR.message_types_by_name["FeRegisterReq"] = _FEREGISTERREQ
+DESCRIPTOR.message_types_by_name["FeSessionReq"] = _FESESSIONREQ
+DESCRIPTOR.message_types_by_name["FeSessionReply"] = _FESESSIONREPLY
+DESCRIPTOR.message_types_by_name["FeLockDsReq"] = _FELOCKDSREQ
+DESCRIPTOR.message_types_by_name["FeLockDsReply"] = _FELOCKDSREPLY
+DESCRIPTOR.message_types_by_name["FeSetConfigReq"] = _FESETCONFIGREQ
+DESCRIPTOR.message_types_by_name["FeSetConfigReply"] = _FESETCONFIGREPLY
+DESCRIPTOR.message_types_by_name["FeCommitConfigReq"] = _FECOMMITCONFIGREQ
+DESCRIPTOR.message_types_by_name["FeCommitConfigReply"] = _FECOMMITCONFIGREPLY
+DESCRIPTOR.message_types_by_name["FeGetReq"] = _FEGETREQ
+DESCRIPTOR.message_types_by_name["FeGetReply"] = _FEGETREPLY
+DESCRIPTOR.message_types_by_name["FeNotifyDataReq"] = _FENOTIFYDATAREQ
+DESCRIPTOR.message_types_by_name["FeRegisterNotifyReq"] = _FEREGISTERNOTIFYREQ
+DESCRIPTOR.message_types_by_name["FeMessage"] = _FEMESSAGE
+DESCRIPTOR.enum_types_by_name["CfgDataReqType"] = _CFGDATAREQTYPE
+DESCRIPTOR.enum_types_by_name["DatastoreId"] = _DATASTOREID
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-YangDataXPath = _reflection.GeneratedProtocolMessageType('YangDataXPath', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATAXPATH,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangDataXPath)
- })
+YangDataXPath = _reflection.GeneratedProtocolMessageType(
+ "YangDataXPath",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATAXPATH,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangDataXPath)
+ },
+)
_sym_db.RegisterMessage(YangDataXPath)
-YangDataValue = _reflection.GeneratedProtocolMessageType('YangDataValue', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATAVALUE,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangDataValue)
- })
+YangDataValue = _reflection.GeneratedProtocolMessageType(
+ "YangDataValue",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATAVALUE,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangDataValue)
+ },
+)
_sym_db.RegisterMessage(YangDataValue)
-YangData = _reflection.GeneratedProtocolMessageType('YangData', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATA,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangData)
- })
+YangData = _reflection.GeneratedProtocolMessageType(
+ "YangData",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATA,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangData)
+ },
+)
_sym_db.RegisterMessage(YangData)
-YangCfgDataReq = _reflection.GeneratedProtocolMessageType('YangCfgDataReq', (_message.Message,), {
- 'DESCRIPTOR' : _YANGCFGDATAREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangCfgDataReq)
- })
+YangCfgDataReq = _reflection.GeneratedProtocolMessageType(
+ "YangCfgDataReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGCFGDATAREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangCfgDataReq)
+ },
+)
_sym_db.RegisterMessage(YangCfgDataReq)
-YangGetDataReq = _reflection.GeneratedProtocolMessageType('YangGetDataReq', (_message.Message,), {
- 'DESCRIPTOR' : _YANGGETDATAREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangGetDataReq)
- })
+YangGetDataReq = _reflection.GeneratedProtocolMessageType(
+ "YangGetDataReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGGETDATAREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangGetDataReq)
+ },
+)
_sym_db.RegisterMessage(YangGetDataReq)
-BeSubscribeReq = _reflection.GeneratedProtocolMessageType('BeSubscribeReq', (_message.Message,), {
- 'DESCRIPTOR' : _BESUBSCRIBEREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReq)
- })
+BeSubscribeReq = _reflection.GeneratedProtocolMessageType(
+ "BeSubscribeReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BESUBSCRIBEREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReq)
+ },
+)
_sym_db.RegisterMessage(BeSubscribeReq)
-BeSubscribeReply = _reflection.GeneratedProtocolMessageType('BeSubscribeReply', (_message.Message,), {
- 'DESCRIPTOR' : _BESUBSCRIBEREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReply)
- })
+BeSubscribeReply = _reflection.GeneratedProtocolMessageType(
+ "BeSubscribeReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BESUBSCRIBEREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReply)
+ },
+)
_sym_db.RegisterMessage(BeSubscribeReply)
-BeTxnReq = _reflection.GeneratedProtocolMessageType('BeTxnReq', (_message.Message,), {
- 'DESCRIPTOR' : _BETXNREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReq)
- })
+BeTxnReq = _reflection.GeneratedProtocolMessageType(
+ "BeTxnReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BETXNREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReq)
+ },
+)
_sym_db.RegisterMessage(BeTxnReq)
-BeTxnReply = _reflection.GeneratedProtocolMessageType('BeTxnReply', (_message.Message,), {
- 'DESCRIPTOR' : _BETXNREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReply)
- })
+BeTxnReply = _reflection.GeneratedProtocolMessageType(
+ "BeTxnReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BETXNREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReply)
+ },
+)
_sym_db.RegisterMessage(BeTxnReply)
-BeCfgDataCreateReq = _reflection.GeneratedProtocolMessageType('BeCfgDataCreateReq', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATACREATEREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReq)
- })
+BeCfgDataCreateReq = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataCreateReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATACREATEREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReq)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataCreateReq)
-BeCfgDataCreateReply = _reflection.GeneratedProtocolMessageType('BeCfgDataCreateReply', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATACREATEREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReply)
- })
+BeCfgDataCreateReply = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataCreateReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATACREATEREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReply)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataCreateReply)
-BeCfgDataApplyReq = _reflection.GeneratedProtocolMessageType('BeCfgDataApplyReq', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATAAPPLYREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReq)
- })
+BeCfgDataApplyReq = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataApplyReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATAAPPLYREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReq)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataApplyReq)
-BeCfgDataApplyReply = _reflection.GeneratedProtocolMessageType('BeCfgDataApplyReply', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATAAPPLYREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReply)
- })
+BeCfgDataApplyReply = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataApplyReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATAAPPLYREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReply)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataApplyReply)
-YangDataReply = _reflection.GeneratedProtocolMessageType('YangDataReply', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATAREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangDataReply)
- })
+YangDataReply = _reflection.GeneratedProtocolMessageType(
+ "YangDataReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATAREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangDataReply)
+ },
+)
_sym_db.RegisterMessage(YangDataReply)
-BeMessage = _reflection.GeneratedProtocolMessageType('BeMessage', (_message.Message,), {
- 'DESCRIPTOR' : _BEMESSAGE,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeMessage)
- })
+BeMessage = _reflection.GeneratedProtocolMessageType(
+ "BeMessage",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BEMESSAGE,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeMessage)
+ },
+)
_sym_db.RegisterMessage(BeMessage)
-FeRegisterReq = _reflection.GeneratedProtocolMessageType('FeRegisterReq', (_message.Message,), {
- 'DESCRIPTOR' : _FEREGISTERREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterReq)
- })
+FeRegisterReq = _reflection.GeneratedProtocolMessageType(
+ "FeRegisterReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEREGISTERREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterReq)
+ },
+)
_sym_db.RegisterMessage(FeRegisterReq)
-FeSessionReq = _reflection.GeneratedProtocolMessageType('FeSessionReq', (_message.Message,), {
- 'DESCRIPTOR' : _FESESSIONREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReq)
- })
+FeSessionReq = _reflection.GeneratedProtocolMessageType(
+ "FeSessionReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESESSIONREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReq)
+ },
+)
_sym_db.RegisterMessage(FeSessionReq)
-FeSessionReply = _reflection.GeneratedProtocolMessageType('FeSessionReply', (_message.Message,), {
- 'DESCRIPTOR' : _FESESSIONREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReply)
- })
+FeSessionReply = _reflection.GeneratedProtocolMessageType(
+ "FeSessionReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESESSIONREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReply)
+ },
+)
_sym_db.RegisterMessage(FeSessionReply)
-FeLockDsReq = _reflection.GeneratedProtocolMessageType('FeLockDsReq', (_message.Message,), {
- 'DESCRIPTOR' : _FELOCKDSREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReq)
- })
+FeLockDsReq = _reflection.GeneratedProtocolMessageType(
+ "FeLockDsReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FELOCKDSREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReq)
+ },
+)
_sym_db.RegisterMessage(FeLockDsReq)
-FeLockDsReply = _reflection.GeneratedProtocolMessageType('FeLockDsReply', (_message.Message,), {
- 'DESCRIPTOR' : _FELOCKDSREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReply)
- })
+FeLockDsReply = _reflection.GeneratedProtocolMessageType(
+ "FeLockDsReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FELOCKDSREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReply)
+ },
+)
_sym_db.RegisterMessage(FeLockDsReply)
-FeSetConfigReq = _reflection.GeneratedProtocolMessageType('FeSetConfigReq', (_message.Message,), {
- 'DESCRIPTOR' : _FESETCONFIGREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReq)
- })
+FeSetConfigReq = _reflection.GeneratedProtocolMessageType(
+ "FeSetConfigReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESETCONFIGREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReq)
+ },
+)
_sym_db.RegisterMessage(FeSetConfigReq)
-FeSetConfigReply = _reflection.GeneratedProtocolMessageType('FeSetConfigReply', (_message.Message,), {
- 'DESCRIPTOR' : _FESETCONFIGREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReply)
- })
+FeSetConfigReply = _reflection.GeneratedProtocolMessageType(
+ "FeSetConfigReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESETCONFIGREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReply)
+ },
+)
_sym_db.RegisterMessage(FeSetConfigReply)
-FeCommitConfigReq = _reflection.GeneratedProtocolMessageType('FeCommitConfigReq', (_message.Message,), {
- 'DESCRIPTOR' : _FECOMMITCONFIGREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReq)
- })
+FeCommitConfigReq = _reflection.GeneratedProtocolMessageType(
+ "FeCommitConfigReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FECOMMITCONFIGREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReq)
+ },
+)
_sym_db.RegisterMessage(FeCommitConfigReq)
-FeCommitConfigReply = _reflection.GeneratedProtocolMessageType('FeCommitConfigReply', (_message.Message,), {
- 'DESCRIPTOR' : _FECOMMITCONFIGREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReply)
- })
+FeCommitConfigReply = _reflection.GeneratedProtocolMessageType(
+ "FeCommitConfigReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FECOMMITCONFIGREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReply)
+ },
+)
_sym_db.RegisterMessage(FeCommitConfigReply)
-FeGetReq = _reflection.GeneratedProtocolMessageType('FeGetReq', (_message.Message,), {
- 'DESCRIPTOR' : _FEGETREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeGetReq)
- })
+FeGetReq = _reflection.GeneratedProtocolMessageType(
+ "FeGetReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEGETREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeGetReq)
+ },
+)
_sym_db.RegisterMessage(FeGetReq)
-FeGetReply = _reflection.GeneratedProtocolMessageType('FeGetReply', (_message.Message,), {
- 'DESCRIPTOR' : _FEGETREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeGetReply)
- })
+FeGetReply = _reflection.GeneratedProtocolMessageType(
+ "FeGetReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEGETREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeGetReply)
+ },
+)
_sym_db.RegisterMessage(FeGetReply)
-FeNotifyDataReq = _reflection.GeneratedProtocolMessageType('FeNotifyDataReq', (_message.Message,), {
- 'DESCRIPTOR' : _FENOTIFYDATAREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeNotifyDataReq)
- })
+FeNotifyDataReq = _reflection.GeneratedProtocolMessageType(
+ "FeNotifyDataReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FENOTIFYDATAREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeNotifyDataReq)
+ },
+)
_sym_db.RegisterMessage(FeNotifyDataReq)
-FeRegisterNotifyReq = _reflection.GeneratedProtocolMessageType('FeRegisterNotifyReq', (_message.Message,), {
- 'DESCRIPTOR' : _FEREGISTERNOTIFYREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterNotifyReq)
- })
+FeRegisterNotifyReq = _reflection.GeneratedProtocolMessageType(
+ "FeRegisterNotifyReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEREGISTERNOTIFYREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterNotifyReq)
+ },
+)
_sym_db.RegisterMessage(FeRegisterNotifyReq)
-FeMessage = _reflection.GeneratedProtocolMessageType('FeMessage', (_message.Message,), {
- 'DESCRIPTOR' : _FEMESSAGE,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeMessage)
- })
+FeMessage = _reflection.GeneratedProtocolMessageType(
+ "FeMessage",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEMESSAGE,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeMessage)
+ },
+)
_sym_db.RegisterMessage(FeMessage)
diff --git a/tests/topotests/mgmt_tests/test_yang_mgmt.py b/tests/topotests/mgmt_tests/test_yang_mgmt.py
index bf4e95b275..605c14285f 100644
--- a/tests/topotests/mgmt_tests/test_yang_mgmt.py
+++ b/tests/topotests/mgmt_tests/test_yang_mgmt.py
@@ -36,6 +36,7 @@ import time
import os
import pytest
import platform
+import json
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -45,7 +46,7 @@ sys.path.append(os.path.join(CWD, "../lib/"))
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
-from lib.topotest import version_cmp
+from lib.topotest import version_cmp, router_json_cmp
# Import topoJson from lib, to create topology and initial configuration
from lib.common_config import (
@@ -401,6 +402,242 @@ def test_mgmt_delete_config(request):
write_test_footer(tc_name)
+def test_mgmt_edit_config(request):
+ """
+ Verify mgmt edit config.
+ """
+ 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)
+
+ reset_config_on_routers(tgen)
+
+ r1 = tgen.gears["r1"]
+
+ # check "create" operation
+ data = {"frr-interface:interface": [{"name": "eth0", "description": "eth0-desc"}]}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit create /frr-interface:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check error on "create" for an existing object
+ data = {"frr-interface:interface": [{"name": "eth0", "description": "eth0-desc"}]}
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit create /frr-interface:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ assert "Data already exists" in ret
+
+ # check adding a leaf to an existing object using "merge"
+ data = {
+ "frr-interface:interface": [
+ {"name": "eth0", "frr-zebra:zebra": {"bandwidth": 100}}
+ ]
+ }
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit merge /frr-interface:lib/interface[name='eth0'] lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = {
+ "frr-interface:interface": [
+ {
+ "name": "eth0",
+ "description": "eth0-desc",
+ "frr-zebra:zebra": {"bandwidth": 100},
+ }
+ ]
+ }
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check replacing an existing object using "replace"
+ data = {
+ "frr-interface:interface": [{"name": "eth0", "description": "eth0-desc-new"}]
+ }
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit replace /frr-interface:lib/interface[name='eth0'] lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check error on "replace" when keys in xpath and data are different
+ data = {
+ "frr-interface:interface": [{"name": "eth1", "description": "eth0-desc-new"}]
+ }
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit replace /frr-interface:lib/interface[name='eth0'] lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ assert "List keys in xpath and data tree are different" in ret
+
+ # check deleting an existing object using "delete"
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit delete /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ {},
+ exact=True,
+ )
+ == None
+ )
+
+ # check error on "delete" for a non-existing object
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit delete /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert "Data missing" in ret
+
+ # check no error on "remove" for a non-existing object
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit remove /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert "Data missing" not in ret
+
+ # check "remove" for an existing object
+ data = {"frr-interface:interface": [{"name": "eth0", "description": "eth0-desc"}]}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit create /frr-interface:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit remove /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ {},
+ exact=True,
+ )
+ == None
+ )
+
+ # check "create" of a top-level node
+ data = {"frr-vrf:lib": {"vrf": [{"name": "vrf1"}]}}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit create / lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-vrf:lib only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check "replace" of a top-level node
+ data = {"frr-vrf:lib": {"vrf": [{"name": "vrf2"}]}}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit replace /frr-vrf:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-vrf:lib only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check "delete" of a top-level node
+ r1.vtysh_cmd(f"conf\nmgmt edit delete /frr-vrf:lib lock commit")
+ assert (
+ router_json_cmp(
+ r1, "show mgmt get-data /frr-vrf:lib only-config exact", {}, exact=True
+ )
+ == None
+ )
+
+ # check replace of the whole config
+ # this test won't work at the moment, because we don't allow to delete
+ # interfaces from the config if they are present in the system
+ # another problem is that we don't allow "/" as an xpath in get-data command
+ # therefore, commenting it out for now
+ # data = {
+ # "frr-interface:lib": {
+ # "interface": [{"name": "eth1", "description": "eth1-desc"}]
+ # },
+ # "frr-vrf:lib": {"vrf": [{"name": "vrf3"}]},
+ # }
+ # r1.vtysh_cmd(
+ # f"conf\nmgmt edit replace / lock commit {json.dumps(data, separators=(',', ':'))}"
+ # )
+ # data_out = data
+ # assert (
+ # router_json_cmp(
+ # r1,
+ # "show mgmt get-data / only-config exact",
+ # data_out,
+ # exact=True,
+ # )
+ # == None
+ # )
+
+ # check "merge" of the whole config
+ data = {
+ "frr-interface:lib": {
+ "interface": [{"name": "eth2", "description": "eth2-desc"}]
+ },
+ "frr-vrf:lib": {"vrf": [{"name": "vrf4"}]},
+ }
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit merge / lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib only-config exact",
+ {
+ "frr-interface:lib": {
+ "interface": [{"name": "eth2", "description": "eth2-desc"}]
+ }
+ },
+ )
+ == None
+ )
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-vrf:lib only-config exact",
+ {"frr-vrf:lib": {"vrf": [{"name": "vrf4"}]}},
+ )
+ == None
+ )
+
+
def test_mgmt_chaos_stop_start_frr(request):
"""
Kill mgmtd - verify that watch frr restarts.
diff --git a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
index 9ee411206d..1775c9baed 100644
--- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
+++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
@@ -202,7 +202,6 @@ def teardown_module():
def clear_bsrp_data(tgen, topo):
-
"""
clear bsm databas after test"
Parameters
@@ -218,7 +217,6 @@ def clear_bsrp_data(tgen, topo):
"""
for dut in tgen.routers():
-
rnode = tgen.routers()[dut]
logger.info("[DUT: %s]: clear_bsrp_data")
diff --git a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
index 302a778585..e4df508909 100644
--- a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
+++ b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
@@ -182,7 +182,6 @@ def teardown_module():
def clear_bsrp_data(tgen, topo):
-
"""
clear bsm databas after test"
Parameters
@@ -198,7 +197,6 @@ def clear_bsrp_data(tgen, topo):
"""
for dut in tgen.routers():
-
rnode = tgen.routers()[dut]
logger.info("[DUT: %s]: clear_bsrp_data")
diff --git a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
index 1de6eac897..f87a90d198 100755
--- a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
+++ b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
@@ -42,7 +42,7 @@ import time
from time import sleep
import pytest
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -83,8 +83,6 @@ from lib.topolog import logger
from lib.topojson import build_config_from_json
-pytestmark = [pytest.mark.pimd]
-
TOPOLOGY = """
diff --git a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
index 17f52cb860..b62f7bbfc9 100755
--- a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
+++ b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
@@ -37,7 +37,7 @@ import sys
import time
import pytest
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -81,8 +81,6 @@ from lib.topolog import logger
from lib.topojson import build_config_from_json
-pytestmark = [pytest.mark.pimd]
-
TOPOLOGY = """
diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
index 2c1241c0cc..ae27546703 100755
--- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
+++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
@@ -45,7 +45,7 @@ from time import sleep
import json
import functools
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -91,7 +91,6 @@ from lib.topolog import logger
from lib.topojson import build_config_from_json
CWD = os.path.dirname(os.path.realpath(__file__))
-pytestmark = pytest.mark.pimd
TOPOLOGY = """
@@ -265,11 +264,14 @@ def verify_state_incremented(state_before, state_after):
for intf, v2 in v1.items():
for state, value in v2.items():
if value >= state_after[ttype][intf][state]:
- errormsg = "[DUT: %s]: state %s value has not incremented, Initial value: %s, Current value: %s [FAILED!!]" % (
- intf,
- state,
- value,
- state_after[ttype][intf][state],
+ errormsg = (
+ "[DUT: %s]: state %s value has not incremented, Initial value: %s, Current value: %s [FAILED!!]"
+ % (
+ intf,
+ state,
+ value,
+ state_after[ttype][intf][state],
+ )
)
return errormsg
@@ -328,7 +330,6 @@ def find_tos_in_tcpdump(tgen, router, message, cap_file):
filepath = os.path.join(tgen.logdir, router, cap_file)
with open(filepath) as f:
-
if len(re.findall(message, f.read())) < 1:
errormsg = "[DUT: %s]: Verify Message: %s in tcpdump" " [FAILED!!]" % (
router,
diff --git a/tests/topotests/munet/__main__.py b/tests/topotests/munet/__main__.py
index 4419ab94a2..e50fea6915 100644
--- a/tests/topotests/munet/__main__.py
+++ b/tests/topotests/munet/__main__.py
@@ -16,6 +16,7 @@ import sys
from . import cli
from . import parser
+from .args import add_launch_args
from .base import get_event_loop
from .cleanup import cleanup_previous
from .compat import PytestConfig
@@ -106,59 +107,35 @@ def main(*args):
cap.add_argument(
"--project-root", help="directory to stop searching for kinds config at"
)
+
rap = ap.add_argument_group(title="Runtime", description="runtime related options")
+ add_launch_args(rap.add_argument)
+
+ # Move to munet.args?
rap.add_argument(
"-C",
"--cleanup",
action="store_true",
help="Remove the entire rundir (not just node subdirs) prior to running.",
)
- rap.add_argument(
- "--gdb", metavar="NODE-LIST", help="comma-sep list of hosts to run gdb on"
- )
- rap.add_argument(
- "--gdb-breakpoints",
- metavar="BREAKPOINT-LIST",
- help="comma-sep list of breakpoints to set",
- )
- rap.add_argument(
- "--host",
- action="store_true",
- help="no isolation for top namespace, bridges exposed to default namespace",
- )
- rap.add_argument(
- "--pcap",
- metavar="TARGET-LIST",
- help="comma-sep list of capture targets (NETWORK or NODE:IFNAME)",
- )
- rap.add_argument(
- "--shell", metavar="NODE-LIST", help="comma-sep list of nodes to open shells on"
- )
- rap.add_argument(
- "--stderr",
- metavar="NODE-LIST",
- help="comma-sep list of nodes to open windows viewing stderr",
- )
- rap.add_argument(
- "--stdout",
- metavar="NODE-LIST",
- help="comma-sep list of nodes to open windows viewing stdout",
- )
+ # Move to munet.args?
rap.add_argument(
"--topology-only",
action="store_true",
help="Do not run any node commands",
)
- rap.add_argument("--unshare-inline", action="store_true", help=argparse.SUPPRESS)
rap.add_argument(
"--validate-only",
action="store_true",
help="Validate the config against the schema definition",
)
+ rap.add_argument("--unshare-inline", action="store_true", help=argparse.SUPPRESS)
+
rap.add_argument("-v", "--verbose", action="store_true", help="be verbose")
rap.add_argument(
"-V", "--version", action="store_true", help="print the verison number and exit"
)
+
eap = ap.add_argument_group(title="Uncommon", description="uncommonly used options")
eap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)")
eap.add_argument(
@@ -181,7 +158,6 @@ def main(*args):
rundir = args.rundir if args.rundir else "/tmp/munet"
args.rundir = rundir
-
if args.cleanup:
if os.path.exists(rundir):
if not os.path.exists(f"{rundir}/config.json"):
@@ -193,7 +169,6 @@ def main(*args):
sys.exit(1)
else:
subprocess.run(["/usr/bin/rm", "-rf", rundir], check=True)
-
subprocess.run(f"mkdir -p {rundir} && chmod 755 {rundir}", check=True, shell=True)
os.environ["MUNET_RUNDIR"] = rundir
diff --git a/tests/topotests/munet/args.py b/tests/topotests/munet/args.py
new file mode 100644
index 0000000000..49ad891cef
--- /dev/null
+++ b/tests/topotests/munet/args.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+#
+# April 14 2024, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2024, LabN Consulting, L.L.C.
+#
+"""Common CLI execute argument."""
+
+
+def add_launch_args(add_func):
+
+ add_func("--gdb", metavar="NODE-LIST", help="comma-sep list of hosts to run gdb on")
+ add_func(
+ "--gdb-breakpoints",
+ metavar="BREAKPOINT-LIST",
+ help="comma-sep list of breakpoints to set",
+ )
+ add_func(
+ "--gdb-use-emacs",
+ action="store_true",
+ help="Use emacsclient to run gdb instead of a shell",
+ )
+
+ add_func(
+ "--host",
+ action="store_true",
+ help="no isolation for top namespace, bridges exposed to default namespace",
+ )
+ add_func(
+ "--pcap",
+ metavar="TARGET-LIST",
+ help="comma-sep list of capture targets (NETWORK or NODE:IFNAME) or 'all'",
+ )
+ add_func(
+ "--shell", metavar="NODE-LIST", help="comma-sep list of nodes to open shells on"
+ )
+ add_func(
+ "--stderr",
+ metavar="NODE-LIST",
+ help="comma-sep list of nodes to open windows viewing stderr",
+ )
+ add_func(
+ "--stdout",
+ metavar="NODE-LIST",
+ help="comma-sep list of nodes to open windows viewing stdout",
+ )
+
+
+def add_testing_args(add_func):
+ add_func(
+ "--cli-on-error",
+ action="store_true",
+ help="CLI on test failure",
+ )
+
+ add_func(
+ "--coverage",
+ action="store_true",
+ help="Enable coverage gathering if supported",
+ )
+
+ add_func(
+ "--cov-build-dir",
+ help="Specify the build dir for locating coverage data files",
+ )
+
+ add_launch_args(add_func)
+
+ add_func(
+ "--pause",
+ action="store_true",
+ help="Pause after each test",
+ )
+ add_func(
+ "--pause-at-end",
+ action="store_true",
+ help="Pause before taking munet down",
+ )
+ add_func(
+ "--pause-on-error",
+ action="store_true",
+ help="Pause after (disables default when --shell or -vtysh given)",
+ )
+ add_func(
+ "--no-pause-on-error",
+ dest="pause_on_error",
+ action="store_false",
+ help="Do not pause after (disables default when --shell or -vtysh given)",
+ )
diff --git a/tests/topotests/munet/base.py b/tests/topotests/munet/base.py
index 72b5df54b9..a4811f179c 100644
--- a/tests/topotests/munet/base.py
+++ b/tests/topotests/munet/base.py
@@ -21,6 +21,7 @@ import subprocess
import sys
import tempfile
import time as time_mod
+
from collections import defaultdict
from pathlib import Path
from typing import Union
@@ -28,8 +29,10 @@ from typing import Union
from . import config as munet_config
from . import linux
+
try:
import pexpect
+
from pexpect.fdpexpect import fdspawn
from pexpect.popen_spawn import PopenSpawn
@@ -273,6 +276,9 @@ def get_event_loop():
"""
policy = asyncio.get_event_loop_policy()
loop = policy.get_event_loop()
+ if not hasattr(os, "pidfd_open"):
+ return loop
+
owatcher = policy.get_child_watcher()
logging.debug(
"event_loop_fixture: global policy %s, current loop %s, current watcher %s",
diff --git a/tests/topotests/munet/mucmd.py b/tests/topotests/munet/mucmd.py
index 5518c6dcfe..d6101e1a55 100644
--- a/tests/topotests/munet/mucmd.py
+++ b/tests/topotests/munet/mucmd.py
@@ -9,7 +9,6 @@
import argparse
import json
import os
-import subprocess
import sys
from pathlib import Path
@@ -90,17 +89,12 @@ def main(*args):
ecmd = "/usr/bin/nsenter"
eargs = [ecmd]
- output = subprocess.check_output(["/usr/bin/nsenter", "--help"], encoding="utf-8")
- if " -a," in output:
- eargs.append("-a")
- else:
- # -U doesn't work
- for flag in ["-u", "-i", "-m", "-n", "-C", "-T"]:
- if f" {flag}," in output:
- eargs.append(flag)
+ # start mucmd same way base process is started
+ eargs.append(f"--mount=/proc/{pid}/ns/mnt")
+ eargs.append(f"--net=/proc/{pid}/ns/net")
eargs.append(f"--pid=/proc/{pid}/ns/pid_for_children")
+ eargs.append(f"--uts=/proc/{pid}/ns/uts")
eargs.append(f"--wd={rundir}")
- eargs.extend(["-t", pid])
eargs += args.shellcmd
# print("Using ", eargs)
return os.execvpe(ecmd, eargs, {**env, **envcfg})
diff --git a/tests/topotests/munet/munet-schema.json b/tests/topotests/munet/munet-schema.json
index a1dcd878dd..7d577e63b3 100644
--- a/tests/topotests/munet/munet-schema.json
+++ b/tests/topotests/munet/munet-schema.json
@@ -99,6 +99,15 @@
"server-port": {
"type": "number"
},
+ "ssh-identity-file": {
+ "type": "string"
+ },
+ "ssh-user": {
+ "type": "string"
+ },
+ "ssh-password": {
+ "type": "string"
+ },
"qemu": {
"type": "object",
"properties": {
@@ -108,6 +117,15 @@
"disk": {
"type": "string"
},
+ "disk-driver": {
+ "type": "string"
+ },
+ "disk-template": {
+ "type": "string"
+ },
+ "initial-cmd": {
+ "type": "string"
+ },
"kerenel": {
"type": "string"
},
@@ -141,6 +159,9 @@
"password": {
"type": "string"
},
+ "initial-password": {
+ "type": "string"
+ },
"expects": {
"type": "array",
"items": {
@@ -407,6 +428,15 @@
"server-port": {
"type": "number"
},
+ "ssh-identity-file": {
+ "type": "string"
+ },
+ "ssh-user": {
+ "type": "string"
+ },
+ "ssh-password": {
+ "type": "string"
+ },
"qemu": {
"type": "object",
"properties": {
@@ -416,6 +446,15 @@
"disk": {
"type": "string"
},
+ "disk-driver": {
+ "type": "string"
+ },
+ "disk-template": {
+ "type": "string"
+ },
+ "initial-cmd": {
+ "type": "string"
+ },
"kerenel": {
"type": "string"
},
@@ -449,6 +488,9 @@
"password": {
"type": "string"
},
+ "initial-password": {
+ "type": "string"
+ },
"expects": {
"type": "array",
"items": {
diff --git a/tests/topotests/munet/mutest/__main__.py b/tests/topotests/munet/mutest/__main__.py
index c87031112d..d94e702c52 100644
--- a/tests/topotests/munet/mutest/__main__.py
+++ b/tests/topotests/munet/mutest/__main__.py
@@ -21,8 +21,11 @@ from pathlib import Path
from typing import Union
from munet import parser
+from munet.args import add_testing_args
from munet.base import Bridge
from munet.base import get_event_loop
+from munet.cli import async_cli
+from munet.compat import PytestConfig
from munet.mutest import userapi as uapi
from munet.native import L3NodeMixin
from munet.native import Munet
@@ -36,7 +39,9 @@ root_logger = logging.getLogger("")
exec_formatter = logging.Formatter("%(asctime)s %(levelname)5s: %(name)s: %(message)s")
-async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = False):
+async def get_unet(
+ config: dict, croot: Path, rundir: Path, args: Namespace, unshare: bool = False
+):
"""Create and run a new Munet topology.
The topology is built from the given ``config`` to run inside the path indicated
@@ -48,6 +53,7 @@ async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = Fals
value will be modified and stored in the built ``Munet`` object.
croot: common root of all tests, used to search for ``kinds.yaml`` files.
rundir: the path to the run directory for this topology.
+ args: argparse args
unshare: True to unshare the process into it's own private namespace.
Yields:
@@ -58,7 +64,11 @@ async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = Fals
try:
try:
unet = await async_build_topology(
- config, rundir=str(rundir), unshare_inline=unshare
+ config,
+ rundir=str(rundir),
+ args=args,
+ pytestconfig=PytestConfig(args),
+ unshare_inline=unshare,
)
except Exception as error:
logging.debug("unet build failed: %s", error, exc_info=True)
@@ -221,9 +231,13 @@ async def execute_test(
targets["."] = unet
tc = uapi.TestCase(
- str(test_num), test_name, test, targets, logger, reslog, args.full_summary
+ str(test_num), test_name, test, targets, args, logger, reslog, args.full_summary
)
- passed, failed, e = tc.execute()
+ try:
+ passed, failed, e = tc.execute()
+ except uapi.CLIOnErrorError as error:
+ await async_cli(unet)
+ passed, failed, e = 0, 0, error
run_time = time.time() - tc.info.start_time
@@ -278,6 +292,10 @@ async def run_tests(args):
start_time = time.time()
try:
for dirpath in tests:
+ if args.validate_only:
+ parser.validate_config(configs[dirpath], reslog, args)
+ continue
+
test_files = tests[dirpath]
for test in test_files:
tnum += 1
@@ -294,10 +312,12 @@ async def run_tests(args):
root_logger.addHandler(exec_handler)
try:
- async for unet in get_unet(config, common, rundir):
+ async for unet in get_unet(config, common, rundir, args):
+
if not printed_header:
print_header(reslog, unet)
printed_header = True
+
passed, failed, e = await execute_test(
unet, test, args, tnum, exec_handler
)
@@ -321,6 +341,9 @@ async def run_tests(args):
except KeyboardInterrupt:
pass
+ if args.validate_only:
+ return False
+
run_time = time.time() - start_time
tnum = 0
tpassed = 0
@@ -386,32 +409,43 @@ async def async_main(args):
def main():
ap = ArgumentParser()
ap.add_argument(
- "--dist",
- type=int,
- nargs="?",
- const=-1,
- default=0,
- action="store",
- metavar="NUM-THREADS",
- help="Run in parallel, value is num. of threads or no value for auto",
+ "-v", dest="verbose", action="count", default=0, help="More -v's, more verbose"
)
- ap.add_argument("-d", "--rundir", help="runtime directory for tempfiles, logs, etc")
ap.add_argument(
+ "-V", "--version", action="store_true", help="print the verison number and exit"
+ )
+ ap.add_argument("paths", nargs="*", help="Paths to collect tests from")
+
+ rap = ap.add_argument_group(title="Runtime", description="runtime related options")
+ rap.add_argument(
+ "-d", "--rundir", help="runtime directory for tempfiles, logs, etc"
+ )
+ add_testing_args(rap.add_argument)
+
+ eap = ap.add_argument_group(title="Uncommon", description="uncommonly used options")
+ eap.add_argument(
"--file-select", default="mutest_*.py", help="shell glob for finding tests"
)
- ap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)")
- ap.add_argument(
- "-V",
+ eap.add_argument(
"--full-summary",
action="store_true",
help="print full summary headers from docstrings",
)
- ap.add_argument(
- "-v", dest="verbose", action="count", default=0, help="More -v's, more verbose"
+ eap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)")
+ eap.add_argument(
+ "--validate-only",
+ action="store_true",
+ help="Validate the munet configs against the schema definition",
)
- ap.add_argument("paths", nargs="*", help="Paths to collect tests from")
+
args = ap.parse_args()
+ if args.version:
+ from importlib import metadata # pylint: disable=C0415
+
+ print(metadata.version("munet"))
+ sys.exit(0)
+
rundir = args.rundir if args.rundir else "/tmp/mutest"
args.rundir = Path(rundir)
os.environ["MUNET_RUNDIR"] = rundir
diff --git a/tests/topotests/munet/mutest/userapi.py b/tests/topotests/munet/mutest/userapi.py
index 7967dd0c09..f42fbc1893 100644
--- a/tests/topotests/munet/mutest/userapi.py
+++ b/tests/topotests/munet/mutest/userapi.py
@@ -65,8 +65,11 @@ import json
import logging
import pprint
import re
+import subprocess
+import sys
import time
+from argparse import Namespace
from pathlib import Path
from typing import Any
from typing import Union
@@ -76,6 +79,51 @@ from deepdiff import DeepDiff as json_cmp
from munet.base import Commander
+class ScriptError(Exception):
+ """An unrecoverable script failure."""
+
+
+class CLIOnErrorError(Exception):
+ """Enter CLI after error."""
+
+
+def pause_test(desc=""):
+ isatty = sys.stdout.isatty()
+ if not isatty:
+ desc = f" for {desc}" if desc else ""
+ logging.info("NO PAUSE on non-tty terminal%s", desc)
+ return
+
+ while True:
+ if desc:
+ print(f"\n== PAUSING: {desc} ==")
+ try:
+ user = input('PAUSED, "cli" for CLI, "pdb" to debug, "Enter" to continue: ')
+ except EOFError:
+ print("^D...continuing")
+ break
+ user = user.strip()
+ if user == "cli":
+ raise CLIOnErrorError()
+ if user == "pdb":
+ breakpoint() # pylint: disable=W1515
+ elif user:
+ print(f'Unrecognized input: "{user}"')
+ else:
+ break
+
+
+def act_on_result(success, args, desc=""):
+ if args.pause:
+ pause_test(desc)
+ elif success:
+ return
+ if args.cli_on_error:
+ raise CLIOnErrorError()
+ if args.pause_on_error:
+ pause_test(desc)
+
+
class TestCaseInfo:
"""Object to hold nestable TestCase Results."""
@@ -140,6 +188,7 @@ class TestCase:
name: str,
path: Path,
targets: dict,
+ args: Namespace,
output_logger: logging.Logger = None,
result_logger: logging.Logger = None,
full_summary: bool = False,
@@ -157,6 +206,7 @@ class TestCase:
self.__in_section = False
self.targets = targets
+ self.args = args
self.last = ""
self.last_m = None
@@ -285,7 +335,10 @@ class TestCase:
# Extract any docstring as a title.
if print_header:
- title = locals()[f"_{name}"].__doc__.lstrip()
+ title = locals()[f"_{name}"].__doc__
+ if title is None:
+ title = ""
+ title = title.lstrip()
if self.__short_doc_header and (title := title.lstrip()):
if (idx := title.find("\n")) != -1:
title = title[:idx].strip()
@@ -299,6 +352,10 @@ class TestCase:
# Here's where we can do async in the future if we want.
# result = await locals()[f"_{name}"](_ok_result)
+ except ScriptError as error:
+ return error
+ except CLIOnErrorError:
+ raise
except Exception as error:
logging.error(
"Unexpected exception executing %s: %s", name, error, exc_info=True
@@ -381,7 +438,9 @@ class TestCase:
target: the target to execute the command on.
cmd: string to execut on the target.
"""
- out = self.targets[target].cmd_nostatus(cmd, warn=False)
+ out = self.targets[target].cmd_nostatus(
+ cmd, stdin=subprocess.DEVNULL, warn=False
+ )
self.last = out = out.rstrip()
report = out if out else "<no output>"
self.logf("COMMAND OUTPUT:\n%s", report)
@@ -398,12 +457,14 @@ class TestCase:
target: the target to execute the command on.
cmd: string to execute on the target.
"""
- out = self.targets[target].cmd_nostatus(cmd, warn=False)
+ out = self.targets[target].cmd_nostatus(
+ cmd, stdin=subprocess.DEVNULL, warn=False
+ )
self.last = out = out.rstrip()
try:
js = json.loads(out)
except Exception as error:
- js = {}
+ js = None
self.olog.warning(
"JSON load failed. Check command output is in JSON format: %s",
error,
@@ -482,20 +543,29 @@ class TestCase:
exact_match: if True then the json must exactly match.
"""
js = self._command_json(target, cmd)
+ if js is None:
+ return expect_fail, {}
+
try:
+ # Convert to string to validate the input is valid JSON
+ if not isinstance(match, str):
+ match = json.dumps(match)
expect = json.loads(match)
except Exception as error:
expect = {}
self.olog.warning(
"JSON load failed. Check match value is in JSON format: %s", error
)
+ return expect_fail, {}
if exact_match:
deep_diff = json_cmp(expect, js)
# Convert DeepDiff completely into dicts or lists at all levels
json_diff = json.loads(deep_diff.to_json())
else:
- deep_diff = json_cmp(expect, js, ignore_order=True)
+ deep_diff = json_cmp(
+ expect, js, ignore_order=True, cutoff_intersection_for_pairs=1
+ )
# Convert DeepDiff completely into dicts or lists at all levels
json_diff = json.loads(deep_diff.to_json())
# Remove new fields in json object from diff
@@ -570,6 +640,7 @@ class TestCase:
"""
path = Path(pathname)
path = self.info.path.parent.joinpath(path)
+ do_cli = False
self.oplogf(
"include: new path: %s create section: %s currently __in_section: %s",
@@ -589,7 +660,12 @@ class TestCase:
self.info.path = path
self.oplogf("include: swapped info path: new %s old %s", path, old_path)
- self.__exec_script(path, print_header=new_section, add_newline=new_section)
+ try:
+ e = self.__exec_script(
+ path, print_header=new_section, add_newline=new_section
+ )
+ except CLIOnErrorError:
+ do_cli = True
if new_section:
# Something within the section creating include has also created a section
@@ -616,6 +692,11 @@ class TestCase:
self.info.path = old_path
self.oplogf("include: restored info path: %s", old_path)
+ if do_cli:
+ raise CLIOnErrorError()
+ if e:
+ raise ScriptError(e)
+
def __end_section(self):
self.oplogf("__end_section: __in_section: %s", self.__in_section)
info = self.__pop_execinfo()
@@ -719,6 +800,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
def test_step(self, expr_or_value: Any, desc: str, target: str = "") -> bool:
@@ -728,6 +810,7 @@ class TestCase:
"""
success = bool(expr_or_value)
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success
def match_step_json(
@@ -760,6 +843,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
def wait_step(
@@ -808,6 +892,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
def wait_step_json(
@@ -846,6 +931,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
diff --git a/tests/topotests/munet/native.py b/tests/topotests/munet/native.py
index 4fbbb85603..de0f0ffc6c 100644
--- a/tests/topotests/munet/native.py
+++ b/tests/topotests/munet/native.py
@@ -8,8 +8,10 @@
# pylint: disable=protected-access
"""A module that defines objects for standalone use."""
import asyncio
+import base64
import errno
import getpass
+import glob
import ipaddress
import logging
import os
@@ -394,6 +396,10 @@ class NodeMixin:
async def async_cleanup_cmd(self):
"""Run the configured cleanup commands for this node."""
+ if self.cleanup_called:
+ return
+ self.cleanup_called = True
+
return await self._async_cleanup_cmd()
def has_ready_cmd(self) -> bool:
@@ -433,14 +439,14 @@ class NodeMixin:
outopt = outopt if outopt is not None else ""
if outopt == "all" or self.name in outopt.split(","):
outname = stdout.name if hasattr(stdout, "name") else stdout
- self.run_in_window(f"tail -F {outname}", title=f"O:{self.name}")
+ self.run_in_window(f"tail -n+1 -F {outname}", title=f"O:{self.name}")
if stderr:
erropt = self.unet.cfgopt.getoption("--stderr")
erropt = erropt if erropt is not None else ""
if erropt == "all" or self.name in erropt.split(","):
errname = stderr.name if hasattr(stderr, "name") else stderr
- self.run_in_window(f"tail -F {errname}", title=f"E:{self.name}")
+ self.run_in_window(f"tail -n+1 -F {errname}", title=f"E:{self.name}")
def pytest_hook_open_shell(self):
if not self.unet:
@@ -615,9 +621,6 @@ class SSHRemote(NodeMixin, Commander):
self.logger.info("%s: created", self)
- def has_ready_cmd(self) -> bool:
- return bool(self.config.get("ready-cmd", "").strip())
-
def _get_pre_cmd(self, use_str, use_pty, ns_only=False, **kwargs):
pre_cmd = []
if self.unet:
@@ -1522,11 +1525,14 @@ class L3ContainerNode(L3NodeMixin, LinuxNamespace):
async def async_cleanup_cmd(self):
"""Run the configured cleanup commands for this node."""
+ if self.cleanup_called:
+ return
self.cleanup_called = True
if "cleanup-cmd" not in self.config:
return
+ # The opposite of other types, the container needs cmd_p running
if not self.cmd_p:
self.logger.warning("async_cleanup_cmd: container no longer running")
return
@@ -1639,7 +1645,15 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
rundir=os.path.join(self.rundir, self.name),
configdir=self.unet.config_dirname,
)
- self.ssh_keyfile = self.qemu_config.get("sshkey")
+ self.ssh_keyfile = self.config.get("ssh-identity-file")
+ if not self.ssh_keyfile:
+ self.ssh_keyfile = self.qemu_config.get("sshkey")
+
+ self.ssh_user = self.config.get("ssh-user")
+ if not self.ssh_user:
+ self.ssh_user = self.qemu_config.get("sshuser", "root")
+
+ self.disk_created = False
@property
def is_vm(self):
@@ -1680,10 +1694,9 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
self.__base_cmd_pty = list(self.__base_cmd)
self.__base_cmd_pty.append("-t")
- user = self.qemu_config.get("sshuser", "root")
- self.__base_cmd.append(f"{user}@{mgmt_ip}")
+ self.__base_cmd.append(f"{self.ssh_user}@{mgmt_ip}")
self.__base_cmd.append("--")
- self.__base_cmd_pty.append(f"{user}@{mgmt_ip}")
+ self.__base_cmd_pty.append(f"{self.ssh_user}@{mgmt_ip}")
# self.__base_cmd_pty.append("--")
return True
@@ -1810,15 +1823,15 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
if args:
self.extra_mounts += args
- async def run_cmd(self):
+ async def _run_cmd(self, cmd_node):
"""Run the configured commands for this node inside VM."""
self.logger.debug(
"[rundir %s exists %s]", self.rundir, os.path.exists(self.rundir)
)
- cmd = self.config.get("cmd", "").strip()
+ cmd = self.config.get(cmd_node, "").strip()
if not cmd:
- self.logger.debug("%s: no `cmd` to run", self)
+ self.logger.debug("%s: no `%s` to run", self, cmd_node)
return None
shell_cmd = self.config.get("shell", "/bin/bash")
@@ -1837,15 +1850,17 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
cmd += "\n"
# Write a copy to the rundir
- cmdpath = os.path.join(self.rundir, "cmd.shebang")
+ cmdpath = os.path.join(self.rundir, f"{cmd_node}.shebang")
with open(cmdpath, mode="w+", encoding="utf-8") as cmdfile:
cmdfile.write(cmd)
commander.cmd_raises(f"chmod 755 {cmdpath}")
# Now write a copy inside the VM
- self.conrepl.cmd_status("cat > /tmp/cmd.shebang << EOF\n" + cmd + "\nEOF")
- self.conrepl.cmd_status("chmod 755 /tmp/cmd.shebang")
- cmds = "/tmp/cmd.shebang"
+ self.conrepl.cmd_status(
+ f"cat > /tmp/{cmd_node}.shebang << EOF\n" + cmd + "\nEOF"
+ )
+ self.conrepl.cmd_status(f"chmod 755 /tmp/{cmd_node}.shebang")
+ cmds = f"/tmp/{cmd_node}.shebang"
else:
cmd = cmd.replace("%CONFIGDIR%", str(self.unet.config_dirname))
cmd = cmd.replace("%RUNDIR%", str(self.rundir))
@@ -1883,16 +1898,22 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
# When run_command supports async_ arg we can use the above...
self.cmd_p = now_proc(self.cmdrepl.run_command(cmds, timeout=120))
-
- # stdout and err both combined into logfile from the spawned repl
- stdout = os.path.join(self.rundir, "_cmdcon-log.txt")
- self.pytest_hook_run_cmd(stdout, None)
else:
# If we only have a console we can't run in parallel, so run to completion
self.cmd_p = now_proc(self.conrepl.run_command(cmds, timeout=120))
return self.cmd_p
+ async def run_cmd(self):
+ if self.disk_created:
+ await self._run_cmd("initial-cmd")
+ await self._run_cmd("cmd")
+
+ # stdout and err both combined into logfile from the spawned repl
+ if self.cmdrepl:
+ stdout = os.path.join(self.rundir, "_cmdcon-log.txt")
+ self.pytest_hook_run_cmd(stdout, None)
+
# InterfaceMixin override
# We need a name unique in the shared namespace.
def get_ns_ifname(self, ifname):
@@ -2044,24 +2065,44 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
async def gather_coverage_data(self):
con = self.conrepl
+ gcda_root = "/sys/kernel/debug/gcov"
+ dest = "/tmp/gcov-data.tgz"
+
+ if gcda_root != "/sys/kernel/debug/gcov":
+ con.cmd_raises(
+ rf"cd {gcda_root} && find * -name '*.gc??' "
+ "| tar -cf - -T - | gzip -c > {dest}"
+ )
+ else:
+ # Some tars dont try and read 0 length files so we need to copy them.
+ tmpdir = con.cmd_raises("mktemp -d").strip()
+ con.cmd_raises(
+ rf"cd {gcda_root} && find -type d -exec mkdir -p {tmpdir}/{{}} \;"
+ )
+ con.cmd_raises(
+ rf"cd {gcda_root} && "
+ rf"find -name '*.gcda' -exec sh -c 'cat < $0 > {tmpdir}/$0' {{}} \;"
+ )
+ con.cmd_raises(
+ rf"cd {gcda_root} && "
+ rf"find -name '*.gcno' -exec sh -c 'cp -d $0 {tmpdir}/$0' {{}} \;"
+ )
+ con.cmd_raises(
+ rf"cd {tmpdir} && "
+ rf"find * -name '*.gc??' | tar -cf - -T - | gzip -c > {dest}"
+ )
+ con.cmd_raises(rf"rm -rf {tmpdir}")
- gcda = "/sys/kernel/debug/gcov"
- tmpdir = con.cmd_raises("mktemp -d").strip()
- dest = "/gcov-data.tgz"
- con.cmd_raises(rf"find {gcda} -type d -exec mkdir -p {tmpdir}/{{}} \;")
- con.cmd_raises(
- rf"find {gcda} -name '*.gcda' -exec sh -c 'cat < $0 > {tmpdir}/$0' {{}} \;"
- )
- con.cmd_raises(
- rf"find {gcda} -name '*.gcno' -exec sh -c 'cp -d $0 {tmpdir}/$0' {{}} \;"
- )
- con.cmd_raises(rf"tar cf - -C {tmpdir} sys | gzip -c > {dest}")
- con.cmd_raises(rf"rm -rf {tmpdir}")
self.logger.info("Saved coverage data in VM at %s", dest)
+ ldest = os.path.join(self.rundir, "gcov-data.tgz")
if self.use_ssh:
- ldest = os.path.join(self.rundir, "gcov-data.tgz")
self.cmd_raises(["/bin/cat", dest], stdout=open(ldest, "wb"))
self.logger.info("Saved coverage data on host at %s", ldest)
+ else:
+ output = con.cmd_raises(rf"base64 {dest}")
+ with open(ldest, "wb") as f:
+ f.write(base64.b64decode(output))
+ self.logger.info("Saved coverage data on host at %s", ldest)
async def _opencons(
self,
@@ -2119,6 +2160,7 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
expects=expects,
sends=sends,
timeout=timeout,
+ init_newline=True,
trace=True,
)
)
@@ -2247,30 +2289,45 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
if not nnics:
args += ["-nic", "none"]
- dtpl = qc.get("disk-template")
+ dtplpath = dtpl = qc.get("disk-template")
diskpath = disk = qc.get("disk")
- if dtpl and not disk:
- disk = qc["disk"] = f"{self.name}-{os.path.basename(dtpl)}"
- diskpath = os.path.join(self.rundir, disk)
+ if diskpath:
+ if diskpath[0] != "/":
+ diskpath = os.path.join(self.unet.config_dirname, diskpath)
+
+ if dtpl and (not disk or not os.path.exists(diskpath)):
+ if not disk:
+ disk = qc["disk"] = f"{self.name}-{os.path.basename(dtpl)}"
+ diskpath = os.path.join(self.rundir, disk)
if self.path_exists(diskpath):
logging.debug("Disk '%s' file exists, using.", diskpath)
else:
- dtplpath = os.path.abspath(
- os.path.join(
- os.path.dirname(self.unet.config["config_pathname"]), dtpl
- )
- )
+ if dtplpath[0] != "/":
+ dtplpath = os.path.join(self.unet.config_dirname, dtpl)
logging.info("Create disk '%s' from template '%s'", diskpath, dtplpath)
self.cmd_raises(
f"qemu-img create -f qcow2 -F qcow2 -b {dtplpath} {diskpath}"
)
+ self.disk_created = True
+ disk_driver = qc.get("disk-driver", "virtio")
if diskpath:
- args.extend(
- ["-drive", f"file={diskpath},if=none,id=sata-disk0,format=qcow2"]
- )
- args.extend(["-device", "ahci,id=ahci"])
- args.extend(["-device", "ide-hd,bus=ahci.0,drive=sata-disk0"])
+ if disk_driver == "virtio":
+ args.extend(["-drive", f"file={diskpath},if=virtio,format=qcow2"])
+ else:
+ args.extend(
+ ["-drive", f"file={diskpath},if=none,id=sata-disk0,format=qcow2"]
+ )
+ args.extend(["-device", "ahci,id=ahci"])
+ args.extend(["-device", "ide-hd,bus=ahci.0,drive=sata-disk0"])
+
+ cidiskpath = qc.get("cloud-init-disk")
+ if cidiskpath:
+ if cidiskpath[0] != "/":
+ cidiskpath = os.path.join(self.unet.config_dirname, cidiskpath)
+ args.extend(["-drive", f"file={cidiskpath},if=virtio,format=qcow2"])
+
+ # args.extend(["-display", "vnc=0.0.0.0:40"])
use_stdio = cc.get("stdio", True)
has_cmd = self.config.get("cmd")
@@ -2360,6 +2417,10 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
if use_cmdcon:
confiles.append("_cmdcon")
+ password = cc.get("password", "")
+ if self.disk_created:
+ password = cc.get("initial-password", password)
+
#
# Connect to the console socket, retrying
#
@@ -2369,7 +2430,7 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
prompt=prompt,
is_bourne=not bool(prompt),
user=cc.get("user", "root"),
- password=cc.get("password", ""),
+ password=password,
expects=cc.get("expects"),
sends=cc.get("sends"),
timeout=int(cc.get("timeout", 60)),
@@ -2425,6 +2486,8 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
async def async_cleanup_cmd(self):
"""Run the configured cleanup commands for this node."""
+ if self.cleanup_called:
+ return
self.cleanup_called = True
if "cleanup-cmd" not in self.config:
@@ -2849,16 +2912,82 @@ ff02::2\tip6-allrouters
mtu = kwargs.get("mtu", config.get("mtu"))
return super().add_switch(name, cls=cls, config=config, mtu=mtu, **kwargs)
+ def coverage_setup(self):
+ bdir = self.cfgopt.getoption("--cov-build-dir")
+ if not bdir:
+ # Try and find the build dir using common prefix of gcno files
+ common = None
+ cwd = os.getcwd()
+ for f in glob.iglob(rf"{cwd}/**/*.gcno", recursive=True):
+ if not common:
+ common = os.path.dirname(f)
+ else:
+ common = os.path.commonprefix([common, f])
+ if not common:
+ break
+ assert (
+ bdir
+ ), "Can't locate build directory for coverage data, use --cov-build-dir"
+
+ bdir = Path(bdir).resolve()
+ rundir = Path(self.rundir).resolve()
+ gcdadir = rundir / "gcda"
+ os.environ["GCOV_BUILD_DIR"] = str(bdir)
+ os.environ["GCOV_PREFIX_STRIP"] = str(len(bdir.parts) - 1)
+ os.environ["GCOV_PREFIX"] = str(gcdadir)
+
+ # commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+rw {{}} +")
+ group_id = bdir.stat().st_gid
+ commander.cmd_raises(f"mkdir -p {gcdadir}")
+ commander.cmd_raises(f"chown -R root:{group_id} {gcdadir}")
+ commander.cmd_raises(f"chmod 2775 {gcdadir}")
+
+ async def coverage_finish(self):
+ rundir = Path(self.rundir).resolve()
+ bdir = Path(os.environ["GCOV_BUILD_DIR"])
+ gcdadir = Path(os.environ["GCOV_PREFIX"])
+
+ # Create GCNO symlinks
+ self.logger.info("Creating .gcno symlinks from '%s' to '%s'", gcdadir, bdir)
+ commander.cmd_raises(
+ f'cd "{gcdadir}"; bdir="{bdir}"'
+ + """
+for f in $(find . -name '*.gcda'); do
+ f=${f#./};
+ f=${f%.gcda}.gcno;
+ ln -fs $bdir/$f $f;
+ touch -h -r $bdir/$f $f;
+ echo $f;
+done"""
+ )
+
+ # Get the results into a summary file
+ data_file = rundir / "coverage.info"
+ self.logger.info("Gathering coverage data into: %s", data_file)
+ commander.cmd_raises(
+ f"lcov --directory {gcdadir} --capture --output-file {data_file}"
+ )
+
+ # Get coverage info filtered to a specific set of files
+ report_file = rundir / "coverage.info"
+ self.logger.debug("Generating coverage summary: %s", report_file)
+ output = commander.cmd_raises(f"lcov --summary {data_file}")
+ self.logger.info("\nCOVERAGE-SUMMARY-START\n%s\nCOVERAGE-SUMMARY-END", output)
+ # terminalreporter.write(
+ # f"\nCOVERAGE-SUMMARY-START\n{output}\nCOVERAGE-SUMMARY-END\n"
+ # )
+
async def run(self):
tasks = []
hosts = self.hosts.values()
launch_nodes = [x for x in hosts if hasattr(x, "launch")]
launch_nodes = [x for x in launch_nodes if x.config.get("qemu")]
- run_nodes = [x for x in hosts if hasattr(x, "has_run_cmd") and x.has_run_cmd()]
- ready_nodes = [
- x for x in hosts if hasattr(x, "has_ready_cmd") and x.has_ready_cmd()
- ]
+ run_nodes = [x for x in hosts if x.has_run_cmd()]
+ ready_nodes = [x for x in hosts if x.has_ready_cmd()]
+
+ if self.cfgopt.getoption("--coverage"):
+ self.coverage_setup()
pcapopt = self.cfgopt.getoption("--pcap")
pcapopt = pcapopt if pcapopt else ""
@@ -2940,15 +3069,6 @@ ff02::2\tip6-allrouters
self.logger.debug("%s: deleting.", self)
- if self.cfgopt.getoption("--coverage"):
- nodes = (
- x for x in self.hosts.values() if hasattr(x, "gather_coverage_data")
- )
- try:
- await asyncio.gather(*(x.gather_coverage_data() for x in nodes))
- except Exception as error:
- logging.warning("Error gathering coverage data: %s", error)
-
pause = bool(self.cfgopt.getoption("--pause-at-end"))
pause = pause or bool(self.cfgopt.getoption("--pause"))
if pause:
@@ -2959,6 +3079,25 @@ ff02::2\tip6-allrouters
except Exception as error:
self.logger.error("\n...continuing after error: %s", error)
+ # Run cleanup-cmd's.
+ nodes = (x for x in self.hosts.values() if x.has_cleanup_cmd())
+ try:
+ await asyncio.gather(*(x.async_cleanup_cmd() for x in nodes))
+ except Exception as error:
+ logging.warning("Error running cleanup cmds: %s", error)
+
+ # Gather any coverage data
+ if self.cfgopt.getoption("--coverage"):
+ nodes = (
+ x for x in self.hosts.values() if hasattr(x, "gather_coverage_data")
+ )
+ try:
+ await asyncio.gather(*(x.gather_coverage_data() for x in nodes))
+ except Exception as error:
+ logging.warning("Error gathering coverage data: %s", error)
+
+ await self.coverage_finish()
+
# XXX should we cancel launch and run tasks?
try:
diff --git a/tests/topotests/munet/parser.py b/tests/topotests/munet/parser.py
index 4fc0c75a60..a8b73a25e7 100644
--- a/tests/topotests/munet/parser.py
+++ b/tests/topotests/munet/parser.py
@@ -230,7 +230,7 @@ def load_kinds(args, search=None):
if args:
os.chdir(args.rundir)
- args_config = args.kinds_config if args else None
+ args_config = args.kinds_config if args and hasattr(args, "kinds_config") else None
try:
if search is None:
search = [cwd]
@@ -305,7 +305,7 @@ async def async_build_topology(
# create search directories from common root if given
cpath = Path(config["config_pathname"]).absolute()
- project_root = args.project_root if args else None
+ project_root = args.project_root if args and hasattr(args, "project_root") else None
if not search_root:
search_root = find_project_root(cpath, project_root)
if not search_root:
@@ -341,7 +341,11 @@ async def async_build_topology(
pytestconfig=pytestconfig,
isolated=isolated,
pid=top_level_pidns,
- unshare_inline=args.unshare_inline if args else unshare_inline,
+ unshare_inline=(
+ args.unshare_inline
+ if args and hasattr(args, "unshare_inline")
+ else unshare_inline
+ ),
logger=logger,
)
diff --git a/tests/topotests/munet/testing/fixtures.py b/tests/topotests/munet/testing/fixtures.py
index 3c6d9460ff..4150d28b59 100644
--- a/tests/topotests/munet/testing/fixtures.py
+++ b/tests/topotests/munet/testing/fixtures.py
@@ -150,7 +150,7 @@ def session_autouse():
@pytest.fixture(autouse=True, scope="module")
def module_autouse(request):
- logpath = get_test_logdir(request.node.name, True)
+ logpath = get_test_logdir(request.node.nodeid, True)
logpath = os.path.join("/tmp/unet-test", logpath, "pytest-exec.log")
with log_handler("module", logpath):
sdir = os.path.dirname(os.path.realpath(request.fspath))
@@ -161,7 +161,7 @@ def module_autouse(request):
raise Exception("Base Munet was not cleaned up/deleted")
-@pytest.fixture(scope="module")
+@pytest.fixture(scope="session")
def event_loop():
"""Create an instance of the default event loop for the session."""
loop = get_event_loop()
@@ -213,18 +213,14 @@ async def _unet_impl(
param,
exc_info=True,
)
- pytest.skip(
- f"unet fixture: unet build failed: {error}", allow_module_level=True
- )
- raise
+ pytest.fail(f"unet fixture: unet build failed: {error}")
try:
tasks = await _unet.run()
except Exception as error:
logging.debug("unet fixture: unet run failed: %s", error, exc_info=True)
await _unet.async_delete()
- pytest.skip(f"unet fixture: unet run failed: {error}", allow_module_level=True)
- raise
+ pytest.fail(f"unet fixture: unet run failed: {error}")
logging.debug("unet fixture: containers running")
diff --git a/tests/topotests/munet/testing/hooks.py b/tests/topotests/munet/testing/hooks.py
index 985eef9c49..f6f2115367 100644
--- a/tests/topotests/munet/testing/hooks.py
+++ b/tests/topotests/munet/testing/hooks.py
@@ -18,6 +18,7 @@ import traceback
import pytest
+from ..args import add_testing_args
from ..base import BaseMunet # pylint: disable=import-error
from ..cli import cli # pylint: disable=import-error
from .util import pause_test
@@ -29,85 +30,7 @@ from .util import pause_test
def pytest_addoption(parser):
- parser.addoption(
- "--cli-on-error",
- action="store_true",
- help="CLI on test failure",
- )
-
- parser.addoption(
- "--coverage",
- action="store_true",
- help="Enable coverage gathering if supported",
- )
-
- parser.addoption(
- "--gdb",
- default="",
- metavar="HOST[,HOST...]",
- help="Comma-separated list of nodes to launch gdb on, or 'all'",
- )
- parser.addoption(
- "--gdb-breakpoints",
- default="",
- metavar="BREAKPOINT[,BREAKPOINT...]",
- help="Comma-separated list of breakpoints",
- )
- parser.addoption(
- "--gdb-use-emacs",
- action="store_true",
- help="Use emacsclient to run gdb instead of a shell",
- )
-
- parser.addoption(
- "--pcap",
- default="",
- metavar="NET[,NET...]",
- help="Comma-separated list of networks to capture packets on, or 'all'",
- )
-
- parser.addoption(
- "--pause",
- action="store_true",
- help="Pause after each test",
- )
- parser.addoption(
- "--pause-at-end",
- action="store_true",
- help="Pause before taking munet down",
- )
- parser.addoption(
- "--pause-on-error",
- action="store_true",
- help="Pause after (disables default when --shell or -vtysh given)",
- )
- parser.addoption(
- "--no-pause-on-error",
- dest="pause_on_error",
- action="store_false",
- help="Do not pause after (disables default when --shell or -vtysh given)",
- )
-
- parser.addoption(
- "--shell",
- default="",
- metavar="NODE[,NODE...]",
- help="Comma-separated list of nodes to spawn shell on, or 'all'",
- )
-
- parser.addoption(
- "--stdout",
- default="",
- metavar="NODE[,NODE...]",
- help="Comma-separated list of nodes to open tail-f stdout window on, or 'all'",
- )
-
- parser.addoption(
- "--stderr",
- default="",
- metavar="NODE[,NODE...]",
- help="Comma-separated list of nodes to open tail-f stderr window on, or 'all'",
- )
+ add_testing_args(parser.addoption)
def pytest_configure(config):
@@ -146,6 +69,18 @@ def pytest_configure(config):
elif b and not is_xdist and not have_windows:
pytest.exit(f"{winopt} use requires byobu/TMUX/SCREEN/XTerm")
+ cli_pause = (
+ config.getoption("--cli-on-error")
+ or config.getoption("--pause")
+ or config.getoption("--pause-at-end")
+ or config.getoption("--pause-on-error")
+ )
+ if config.getoption("--capture") == "fd" and cli_pause:
+ pytest.exit(
+ "CLI is not compatible with `--capture=fd`, "
+ "please run again with `-s` or other `--capture` value"
+ )
+
def pytest_runtest_makereport(item, call):
"""Pause or invoke CLI as directed by config."""
diff --git a/tests/topotests/munet/watchlog.py b/tests/topotests/munet/watchlog.py
index 27bc3251a6..f764f9dac3 100644
--- a/tests/topotests/munet/watchlog.py
+++ b/tests/topotests/munet/watchlog.py
@@ -15,6 +15,7 @@ from pathlib import Path
class MatchFoundError(Exception):
"""An error raised when a match is not found."""
+
def __init__(self, watchlog, match):
self.watchlog = watchlog
self.match = match
diff --git a/tests/topotests/nb_config/test_nb_config.py b/tests/topotests/nb_config/test_nb_config.py
index f699a4e20e..8def19ffd5 100644
--- a/tests/topotests/nb_config/test_nb_config.py
+++ b/tests/topotests/nb_config/test_nb_config.py
@@ -24,9 +24,7 @@ CWD = os.path.dirname(os.path.realpath(__file__))
def tgen(request):
"Setup/Teardown the environment and provide tgen argument to tests"
- topodef = {
- "s1": ("r1",)
- }
+ topodef = {"s1": ("r1",)}
tgen = Topogen(topodef, request.module.__name__)
tgen.start_topology()
@@ -46,12 +44,14 @@ def test_access_list_config_ordering(tgen):
r1 = tgen.gears["r1"]
- output = r1.vtysh_multicmd([
- "conf t",
- "access-list test seq 1 permit host 10.0.0.1"])
+ output = r1.vtysh_multicmd(
+ ["conf t", "access-list test seq 1 permit host 10.0.0.1"]
+ )
output = r1.vtysh_cmd("show ip access-list test json")
got = json.loads(output)
- expected = json.loads('{"ZEBRA":{"test":{"type":"Standard", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "address":"10.0.0.1", "mask":"0.0.0.0"}]}}}')
+ expected = json.loads(
+ '{"ZEBRA":{"test":{"type":"Standard", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "address":"10.0.0.1", "mask":"0.0.0.0"}]}}}'
+ )
result = json_cmp(got, expected)
assert result is None
@@ -59,11 +59,11 @@ def test_access_list_config_ordering(tgen):
# If the northbound mis-orders the create/delete then this test fails.
# https://github.com/FRRouting/frr/pull/15423/commits/38b85e0c2bc555b8827dbd2cb6515b6febf548b4
#
- output = r1.vtysh_multicmd([
- "conf t",
- "access-list test seq 1 permit 10.0.0.0/8"])
+ output = r1.vtysh_multicmd(["conf t", "access-list test seq 1 permit 10.0.0.0/8"])
output = r1.vtysh_cmd("show ip access-list test json")
got = json.loads(output)
- expected = json.loads('{"ZEBRA":{"test":{"type":"Zebra", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "prefix":"10.0.0.0/8", "exact-match":false}]}}}')
+ expected = json.loads(
+ '{"ZEBRA":{"test":{"type":"Zebra", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "prefix":"10.0.0.0/8", "exact-match":false}]}}}'
+ )
result = json_cmp(got, expected)
assert result is None
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py b/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py
index bd7db644d1..62b8212203 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py
@@ -183,7 +183,6 @@ def teardown_module(mod):
logger.info("=" * 40)
-
def red_static(dut, config=True):
"""Local def for Redstribute static routes inside ospf."""
global topo
@@ -367,7 +366,13 @@ def test_ospf_flood_red_tc1_p0(request):
},
}
result = verify_ospf_database(
- tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False
+ tgen,
+ topo,
+ dut,
+ input_dict_db,
+ lsatype="router",
+ rid="100.1.1.0",
+ expected=False,
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -573,7 +578,9 @@ def test_ospf_flood_red_tc2_p0(request):
result = verify_ospf_database(
tgen, topo, dut, input_dict_db, lsatype="router", rid=lsid
)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
step("Wait for 120 secs and verify that LSA's are not refreshed. ")
# get LSA age
@@ -636,7 +643,13 @@ def test_ospf_flood_red_tc2_p0(request):
},
}
result = verify_ospf_database(
- tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False
+ tgen,
+ topo,
+ dut,
+ input_dict_db,
+ lsatype="router",
+ rid="100.1.1.0",
+ expected=False,
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -815,7 +828,9 @@ def test_ospf_flood_red_tc3_p0(request):
result = verify_ospf_database(
tgen, topo, dut, input_dict_db, lsatype="router", rid=lsid
)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
step("Wait for 120 secs and verify that LSA's are not refreshed. ")
# get LSA age
@@ -1022,7 +1037,13 @@ def test_ospf_flood_red_tc3_p0(request):
},
}
result = verify_ospf_database(
- tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False
+ tgen,
+ topo,
+ dut,
+ input_dict_db,
+ lsatype="router",
+ rid="100.1.1.0",
+ expected=False,
)
assert result is not True, (
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
index d669e21d4d..4a40b3e9ec 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
@@ -165,7 +165,7 @@ def test_ospf_learning_tc15_p0(request):
step("Verify that Type 3 summary LSA is originated for the same Area 0")
ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
dut = "r0"
input_dict = {
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
index f0950a2db3..d169245f4e 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
@@ -49,7 +49,7 @@ from lib.ospf import (
verify_ospf_interface,
)
-pytestmark = [pytest.mark.ospfd, pytest.mark.staticd]
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd, pytest.mark.staticd]
# Global variables
@@ -177,7 +177,7 @@ def test_ospf_redistribution_tc5_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
input_dict = {
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
@@ -301,7 +301,7 @@ def test_ospf_redistribution_tc6_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
input_dict = {
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
index 757d6fb1d5..172f79d458 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
@@ -634,7 +634,7 @@ def test_ospf_show_p1(request):
# show ip ospf route
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
input_dict = {
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
diff --git a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
index 46c0da309f..3468a6511b 100644
--- a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
+++ b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
@@ -190,8 +190,10 @@ def test_ospf_gr_helper_tc3_p1(request):
ospf_covergence is True
), "OSPF is not after reset config \n Error: {}".format(ospf_covergence)
- step("Configure DR priority 100 on R0 and clear ospf neighbors "
- "on all the routers.")
+ step(
+ "Configure DR priority 100 on R0 and clear ospf neighbors "
+ "on all the routers."
+ )
input_dict = {
"r0": {
diff --git a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
index 9dfe5e1b76..590b0d5e68 100644
--- a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
+++ b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
@@ -64,16 +64,9 @@ def setup_module(module):
# This is a sample of configuration loading.
r1 = tgen.gears["r1"]
- r1.load_config(
- TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf")
- )
- r1.load_config(
- TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"),
- "-n 3"
- )
- r1.load_config(
- TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf")
- )
+ r1.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf"))
+ r1.load_config(TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"), "-n 3")
+ r1.load_config(TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf"))
tgen.start_router()
@@ -103,13 +96,15 @@ def test_install_sharp_instance_routes():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip route summ json", expected)
+ topotest.router_json_cmp, r1, "show ip route summ json", expected
+ )
logger.info("Ensuring that they exist in the rib/fib")
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" sharp routes are not installed'
assert result is None, assertmsg
+
def test_ospf_instance_redistribute():
tgen = get_topogen()
@@ -124,7 +119,8 @@ def test_ospf_instance_redistribute():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes'
@@ -139,7 +135,8 @@ def test_ospf_instance_redistribute():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes'
@@ -161,15 +158,14 @@ def test_ospf_instance_default_information():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" ospf instance 3 does not properly redistribute the default route'
assert result is None, assertmsg
-
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
-
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py b/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py
index 792304e19d..ee0a0f6c3b 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py
@@ -182,9 +182,7 @@ def test_ospf_convergence():
"show ip ospf vrf {} route".format(vrf),
expected,
)
- result, diff = topotest.run_and_expect(
- test_func, "", count=80, wait=1
- )
+ result, diff = topotest.run_and_expect(test_func, "", count=80, wait=1)
assertmsg = "OSPF did not converge on {}:\n{}".format(rname, diff)
assert result, assertmsg
@@ -207,9 +205,7 @@ def test_ospf_kernel_route():
test_func = partial(
compare_show_ip_route_vrf, router.name, expected, vrf
)
- result, diff = topotest.run_and_expect(
- test_func, "", count=80, wait=1
- )
+ result, diff = topotest.run_and_expect(test_func, "", count=80, wait=1)
assertmsg = 'OSPF IPv4 route mismatch in router "{}": {}'.format(
router.name, diff
)
diff --git a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
index 432ddf0986..d8cd1322bd 100644
--- a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
+++ b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
@@ -199,9 +199,7 @@ def test_rib_step3():
pytest.skip(tgen.errors)
logger.info("Removing NSSA default on rt4")
- tgen.net["rt3"].cmd(
- 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"'
- )
+ tgen.net["rt3"].cmd('vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"')
for rname in ["rt1", "rt2", "rt3", "rt4"]:
router_compare_json_output(
diff --git a/tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000000..ca84349cdc
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,26 @@
+!
+hostname r1
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r1-eth0
+ ip address 10.1.0.1/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r1-eth1
+ ip address 10.1.1.1/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+router ospf
+ ospf router-id 1.1.1.1
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.1.0/24 area 0
+ neighbor 10.1.0.2 poll-interval 5
+ neighbor 10.1.0.3 poll-interval 5
+ neighbor 10.1.0.4 poll-interval 5
+!
diff --git a/tests/topotests/ospf_p2mp/r1/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r1/frr-p2mp.conf
new file mode 100644
index 0000000000..cb4538c0e3
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r1/frr-p2mp.conf
@@ -0,0 +1,23 @@
+!
+hostname r1
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r1-eth0
+ ip address 10.1.0.1/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r1-eth1
+ ip address 10.1.1.1/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+router ospf
+ ospf router-id 1.1.1.1
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.1.0/24 area 0
+!
diff --git a/tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000000..6e26897c49
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,29 @@
+!
+hostname r2
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r2-eth0
+ ip address 10.1.0.2/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r2-eth1
+ ip address 10.1.2.2/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+!
+!
+router ospf
+ ospf router-id 2.2.2.2
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.2.0/24 area 0
+ neighbor 10.1.0.1 poll-interval 5
+ neighbor 10.1.0.3 poll-interval 5
+ neighbor 10.1.0.4 poll-interval 5
+!
diff --git a/tests/topotests/ospf_p2mp/r2/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r2/frr-p2mp.conf
new file mode 100644
index 0000000000..0ca8aec3bf
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r2/frr-p2mp.conf
@@ -0,0 +1,26 @@
+!
+hostname r2
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r2-eth0
+ ip address 10.1.0.2/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r2-eth1
+ ip address 10.1.2.2/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+!
+!
+router ospf
+ ospf router-id 2.2.2.2
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.2.0/24 area 0
+!
diff --git a/tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000000..a69e0557be
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,28 @@
+!
+hostname r3
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r3-eth0
+ ip address 10.1.0.3/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r3-eth1
+ ip address 10.1.3.3/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 3.3.3.3
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.3.0/24 area 0
+ neighbor 10.1.0.1 poll-interval 5
+ neighbor 10.1.0.2 poll-interval 5
+ neighbor 10.1.0.4 poll-interval 5
diff --git a/tests/topotests/ospf_p2mp/r3/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r3/frr-p2mp.conf
new file mode 100644
index 0000000000..41ea70d443
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r3/frr-p2mp.conf
@@ -0,0 +1,25 @@
+!
+hostname r3
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r3-eth0
+ ip address 10.1.0.3/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r3-eth1
+ ip address 10.1.3.3/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 3.3.3.3
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.3.0/24 area 0
diff --git a/tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000000..1b8388584b
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,28 @@
+!
+hostname r4
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r4-eth0
+ ip address 10.1.0.4/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r4-eth1
+ ip address 10.1.4.4/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 4.4.4.4
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.4.0/24 area 0
+ neighbor 10.1.0.1 poll-interval 5
+ neighbor 10.1.0.2 poll-interval 5
+ neighbor 10.1.0.3 poll-interval 5
diff --git a/tests/topotests/ospf_p2mp/r4/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r4/frr-p2mp.conf
new file mode 100644
index 0000000000..21fa9c72f9
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r4/frr-p2mp.conf
@@ -0,0 +1,25 @@
+!
+hostname r4
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r4-eth0
+ ip address 10.1.0.4/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r4-eth1
+ ip address 10.1.4.4/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 4.4.4.4
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.4.0/24 area 0
diff --git a/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py b/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py
new file mode 100644
index 0000000000..1f0f87959a
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py
@@ -0,0 +1,472 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+#
+# test_ospf_prefix_p2mp_broadcast.py
+#
+# Copyright (c) 2024 LabN Consulting
+# Acee Lindem
+#
+
+import os
+import sys
+import json
+from time import sleep
+from functools import partial
+import pytest
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from lib.common_config import (
+ run_frr_cmd,
+ shutdown_bringup_interface,
+ start_router_daemons,
+ step,
+)
+
+
+"""
+test_ospf_p2mp_broadcast.py: Test OSPF Point-to-multipoint
+"""
+
+TOPOLOGY = """
+ +-----+ +-----+
+10.1.1.0/24 | r1 | | r2 | 10.1.2.0/24
+ -----------+ | | +----------
+ +--+--+ +--+--+
+ | 10.1.0.0/24 |
+ | +-------+ |
+ +---- | |-----+
+ | P2MP |
+ +---- | |-----+
+ | +-------+ |
+ | |
+ | |
+ +--+--+ +-+---+
+10.1.3.0/24 | r3 | | r4 | 10.1.4.0/24
+ -----------+ | | +----------
+ +-----+ +-----+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.ospfd, pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 4 routers
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+ tgen.add_router("r3")
+ tgen.add_router("r4")
+
+ # Interconect them all to the P2MP network
+ switch = tgen.add_switch("s0-p2mp")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+ # Add standalone network to router 1
+ switch = tgen.add_switch("s-r1-1")
+ switch.add_link(tgen.gears["r1"])
+
+ # Add standalone network to router 2
+ switch = tgen.add_switch("s-r2-1")
+ switch.add_link(tgen.gears["r2"])
+
+ # Add standalone network to router 3
+ switch = tgen.add_switch("s-r3-1")
+ switch.add_link(tgen.gears["r3"])
+
+ # Add standalone network to router 4
+ switch = tgen.add_switch("s-r4-1")
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ logger.info("OSPF Point-to-MultiPoint:\n {}".format(TOPOLOGY))
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+
+ for rname, router in router_list.items():
+ logger.info("Loading router %s" % rname)
+ router.load_frr_config(os.path.join(CWD, "{}/frr-p2mp.conf".format(rname)))
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, nbr_filter):
+ "Verify the P2MP Configuration and interface settings"
+
+ topo_router = tgen.gears[router]
+
+ step("Test running configuration for P2MP configuration")
+ rc = 0
+ rc, _, _ = tgen.net[router].cmd_status(
+ "show running ospfd | grep 'ip ospf network point-to-multipoint'", warn=False
+ )
+ assertmsg = (
+ "'ip ospf network point-to-multipoint' applied, but not present in "
+ + router
+ + "configuration"
+ )
+ assert rc, assertmsg
+
+ step("Test OSPF interface for P2MP settings")
+ input_dict = {
+ "interfaces": {
+ "r1-eth0": {
+ "ospfEnabled": True,
+ "interfaceIp": {
+ "10.1.0.1": {
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "nbrFilterPrefixList": nbr_filter,
+ }
+ },
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "area": "0.0.0.0",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "opaqueCapable": True,
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "nbrFilterPrefixList": nbr_filter,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf interface r1-eth0 json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Interface Mismatch on router r1"
+ assert result is None, assertmsg
+
+
+def verify_non_p2mp_interface(tgen):
+ "Verify the removal of P2MP Configuration and interface settings"
+ r1 = tgen.gears["r1"]
+
+ step("Test running configuration for removal of P2MP configuration")
+ rc = 0
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf network point-to-multipoint'", warn=False
+ )
+ assertmsg = "'ip ospf network point-to-multipoint' not applied, but present in r1 configuration"
+ assert rc, assertmsg
+
+ step("Test OSPF interface for default settings")
+ input_dict = {
+ "interfaces": {
+ "r1-eth0": {
+ "ospfEnabled": True,
+ "interfaceIp": {
+ "10.1.0.1": {
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "routerId": "1.1.1.1",
+ "networkType": "BROADCAST",
+ "cost": 10,
+ "prefixSuppression": False,
+ }
+ },
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "area": "0.0.0.0",
+ "routerId": "1.1.1.1",
+ "networkType": "BROADCAST",
+ "cost": 10,
+ "opaqueCapable": True,
+ "prefixSuppression": False,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf interface r1-eth0 json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Interface Mismatch on router r1"
+ assert result is None, assertmsg
+
+
+def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify neighbor " + neighbor + " in " + state + " state")
+ input_dict = {
+ "default": {
+ neighbor: [
+ {
+ "nbrState": state,
+ "ifaceAddress": intf_addr,
+ "ifaceName": interface,
+ }
+ ],
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf neighbor " + neighbor + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Neighbor " + neighbor + " not in " + state
+ assert result is None, assertmsg
+
+
+def verify_p2mp_neighbor_missing(tgen, router, neighbor):
+ topo_router = tgen.gears[router]
+
+ step("Verify neighbor " + neighbor + " missing")
+ input_dict = {"default": {}}
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf neighbor " + neighbor + " json",
+ input_dict,
+ True, # Require exact match for missing neighbor
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Neighbor " + neighbor + " not missing"
+ assert result is None, assertmsg
+
+
+def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify router " + router + " p2mp route " + prefix + " installed")
+ input_dict = {
+ prefix: [
+ {
+ "prefix": prefix,
+ "prefixLen": prefix_len,
+ "protocol": "ospf",
+ "nexthops": [
+ {
+ "ip": nexthop,
+ "interfaceName": interface,
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip route " + prefix + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = prefix + " not installed on router " + router
+ assert result is None, assertmsg
+
+
+def test_p2mp_broadcast_interface():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Verify router r1 p2mp interface r1-eth0 neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 p2mp routes installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration removal")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf network point-to-multipoint")
+ verify_non_p2mp_interface(tgen)
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration application")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Verify restablishment of r1-eth0 p2mp neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 p2mp routes reinstalled")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+
+def test_p2mp_broadcast_neighbor_filter():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Verify router r1 p2mp interface r1-eth0 neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Add OSPF interface neighbor-filter to r1")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
+
+ step("Verify the R1 configuration of 'ip ospf neighbor-filter nbr-filter'")
+ neighbor_filter_cfg = (
+ tgen.net["r1"]
+ .cmd(
+ 'vtysh -c "show running ospfd" | grep "^ ip ospf neighbor-filter nbr-filter"'
+ )
+ .rstrip()
+ )
+ assertmsg = (
+ "'ip ospf neighbor-filter nbr-filter' applied, but not present in configuration"
+ )
+ assert neighbor_filter_cfg == " ip ospf neighbor-filter nbr-filter", assertmsg
+
+ step("Verify non-existent neighbor-filter is not applied to r1 interfaces")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Add nbr-filter prefix-list configuration to r1")
+ r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 200 permit any")
+
+ step(
+ "Verify neighbor-filter is now applied to r1 interface and neighbors still adjacent"
+ )
+ verify_p2mp_interface(tgen, "r1", 3, 3, "nbr-filter")
+
+ step("Add nbr-filter prefix-list configuration to block r4")
+ r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.4/32")
+
+ step(
+ "Verify neighbor-filter is now applied to r1 interface and r4 is no longer adjacent"
+ )
+ verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
+ verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
+
+ step("Verify route to r4 subnet is now through r2")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.2", "r1-eth0")
+
+ step("Add nbr-filter prefix-list configuration to block r2")
+ r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 20 deny 10.1.0.2/32")
+
+ step(
+ "Verify neighbor-filter is now applied to r1 interface and r2 is no longer adjacent"
+ )
+ verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
+ verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
+
+ step("Verify route to r4 and r2 subnet are now through r3")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.3", "r1-eth0")
+
+ step("Remove neighbor filter configuration and verify")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf neighbor-filter")
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf neighbor-filter'", warn=False
+ )
+ assertmsg = "'ip ospf neighbor' not applied, but present in R1 configuration"
+ assert rc, assertmsg
+
+ step("Verify interface neighbor-filter is removed and neighbors present")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Add neighbor filter configuration and verify neighbors are filtered")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
+ verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
+ verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
+ verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
+
+ step("Remove nbr-filter prefix-list configuration to block r2 and verify neighbor")
+ r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter seq 20")
+ verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+
+ step("Delete nbr-filter prefix-list and verify neighbors are present")
+ r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py b/tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py
new file mode 100644
index 0000000000..175dca74e7
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py
@@ -0,0 +1,467 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# test_ospf_prefix_p2mp_non_broadcast.py
+#
+# Copyright (c) 2024 LabN Consulting
+# Acee Lindem
+#
+
+import os
+import sys
+import json
+from time import sleep
+from functools import partial
+import pytest
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from lib.common_config import (
+ run_frr_cmd,
+ shutdown_bringup_interface,
+ start_router_daemons,
+ step,
+)
+
+
+"""
+test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
+ Full Mesh
+"""
+
+TOPOLOGY = """
+ +-----+ +-----+
+10.1.1.0/24 | r1 | | r2 | 10.1.2.0/24
+ -----------+ | | +----------
+ +--+--+ +--+--+
+ | 10.1.0.0/24 |
+ | +-------+ |
+ +---- | |-----+
+ | P2MP |
+ +---- | |-----+
+ | +-------+ |
+ | |
+ | |
+ +--+--+ +-+---+
+10.1.3.0/24 | r3 | | r4 | 10.1.4.0/24
+ -----------+ | | +----------
+ +-----+ +-----+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.ospfd, pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 4 routers
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+ tgen.add_router("r3")
+ tgen.add_router("r4")
+
+ # Interconect them all to the P2MP network
+ switch = tgen.add_switch("s0-p2mp")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+ # Add standalone network to router 1
+ switch = tgen.add_switch("s-r1-1")
+ switch.add_link(tgen.gears["r1"])
+
+ # Add standalone network to router 2
+ switch = tgen.add_switch("s-r2-1")
+ switch.add_link(tgen.gears["r2"])
+
+ # Add standalone network to router 3
+ switch = tgen.add_switch("s-r3-1")
+ switch.add_link(tgen.gears["r3"])
+
+ # Add standalone network to router 4
+ switch = tgen.add_switch("s-r4-1")
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+
+ for rname, router in router_list.items():
+ logger.info("Loading router %s" % rname)
+ router.load_frr_config(
+ os.path.join(CWD, "{}/frr-p2mp-non-broadcast.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, non_broadcast):
+ "Verify the P2MP Configuration and interface settings"
+
+ topo_router = tgen.gears[router]
+
+ step("Test running configuration for P2MP configuration")
+ rc = 0
+ rc, _, _ = tgen.net[router].cmd_status(
+ "show running ospfd | grep 'ip ospf network point-to-multipoint'", warn=False
+ )
+ assertmsg = (
+ "'ip ospf network point-to-multipoint' applied, but not present in "
+ + router
+ + "configuration"
+ )
+ assert rc, assertmsg
+
+ step("Test OSPF interface for P2MP settings")
+ input_dict = {
+ "interfaces": {
+ "r1-eth0": {
+ "ospfEnabled": True,
+ "interfaceIp": {
+ "10.1.0.1": {
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "p2mpNonBroadcast": non_broadcast,
+ }
+ },
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "area": "0.0.0.0",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "opaqueCapable": True,
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "p2mpNonBroadcast": non_broadcast,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf interface r1-eth0 json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Interface Mismatch on router r1"
+ assert result is None, assertmsg
+
+
+def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify neighbor " + neighbor + " in " + state + " state")
+ input_dict = {
+ "default": {
+ neighbor: [
+ {
+ "nbrState": state,
+ "ifaceAddress": intf_addr,
+ "ifaceName": interface,
+ }
+ ],
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf neighbor " + neighbor + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Neighbor " + neighbor + " not in " + state
+ assert result is None, assertmsg
+
+
+def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify router " + router + " p2mp route " + prefix + " installed")
+ input_dict = {
+ prefix: [
+ {
+ "prefix": prefix,
+ "prefixLen": prefix_len,
+ "protocol": "ospf",
+ "nexthops": [
+ {
+ "ip": nexthop,
+ "interfaceName": interface,
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip route " + prefix + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = prefix + " not installed on router " + router
+ assert result is None, assertmsg
+
+
+def test_p2mp_non_broadcast_connectivity():
+ tgen = get_topogen()
+ r1 = tgen.gears["r1"]
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 3, 3, True)
+
+ step("Verify router r1 interface r1-eth0 p2mp non-broadcast configuration")
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf network point-to-multipoint non-broadcast'",
+ warn=False,
+ )
+ assertmsg = "'ip ospf network point-to-multipoint non-broadcast' applied, but not present in R1 configuration"
+ assert rc, assertmsg
+
+ step("Verify router r1 OSPF point-to-multipoint neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 OSPF point-to-multipoint routes are installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+ step("Remove r1 interface r1-eth0 p2mp non-broadcast configuration")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf network point-to-multipoint non-broadcast'",
+ warn=False,
+ )
+ assertmsg = "'ip ospf network point-to-multipoint non-broadcast' not applied, but present in r1 configuration"
+ assert rc, assertmsg
+
+ step("Verify router r1 interface OSPF point-to-multipoint broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 3, 3, False)
+
+ step("Add r1 interface r1-eth0 p2mp non-broadcast configuration back")
+ r1.vtysh_cmd(
+ "conf t\ninterface r1-eth0\nip ospf network point-to-multipoint non-broadcast"
+ )
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep 'ip ospf network point-to-multipoint non-broadcast'",
+ warn=False,
+ )
+ assertmsg = "'ip ospf netrwork point-to-multipoint non-broadcast' applied, but not present in R1 configuration"
+ assert rc, assertmsg
+
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 3, 3, True)
+
+ step(
+ "Verify router r1 OSPF point-to-multipoint neighbors adjacencies restablished."
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+
+def test_p2mp_non_broadcast_partial_mesh_connectivity():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ """
+ test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
+ Partial Mesh
+ """
+
+ TOPOLOGY = """
+ +-----+ +------+
+ 10.1.1.0/24 | r1 | | r4 | 10.1.4.0/24
+ -----------+ | | +----------
+ +-+---+ +--+-+-+
+ | P2MP |
+ | Non-Broadcast |
+ | 10.1.0.0/24 |
+ +-+---+ +-+---+
+ 10.1.2.0/24 | r2 | | r3 | 10.1.3.0/24
+ -----------+ +--------------+ +----------
+ +-----+ +-----+
+
+
+ """
+ logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
+
+ step("Change configuration to a partial mesh")
+ step("Delete neighbors in full mesh")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.3")
+ r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.4")
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.4")
+ r3 = tgen.gears["r3"]
+ r3.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
+ r4 = tgen.gears["r4"]
+ r4.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
+ r4.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.2")
+
+ step("Flap interfaces on P2MP network to avoid transients")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nshut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nshut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nshut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nshut")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno shut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nno shut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nno shut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nno shut")
+
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 1, 1, True)
+
+ step("Verify router r1 interface r1-eth0 p2mp neighbor")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 p2mp routes are installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.2", "r1-eth0")
+
+ """
+ test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
+ Modified Partial Mesh
+ """
+
+ TOPOLOGY = """
+ +-----+ +------+
+ 10.1.1.0/24 | r1 | | r4 | 10.1.4.0/24
+ -----------+ +-------------+ +----------
+ +-----+ +--+-+-+
+ P2MP |
+ Non-Broadcast |
+ 10.1.0.0/24 |
+ +-+---+ +-+---+
+ 10.1.2.0/24 | r2 | | r3 | 10.1.3.0/24
+ -----------+ +--------------+ +----------
+ +-----+ +-----+
+
+
+ """
+ logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
+
+ step("Change configuration to a partial mesh")
+ step("Modify neighbors in partial mesh")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.2")
+ r1.vtysh_cmd("conf t\nrouter ospf\nneighbor 10.1.0.4 poll-interval 5")
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
+ r4 = tgen.gears["r4"]
+ r4.vtysh_cmd("conf t\nrouter ospf\nneighbor 10.1.0.1")
+
+ step("Flap interfaces on P2MP network to avoid transients")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nshut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nshut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nshut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nshut")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno shut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nno shut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nno shut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nno shut")
+
+ step("Verify router r1 interface r1-eth0")
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 1, 1, True)
+
+ step("Verify router r1 interface r1-eth0 p2mp neighbor")
+ input_dict = {
+ "neighbors": {
+ "4.4.4.4": [
+ {
+ "nbrState": "Full/DROther",
+ "ifaceAddress": "10.1.0.4",
+ "ifaceName": "r1-eth0:10.1.0.1",
+ }
+ ],
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf neighbor json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Non-Broadcast Neighbors not adjacent on router r1"
+ assert result is None, assertmsg
+
+ step("Verify router r1 interface r1-eth0 p2mp routes are installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.4", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.4", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_single_switch/test_ospf_single_switch.py b/tests/topotests/ospf_single_switch/test_ospf_single_switch.py
index 65c918283f..e53b5f5b1e 100644
--- a/tests/topotests/ospf_single_switch/test_ospf_single_switch.py
+++ b/tests/topotests/ospf_single_switch/test_ospf_single_switch.py
@@ -97,14 +97,18 @@ def is_iproute2_json_supported():
Checks if the command 'ip -j route' is supported.
"""
try:
- output = subprocess.run(['ip', '-j', 'route', 'get', '0.0.0.0'], stdout=subprocess.PIPE).stdout.decode()
+ output = subprocess.run(
+ ["ip", "-j", "route", "get", "0.0.0.0"], stdout=subprocess.PIPE
+ ).stdout.decode()
json.loads(output)
return True
except json.decoder.JSONDecodeError:
return False
-@pytest.mark.skipif(not is_iproute2_json_supported(), reason="'ip -j route' not supported")
+@pytest.mark.skipif(
+ not is_iproute2_json_supported(), reason="'ip -j route' not supported"
+)
def test_all_routes_advertised():
tgen = get_topogen()
@@ -135,9 +139,13 @@ def test_all_routes_advertised():
]
}
}
- result = verify_ospf_rib(tgen, router_orig, input_dict, next_hop=network[1])
+ result = verify_ospf_rib(
+ tgen, router_orig, input_dict, next_hop=network[1]
+ )
assert result is True, "Error: {}".format(result)
- result = verify_rib(tgen, "ipv4", router_orig, input_dict, next_hop=network[1])
+ result = verify_rib(
+ tgen, "ipv4", router_orig, input_dict, next_hop=network[1]
+ )
assert result is True, "Error: {}".format(result)
check_route(router_orig, network[0], network[1])
@@ -181,7 +189,9 @@ def check_route(router_name, network, expected_nexthop):
output = router.cmd(f"ip -j route get {address}")
logger.info(output)
routes = json.loads(output)
- assert routes[0]["gateway"] == expected_nexthop, f"{router_name} (kernel): no route {address} via {expected_nexthop}"
+ assert (
+ routes[0]["gateway"] == expected_nexthop
+ ), f"{router_name} (kernel): no route {address} via {expected_nexthop}"
if __name__ == "__main__":
diff --git a/tests/topotests/ospfapi/test_ospf_clientapi.py b/tests/topotests/ospfapi/test_ospf_clientapi.py
index 49dd34d650..626a9d3185 100644
--- a/tests/topotests/ospfapi/test_ospf_clientapi.py
+++ b/tests/topotests/ospfapi/test_ospf_clientapi.py
@@ -277,9 +277,7 @@ def _test_add_data(tgen, apibin):
"linkStateId": "230.0.0.2",
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
- "opaqueValues": {
- "opaqueData": "00000202"
- }
+ "opaqueValues": {"opaqueData": "00000202"},
},
],
}
@@ -330,8 +328,8 @@ def _test_add_data(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "00010101",
- }
+ "opaqueData": "00010101",
+ },
},
],
}
@@ -381,8 +379,8 @@ def _test_add_data(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "deadbeaf01234567",
- }
+ "opaqueData": "deadbeaf01234567",
+ },
},
]
}
@@ -434,8 +432,8 @@ def _test_add_data(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000002",
"opaqueValues": {
- "opaqueData": "ebadf00d",
- }
+ "opaqueData": "ebadf00d",
+ },
},
]
}
@@ -1664,8 +1662,8 @@ def _test_opaque_link_local_lsa_crash(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "feedaceedeadbeef",
- }
+ "opaqueData": "feedaceedeadbeef",
+ },
},
],
}
@@ -1695,8 +1693,8 @@ def _test_opaque_link_local_lsa_crash(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "feedaceecafebeef",
- }
+ "opaqueData": "feedaceecafebeef",
+ },
},
],
}
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py
index 90548fb5ce..5a6c377aef 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py
@@ -410,7 +410,7 @@ def test_ospfv3_learning_tc15_p0(request):
step("Verify that Type 3 summary LSA is originated for the same Area 0")
ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
input_dict = {
"r1": {
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py
index 645dea8dec..916f655550 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py
@@ -262,7 +262,7 @@ def test_ospfv3_redistribution_tc5_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
llip = get_llip("r0", "r1")
assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip)
@@ -379,7 +379,7 @@ def test_ospfv3_redistribution_tc6_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
llip = get_llip("r0", "r1")
assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip)
nh = llip
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
index 7199f160fe..3bafd27f24 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
@@ -1124,7 +1124,7 @@ def test_ospfv3_show_p1(request):
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv6"].split("/")[0]
input_dict = {
"r1": {
diff --git a/tests/topotests/pim_basic/test_pim.py b/tests/topotests/pim_basic/test_pim.py
index 24987e516d..85b49aacc6 100644
--- a/tests/topotests/pim_basic/test_pim.py
+++ b/tests/topotests/pim_basic/test_pim.py
@@ -18,7 +18,7 @@ import pytest
import json
from functools import partial
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -29,9 +29,6 @@ from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-pytestmark = [pytest.mark.pimd]
-
-
def build_topo(tgen):
"Build function"
diff --git a/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py b/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py
index 71c90931fb..d03d5479fd 100644
--- a/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py
+++ b/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py
@@ -32,10 +32,7 @@ pytestmark = [
def tgen(request):
"Setup/Teardown the environment and provide tgen argument to tests"
- topodef = {
- "s1": ("r1", "r2"),
- "s2": ("r1", "r3")
- }
+ topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r3")}
tgen = Topogen(topodef, request.module.__name__)
tgen.start_topology()
@@ -68,16 +65,17 @@ def show_rip_json(router):
for route in routes:
match = re.match(
- r"(.)\((.)\)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)", route)
+ r"(.)\((.)\)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)", route
+ )
if match is None:
continue
route_entry = {
- "code": match[1],
- "subCode": match[2],
- "nextHop": match[4],
- "metric": int(match[5]),
- "from": match[6],
+ "code": match[1],
+ "subCode": match[2],
+ "nextHop": match[4],
+ "metric": int(match[5]),
+ "from": match[6],
}
if json.get(match[3]) is None:
@@ -95,12 +93,8 @@ def expect_routes(router, routes, time_amount):
"Internal test function."
return topotest.json_cmp(show_rip_json(router), routes)
- _, result = topotest.run_and_expect(test_function,
- None,
- count=time_amount,
- wait=1)
- assert result is None, "Unexpected routing table in {}".format(
- router.name)
+ _, result = topotest.run_and_expect(test_function, None, count=time_amount, wait=1)
+ assert result is None, "Unexpected routing table in {}".format(router.name)
def expect_bfd_peers(router, peers):
@@ -119,91 +113,87 @@ def test_rip_convergence(tgen):
"Test that RIP learns the neighbor routes."
expect_routes(
- tgen.gears["r1"], {
- "10.254.254.2/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2"
- }],
- "10.254.254.3/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.2"
- }],
- "10.254.254.100/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2",
- }, {
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.2",
- }]
- }, 40)
-
- expect_bfd_peers(tgen.gears["r1"], [{
- "peer": "192.168.0.2",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }, {
- "peer": "192.168.1.2",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }])
+ tgen.gears["r1"],
+ {
+ "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.0.2"}],
+ "10.254.254.3/32": [{"code": "R", "subCode": "n", "from": "192.168.1.2"}],
+ "10.254.254.100/32": [
+ {
+ "code": "R",
+ "subCode": "n",
+ "from": "192.168.0.2",
+ },
+ {
+ "code": "R",
+ "subCode": "n",
+ "from": "192.168.1.2",
+ },
+ ],
+ },
+ 40,
+ )
+
+ expect_bfd_peers(
+ tgen.gears["r1"],
+ [
+ {
+ "peer": "192.168.0.2",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ },
+ {
+ "peer": "192.168.1.2",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ },
+ ],
+ )
expect_routes(
- tgen.gears["r2"], {
- "10.254.254.1/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.1"
- }],
- "10.254.254.3/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.1"
- }],
- "10.254.254.100/32": [{
- "code": "S",
- "subCode": "r",
- "from": "self"
- }]
- }, 40)
-
- expect_bfd_peers(tgen.gears["r2"], [{
- "peer": "192.168.0.1",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }])
+ tgen.gears["r2"],
+ {
+ "10.254.254.1/32": [{"code": "R", "subCode": "n", "from": "192.168.0.1"}],
+ "10.254.254.3/32": [{"code": "R", "subCode": "n", "from": "192.168.0.1"}],
+ "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}],
+ },
+ 40,
+ )
+
+ expect_bfd_peers(
+ tgen.gears["r2"],
+ [
+ {
+ "peer": "192.168.0.1",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ }
+ ],
+ )
expect_routes(
- tgen.gears["r3"], {
- "10.254.254.1/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.1"
- }],
- "10.254.254.2/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.1"
- }],
- "10.254.254.100/32": [{
- "code": "S",
- "subCode": "r",
- "from": "self"
- }]
- }, 40)
-
- expect_bfd_peers(tgen.gears["r3"], [{
- "peer": "192.168.1.1",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }])
+ tgen.gears["r3"],
+ {
+ "10.254.254.1/32": [{"code": "R", "subCode": "n", "from": "192.168.1.1"}],
+ "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.1.1"}],
+ "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}],
+ },
+ 40,
+ )
+
+ expect_bfd_peers(
+ tgen.gears["r3"],
+ [
+ {
+ "peer": "192.168.1.1",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ }
+ ],
+ )
def test_rip_bfd_convergence(tgen):
@@ -212,30 +202,30 @@ def test_rip_bfd_convergence(tgen):
tgen.gears["r3"].link_enable("r3-eth0", False)
expect_routes(
- tgen.gears["r1"], {
- "10.254.254.2/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2"
- }],
+ tgen.gears["r1"],
+ {
+ "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.0.2"}],
"10.254.254.3/32": None,
- "10.254.254.100/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2",
- }]
- }, 6)
+ "10.254.254.100/32": [
+ {
+ "code": "R",
+ "subCode": "n",
+ "from": "192.168.0.2",
+ }
+ ],
+ },
+ 6,
+ )
expect_routes(
- tgen.gears["r3"], {
+ tgen.gears["r3"],
+ {
"10.254.254.1/32": None,
"10.254.254.2/32": None,
- "10.254.254.100/32": [{
- "code": "S",
- "subCode": "r",
- "from": "self"
- }]
- }, 6)
+ "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}],
+ },
+ 6,
+ )
def test_memory_leak(tgen):
diff --git a/tests/topotests/route_scale/scale_test_common.py b/tests/topotests/route_scale/scale_test_common.py
index 6227e81b98..b3cba1cb4e 100644
--- a/tests/topotests/route_scale/scale_test_common.py
+++ b/tests/topotests/route_scale/scale_test_common.py
@@ -151,7 +151,7 @@ def route_install_helper(iter):
logger.info(
"Limited memory available: {}, skipping x32 testcase".format(total_mem)
)
- return;
+ return
installed_file = "{}/r1/installed.routes.json".format(CWD)
expected_installed = json.loads(open(installed_file).read())
diff --git a/tests/topotests/route_scale/test_route_scale1.py b/tests/topotests/route_scale/test_route_scale1.py
index 0f25b28c74..ccbdd51595 100644
--- a/tests/topotests/route_scale/test_route_scale1.py
+++ b/tests/topotests/route_scale/test_route_scale1.py
@@ -30,35 +30,51 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module
+from scale_test_common import (
+ scale_build_common,
+ scale_setup_module,
+ route_install_helper,
+ scale_test_memory_leak,
+ scale_converge_protocols,
+ scale_teardown_module,
+)
pytestmark = [pytest.mark.sharpd]
+
def build(tgen):
scale_build_common(tgen)
+
def setup_module(module):
scale_setup_module(module)
+
def teardown_module(_mod):
scale_teardown_module(_mod)
+
def test_converge_protocols():
scale_converge_protocols()
+
def test_route_install_2nh():
route_install_helper(1)
+
def test_route_install_4nh():
route_install_helper(2)
+
def test_route_install_16nh():
route_install_helper(4)
+
def test_memory_leak():
scale_test_memory_leak()
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/route_scale/test_route_scale2.py b/tests/topotests/route_scale/test_route_scale2.py
index 3b55fcd8f5..e244d4fbbc 100644
--- a/tests/topotests/route_scale/test_route_scale2.py
+++ b/tests/topotests/route_scale/test_route_scale2.py
@@ -30,35 +30,51 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module
+from scale_test_common import (
+ scale_build_common,
+ scale_setup_module,
+ route_install_helper,
+ scale_test_memory_leak,
+ scale_converge_protocols,
+ scale_teardown_module,
+)
pytestmark = [pytest.mark.sharpd]
+
def build(tgen):
scale_build_common(tgen)
+
def setup_module(module):
scale_setup_module(module)
+
def teardown_module(_mod):
scale_teardown_module(_mod)
+
def test_converge_protocols():
scale_converge_protocols()
+
def test_route_install_1nh():
route_install_helper(0)
+
def test_route_install_8nh():
route_install_helper(3)
+
def test_route_install_32nh():
route_install_helper(5)
+
def test_memory_leak():
scale_test_memory_leak()
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py b/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py
index 4239193317..b8bcab8d93 100755
--- a/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py
+++ b/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py
@@ -63,16 +63,16 @@ def teardown_module(mod):
def test_zebra_srv6_encap_src_addr(tgen):
"Test SRv6 encapsulation source address."
- logger.info(
- "Test SRv6 encapsulation source address."
- )
+ logger.info("Test SRv6 encapsulation source address.")
r1 = tgen.gears["r1"]
# Generate expected results
json_file = "{}/r1/expected_srv6_encap_src_addr.json".format(CWD)
expected = json.loads(open(json_file).read())
- ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected)
+ ok = topotest.router_json_cmp_retry(
+ r1, "show segment-routing srv6 manager json", expected
+ )
assert ok, '"r1" JSON output mismatches'
output = r1.cmd("ip sr tunsrc show")
@@ -81,9 +81,7 @@ def test_zebra_srv6_encap_src_addr(tgen):
def test_zebra_srv6_encap_src_addr_unset(tgen):
"Test SRv6 encapsulation source address unset."
- logger.info(
- "Test SRv6 encapsulation source address unset."
- )
+ logger.info("Test SRv6 encapsulation source address unset.")
r1 = tgen.gears["r1"]
# Unset SRv6 encapsulation source address
@@ -101,7 +99,9 @@ def test_zebra_srv6_encap_src_addr_unset(tgen):
json_file = "{}/r1/expected_srv6_encap_src_addr_unset.json".format(CWD)
expected = json.loads(open(json_file).read())
- ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected)
+ ok = topotest.router_json_cmp_retry(
+ r1, "show segment-routing srv6 manager json", expected
+ )
assert ok, '"r1" JSON output mismatches'
output = r1.cmd("ip sr tunsrc show")
@@ -110,9 +110,7 @@ def test_zebra_srv6_encap_src_addr_unset(tgen):
def test_zebra_srv6_encap_src_addr_set(tgen):
"Test SRv6 encapsulation source address set."
- logger.info(
- "Test SRv6 encapsulation source address set."
- )
+ logger.info("Test SRv6 encapsulation source address set.")
r1 = tgen.gears["r1"]
# Set SRv6 encapsulation source address
@@ -130,7 +128,9 @@ def test_zebra_srv6_encap_src_addr_set(tgen):
json_file = "{}/r1/expected_srv6_encap_src_addr_set.json".format(CWD)
expected = json.loads(open(json_file).read())
- ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected)
+ ok = topotest.router_json_cmp_retry(
+ r1, "show segment-routing srv6 manager json", expected
+ )
assert ok, '"r1" JSON output mismatches'
output = r1.cmd("ip sr tunsrc show")
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
index 2efc0fdf1b..3e03055acd 100644
--- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
+++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
@@ -65,8 +65,6 @@ ADDR_TYPES = check_address_types()
NETWORK = {"ipv4": "2.2.2.2/32", "ipv6": "22:22::2/128"}
NEXT_HOP_IP = {}
-pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
-
def setup_module(mod):
"""
@@ -551,7 +549,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -571,7 +569,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
dut = "r2"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
@@ -914,7 +912,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -931,7 +929,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
dut = "r1"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -945,7 +943,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
dut = "r2"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -959,7 +957,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
protocol = "bgp"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
index 0378240959..0fc81aaf1e 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
@@ -547,7 +547,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -567,7 +567,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
dut = "r2"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
@@ -910,7 +910,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -927,7 +927,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
dut = "r1"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -941,7 +941,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
dut = "r2"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -955,7 +955,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
protocol = "bgp"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
diff --git a/tests/topotests/tc_basic/test_tc_basic.py b/tests/topotests/tc_basic/test_tc_basic.py
index f64e83c3cb..822d2016a8 100755
--- a/tests/topotests/tc_basic/test_tc_basic.py
+++ b/tests/topotests/tc_basic/test_tc_basic.py
@@ -22,9 +22,8 @@ sys.path.append(os.path.join(CWD, "../lib/"))
from lib.topogen import Topogen, TopoRouter
from lib.topolog import logger
-pytestmark = [
- pytest.mark.sharpd
-]
+pytestmark = [pytest.mark.sharpd]
+
def build_topo(tgen):
"Build function"
@@ -42,6 +41,7 @@ def build_topo(tgen):
switch = tgen.add_switch("s2")
switch.add_link(r2)
+
# New form of setup/teardown using pytest fixture
@pytest.fixture(scope="module")
def tgen(request):
@@ -79,22 +79,28 @@ def skip_on_failure(tgen):
if tgen.routers_have_failure():
pytest.skip("skipped because of previous test failure")
+
def fetch_iproute2_tc_info(r, interface):
qdisc = r.cmd("tc qdisc show dev %s" % interface)
tclass = r.cmd("tc class show dev %s" % interface)
tfilter = r.cmd("tc filter show dev %s" % interface)
return qdisc, tclass, tfilter
+
# ===================
# The tests functions
# ===================
+
def test_tc_basic(tgen):
"Test installing one pair of filter & class by sharpd"
r1 = tgen.gears["r1"]
intf = "r1-eth0"
- r1.vtysh_cmd("sharp tc dev %s source 192.168.100.0/24 destination 192.168.101.0/24 ip-protocol tcp src-port 8000 dst-port 8001 rate 20mbit" % intf)
+ r1.vtysh_cmd(
+ "sharp tc dev %s source 192.168.100.0/24 destination 192.168.101.0/24 ip-protocol tcp src-port 8000 dst-port 8001 rate 20mbit"
+ % intf
+ )
time.sleep(3)
@@ -115,6 +121,7 @@ def test_tc_basic(tgen):
assert "dst_port 8001" in tfilter
assert "src_port 8000" in tfilter
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
- sys.exit(pytest.main(args)) \ No newline at end of file
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/zebra_netlink/test_zebra_netlink.py b/tests/topotests/zebra_netlink/test_zebra_netlink.py
index 522c390c39..d970c04ee2 100644
--- a/tests/topotests/zebra_netlink/test_zebra_netlink.py
+++ b/tests/topotests/zebra_netlink/test_zebra_netlink.py
@@ -94,7 +94,7 @@ def test_zebra_netlink_batching(tgen):
}
match = {}
- base = int(ipaddress.ip_address(u"2.1.3.7"))
+ base = int(ipaddress.ip_address("2.1.3.7"))
for i in range(base, base + count):
pfx = str(ipaddress.ip_network((i, 32)))
match[pfx] = [dict(entry, prefix=pfx)]
diff --git a/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py b/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py
index 6956ab7409..fbef0fefc7 100644
--- a/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py
+++ b/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py
@@ -33,30 +33,36 @@ sys.path.append(os.path.join(CWD, "../"))
pytestmark = [pytest.mark.sharpd]
-#GLOBAL VARIABLES
+# GLOBAL VARIABLES
NH1 = "2.2.2.32"
+
def build_topo(tgen):
tgen.add_router("r1")
switch = tgen.add_switch("sw1")
switch.add_link(tgen.gears["r1"])
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
for rname, router in tgen.routers().items():
- router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
router.load_config(
TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
)
tgen.start_router()
+
def teardown_module(_mod):
tgen = get_topogen()
tgen.stop_topology()
+
def test_verify_zebra_nh_resolution(request):
tgen = get_topogen()
tc_name = request.node.name
@@ -67,31 +73,18 @@ def test_verify_zebra_nh_resolution(request):
step("Configure static route")
input_dict_1 = {
- "r1": {
- "static_routes": [
- {"network": "2.2.2.0/24", "next_hop": "r1-eth0"}
- ]
- }
- }
+ "r1": {"static_routes": [{"network": "2.2.2.0/24", "next_hop": "r1-eth0"}]}
+ }
result = create_static_routes(tgen, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
- )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify static routes in RIB of R1")
- input_dict_2 = {
- "r1": {
- "static_routes": [
- {"network": "2.2.2.0/24"}
- ]
- }
- }
+ input_dict_2 = {"r1": {"static_routes": [{"network": "2.2.2.0/24"}]}}
dut = "r1"
result = verify_rib(tgen, "ipv4", dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("Set the connected flag on the NH tracking entry")
r1.vtysh_cmd("sharp watch nexthop 2.2.2.32 connected")
@@ -108,8 +101,7 @@ def test_verify_zebra_nh_resolution(request):
}
result = verify_ip_nht(tgen, input_dict_nh)
assert result is True, "Testcase {} : Failed \n"
- "Error: Nexthop is missing in RIB".format(
- tc_name, result)
+ "Error: Nexthop is missing in RIB".format(tc_name, result)
step("Add a .32/32 route with the NH as itself")
r1.vtysh_cmd("sharp install routes 2.2.2.32 nexthop 2.2.2.32 1")
@@ -126,11 +118,12 @@ def test_verify_zebra_nh_resolution(request):
}
result = verify_ip_nht(tgen, input_dict_nh)
assert result is True, "Testcase {} : Failed \n"
- "Error: Nexthop became unresolved".format(
- tc_name, result)
+ "Error: Nexthop became unresolved".format(tc_name, result)
- step("Add a .31/32 route with the NH as 2.2.2.32"
- "to verify the NH Resolution behaviour")
+ step(
+ "Add a .31/32 route with the NH as 2.2.2.32"
+ "to verify the NH Resolution behaviour"
+ )
r1.vtysh_cmd("sharp install routes 2.2.2.31 nexthop 2.2.2.32 1")
step("Verify that NH 2.2.2.2/32 doesn't become unresolved")
@@ -145,8 +138,8 @@ def test_verify_zebra_nh_resolution(request):
}
result = verify_ip_nht(tgen, input_dict_nh)
assert result is True, "Testcase {} : Failed \n"
- "Error: Nexthop became unresolved".format(
- tc_name, result)
+ "Error: Nexthop became unresolved".format(tc_name, result)
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/tools/etc/iproute2/rt_protos.d/frr.conf b/tools/etc/iproute2/rt_protos.d/frr.conf
index bbb358fc6c..3e0fc2ea37 100644
--- a/tools/etc/iproute2/rt_protos.d/frr.conf
+++ b/tools/etc/iproute2/rt_protos.d/frr.conf
@@ -12,3 +12,4 @@
195 pbr
196 static
197 openfabric
+198 srte
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index ef92e8b59f..461f0e8c61 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -220,6 +220,23 @@ def get_normalized_mac_ip_line(line):
return line
+def get_normalized_interface_vrf(line):
+ """
+ If 'interface <int_name> vrf <vrf_name>' is present in file,
+ we need to remove the explicit "vrf <vrf_name>"
+ so that the context information is created
+ correctly and configurations are matched appropriately.
+ """
+
+ intf_vrf = re.search("interface (\S+) vrf (\S+)", line)
+ if intf_vrf:
+ old_line = "vrf %s" % intf_vrf.group(2)
+ new_line = line.replace(old_line, "").strip()
+ return new_line
+
+ return line
+
+
# This dictionary contains a tree of all commands that we know start a
# new multi-line context. All other commands are treated either as
# commands inside a multi-line context or as single-line contexts. This
@@ -295,6 +312,10 @@ class Config(object):
# Compress duplicate whitespaces
line = " ".join(line.split())
+ # Remove 'vrf <vrf_name>' from 'interface <x> vrf <vrf_name>'
+ if line.startswith("interface ") and "vrf" in line:
+ line = get_normalized_interface_vrf(line)
+
if ":" in line:
line = get_normalized_mac_ip_line(line)
@@ -1062,19 +1083,34 @@ def pim_delete_move_lines(lines_to_add, lines_to_del):
# Remove all such depdendent options from delete
# pending list.
pim_disable = False
+ lines_to_del_to_del = []
+ index = -1
for ctx_keys, line in lines_to_del:
+ index = index + 1
if ctx_keys[0].startswith("interface") and line and line == "ip pim":
pim_disable = True
+ # no ip msdp peer <> does not accept source so strip it off.
+ if line and line.startswith("ip msdp peer "):
+ pim_msdp_peer = re.search("ip msdp peer (\S+) source (\S+)", line)
+ if pim_msdp_peer:
+ source_sub_str = "source %s" % pim_msdp_peer.group(2)
+ new_line = line.replace(source_sub_str, "").strip()
+ lines_to_del.remove((ctx_keys, line))
+ lines_to_del.insert(index, (ctx_keys, new_line))
+
if pim_disable:
for ctx_keys, line in lines_to_del:
if (
ctx_keys[0].startswith("interface")
and line
- and line.startswith("ip pim ")
+ and (line.startswith("ip pim ") or line.startswith("ip multicast "))
):
- lines_to_del.remove((ctx_keys, line))
+ lines_to_del_to_del.append((ctx_keys, line))
+
+ for ctx_keys, line in lines_to_del_to_del:
+ lines_to_del.remove((ctx_keys, line))
return (lines_to_add, lines_to_del)
@@ -1439,6 +1475,35 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
lines_to_add.append((add_cmd, None))
lines_to_del_to_del.append((ctx_keys, None))
+ # bgp as-path access-list can be specified without a seq number.
+ # However, the running config always
+ # adds `seq X` (sequence number). So, ignore such lines as well.
+ # Examples:
+ # bgp as-path access-list important_internet_bgp_as_numbers seq 30 permit _40841_"
+ re_bgp_as_path = re.search(
+ "^(bgp )(as-path )(access-list )(\S+\s+)(seq \d+\s+)(permit|deny)(.*)$",
+ ctx_keys[0],
+ )
+ if re_bgp_as_path:
+ found = False
+ tmpline = (
+ re_bgp_as_path.group(1)
+ + re_bgp_as_path.group(2)
+ + re_bgp_as_path.group(3)
+ + re_bgp_as_path.group(4)
+ + re_bgp_as_path.group(6)
+ + re_bgp_as_path.group(7)
+ )
+ for ctx in lines_to_add:
+ if ctx[0][0] == tmpline:
+ lines_to_del_to_del.append((ctx_keys, None))
+ lines_to_add_to_del.append(((tmpline,), None))
+ found = True
+ if found is False:
+ add_cmd = ("no " + ctx_keys[0],)
+ lines_to_add.append((add_cmd, None))
+ lines_to_del_to_del.append((ctx_keys, None))
+
if (
len(ctx_keys) == 3
and ctx_keys[0].startswith("router bgp")
diff --git a/tools/indent.py b/tools/indent.py
index fe9eb7c252..dac7d3f04b 100755
--- a/tools/indent.py
+++ b/tools/indent.py
@@ -34,13 +34,13 @@ def wrap_file(fn):
ci = subprocess.Popen(
["clang-format"], stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
- stdout, ign = ci.communicate(text)
+ stdout, ign = ci.communicate(text.encode("utf-8"))
ci.wait()
if ci.returncode != 0:
raise IOError("clang-format returned %d" % (ci.returncode))
# remove the bits we inserted above
- final = clean_re.sub("", stdout)
+ final = clean_re.sub("", stdout.decode("utf-8"))
tmpname = fn + ".indent"
with open(tmpname, "w") as ofd:
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 5cab10c60d..1a358017dc 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -39,7 +39,6 @@
#include "frrstr.h"
#include "json.h"
#include "ferr.h"
-#include "bgpd/bgp_vty.h"
DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy");
@@ -3423,7 +3422,7 @@ static void show_route_map_send(const char *route_map, bool json)
bool first = true;
char command_line[128];
- snprintf(command_line, sizeof(command_line), "show route-map ");
+ snprintf(command_line, sizeof(command_line), "do show route-map ");
if (route_map)
strlcat(command_line, route_map, sizeof(command_line));
if (json)
@@ -3474,6 +3473,161 @@ DEFPY (show_route_map,
return CMD_SUCCESS;
}
+static void show_prefix_list_send(afi_t afi, const char *prefix_list,
+ const char *seq, enum display_type dtype,
+ bool json)
+{
+ unsigned int i;
+ bool first = true;
+ char command_line[128];
+
+ if (afi == AFI_IP)
+ snprintf(command_line, sizeof(command_line),
+ "do show ip prefix-list ");
+ else if (afi == AFI_IP6)
+ snprintf(command_line, sizeof(command_line),
+ "do show ipv6 prefix-list ");
+ if (dtype == detail_display)
+ strlcat(command_line, "detail ", sizeof(command_line));
+ else if (dtype == summary_display)
+ strlcat(command_line, "summary ", sizeof(command_line));
+ if (prefix_list)
+ strlcat(command_line, prefix_list, sizeof(command_line));
+ if (dtype == sequential_display) {
+ strlcat(command_line, " seq ", sizeof(command_line));
+ strlcat(command_line, seq, sizeof(command_line));
+ }
+ if (json)
+ strlcat(command_line, " json", sizeof(command_line));
+
+ if (json)
+ vty_out(vty, "{");
+
+ for (i = 0; i < array_size(vtysh_client); i++) {
+ const struct vtysh_client *client = &vtysh_client[i];
+ bool is_connected = true;
+
+ if (!CHECK_FLAG(client->flag, VTYSH_PREFIX_LIST_SHOW))
+ continue;
+
+ for (; client; client = client->next)
+ if (client->fd < 0)
+ is_connected = false;
+
+ if (!is_connected)
+ continue;
+
+ if (json && !first)
+ vty_out(vty, ",");
+ else
+ first = false;
+
+ if (json)
+ vty_out(vty, "\"%s\":", vtysh_client[i].name);
+
+ vtysh_client_execute_name(vtysh_client[i].name, command_line);
+ }
+
+ if (json)
+ vty_out(vty, "}\n");
+}
+
+DEFPY (show_ip_prefix_list,
+ show_ip_prefix_list_cmd,
+ "show ip prefix-list [PREFIXLIST4_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
+ SHOW_STR
+ IP_STR
+ PREFIX_LIST_STR
+ "Name of a prefix list\n"
+ "sequence number of an entry\n"
+ "Sequence number\n"
+ JSON_STR)
+{
+ enum display_type dtype = normal_display;
+
+ if (dseq)
+ dtype = sequential_display;
+
+ show_prefix_list_send(AFI_IP, name, arg_str, dtype, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ip_prefix_list_summary,
+ show_ip_prefix_list_summary_cmd,
+ "show ip prefix-list summary [PREFIXLIST4_NAME$name] [json$uj]",
+ SHOW_STR
+ IP_STR
+ PREFIX_LIST_STR
+ "Summary of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP, name, NULL, summary_display, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ip_prefix_list_detail,
+ show_ip_prefix_list_detail_cmd,
+ "show ip prefix-list detail [PREFIXLIST4_NAME$name] [json$uj]",
+ SHOW_STR
+ IP_STR
+ PREFIX_LIST_STR
+ "Detail of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP, name, NULL, detail_display, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_prefix_list,
+ show_ipv6_prefix_list_cmd,
+ "show ipv6 prefix-list [PREFIXLIST6_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ PREFIX_LIST_STR
+ "Name of a prefix list\n"
+ "sequence number of an entry\n"
+ "Sequence number\n"
+ JSON_STR)
+{
+ enum display_type dtype = normal_display;
+
+ if (dseq)
+ dtype = sequential_display;
+
+ show_prefix_list_send(AFI_IP6, name, arg_str, dtype, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_prefix_list_summary,
+ show_ipv6_prefix_list_summary_cmd,
+ "show ipv6 prefix-list summary [PREFIXLIST6_NAME$name] [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ PREFIX_LIST_STR
+ "Summary of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP6, name, NULL, summary_display, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_prefix_list_detail,
+ show_ipv6_prefix_list_detail_cmd,
+ "show ipv6 prefix-list detail [PREFIXLIST6_NAME$name] [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ PREFIX_LIST_STR
+ "Detail of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP6, name, NULL, detail_display, !!uj);
+ return CMD_SUCCESS;
+}
+
DEFUN (vtysh_integrated_config,
vtysh_integrated_config_cmd,
"service integrated-vtysh-config",
@@ -3498,8 +3652,8 @@ DEFUN (no_vtysh_integrated_config,
static void backup_config_file(const char *fbackup)
{
char *integrate_sav = NULL;
-
size_t integrate_sav_sz = strlen(fbackup) + strlen(CONF_BACKUP_EXT) + 1;
+
integrate_sav = malloc(integrate_sav_sz);
strlcpy(integrate_sav, fbackup, integrate_sav_sz);
strlcat(integrate_sav, CONF_BACKUP_EXT, integrate_sav_sz);
@@ -4999,11 +5153,13 @@ void vtysh_init_vty(void)
install_element(VRF_NODE, &vtysh_exit_vrf_cmd);
install_element(VRF_NODE, &vtysh_quit_vrf_cmd);
+#ifdef HAVE_BGPD
install_node(&rpki_vrf_node);
install_element(VRF_NODE, &rpki_cmd);
install_element(RPKI_VRF_NODE, &rpki_exit_cmd);
install_element(RPKI_VRF_NODE, &rpki_quit_cmd);
install_element(RPKI_VRF_NODE, &vtysh_end_all_cmd);
+#endif
install_element(CONFIG_NODE, &vtysh_affinity_map_cmd);
install_element(CONFIG_NODE, &vtysh_no_affinity_map_cmd);
@@ -5072,6 +5228,12 @@ void vtysh_init_vty(void)
install_element(ENABLE_NODE, &vtysh_copy_to_running_cmd);
install_element(ENABLE_NODE, &show_route_map_cmd);
+ install_element(ENABLE_NODE, &show_ip_prefix_list_cmd);
+ install_element(ENABLE_NODE, &show_ip_prefix_list_summary_cmd);
+ install_element(ENABLE_NODE, &show_ip_prefix_list_detail_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_prefix_list_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_prefix_list_summary_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_prefix_list_detail_cmd);
/* "write terminal" command. */
install_element(ENABLE_NODE, &vtysh_write_terminal_cmd);
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index b35d56672a..131fbef8ba 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -68,6 +68,10 @@ extern struct event_loop *master;
VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
VTYSH_BGPD | VTYSH_ISISD | VTYSH_PIMD | VTYSH_EIGRPD | \
VTYSH_FABRICD
+#define VTYSH_PREFIX_LIST_SHOW \
+ VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
+ VTYSH_BGPD | VTYSH_ISISD | VTYSH_PIMD | VTYSH_EIGRPD | \
+ VTYSH_FABRICD
#define VTYSH_INTERFACE_SUBSET \
VTYSH_OSPFD | VTYSH_OSPF6D | \
VTYSH_ISISD | VTYSH_PIMD | VTYSH_PIM6D | VTYSH_NHRPD | \
@@ -90,7 +94,17 @@ enum vtysh_write_integrated {
WRITE_INTEGRATED_YES
};
+enum display_type {
+ normal_display,
+ summary_display,
+ detail_display,
+ sequential_display,
+ longer_display,
+ first_match_display
+};
+
extern enum vtysh_write_integrated vtysh_write_integrated;
+extern enum display_type display_type;
extern char frr_config[];
extern char vtydir[];
diff --git a/yang/confd/confd.frr-ripd.yang b/yang/confd/confd.frr-ripd.yang
deleted file mode 100644
index 7bbe54cca9..0000000000
--- a/yang/confd/confd.frr-ripd.yang
+++ /dev/null
@@ -1,24 +0,0 @@
-module confd.frr-ripd {
- namespace "urn:dummy";
- prefix "dummy";
-
- import tailf-common {
- prefix tailf;
- }
- import frr-ripd {
- prefix frr-ripd;
- }
-
- tailf:annotate-module "frr-ripd" {
- tailf:annotate-statement "container[name='ripd']" {
- tailf:annotate-statement "list[name='instance']" {
- tailf:annotate-statement "container[name='state']" {
- tailf:callpoint "state";
- }
- }
- }
- tailf:annotate-statement "rpc[name='clear-rip-route']" {
- tailf:actionpoint "actionpoint";
- }
- }
-}
diff --git a/yang/confd/confd.frr-ripngd.yang b/yang/confd/confd.frr-ripngd.yang
deleted file mode 100644
index 83383fb454..0000000000
--- a/yang/confd/confd.frr-ripngd.yang
+++ /dev/null
@@ -1,24 +0,0 @@
-module confd.frr-ripngd {
- namespace "urn:dummy";
- prefix "dummy";
-
- import tailf-common {
- prefix tailf;
- }
- import frr-ripngd {
- prefix frr-ripngd;
- }
-
- tailf:annotate-module "frr-ripngd" {
- tailf:annotate-statement "container[name='ripngd']" {
- tailf:annotate-statement "list[name='instance']" {
- tailf:annotate-statement "container[name='state']" {
- tailf:callpoint "state";
- }
- }
- }
- tailf:annotate-statement "rpc[name='clear-ripng-route']" {
- tailf:actionpoint "actionpoint";
- }
- }
-}
diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang
index c679f3b911..b0858e153c 100644
--- a/yang/frr-bgp-route-map.yang
+++ b/yang/frr-bgp-route-map.yang
@@ -881,9 +881,7 @@ identity set-extcommunity-color {
leaf bandwidth {
when "../lb-type = 'explicit-bandwidth'";
mandatory true;
- type uint16 {
- range "1..25600";
- }
+ type uint32;
description
"Bandwidth value in Mbps";
}
diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang
index f1a69068c3..79c524a40a 100644
--- a/yang/frr-zebra.yang
+++ b/yang/frr-zebra.yang
@@ -151,6 +151,12 @@ module frr-zebra {
"Zebra interface type macvlan.";
}
+ identity zif-gre {
+ base zebra-interface-type;
+ description
+ "Zebra interface type gre.";
+ }
+
/*
* Multicast RPF mode configurable type
*/
diff --git a/yang/subdir.am b/yang/subdir.am
index 6745d53712..71aa040878 100644
--- a/yang/subdir.am
+++ b/yang/subdir.am
@@ -106,31 +106,4 @@ endif
CLEANFILES += \
yang/*.c \
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/interface.c b/zebra/interface.c
index 8111863558..b824977f9e 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -176,6 +176,10 @@ static void if_nhg_dependents_release(const struct interface *ifp)
frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
rb_node_dep->nhe->ifp = NULL; /* Null it out */
zebra_nhg_check_valid(rb_node_dep->nhe);
+ if (CHECK_FLAG(rb_node_dep->nhe->flags,
+ NEXTHOP_GROUP_KEEP_AROUND) &&
+ rb_node_dep->nhe->refcnt == 1)
+ zebra_nhg_decrement_ref(rb_node_dep->nhe);
}
}
@@ -1741,6 +1745,9 @@ interface_bridge_vxlan_vlan_vni_map_update(struct zebra_dplane_ctx *ctx,
vlanid_t vid;
int i;
+ if (vniarray == NULL)
+ return;
+
memset(&vni_start, 0, sizeof(vni_start));
memset(&vni_end, 0, sizeof(vni_end));
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f092fc5c85..4a15b74004 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1550,7 +1550,7 @@ static ssize_t fill_seg6ipt_encap(char *buffer, size_t buflen,
srh->first_segment = segs->num_segs - 1;
for (i = 0; i < segs->num_segs; i++) {
- memcpy(&srh->segments[i], &segs->seg[i],
+ memcpy(&srh->segments[segs->num_segs - i - 1], &segs->seg[i],
sizeof(struct in6_addr));
}
@@ -1683,6 +1683,16 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
sizeof(struct in_addr)))
return false;
break;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
+ if (!nl_attr_put32(nlmsg, req_size,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DX6))
+ return false;
+ if (!nl_attr_put(nlmsg, req_size,
+ SEG6_LOCAL_NH6, &ctx->nh6,
+ sizeof(struct in_addr)))
+ return false;
+ break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
if (!nl_attr_put32(nlmsg, req_size,
SEG6_LOCAL_ACTION,
@@ -1714,7 +1724,6 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
return false;
break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
- case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
@@ -2931,6 +2940,18 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
sizeof(struct in_addr)))
return 0;
break;
+ case SEG6_LOCAL_ACTION_END_DX6:
+ if (!nl_attr_put32(&req->n,
+ buflen,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DX6))
+ return 0;
+ if (!nl_attr_put(&req->n, buflen,
+ SEG6_LOCAL_NH6,
+ &ctx->nh6,
+ sizeof(struct in_addr)))
+ return 0;
+ break;
case SEG6_LOCAL_ACTION_END_DT6:
if (!nl_attr_put32(
&req->n, buflen,
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 6aca643bd8..470391de9b 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -184,13 +184,13 @@ static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
static void rtadv_send_packet(int sock, struct interface *ifp,
enum ipv6_nd_suppress_ra_status stop)
{
- struct msghdr msg;
- struct iovec iov;
+ struct msghdr msg = { 0 };
+ struct iovec iov = { 0 };
struct cmsghdr *cmsgptr;
struct in6_pktinfo *pkt;
- struct sockaddr_in6 addr;
- unsigned char buf[RTADV_MSG_SIZE];
- char adata[RTADV_ADATA_SIZE];
+ struct sockaddr_in6 addr = { 0 };
+ unsigned char buf[RTADV_MSG_SIZE] = { 0 };
+ char adata[RTADV_ADATA_SIZE] = { 0 };
struct nd_router_advert *rtadv;
int ret;
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 76cabd1bf0..d585ef996b 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1724,7 +1724,7 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
* Let's convert the weights to a scaled value
* between 1 and zrouter.nexthop_weight_scale_value
* This is a simple application of a ratio:
- * scaled_weight/zrouter.nexthop_weight_scale_value =
+ * scaled_weight/zrouter.nexthop_weight_scale_value =
* weight/max_weight
* This translates to:
* scaled_weight = weight * zrouter.nexthop_weight_scale_value
@@ -1738,9 +1738,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
for (i = 0; i < nexthop_num; i++) {
znh = &nhops[i];
- tmp = (uint64_t)znh->weight *
- zrouter.nexthop_weight_scale_value;
- znh->weight = MAX(1, ((uint32_t)(tmp / max_weight)));
+ tmp = znh->weight * zrouter.nexthop_weight_scale_value;
+ znh->weight = MAX(1, (tmp / max_weight));
}
}
diff --git a/zebra/zebra_cli.c b/zebra/zebra_cli.c
index 00e0a49cb8..3e03d74775 100644
--- a/zebra/zebra_cli.c
+++ b/zebra/zebra_cli.c
@@ -241,7 +241,7 @@ DEFUN_YANG_NOSH (link_params,
return ret;
}
-DEFUN_NOSH (exit_link_params,
+DEFUN_YANG_NOSH (exit_link_params,
exit_link_params_cmd,
"exit-link-params",
"Exit from Link Params configuration mode\n")
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 006ab504ef..06b34da209 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -39,6 +39,13 @@ DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes");
# define AOK 0
#endif
+/*
+ * Dataplane API version. This must be updated when any incompatible changes
+ * are made. The minor version (at least) should be updated when new APIs
+ * are introduced.
+ */
+static uint32_t zdplane_version = MAKE_FRRVERSION(2, 0, 0);
+
/* Control for collection of extra interface info with route updates; a plugin
* can enable the extra info via a dplane api.
*/
@@ -664,6 +671,12 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
* Public APIs
*/
+/* Access the dplane API version */
+uint32_t zebra_dplane_get_version(void)
+{
+ return zdplane_version;
+}
+
/* Obtain thread_master for dataplane thread */
struct event_loop *dplane_get_thread_master(void)
{
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 2f7d218508..060b1c8b9e 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -24,6 +24,13 @@
extern "C" {
#endif
+/* Retrieve the dataplane API version number; see libfrr.h to decode major,
+ * minor, sub version values.
+ * Plugins should pay attention to the major version number, at least, to
+ * be able to detect API changes that may not be backward-compatible.
+ */
+uint32_t zebra_dplane_get_version(void);
+
/* Key netlink info from zebra ns */
struct zebra_dplane_info {
ns_id_t ns_id;
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index ae9b3c49eb..ebb5a42298 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -351,7 +351,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, cmd, vrf_id);
stream_put(s, p, sizeof(struct prefix));
@@ -1140,7 +1140,7 @@ int zebra_evpn_send_add_to_client(struct zebra_evpn *zevpn)
svi_index = zevpn->svi_if ? zevpn->svi_if->ifindex : 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id());
stream_putl(s, zevpn->vni);
@@ -1192,7 +1192,7 @@ int zebra_evpn_send_del_to_client(struct zebra_evpn *zevpn)
zebra_evpn_update_all_es(zevpn);
}
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
stream_reset(s);
zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id());
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 753354df61..bfc060db61 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -933,7 +933,7 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, cmd, zebra_vrf_get_evpn_id());
stream_putl(s, vni);
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 35d5027fb8..0d9d912f83 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -1935,7 +1935,7 @@ static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es)
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, ZEBRA_LOCAL_ES_ADD, zebra_vrf_get_evpn_id());
stream_put(s, &es->esi, sizeof(esi_t));
@@ -1971,7 +1971,7 @@ static int zebra_evpn_es_send_del_to_client(struct zebra_evpn_es *es)
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
stream_reset(s);
zclient_create_header(s, ZEBRA_LOCAL_ES_DEL, zebra_vrf_get_evpn_id());
@@ -2639,7 +2639,7 @@ static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s,
add ? ZEBRA_LOCAL_ES_EVI_ADD : ZEBRA_LOCAL_ES_EVI_DEL,
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 90695261eb..4cc85d461f 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -2291,7 +2291,7 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
new_client = true;
} else {
/* Check if the FEC has been statically defined in the config */
- is_configured_fec = fec->flags & FEC_FLAG_CONFIGURED;
+ is_configured_fec = CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED);
/* Client may register same FEC with different label index. */
new_client =
(listnode_lookup(fec->client_list, client) == NULL);
@@ -2382,8 +2382,8 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
/* If not a configured entry, delete the FEC if no other clients. Before
* deleting, see if any LSP needs to be uninstalled.
*/
- if (!(fec->flags & FEC_FLAG_CONFIGURED)
- && list_isempty(fec->client_list)) {
+ if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED) &&
+ list_isempty(fec->client_list)) {
mpls_label_t old_label = fec->label;
fec->label = MPLS_INVALID_LABEL; /* reset */
fec_change_update_lsp(zvrf, fec, old_label);
@@ -2476,7 +2476,7 @@ static int zebra_mpls_cleanup_zclient_labels(struct zserv *client)
* hash..
*/
struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
- mpls_label_t label)
+ struct prefix *p, mpls_label_t label)
{
struct route_node *rn;
struct zebra_fec *fec;
@@ -2491,8 +2491,11 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
if (!rn->info)
continue;
fec = rn->info;
- if (fec->label == label)
+ if (fec->label == label) {
+ if (p && prefix_same(p, &rn->p))
+ return NULL;
return fec;
+ }
}
}
@@ -2502,9 +2505,10 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
/*
* Inform if specified label is currently bound to a FEC or not.
*/
-int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label)
+int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p,
+ mpls_label_t label)
{
- return (zebra_mpls_fec_for_label(zvrf, label) ? 1 : 0);
+ return (zebra_mpls_fec_for_label(zvrf, p, label) ? 1 : 0);
}
/*
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index 1ed2f9b41c..dd6f960146 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -203,12 +203,13 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
* hash..
*/
struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
- mpls_label_t label);
+ struct prefix *p, mpls_label_t label);
/*
* Inform if specified label is currently bound to a FEC or not.
*/
-int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label);
+int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p,
+ mpls_label_t label);
/*
* Add static FEC to label binding. If there are clients registered for this
diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c
index fd09e6b444..8248d4a555 100644
--- a/zebra/zebra_mpls_vty.c
+++ b/zebra/zebra_mpls_vty.c
@@ -210,7 +210,7 @@ static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix,
vty_out(vty, "%% Invalid label\n");
return CMD_WARNING_CONFIG_FAILED;
}
- if (zebra_mpls_label_already_bound(zvrf, label)) {
+ if (zebra_mpls_label_already_bound(zvrf, &p, label)) {
vty_out(vty,
"%% Label already bound to a FEC\n");
return CMD_WARNING_CONFIG_FAILED;
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index 04eac63d3e..ae6232a1bb 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -3187,6 +3187,7 @@ int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create(
strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"),
sizeof(dnssl.name));
ret = rtadv_dnssl_encode(dnssl.encoded_name, dnssl.name);
+ dnssl.encoded_len = ret;
if (args->event == NB_EV_VALIDATE) {
if (ret < 0) {
diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c
index 46492f023a..63ac7877d0 100644
--- a/zebra/zebra_nb_state.c
+++ b/zebra/zebra_nb_state.c
@@ -55,6 +55,10 @@ lib_interface_zebra_state_zif_type_get_elem(struct nb_cb_get_elem_args *args)
zebra_if = ifp->info;
+ /*
+ * NOTE: when adding a new type to the switch, make sure it is defined
+ * in it's YANG model.
+ */
switch (zebra_if->zif_type) {
case ZEBRA_IF_OTHER:
type = "frr-zebra:zif-other";
diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c
index 941088afd6..a222e7f6e8 100644
--- a/zebra/zebra_neigh.c
+++ b/zebra/zebra_neigh.c
@@ -83,7 +83,7 @@ zebra_neigh_new(ifindex_t ifindex, struct ipaddr *ip, struct ethaddr *mac)
n->ifindex = ifindex;
if (mac) {
memcpy(&n->mac, mac, sizeof(*mac));
- n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
}
/* Add to rb_tree */
@@ -118,10 +118,8 @@ static void zebra_neigh_free(struct zebra_neigh_ent *n)
/* if rules are still using the neigh mark it as inactive and
* update the dataplane
*/
- if (n->flags & ZEBRA_NEIGH_ENT_ACTIVE) {
- n->flags &= ~ZEBRA_NEIGH_ENT_ACTIVE;
- memset(&n->mac, 0, sizeof(n->mac));
- }
+ UNSET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
+ memset(&n->mac, 0, sizeof(n->mac));
zebra_neigh_pbr_rules_update(n);
return;
}
@@ -181,7 +179,7 @@ void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip,
return;
memcpy(&n->mac, mac, sizeof(*mac));
- n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
/* update rules linked to the neigh */
zebra_neigh_pbr_rules_update(n);
@@ -201,7 +199,7 @@ void zebra_neigh_deref(struct zebra_pbr_rule *rule)
rule->action.neigh = NULL;
/* remove rule from the list and free if it is inactive */
list_delete_node(n->pbr_rule_list, &rule->action.neigh_listnode);
- if (!(n->flags & ZEBRA_NEIGH_ENT_ACTIVE))
+ if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE))
zebra_neigh_free(n);
}
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 1af3a3e857..4cee3b89f1 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -42,7 +42,7 @@
#define NETLINK_SOCKET_BUFFER_SIZE 512
#define NETLINK_ALIGNTO 4
#define NETLINK_ALIGN(len) \
- (((len) + NETLINK_ALIGNTO - 1) & ~(NETLINK_ALIGNTO - 1))
+ CHECK_FLAG(((len) + NETLINK_ALIGNTO - 1), ~(NETLINK_ALIGNTO - 1))
#define NETLINK_NLATTR_LEN(_a, _b) (unsigned int)((char *)_a - (char *)_b)
#endif /* defined(HAVE_NETLINK) */
@@ -66,7 +66,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type)
nlh->nlmsg_type = type;
nlh->nlmsg_flags = NLM_F_REQUEST;
if (type == RTM_NEWNSID)
- nlh->nlmsg_flags |= NLM_F_ACK;
+ SET_FLAG(nlh->nlmsg_flags, NLM_F_ACK);
nlh->nlmsg_seq = *seq = frr_sequence32_next();
return nlh;
}
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 1bb1292e34..617a2225f8 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -304,7 +304,7 @@ static void zebra_ns_notify_read(struct event *t)
char *netnspath;
struct zebra_netns_info *netnsinfo;
- if (!(event->mask & (IN_CREATE | IN_DELETE)))
+ if (!CHECK_FLAG(event->mask, (IN_CREATE | IN_DELETE)))
continue;
if (offsetof(struct inotify_event, name) + event->len
@@ -350,7 +350,7 @@ static void zebra_ns_notify_read(struct event *t)
memcpy(event_name, event->name, event->len);
event_name[event->len - 1] = 0;
- if (event->mask & IN_DELETE) {
+ if (CHECK_FLAG(event->mask, IN_DELETE)) {
zebra_ns_delete(event_name);
continue;
}
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index 934b8ba0db..1246e4dba2 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1795,8 +1795,8 @@ static struct nexthop *nexthop_set_resolved(afi_t afi,
break;
}
- if (newhop->flags & NEXTHOP_FLAG_ONLINK)
- resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
+ if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_ONLINK))
+ SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ONLINK);
/* Copy labels of the resolved route and the parent resolving to it */
if (policy) {
@@ -3664,8 +3664,9 @@ void zebra_interface_nhg_reinstall(struct interface *ifp)
"%s: Setting the valid flag for nhe %pNG, interface: %s",
__func__, rb_node_dep->nhe, ifp->name);
}
+
/* Check for singleton NHG associated to interface */
- if (nexthop_is_ifindex_type(nh) &&
+ if (!nexthop_is_blackhole(nh) &&
zebra_nhg_depends_is_empty(rb_node_dep->nhe)) {
struct nhg_connected *rb_node_dependent;
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index da6e2069ff..0b5362094e 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -60,18 +60,19 @@ struct route_show_ctx {
};
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, bool use_json,
- route_tag_t tag,
+ safi_t safi, bool use_fib, json_object *vrf_json,
+ bool use_json, route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
bool show_ng, struct route_show_ctx *ctx);
static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
int mcast, bool use_fib, bool show_ng);
-static void vty_show_ip_route_summary(struct vty *vty,
- struct route_table *table, bool use_json);
+static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table,
+ json_object *vrf_json, bool use_json);
static void vty_show_ip_route_summary_prefix(struct vty *vty,
struct route_table *table,
+ json_object *vrf_json,
bool use_json);
/* Helper api to format a nexthop in the 'detailed' output path. */
static void show_nexthop_detail_helper(struct vty *vty,
@@ -148,8 +149,8 @@ DEFPY (show_ip_rpf,
};
return do_show_ip_route(vty, VRF_DEFAULT_NAME, ip ? AFI_IP : AFI_IP6,
- SAFI_MULTICAST, false, uj, 0, NULL, false, 0, 0,
- 0, false, &ctx);
+ SAFI_MULTICAST, false, NULL, uj, 0, NULL, false,
+ 0, 0, 0, false, &ctx);
}
DEFPY (show_ip_rpf_addr,
@@ -856,14 +857,13 @@ static void vty_show_ip_route_detail_json(struct vty *vty,
vty_json(vty, json);
}
-static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
- struct route_table *table, afi_t afi,
- bool use_fib, route_tag_t tag,
- const struct prefix *longer_prefix_p,
- bool supernets_only, int type,
- unsigned short ospf_instance_id, bool use_json,
- uint32_t tableid, bool show_ng,
- struct route_show_ctx *ctx)
+static void
+do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
+ struct route_table *table, afi_t afi, bool use_fib,
+ json_object *vrf_json, route_tag_t tag,
+ const struct prefix *longer_prefix_p, bool supernets_only,
+ int type, unsigned short ospf_instance_id, bool use_json,
+ uint32_t tableid, bool show_ng, struct route_show_ctx *ctx)
{
struct route_node *rn;
struct route_entry *re;
@@ -885,7 +885,7 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
* => display the VRF and table if specific
*/
- if (use_json)
+ if (use_json && !vrf_json)
json = json_object_new_object();
/* Show all routes. */
@@ -960,7 +960,11 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
if (json_prefix) {
prefix2str(&rn->p, buf, sizeof(buf));
- json_object_object_add(json, buf, json_prefix);
+ if (!vrf_json)
+ json_object_object_add(json, buf, json_prefix);
+ else
+ json_object_object_add(vrf_json, buf,
+ json_prefix);
json_prefix = NULL;
}
}
@@ -969,13 +973,15 @@ static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
* This is an extremely expensive operation at scale
* and non-pretty reduces memory footprint significantly.
*/
- if (use_json)
+ if (use_json && !vrf_json) {
vty_json_no_pretty(vty, json);
+ json = NULL;
+ }
}
static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
- afi_t afi, bool use_fib, bool use_json,
- route_tag_t tag,
+ afi_t afi, bool use_fib, json_object *vrf_json,
+ bool use_json, route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, bool show_ng,
@@ -995,15 +1001,15 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
continue;
do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
- use_fib, use_json, tag, longer_prefix_p,
- supernets_only, type, ospf_instance_id,
- zrt->tableid, show_ng, ctx);
+ use_fib, vrf_json, use_json, tag,
+ longer_prefix_p, supernets_only, type,
+ ospf_instance_id, zrt->tableid, show_ng, ctx);
}
}
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, bool use_json,
- route_tag_t tag,
+ safi_t safi, bool use_fib, json_object *vrf_json,
+ bool use_json, route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
@@ -1038,7 +1044,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
return CMD_SUCCESS;
}
- do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
+ do_show_route_helper(vty, zvrf, table, afi, use_fib, vrf_json, tag,
longer_prefix_p, supernets_only, type,
ospf_instance_id, use_json, tableid, show_ng, ctx);
@@ -1741,6 +1747,7 @@ DEFPY (show_route,
struct route_show_ctx ctx = {
.multi = vrf_all || table_all,
};
+ json_object *root_json = NULL;
if (!vrf_is_backend_netns()) {
if ((vrf_all || vrf_name) && (table || table_all)) {
@@ -1762,24 +1769,42 @@ DEFPY (show_route,
}
if (vrf_all) {
+ if (!!json)
+ root_json = json_object_new_object();
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+ json_object *vrf_json = NULL;
+
if ((zvrf = vrf->info) == NULL
|| (zvrf->table[afi][SAFI_UNICAST] == NULL))
continue;
+ if (!!json)
+ vrf_json = json_object_new_object();
+
if (table_all)
- do_show_ip_route_all(
- vty, zvrf, afi, !!fib, !!json, tag,
- prefix_str ? prefix : NULL,
- !!supernets_only, type,
- ospf_instance_id, !!ng, &ctx);
+ do_show_ip_route_all(vty, zvrf, afi, !!fib,
+ vrf_json, !!json, tag,
+ prefix_str ? prefix : NULL,
+ !!supernets_only, type,
+ ospf_instance_id, !!ng,
+ &ctx);
else
- do_show_ip_route(
- vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
- !!fib, !!json, tag,
- prefix_str ? prefix : NULL,
- !!supernets_only, type,
- ospf_instance_id, table, !!ng, &ctx);
+ do_show_ip_route(vty, zvrf_name(zvrf), afi,
+ SAFI_UNICAST, !!fib, vrf_json,
+ !!json, tag,
+ prefix_str ? prefix : NULL,
+ !!supernets_only, type,
+ ospf_instance_id, table, !!ng,
+ &ctx);
+
+ if (!!json)
+ json_object_object_add(root_json,
+ zvrf_name(zvrf),
+ vrf_json);
+ }
+ if (!!json) {
+ vty_json_no_pretty(vty, root_json);
+ root_json = NULL;
}
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -1795,13 +1820,13 @@ DEFPY (show_route,
return CMD_SUCCESS;
if (table_all)
- do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
- prefix_str ? prefix : NULL,
+ do_show_ip_route_all(vty, zvrf, afi, !!fib, NULL, !!json,
+ tag, prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, !!ng, &ctx);
else
do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
- !!fib, !!json, tag,
+ !!fib, NULL, !!json, tag,
prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, table, !!ng, &ctx);
@@ -1973,11 +1998,15 @@ DEFPY (show_route_summary,
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
struct route_table *table;
bool uj = use_json(argc, argv);
+ json_object *vrf_json = NULL;
if (vrf_all) {
struct vrf *vrf;
struct zebra_vrf *zvrf;
+ if (uj && !vrf_json)
+ vrf_json = json_object_new_object();
+
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if ((zvrf = vrf->info) == NULL)
continue;
@@ -1995,10 +2024,14 @@ DEFPY (show_route_summary,
if (prefix)
vty_show_ip_route_summary_prefix(vty, table,
- uj);
+ vrf_json, uj);
else
- vty_show_ip_route_summary(vty, table, uj);
+ vty_show_ip_route_summary(vty, table, vrf_json,
+ uj);
}
+
+ if (uj)
+ vty_json(vty, vrf_json);
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -2014,9 +2047,9 @@ DEFPY (show_route_summary,
return CMD_SUCCESS;
if (prefix)
- vty_show_ip_route_summary_prefix(vty, table, uj);
+ vty_show_ip_route_summary_prefix(vty, table, NULL, uj);
else
- vty_show_ip_route_summary(vty, table, uj);
+ vty_show_ip_route_summary(vty, table, NULL, uj);
}
return CMD_SUCCESS;
@@ -2222,8 +2255,8 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
}
}
-static void vty_show_ip_route_summary(struct vty *vty,
- struct route_table *table, bool use_json)
+static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table,
+ json_object *vrf_json, bool use_json)
{
struct route_node *rn;
struct route_entry *re;
@@ -2237,6 +2270,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
uint32_t is_ibgp;
json_object *json_route_summary = NULL;
json_object *json_route_routes = NULL;
+ const char *vrf_name = zvrf_name(
+ ((struct rib_table_info *)route_table_get_info(table))->zvrf);
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
@@ -2287,10 +2322,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
- "Routes", "FIB",
- zvrf_name(((struct rib_table_info *)
- route_table_get_info(table))
- ->zvrf));
+ "Routes", "FIB", vrf_name);
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
@@ -2382,7 +2414,11 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(json_route_summary, "routesTotalFib",
fib_cnt[ZEBRA_ROUTE_TOTAL]);
- vty_json(vty, json_route_summary);
+ if (!vrf_json)
+ vty_json(vty, json_route_summary);
+ else
+ json_object_object_add(vrf_json, vrf_name,
+ json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
@@ -2400,6 +2436,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
*/
static void vty_show_ip_route_summary_prefix(struct vty *vty,
struct route_table *table,
+ json_object *vrf_json,
bool use_json)
{
struct route_node *rn;
@@ -2413,6 +2450,8 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
int cnt;
json_object *json_route_summary = NULL;
json_object *json_route_routes = NULL;
+ const char *vrf_name = zvrf_name(
+ ((struct rib_table_info *)route_table_get_info(table))->zvrf);
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
@@ -2452,10 +2491,7 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
- "Prefix Routes", "FIB",
- zvrf_name(((struct rib_table_info *)
- route_table_get_info(table))
- ->zvrf));
+ "Prefix Routes", "FIB", vrf_name);
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (rib_cnt[i] > 0) {
@@ -2530,7 +2566,11 @@ 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_json(vty, json_route_summary);
+ if (!vrf_json)
+ vty_json(vty, json_route_summary);
+ else
+ json_object_object_add(vrf_json, vrf_name,
+ json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
diff --git a/zebra/zserv.c b/zebra/zserv.c
index e2681289b1..27668534ee 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -1125,12 +1125,10 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
vty_out(vty, "ES-EVI %-12u%-12u%-12u\n",
client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt);
vty_out(vty, "Errors: %u\n", client->error_cnt);
-
-#if defined DEV_BUILD
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
client->obuf_fifo->count, client->obuf_fifo->max_count);
-#endif
+
vty_out(vty, "\n");
}