summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am8
-rw-r--r--babeld/babeld.c3
-rw-r--r--babeld/message.c15
-rw-r--r--babeld/route.c13
-rw-r--r--bfdd/bfd.c10
-rw-r--r--bfdd/bfdd_cli.c20
-rw-r--r--bfdd/bfdd_nb_config.c89
-rw-r--r--bfdd/bfdd_vty.c2
-rw-r--r--bfdd/ptm_adapter.c3
-rw-r--r--bgpd/bgp_attr.c30
-rw-r--r--bgpd/bgp_damp.c14
-rw-r--r--bgpd/bgp_damp.h4
-rw-r--r--bgpd/bgp_evpn.c77
-rw-r--r--bgpd/bgp_evpn_mh.c194
-rw-r--r--bgpd/bgp_evpn_mh.h8
-rw-r--r--bgpd/bgp_evpn_vty.c9
-rw-r--r--bgpd/bgp_fsm.c16
-rw-r--r--bgpd/bgp_fsm.h8
-rw-r--r--bgpd/bgp_io.c61
-rw-r--r--bgpd/bgp_label.c16
-rw-r--r--bgpd/bgp_mpath.c35
-rw-r--r--bgpd/bgp_nb_config.c11
-rw-r--r--bgpd/bgp_network.c22
-rw-r--r--bgpd/bgp_open.c36
-rw-r--r--bgpd/bgp_open.h2
-rw-r--r--bgpd/bgp_packet.c42
-rw-r--r--bgpd/bgp_packet.h4
-rw-r--r--bgpd/bgp_route.c142
-rw-r--r--bgpd/bgp_route.h2
-rw-r--r--bgpd/bgp_routemap.c39
-rw-r--r--bgpd/bgp_rpki.c1
-rw-r--r--bgpd/bgp_table.c10
-rw-r--r--bgpd/bgp_updgrp.c16
-rw-r--r--bgpd/bgp_updgrp_packet.c43
-rw-r--r--bgpd/bgp_vty.c124
-rw-r--r--bgpd/bgp_zebra.c45
-rw-r--r--bgpd/bgpd.c17
-rw-r--r--bgpd/bgpd.h11
-rwxr-xr-xconfigure.ac14
-rw-r--r--debian/control1
-rw-r--r--doc/developer/building-frr-for-archlinux.rst2
-rw-r--r--doc/developer/building-frr-for-centos6.rst3
-rw-r--r--doc/developer/building-frr-for-centos7.rst3
-rw-r--r--doc/developer/building-frr-for-centos8.rst3
-rw-r--r--doc/developer/building-frr-for-debian8.rst2
-rw-r--r--doc/developer/building-frr-for-debian9.rst2
-rw-r--r--doc/developer/building-frr-for-fedora.rst3
-rw-r--r--doc/developer/building-frr-for-opensuse.rst3
-rw-r--r--doc/developer/building-frr-for-ubuntu1404.rst2
-rw-r--r--doc/developer/building-frr-for-ubuntu1604.rst3
-rw-r--r--doc/developer/building-frr-for-ubuntu1804.rst3
-rw-r--r--doc/developer/building-frr-for-ubuntu2004.rst4
-rw-r--r--doc/developer/logging.rst4
-rw-r--r--doc/developer/tracing.rst266
-rw-r--r--doc/developer/workflow.rst32
-rw-r--r--doc/developer/xrefs.rst49
-rw-r--r--doc/user/babeld.rst48
-rw-r--r--doc/user/basic.rst78
-rw-r--r--doc/user/bfd.rst99
-rw-r--r--doc/user/bgp.rst508
-rw-r--r--doc/user/bmp.rst25
-rw-r--r--doc/user/bugs.rst4
-rw-r--r--doc/user/conf.py2
-rw-r--r--doc/user/eigrpd.rst83
-rw-r--r--doc/user/fabricd.rst162
-rw-r--r--doc/user/filter.rst29
-rw-r--r--doc/user/flowspec.rst16
-rw-r--r--doc/user/installation.rst45
-rw-r--r--doc/user/ipv6.rst62
-rw-r--r--doc/user/isisd.rst365
-rw-r--r--doc/user/ldpd.rst48
-rw-r--r--doc/user/nhrpd.rst15
-rw-r--r--doc/user/ospf6d.rst58
-rw-r--r--doc/user/ospf_fundamentals.rst34
-rw-r--r--doc/user/ospfd.rst345
-rw-r--r--doc/user/overview.rst35
-rw-r--r--doc/user/pathd.rst74
-rw-r--r--doc/user/pbr.rst11
-rw-r--r--doc/user/pim.rst140
-rw-r--r--doc/user/ripd.rst158
-rw-r--r--doc/user/ripngd.rst16
-rw-r--r--doc/user/routemap.rst57
-rw-r--r--doc/user/routeserver.rst6
-rw-r--r--doc/user/rpki.rst18
-rw-r--r--doc/user/sharp.rst16
-rw-r--r--doc/user/snmp.rst3
-rw-r--r--doc/user/static.rst2
-rw-r--r--doc/user/vnc.rst60
-rw-r--r--doc/user/vrrp.rst31
-rw-r--r--doc/user/vtysh.rst9
-rw-r--r--doc/user/watchfrr.rst4
-rw-r--r--doc/user/wecmp_linkbw.rst1
-rw-r--r--doc/user/zebra.rst134
-rw-r--r--eigrpd/eigrp_packet.c12
-rw-r--r--eigrpd/eigrp_zebra.c4
-rw-r--r--isisd/isis_adjacency.c17
-rw-r--r--isisd/isis_adjacency.h2
-rw-r--r--isisd/isis_circuit.c74
-rw-r--r--isisd/isis_circuit.h9
-rw-r--r--isisd/isis_cli.c137
-rw-r--r--isisd/isis_dr.c1
-rw-r--r--isisd/isis_dynhn.c35
-rw-r--r--isisd/isis_dynhn.h3
-rw-r--r--isisd/isis_lfa.c23
-rw-r--r--isisd/isis_lsp.c20
-rw-r--r--isisd/isis_lsp.h4
-rw-r--r--isisd/isis_misc.c77
-rw-r--r--isisd/isis_nb.c23
-rw-r--r--isisd/isis_nb.h99
-rw-r--r--isisd/isis_nb_config.c75
-rw-r--r--isisd/isis_nb_notifications.c136
-rw-r--r--isisd/isis_pdu.c180
-rw-r--r--isisd/isis_redist.c5
-rw-r--r--isisd/isis_redist.h3
-rw-r--r--isisd/isis_routemap.c33
-rw-r--r--isisd/isis_snmp.c3457
-rw-r--r--isisd/isis_spf.c16
-rw-r--r--isisd/isis_sr.c16
-rw-r--r--isisd/isis_vty_fabricd.c2
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--isisd/isisd.c13
-rw-r--r--isisd/isisd.h18
-rw-r--r--isisd/subdir.am10
-rw-r--r--ldpd/lde.c12
-rw-r--r--ldpd/ldp_snmp.c1087
-rw-r--r--ldpd/ldpd.c29
-rw-r--r--ldpd/ldpd.h9
-rw-r--r--ldpd/ldpe.c20
-rw-r--r--ldpd/ldpe.h5
-rw-r--r--ldpd/neighbor.c31
-rw-r--r--ldpd/subdir.am9
-rw-r--r--lib/agentx.c23
-rw-r--r--lib/clippy.c6
-rw-r--r--lib/clippy.h2
-rw-r--r--lib/command_graph.h2
-rw-r--r--lib/command_py.c2
-rw-r--r--lib/elf_py.c1301
-rw-r--r--lib/nexthop.c10
-rw-r--r--lib/northbound.c70
-rw-r--r--lib/northbound.h13
-rw-r--r--lib/northbound_cli.c2
-rw-r--r--lib/prefix.c58
-rw-r--r--lib/prefix.h2
-rw-r--r--lib/ringbuf.c35
-rw-r--r--lib/ringbuf.h11
-rw-r--r--lib/routing_nb.h7
-rw-r--r--lib/routing_nb_config.c61
-rw-r--r--lib/smux.h8
-rw-r--r--lib/sockunion.c59
-rw-r--r--lib/srcdest_table.c9
-rw-r--r--lib/subdir.am30
-rw-r--r--lib/thread.c214
-rw-r--r--lib/thread.h20
-rw-r--r--lib/vrf.c7
-rw-r--r--lib/vrf.h3
-rw-r--r--lib/vty.c34
-rw-r--r--lib/zclient.c15
-rw-r--r--lib/zclient.h6
-rw-r--r--lib/zlog.h27
-rw-r--r--nhrpd/netlink_arp.c18
-rw-r--r--nhrpd/nhrp_cache.c35
-rw-r--r--nhrpd/nhrp_event.c4
-rw-r--r--nhrpd/nhrp_interface.c6
-rw-r--r--nhrpd/nhrp_nhs.c22
-rw-r--r--nhrpd/nhrp_peer.c58
-rw-r--r--nhrpd/nhrp_route.c6
-rw-r--r--nhrpd/nhrp_shortcut.c25
-rw-r--r--nhrpd/nhrp_vc.c7
-rw-r--r--ospf6d/ospf6_abr.c6
-rw-r--r--ospf6d/ospf6_area.c53
-rw-r--r--ospf6d/ospf6_asbr.c30
-rw-r--r--ospf6d/ospf6_asbr.h1
-rw-r--r--ospf6d/ospf6_interface.c3
-rw-r--r--ospf6d/ospf6_intra.c54
-rw-r--r--ospf6d/ospf6_lsa.c21
-rw-r--r--ospf6d/ospf6_message.c75
-rw-r--r--ospf6d/ospf6_proto.c9
-rw-r--r--ospf6d/ospf6_proto.h2
-rw-r--r--ospf6d/ospf6_spf.c53
-rw-r--r--ospf6d/ospf6_spf.h4
-rw-r--r--ospf6d/ospf6_zebra.c10
-rw-r--r--ospfd/ospf_dump.c70
-rw-r--r--ospfd/ospf_ext.c3
-rw-r--r--ospfd/ospf_flood.c18
-rw-r--r--ospfd/ospf_main.c20
-rw-r--r--ospfd/ospf_packet.c59
-rw-r--r--ospfd/ospf_spf.c45
-rw-r--r--ospfd/ospf_sr.c26
-rw-r--r--ospfd/ospf_vty.c220
-rw-r--r--ospfd/ospf_zebra.c2
-rw-r--r--ospfd/ospfd.c26
-rw-r--r--ospfd/ospfd.h3
-rw-r--r--pimd/pim_cmd.c4
-rw-r--r--pimd/pim_igmp_mtrace.c83
-rw-r--r--pimd/pim_main.c2
-rw-r--r--pimd/pim_msdp_socket.c8
-rw-r--r--pimd/pim_nb_config.c29
-rw-r--r--python/clippy/__init__.py2
-rw-r--r--python/clippy/elf.py574
-rw-r--r--python/clippy/uidhash.py71
-rw-r--r--python/makefile.py12
-rw-r--r--python/runtests.py14
-rw-r--r--python/test_xrelfo.py65
-rw-r--r--python/tiabwarfo.py203
-rw-r--r--python/xrefstructs.json140
-rw-r--r--python/xrelfo.py424
-rw-r--r--ripd/ripd.c21
-rw-r--r--ripngd/ripngd.c7
-rw-r--r--sharpd/sharp_zebra.c17
-rw-r--r--staticd/static_main.c2
-rw-r--r--staticd/static_nb_config.c36
-rw-r--r--staticd/static_vty.c5
-rw-r--r--tests/bgpd/test_aspath.c5
-rw-r--r--tests/bgpd/test_capability.c2
-rw-r--r--tests/bgpd/test_mp_attr.c2
-rw-r--r--tests/isisd/test_isis_spf.refout86
-rw-r--r--tests/topotests/all-protocol-startup/test_all_protocol_startup.py25
-rw-r--r--tests/topotests/bfd-bgp-cbit-topo3/test_bfd_bgp_cbit_topo3.py4
-rw-r--r--tests/topotests/bfd-isis-topo1/test_bfd_isis_topo1.py5
-rwxr-xr-xtests/topotests/bfd-ospf-topo1/test_bfd_ospf_topo1.py2
-rw-r--r--tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py5
-rw-r--r--tests/topotests/bfd-topo1/test_bfd_topo1.py4
-rw-r--r--tests/topotests/bfd-topo2/test_bfd_topo2.py4
-rw-r--r--tests/topotests/bfd-topo3/test_bfd_topo3.py2
-rw-r--r--tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py4
-rw-r--r--tests/topotests/bgp-aggregator-zero/__init__.py0
-rw-r--r--tests/topotests/bgp-aggregator-zero/exabgp.env53
-rw-r--r--tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg18
-rw-r--r--tests/topotests/bgp-aggregator-zero/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp-aggregator-zero/r1/zebra.conf6
-rw-r--r--tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py141
-rw-r--r--tests/topotests/bgp-auth/test_bgp_auth.py2
-rw-r--r--tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py3
-rw-r--r--tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py5
-rw-r--r--tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py5
-rw-r--r--tests/topotests/bgp-evpn-mh/test_evpn_mh.py29
-rwxr-xr-xtests/topotests/bgp-evpn-vxlan_topo1/test_bgp_evpn_vxlan.py2
-rwxr-xr-xtests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py26
-rw-r--r--tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py2
-rw-r--r--tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py2
-rw-r--r--tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py3
-rw-r--r--tests/topotests/bgp_as_wide_bgp_identifier/test_bgp_as_wide_bgp_identifier.py2
-rw-r--r--tests/topotests/bgp_blackhole_community/test_bgp_blackhole_community.py2
-rw-r--r--tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py2
-rw-r--r--tests/topotests/bgp_communities_topo1/test_bgp_communities.py3
-rw-r--r--tests/topotests/bgp_communities_topo1/test_bgp_communities_topo2.py3
-rw-r--r--tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py2
-rw-r--r--tests/topotests/bgp_features/peer1/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_features/peer2/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_features/peer3/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_features/peer4/exa_readpipe.py2
-rw-r--r--tests/topotests/bgp_features/test_bgp_features.py2
-rw-r--r--tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py115
-rw-r--r--tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py146
-rwxr-xr-xtests/topotests/bgp_l3vpn_to_bgp_direct/test_bgp_l3vpn_to_bgp_direct.py2
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py25
-rwxr-xr-xtests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py2
-rw-r--r--tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py15
-rwxr-xr-xtests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py2
-rw-r--r--tests/topotests/bgp_lu_topo1/test_bgp_lu.py34
-rw-r--r--tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py15
-rw-r--r--tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py10
-rw-r--r--tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py72
-rwxr-xr-xtests/topotests/bgp_rfapi_basic_sanity/test_bgp_rfapi_basic_sanity.py2
-rw-r--r--tests/topotests/bgp_rr_ibgp/spine1/staticd.conf1
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor1/staticd.conf1
-rw-r--r--tests/topotests/bgp_rr_ibgp/tor2/staticd.conf1
-rw-r--r--tests/topotests/bgp_suppress_fib/r3/v4_route.json1
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py24
-rw-r--r--tests/topotests/eigrp-topo1/test_eigrp_topo1.py4
-rw-r--r--tests/topotests/evpn-pim-1/test_evpn_pim_topo1.py2
-rw-r--r--tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py8
-rw-r--r--tests/topotests/example-test/test_template.py2
-rwxr-xr-xtests/topotests/example-topojson-test/test_topo_json_multiple_links/test_example_topojson_multiple_links.py2
-rwxr-xr-xtests/topotests/example-topojson-test/test_topo_json_single_link/test_example_topojson.py2
-rwxr-xr-xtests/topotests/example-topojson-test/test_topo_json_single_link_loopback/test_example_topojson.py2
-rwxr-xr-xtests/topotests/isis-lfa-topo1/test_isis_lfa_topo1.py4
-rw-r--r--tests/topotests/isis-lsp-bits-topo1/rt5/step1/show_ip_route.ref2
-rw-r--r--tests/topotests/isis-lsp-bits-topo1/rt6/step1/show_ip_route.ref1
-rw-r--r--tests/topotests/isis-lsp-bits-topo1/rt6/step2/show_ip_route.ref1
-rw-r--r--tests/topotests/isis-lsp-bits-topo1/rt6/step3/show_ip_route.ref1
-rw-r--r--tests/topotests/isis-lsp-bits-topo1/rt6/step4/show_ip_route.ref1
-rwxr-xr-xtests/topotests/isis-lsp-bits-topo1/test_isis_lsp_bits_topo1.py135
-rwxr-xr-xtests/topotests/isis-rlfa-topo1/test_isis_rlfa_topo1.py4
-rw-r--r--tests/topotests/isis-snmp/ce3/zebra.conf12
-rw-r--r--tests/topotests/isis-snmp/r1/isisd.conf24
-rw-r--r--tests/topotests/isis-snmp/r1/ldpd.conf26
-rw-r--r--tests/topotests/isis-snmp/r1/show_ip_route.ref143
-rw-r--r--tests/topotests/isis-snmp/r1/show_yang_interface_isis_adjacencies.ref40
-rw-r--r--tests/topotests/isis-snmp/r1/snmpd.conf15
-rw-r--r--tests/topotests/isis-snmp/r1/zebra.conf24
-rw-r--r--tests/topotests/isis-snmp/r2/isisd.conf25
-rw-r--r--tests/topotests/isis-snmp/r2/ldpd.conf25
-rw-r--r--tests/topotests/isis-snmp/r2/show_ip_route.ref143
-rw-r--r--tests/topotests/isis-snmp/r2/show_yang_interface_isis_adjacencies.ref40
-rw-r--r--tests/topotests/isis-snmp/r2/snmpd.conf15
-rw-r--r--tests/topotests/isis-snmp/r2/zebra.conf24
-rw-r--r--tests/topotests/isis-snmp/r3/isisd.conf25
-rw-r--r--tests/topotests/isis-snmp/r3/ldpd.conf25
-rw-r--r--tests/topotests/isis-snmp/r3/show_ip_route.ref143
-rw-r--r--tests/topotests/isis-snmp/r3/show_yang_interface_isis_adjacencies.ref40
-rw-r--r--tests/topotests/isis-snmp/r3/snmpd.conf15
-rw-r--r--tests/topotests/isis-snmp/r3/zebra.conf28
-rw-r--r--tests/topotests/isis-snmp/r4/isisd.conf24
-rw-r--r--tests/topotests/isis-snmp/r4/ldpd.conf25
-rw-r--r--tests/topotests/isis-snmp/r4/show_ip_route.ref143
-rw-r--r--tests/topotests/isis-snmp/r4/show_yang_interface_isis_adjacencies.ref40
-rw-r--r--tests/topotests/isis-snmp/r4/snmpd.conf15
-rw-r--r--tests/topotests/isis-snmp/r4/zebra.conf24
-rw-r--r--tests/topotests/isis-snmp/r5/isisd.conf25
-rw-r--r--tests/topotests/isis-snmp/r5/ldpd.conf25
-rw-r--r--tests/topotests/isis-snmp/r5/ldpdconf25
-rw-r--r--tests/topotests/isis-snmp/r5/show_ip_route.ref143
-rw-r--r--tests/topotests/isis-snmp/r5/show_yang_interface_isis_adjacencies.ref40
-rw-r--r--tests/topotests/isis-snmp/r5/snmpd.conf15
-rw-r--r--tests/topotests/isis-snmp/r5/zebra.conf24
-rw-r--r--tests/topotests/isis-snmp/test_isis_snmp.dot114
-rwxr-xr-xtests/topotests/isis-snmp/test_isis_snmp.py369
-rwxr-xr-xtests/topotests/isis-sr-te-topo1/test_isis_sr_te_topo1.py467
-rw-r--r--tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py4
-rwxr-xr-xtests/topotests/isis-tilfa-topo1/test_isis_tilfa_topo1.py4
-rw-r--r--tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py49
-rw-r--r--tests/topotests/isis-topo1/test_isis_topo1.py54
-rw-r--r--tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py2
-rw-r--r--tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py2
-rw-r--r--tests/topotests/ldp-snmp/ce1/zebra.conf12
-rw-r--r--tests/topotests/ldp-snmp/ce2/zebra.conf12
-rw-r--r--tests/topotests/ldp-snmp/ce3/zebra.conf12
-rw-r--r--tests/topotests/ldp-snmp/r1/isisd.conf27
-rw-r--r--tests/topotests/ldp-snmp/r1/ldpd.conf35
-rw-r--r--tests/topotests/ldp-snmp/r1/show_ip_route.ref134
-rw-r--r--tests/topotests/ldp-snmp/r1/show_isis_interface_detail.ref16
-rw-r--r--tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r1_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r2_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r1/show_isis_ldp_sync.ref13
-rw-r--r--tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r1_eth1_shutdown.ref11
-rw-r--r--tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r2_eth1_shutdown.ref13
-rw-r--r--tests/topotests/ldp-snmp/r1/show_l2vpn_binding.ref16
-rw-r--r--tests/topotests/ldp-snmp/r1/show_l2vpn_vc.ref8
-rw-r--r--tests/topotests/ldp-snmp/r1/show_ldp_binding.ref44
-rw-r--r--tests/topotests/ldp-snmp/r1/show_ldp_discovery.ref25
-rw-r--r--tests/topotests/ldp-snmp/r1/show_ldp_igp_sync.ref16
-rw-r--r--tests/topotests/ldp-snmp/r1/show_ldp_igp_sync_r1_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r1/show_ldp_neighbor.ref16
-rw-r--r--tests/topotests/ldp-snmp/r1/show_yang_interface_isis_adjacencies.ref42
-rw-r--r--tests/topotests/ldp-snmp/r1/snmpd.conf15
-rw-r--r--tests/topotests/ldp-snmp/r1/zebra.conf29
-rw-r--r--tests/topotests/ldp-snmp/r2/isisd.conf28
-rw-r--r--tests/topotests/ldp-snmp/r2/ldpd.conf35
-rw-r--r--tests/topotests/ldp-snmp/r2/ospfd.conf (renamed from tests/topotests/ldp-sync-isis-topo1/r2/ospfd.conf)0
-rw-r--r--tests/topotests/ldp-snmp/r2/show_ip_route.ref134
-rw-r--r--tests/topotests/ldp-snmp/r2/show_isis_interface_detail.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r1_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r2_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_isis_ldp_sync.ref13
-rw-r--r--tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r1_eth1_shutdown.ref13
-rw-r--r--tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r2_eth1_shutdown.ref11
-rw-r--r--tests/topotests/ldp-snmp/r2/show_l2vpn_binding.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_l2vpn_vc.ref8
-rw-r--r--tests/topotests/ldp-snmp/r2/show_ldp_binding.ref44
-rw-r--r--tests/topotests/ldp-snmp/r2/show_ldp_discovery.ref25
-rw-r--r--tests/topotests/ldp-snmp/r2/show_ldp_igp_sync.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r1_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r2_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_ldp_neighbor.ref16
-rw-r--r--tests/topotests/ldp-snmp/r2/show_yang_interface_isis_adjacencies.ref42
-rw-r--r--tests/topotests/ldp-snmp/r2/snmpd.conf15
-rw-r--r--tests/topotests/ldp-snmp/r2/zebra.conf28
-rw-r--r--tests/topotests/ldp-snmp/r3/isisd.conf29
-rw-r--r--tests/topotests/ldp-snmp/r3/ldpd.conf27
-rw-r--r--tests/topotests/ldp-snmp/r3/show_ip_route.ref134
-rw-r--r--tests/topotests/ldp-snmp/r3/show_isis_interface_detail.ref16
-rw-r--r--tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r1_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r2_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r3/show_isis_ldp_sync.ref13
-rw-r--r--tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref13
-rw-r--r--tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref13
-rw-r--r--tests/topotests/ldp-snmp/r3/show_l2vpn_binding.ref2
-rw-r--r--tests/topotests/ldp-snmp/r3/show_l2vpn_vc.ref2
-rw-r--r--tests/topotests/ldp-snmp/r3/show_ldp_binding.ref44
-rw-r--r--tests/topotests/ldp-snmp/r3/show_ldp_discovery.ref18
-rw-r--r--tests/topotests/ldp-snmp/r3/show_ldp_igp_sync.ref16
-rw-r--r--tests/topotests/ldp-snmp/r3/show_ldp_igp_sync_r1_eth1_shutdown.ref16
-rw-r--r--tests/topotests/ldp-snmp/r3/show_ldp_neighbor.ref16
-rw-r--r--tests/topotests/ldp-snmp/r3/show_yang_interface_isis_adjacencies.ref42
-rw-r--r--tests/topotests/ldp-snmp/r3/zebra.conf32
-rw-r--r--tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py373
-rw-r--r--tests/topotests/ldp-sync-ospf-topo1/test_ldp_sync_ospf_topo1.py2
-rw-r--r--tests/topotests/ldp-topo1/test_ldp_topo1.py4
-rw-r--r--tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py5
-rw-r--r--tests/topotests/lib/bgp.py46
-rw-r--r--tests/topotests/lib/common_config.py20
-rw-r--r--tests/topotests/lib/lutil.py32
-rw-r--r--tests/topotests/lib/ospf.py4
-rw-r--r--tests/topotests/lib/pim.py106
-rw-r--r--tests/topotests/lib/snmptest.py13
-rw-r--r--tests/topotests/lib/topogen.py2
-rw-r--r--tests/topotests/lib/topotest.py10
-rw-r--r--tests/topotests/multicast-pim-bsm-topo1/test_mcast_pim_bsmp_01.py70
-rw-r--r--tests/topotests/multicast-pim-bsm-topo2/test_mcast_pim_bsmp_02.py13
-rwxr-xr-xtests/topotests/multicast-pim-sm-topo1/test_multicast_pim_sm_topo1.py2
-rwxr-xr-xtests/topotests/multicast-pim-sm-topo2/test_multicast_pim_sm_topo2.py16
-rwxr-xr-xtests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo3.py230
-rwxr-xr-xtests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py58
-rwxr-xr-xtests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py440
-rw-r--r--[-rwxr-xr-x]tests/topotests/ospf-sr-topo1/__init__.py0
-rw-r--r--tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json161
-rw-r--r--tests/topotests/ospf-sr-topo1/r1/ospfd.conf27
-rw-r--r--tests/topotests/ospf-sr-topo1/r1/zebra.conf12
-rw-r--r--tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json115
-rw-r--r--tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json183
-rw-r--r--tests/topotests/ospf-sr-topo1/r2/ospfd.conf36
-rw-r--r--tests/topotests/ospf-sr-topo1/r2/zebra.conf18
-rw-r--r--tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json179
-rw-r--r--tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json130
-rw-r--r--tests/topotests/ospf-sr-topo1/r3/ospfd.conf22
-rw-r--r--tests/topotests/ospf-sr-topo1/r3/zebra.conf9
-rw-r--r--tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json130
-rw-r--r--tests/topotests/ospf-sr-topo1/r4/ospfd.conf23
-rw-r--r--tests/topotests/ospf-sr-topo1/r4/zebra.conf9
-rw-r--r--tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json97
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/ospfd.conf29
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step1/show_ip_route.ref289
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step1/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step10/show_ip_route.ref282
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step10/show_mpls_table.ref79
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step2/show_ip_route.ref282
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step2/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step3/show_ip_route.ref249
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step3/show_mpls_table.ref50
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step4/show_ip_route.ref282
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step4/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step5/show_ip_route.ref276
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step5/show_mpls_table.ref50
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step6/show_ip_route.ref282
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step6/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step7/show_ip_route.ref282
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step7/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step8/show_ip_route.ref282
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step8/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step9/show_ip_route.ref282
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/step9/show_mpls_table.ref79
-rw-r--r--tests/topotests/ospf-sr-topo1/rt1/zebra.conf18
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/ospfd.conf35
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step1/show_ip_route.ref330
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step1/show_mpls_table.ref97
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step10/show_ip_route.ref254
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step10/show_mpls_table.ref73
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step2/show_ip_route.ref303
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step2/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step3/show_ip_route.ref256
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step3/show_mpls_table.ref67
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step4/show_ip_route.ref303
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step4/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step5/show_ip_route.ref297
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step5/show_mpls_table.ref67
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step6/show_ip_route.ref303
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step6/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step7/show_ip_route.ref300
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step7/show_mpls_table.ref73
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step8/show_ip_route.ref303
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step8/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step9/show_ip_route.ref303
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/step9/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt2/zebra.conf24
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/ospfd.conf35
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step1/show_ip_route.ref330
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step1/show_mpls_table.ref97
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step10/show_ip_route.ref310
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step10/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step2/show_ip_route.ref310
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step2/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step3/show_ip_route.ref263
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step3/show_mpls_table.ref67
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step4/show_ip_route.ref310
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step4/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step5/show_ip_route.ref304
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step5/show_mpls_table.ref67
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step6/show_ip_route.ref310
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step6/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step7/show_ip_route.ref307
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step7/show_mpls_table.ref73
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step8/show_ip_route.ref310
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step8/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step9/show_ip_route.ref310
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/step9/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt3/zebra.conf24
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/ospfd.conf38
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step1/show_ip_route.ref311
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step1/show_mpls_table.ref97
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step10/show_ip_route.ref278
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step10/show_mpls_table.ref (renamed from tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json)65
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step2/show_ip_route.ref324
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step2/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step3/show_ip_route.ref296
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step3/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step4/show_ip_route.ref324
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step4/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step5/show_ip_route.ref318
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step5/show_mpls_table.ref67
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step6/show_ip_route.ref324
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step6/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step7/show_ip_route.ref318
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step7/show_mpls_table.ref73
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step8/show_ip_route.ref324
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step8/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step9/show_ip_route.ref324
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/step9/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt4/zebra.conf27
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/ospfd.conf38
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step1/show_ip_route.ref311
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step1/show_mpls_table.ref97
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step10/show_ip_route.ref300
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step10/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step2/show_ip_route.ref307
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step2/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step3/show_ip_route.ref272
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step3/show_mpls_table.ref85
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step4/show_ip_route.ref307
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step4/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step5/show_ip_route.ref286
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step5/show_mpls_table.ref67
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step6/show_ip_route.ref307
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step6/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step7/show_ip_route.ref286
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step7/show_mpls_table.ref73
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step8/show_ip_route.ref307
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step8/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step9/show_ip_route.ref292
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/step9/show_mpls_table.ref91
-rw-r--r--tests/topotests/ospf-sr-topo1/rt5/zebra.conf27
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/ospfd.conf32
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step1/show_ip_route.ref291
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step1/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step10/show_ip_route.ref284
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step10/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step2/show_ip_route.ref284
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step2/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step3/show_ip_route.ref2
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step3/show_mpls_table.ref2
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step4/show_ip_route.ref284
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step4/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step5/show_ip_route.ref266
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step5/show_mpls_table.ref2
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step6/show_ip_route.ref284
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step6/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step7/show_ip_route.ref278
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step7/show_mpls_table.ref50
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step8/show_ip_route.ref284
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step8/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step9/show_ip_route.ref284
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/step9/show_mpls_table.ref68
-rw-r--r--tests/topotests/ospf-sr-topo1/rt6/zebra.conf21
-rw-r--r--tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.dot78
-rw-r--r--tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.jpgbin48784 -> 0 bytes
-rw-r--r--tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py666
-rw-r--r--tests/topotests/ospf-tilfa-topo1/test_ospf_tilfa_topo1.py8
-rw-r--r--tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py2
-rw-r--r--tests/topotests/ospf-topo1/test_ospf_topo1.py2
-rw-r--r--tests/topotests/ospf6-topo1/test_ospf6_topo1.py5
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_chaos.py336
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py30
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py10
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_lan.py5
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py6
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py70
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py24
-rw-r--r--tests/topotests/pbr-topo1/test_pbr_topo1.py4
-rw-r--r--tests/topotests/pim-basic/test_pim.py2
-rw-r--r--tests/topotests/pytest.ini1
-rw-r--r--tests/topotests/rip-topo1/test_rip_topo1.py3
-rw-r--r--tests/topotests/ripng-topo1/test_ripng_topo1.py3
-rwxr-xr-xtests/topotests/simple-snmp-test/test_simple_snmp.py2
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py12
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py42
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py2
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py15
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py10
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py69
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py10
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py16
-rw-r--r--tests/topotests/zebra_rib/test_zebra_rib.py62
-rwxr-xr-xtools/frr-reload.py11
-rwxr-xr-xtools/nhrpd-event-handler.sh216
-rwxr-xr-xvtysh/extract.pl.in2
-rw-r--r--vtysh/vtysh.c21
-rw-r--r--watchfrr/watchfrr.c6
-rw-r--r--yang/frr-bfdd.yang2
-rw-r--r--yang/frr-isisd.yang69
-rw-r--r--zebra/connected.c8
-rw-r--r--zebra/if_netlink.c31
-rw-r--r--zebra/interface.c10
-rw-r--r--zebra/interface.h14
-rw-r--r--zebra/irdp_interface.c18
-rw-r--r--zebra/kernel_netlink.c8
-rw-r--r--zebra/redistribute.c2
-rw-r--r--zebra/rt_netlink.c117
-rw-r--r--zebra/zapi_msg.c61
-rw-r--r--zebra/zapi_msg.h14
-rw-r--r--zebra/zebra_dplane.c494
-rw-r--r--zebra/zebra_dplane.h46
-rw-r--r--zebra/zebra_evpn.c61
-rw-r--r--zebra/zebra_evpn_mac.c425
-rw-r--r--zebra/zebra_evpn_mac.h34
-rw-r--r--zebra/zebra_evpn_mh.c424
-rw-r--r--zebra/zebra_evpn_mh.h25
-rw-r--r--zebra/zebra_evpn_neigh.c273
-rw-r--r--zebra/zebra_evpn_neigh.h20
-rw-r--r--zebra/zebra_fpm.c6
-rw-r--r--zebra/zebra_fpm_netlink.c11
-rw-r--r--zebra/zebra_l2.c64
-rw-r--r--zebra/zebra_l2.h2
-rw-r--r--zebra/zebra_nhg.c6
-rw-r--r--zebra/zebra_pbr.c199
-rw-r--r--zebra/zebra_pbr.h16
-rw-r--r--zebra/zebra_rib.c10
-rw-r--r--zebra/zebra_vxlan.c132
618 files changed, 41739 insertions, 7517 deletions
diff --git a/.gitignore b/.gitignore
index fbbb04b60c..97349769ad 100644
--- a/.gitignore
+++ b/.gitignore
@@ -59,6 +59,7 @@
*.cg.json
*.cg.dot
*.cg.svg
+*.xref
### gcov outputs
diff --git a/Makefile.am b/Makefile.am
index 90c8407010..bb8e97a115 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -187,8 +187,16 @@ EXTRA_DIST += \
\
python/clidef.py \
python/clippy/__init__.py \
+ python/clippy/elf.py \
+ python/clippy/uidhash.py \
python/makevars.py \
python/makefile.py \
+ python/tiabwarfo.py \
+ python/xrelfo.py \
+ python/test_xrelfo.py \
+ python/runtests.py \
+ \
+ python/xrefstructs.json \
\
redhat/frr.logrotate \
redhat/frr.pam \
diff --git a/babeld/babeld.c b/babeld/babeld.c
index 895ede7040..a907daf6c2 100644
--- a/babeld/babeld.c
+++ b/babeld/babeld.c
@@ -265,8 +265,7 @@ babel_get_myid(void)
return;
}
- flog_err(EC_BABEL_CONFIG,
- "Warning: couldn't find router id -- using random value.");
+ flog_err(EC_BABEL_CONFIG, "Couldn't find router id -- using random value.");
rc = read_random_bytes(myid, 8);
if(rc < 0) {
diff --git a/babeld/message.c b/babeld/message.c
index edb9806011..5c2e29d8b3 100644
--- a/babeld/message.c
+++ b/babeld/message.c
@@ -746,10 +746,9 @@ flushbuf(struct interface *ifp)
if(rc < 0)
flog_err(EC_BABEL_PACKET, "send: %s", safe_strerror(errno));
} else {
- flog_err(EC_BABEL_PACKET,
- "Warning: bucket full, dropping packet to %s.",
- ifp->name);
- }
+ flog_err(EC_BABEL_PACKET, "Bucket full, dropping packet to %s.",
+ ifp->name);
+ }
}
VALGRIND_MAKE_MEM_UNDEFINED(babel_ifp->sendbuf, babel_ifp->bufsize);
babel_ifp->buffered = 0;
@@ -1009,10 +1008,10 @@ flush_unicast(int dofree)
flog_err(EC_BABEL_PACKET, "send(unicast): %s",
safe_strerror(errno));
} else {
- flog_err(EC_BABEL_PACKET,
- "Warning: bucket full, dropping unicast packet to %s if %s.",
- format_address(unicast_neighbour->address),
- unicast_neighbour->ifp->name);
+ flog_err(EC_BABEL_PACKET,
+ "Bucket full, dropping unicast packet to %s if %s.",
+ format_address(unicast_neighbour->address),
+ unicast_neighbour->ifp->name);
}
done:
diff --git a/babeld/route.c b/babeld/route.c
index 0f6f6486f2..dfd0bfab89 100644
--- a/babeld/route.c
+++ b/babeld/route.c
@@ -399,15 +399,17 @@ install_route(struct babel_route *route)
return;
if(!route_feasible(route))
- flog_err(EC_BABEL_ROUTE, "WARNING: installing unfeasible route (this shouldn't happen).");
+ flog_err(EC_BABEL_ROUTE,
+ "Installing unfeasible route (this shouldn't happen).");
i = find_route_slot(route->src->prefix, route->src->plen, NULL);
assert(i >= 0 && i < route_slots);
if(routes[i] != route && routes[i]->installed) {
- flog_err(EC_BABEL_ROUTE,
- "WARNING: attempting to install duplicate route (this shouldn't happen).");
- return;
+ flog_err(
+ EC_BABEL_ROUTE,
+ "Attempting to install duplicate route (this shouldn't happen).");
+ return;
}
rc = kernel_route(ROUTE_ADD, route->src->prefix, route->src->plen,
@@ -463,7 +465,8 @@ switch_routes(struct babel_route *old, struct babel_route *new)
return;
if(!route_feasible(new))
- flog_err(EC_BABEL_ROUTE, "WARNING: switching to unfeasible route (this shouldn't happen).");
+ flog_err(EC_BABEL_ROUTE,
+ "Switching to unfeasible route (this shouldn't happen).");
rc = kernel_route(ROUTE_MODIFY, old->src->prefix, old->src->plen,
old->nexthop, old->neigh->ifp->ifindex,
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index 3e45bf0e04..3cbb3691ec 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -85,7 +85,7 @@ struct bfd_profile *bfd_profile_lookup(const char *name)
static void bfd_profile_set_default(struct bfd_profile *bp)
{
- bp->admin_shutdown = true;
+ bp->admin_shutdown = false;
bp->detection_multiplier = BFD_DEFDETECTMULT;
bp->echo_mode = false;
bp->passive = false;
@@ -206,7 +206,7 @@ void bfd_session_apply(struct bfd_session *bs)
bfd_set_passive_mode(bs, bs->peer_profile.passive);
/* Toggle 'no shutdown' if default value. */
- if (bs->peer_profile.admin_shutdown)
+ if (bs->peer_profile.admin_shutdown == false)
bfd_set_shutdown(bs, bp->admin_shutdown);
else
bfd_set_shutdown(bs, bs->peer_profile.admin_shutdown);
@@ -1252,12 +1252,12 @@ void bs_final_handler(struct bfd_session *bs)
* TODO: support sending/counting more packets inside detection
* timeout.
*/
- if (bs->remote_timers.required_min_rx > bs->timers.desired_min_tx)
+ if (bs->timers.required_min_rx > bs->remote_timers.desired_min_tx)
bs->detect_TO = bs->remote_detect_mult
- * bs->remote_timers.required_min_rx;
+ * bs->timers.required_min_rx;
else
bs->detect_TO = bs->remote_detect_mult
- * bs->timers.desired_min_tx;
+ * bs->remote_timers.desired_min_tx;
/* Apply new receive timer immediately. */
bfd_recvtimer_update(bs);
diff --git a/bfdd/bfdd_cli.c b/bfdd/bfdd_cli.c
index b9e7903613..206f6c7d0c 100644
--- a/bfdd/bfdd_cli.c
+++ b/bfdd/bfdd_cli.c
@@ -57,6 +57,12 @@ bfd_cli_is_single_hop(struct vty *vty)
return strstr(VTY_CURR_XPATH, "/single-hop") != NULL;
}
+static bool
+bfd_cli_is_profile(struct vty *vty)
+{
+ return strstr(VTY_CURR_XPATH, "/bfd/profile") != NULL;
+}
+
/*
* Functions.
*/
@@ -117,10 +123,14 @@ DEFPY_YANG_NOSH(
char source_str[INET6_ADDRSTRLEN + 32];
char xpath[XPATH_MAXLEN], xpath_srcaddr[XPATH_MAXLEN + 32];
- if (multihop)
+ if (multihop) {
+ if (!local_address_str) {
+ vty_out(vty, "%% local-address is required when using multihop\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
snprintf(source_str, sizeof(source_str), "[source-addr='%s']",
local_address_str);
- else
+ } else
source_str[0] = 0;
slen = snprintf(xpath, sizeof(xpath),
@@ -264,7 +274,7 @@ void bfd_cli_show_shutdown(struct vty *vty, struct lyd_node *dnode,
bool show_defaults)
{
if (show_defaults)
- vty_out(vty, " shutdown\n");
+ vty_out(vty, " no shutdown\n");
else
vty_out(vty, " %sshutdown\n",
yang_dnode_get_bool(dnode, NULL) ? "" : "no ");
@@ -418,7 +428,7 @@ DEFPY_YANG(
NO_STR
"Configure echo mode\n")
{
- if (!bfd_cli_is_single_hop(vty)) {
+ if (!bfd_cli_is_profile(vty) && !bfd_cli_is_single_hop(vty)) {
vty_out(vty, "%% Echo mode is only available for single hop sessions.\n");
return CMD_WARNING_CONFIG_FAILED;
}
@@ -446,7 +456,7 @@ DEFPY_YANG(
{
char value[32];
- if (!bfd_cli_is_single_hop(vty)) {
+ if (!bfd_cli_is_profile(vty) && !bfd_cli_is_single_hop(vty)) {
vty_out(vty, "%% Echo mode is only available for single hop sessions.\n");
return CMD_WARNING_CONFIG_FAILED;
}
diff --git a/bfdd/bfdd_nb_config.c b/bfdd/bfdd_nb_config.c
index fe6a0b7905..c8dd5cc3f6 100644
--- a/bfdd/bfdd_nb_config.c
+++ b/bfdd/bfdd_nb_config.c
@@ -55,36 +55,87 @@ static void bfd_session_get_key(bool mhop, const struct lyd_node *dnode,
gen_bfd_key(bk, &psa, &lsa, mhop, ifname, vrfname);
}
-static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
- union nb_resource *resource, bool mhop)
+struct session_iter {
+ int count;
+ bool wildcard;
+};
+
+static int session_iter_cb(const struct lyd_node *dnode, void *arg)
{
+ struct session_iter *iter = arg;
+ const char *ifname;
+
+ ifname = yang_dnode_get_string(dnode, "./interface");
+
+ if (strmatch(ifname, "*"))
+ iter->wildcard = true;
+
+ iter->count++;
+
+ return YANG_ITER_CONTINUE;
+}
+
+static int bfd_session_create(struct nb_cb_create_args *args, bool mhop)
+{
+ const struct lyd_node *sess_dnode;
+ struct session_iter iter;
struct bfd_session *bs;
+ const char *source;
+ const char *dest;
const char *ifname;
+ const char *vrfname;
struct bfd_key bk;
struct prefix p;
- switch (event) {
+ switch (args->event) {
case NB_EV_VALIDATE:
/*
* When `dest-addr` is IPv6 and link-local we must
* require interface name, otherwise we can't figure
* which interface to use to send the packets.
*/
- yang_dnode_get_prefix(&p, dnode, "./dest-addr");
+ yang_dnode_get_prefix(&p, args->dnode, "./dest-addr");
- ifname = yang_dnode_get_string(dnode, "./interface");
+ ifname = yang_dnode_get_string(args->dnode, "./interface");
if (p.family == AF_INET6 && IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)
&& strcmp(ifname, "*") == 0) {
- zlog_warn(
- "%s: when using link-local you must specify an interface.",
- __func__);
+ snprintf(
+ args->errmsg, args->errmsg_len,
+ "When using link-local you must specify an interface");
+ return NB_ERR_VALIDATION;
+ }
+
+ iter.count = 0;
+ iter.wildcard = false;
+
+ sess_dnode = yang_dnode_get_parent(args->dnode, "sessions");
+
+ dest = yang_dnode_get_string(args->dnode, "./dest-addr");
+ vrfname = yang_dnode_get_string(args->dnode, "./vrf");
+
+ if (mhop) {
+ source = yang_dnode_get_string(args->dnode, "./source-addr");
+
+ yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
+ "./multi-hop[source-addr='%s'][dest-addr='%s'][vrf='%s']",
+ source, dest, vrfname);
+ } else {
+ yang_dnode_iterate(session_iter_cb, &iter, sess_dnode,
+ "./single-hop[dest-addr='%s'][vrf='%s']",
+ dest, vrfname);
+ }
+
+ if (iter.wildcard && iter.count > 1) {
+ snprintf(
+ args->errmsg, args->errmsg_len,
+ "It is not allowed to configure the same peer with and without ifname");
return NB_ERR_VALIDATION;
}
break;
case NB_EV_PREPARE:
- bfd_session_get_key(mhop, dnode, &bk);
+ bfd_session_get_key(mhop, args->dnode, &bk);
bs = bfd_key_lookup(bk);
/* This session was already configured by another daemon. */
@@ -93,14 +144,14 @@ static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
SET_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG);
bs->refcount++;
- resource->ptr = bs;
+ args->resource->ptr = bs;
break;
}
bs = bfd_session_new();
/* Fill the session key. */
- bfd_session_get_key(mhop, dnode, &bs->key);
+ bfd_session_get_key(mhop, args->dnode, &bs->key);
/* Set configuration flags. */
bs->refcount = 1;
@@ -110,23 +161,23 @@ static int bfd_session_create(enum nb_event event, const struct lyd_node *dnode,
if (bs->key.family == AF_INET6)
SET_FLAG(bs->flags, BFD_SESS_FLAG_IPV6);
- resource->ptr = bs;
+ args->resource->ptr = bs;
break;
case NB_EV_APPLY:
- bs = resource->ptr;
+ bs = args->resource->ptr;
/* Only attempt to registrate if freshly allocated. */
if (bs->discrs.my_discr == 0 && bs_registrate(bs) == NULL)
return NB_ERR_RESOURCE;
- nb_running_set_entry(dnode, bs);
+ nb_running_set_entry(args->dnode, bs);
break;
case NB_EV_ABORT:
- bs = resource->ptr;
+ bs = args->resource->ptr;
if (bs->refcount <= 1)
- bfd_session_free(resource->ptr);
+ bfd_session_free(bs);
break;
}
@@ -474,8 +525,7 @@ int bfdd_bfd_profile_desired_echo_transmission_interval_modify(
*/
int bfdd_bfd_sessions_single_hop_create(struct nb_cb_create_args *args)
{
- return bfd_session_create(args->event, args->dnode, args->resource,
- false);
+ return bfd_session_create(args, false);
}
int bfdd_bfd_sessions_single_hop_destroy(struct nb_cb_destroy_args *args)
@@ -759,8 +809,7 @@ int bfdd_bfd_sessions_single_hop_desired_echo_transmission_interval_modify(
*/
int bfdd_bfd_sessions_multi_hop_create(struct nb_cb_create_args *args)
{
- return bfd_session_create(args->event, args->dnode, args->resource,
- true);
+ return bfd_session_create(args, true);
}
int bfdd_bfd_sessions_multi_hop_destroy(struct nb_cb_destroy_args *args)
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index 53e23cf6c2..cb140f7b18 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -840,7 +840,7 @@ static int bfd_configure_peer(struct bfd_peer_cfg *bpc, bool mhop,
memset(bpc, 0, sizeof(*bpc));
/* Defaults */
- bpc->bpc_shutdown = true;
+ bpc->bpc_shutdown = false;
bpc->bpc_detectmultiplier = BPC_DEF_DETECTMULTIPLIER;
bpc->bpc_recvinterval = BPC_DEF_RECEIVEINTERVAL;
bpc->bpc_txinterval = BPC_DEF_TRANSMITINTERVAL;
diff --git a/bfdd/ptm_adapter.c b/bfdd/ptm_adapter.c
index 0c70600f20..4135e5fb49 100644
--- a/bfdd/ptm_adapter.c
+++ b/bfdd/ptm_adapter.c
@@ -492,9 +492,6 @@ static void bfdd_dest_register(struct stream *msg, vrf_id_t vrf_id)
"ptm-add-dest: failed to create BFD session");
return;
}
-
- /* Protocol created peers are 'no shutdown' by default. */
- bs->peer_profile.admin_shutdown = false;
} else {
/*
* BFD session was already created, we are just updating the
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index dc8cc81042..f658b0d0f0 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -2133,19 +2133,11 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
}
stream_get(&attr->mp_nexthop_local, s, IPV6_MAX_BYTELEN);
if (!IN6_IS_ADDR_LINKLOCAL(&attr->mp_nexthop_local)) {
- char buf1[INET6_ADDRSTRLEN];
- char buf2[INET6_ADDRSTRLEN];
-
if (bgp_debug_update(peer, NULL, NULL, 1))
zlog_debug(
- "%s sent next-hops %s and %s. Ignoring non-LL value",
- peer->host,
- inet_ntop(AF_INET6,
- &attr->mp_nexthop_global,
- buf1, INET6_ADDRSTRLEN),
- inet_ntop(AF_INET6,
- &attr->mp_nexthop_local, buf2,
- INET6_ADDRSTRLEN));
+ "%s sent next-hops %pI6 and %pI6. Ignoring non-LL value",
+ peer->host, &attr->mp_nexthop_global,
+ &attr->mp_nexthop_local);
attr->mp_nexthop_len = IPV6_MAX_BYTELEN;
}
@@ -2344,16 +2336,10 @@ bgp_attr_ext_communities(struct bgp_attr_parser_args *args)
/* Extract the Rmac, if any */
if (bgp_attr_rmac(attr, &attr->rmac)) {
- if (bgp_debug_update(peer, NULL, NULL, 1) &&
- bgp_mac_exist(&attr->rmac)) {
- char buf1[ETHER_ADDR_STRLEN];
-
- zlog_debug("%s: router mac %s is self mac",
- __func__,
- prefix_mac2str(&attr->rmac, buf1,
- sizeof(buf1)));
- }
-
+ if (bgp_debug_update(peer, NULL, NULL, 1)
+ && bgp_mac_exist(&attr->rmac))
+ zlog_debug("%s: router mac %pEA is self mac", __func__,
+ &attr->rmac);
}
/* Get the tunnel type from encap extended community */
@@ -3103,7 +3089,7 @@ bgp_attr_parse_ret_t bgp_attr_parse(struct peer *peer, struct attr *attr,
* a stack buffer, since they perform bounds checking
* and we are working with untrusted data.
*/
- unsigned char ndata[BGP_MAX_PACKET_SIZE];
+ unsigned char ndata[peer->max_packet_size];
memset(ndata, 0x00, sizeof(ndata));
size_t lfl =
CHECK_FLAG(flag, BGP_ATTR_FLAG_EXTLEN) ? 2 : 1;
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index b740979b82..3db142b8cf 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -545,7 +545,8 @@ int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
}
/* Clean all the bgp_damp_info stored in reuse_list and no_reuse_list. */
-void bgp_damp_info_clean(struct bgp_damp_config *bdc, afi_t afi, safi_t safi)
+void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
+ afi_t afi, safi_t safi)
{
struct bgp_damp_info *bdi;
struct reuselist_node *rn;
@@ -557,6 +558,13 @@ void bgp_damp_info_clean(struct bgp_damp_config *bdc, afi_t afi, safi_t safi)
list = &bdc->reuse_list[i];
while ((rn = SLIST_FIRST(list)) != NULL) {
bdi = rn->info;
+ if (bdi->lastrecord == BGP_RECORD_UPDATE) {
+ bgp_aggregate_increment(bgp, &bdi->dest->p,
+ bdi->path, bdi->afi,
+ bdi->safi);
+ bgp_process(bgp, bdi->dest, bdi->afi,
+ bdi->safi);
+ }
bgp_reuselist_del(list, &rn);
bgp_damp_info_free(&bdi, bdc, 1, afi, safi);
}
@@ -607,7 +615,7 @@ int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi)
thread_cancel(&bdc->t_reuse);
/* Clean BGP dampening information. */
- bgp_damp_info_clean(bdc, afi, safi);
+ bgp_damp_info_clean(bgp, bdc, afi, safi);
UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
@@ -896,7 +904,7 @@ void bgp_peer_damp_disable(struct peer *peer, afi_t afi, safi_t safi)
bdc = &peer->damp[afi][safi];
if (!bdc)
return;
- bgp_damp_info_clean(bdc, afi, safi);
+ bgp_damp_info_clean(peer->bgp, bdc, afi, safi);
UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING);
}
diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h
index 521f59b296..3c8f138d6a 100644
--- a/bgpd/bgp_damp.h
+++ b/bgpd/bgp_damp.h
@@ -151,8 +151,8 @@ extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
extern void bgp_damp_info_free(struct bgp_damp_info **path,
struct bgp_damp_config *bdc, int withdraw,
afi_t afi, safi_t safi);
-extern void bgp_damp_info_clean(struct bgp_damp_config *bdc, afi_t afi,
- safi_t safi);
+extern void bgp_damp_info_clean(struct bgp *bgp, struct bgp_damp_config *bdc,
+ afi_t afi, safi_t safi);
extern void bgp_damp_config_clean(struct bgp_damp_config *bdc);
extern int bgp_damp_decay(time_t, int, struct bgp_damp_config *damp);
extern void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi,
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index c976632678..7b29f1e4c9 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -592,9 +592,6 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
{
struct stream *s;
int ipa_len;
- char buf1[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
- char buf3[INET6_ADDRSTRLEN];
static struct in_addr zero_remote_vtep_ip;
/* Check socket. */
@@ -649,14 +646,10 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
if (bgp_debug_zebra(NULL))
zlog_debug(
- "Tx %s MACIP, VNI %u MAC %s IP %s flags 0x%x seq %u remote VTEP %s",
+ "Tx %s MACIP, VNI %u MAC %pEA IP %pIA flags 0x%x seq %u remote VTEP %pI4",
add ? "ADD" : "DEL", vpn->vni,
- prefix_mac2str(&p->prefix.macip_addr.mac,
- buf1, sizeof(buf1)),
- ipaddr2str(&p->prefix.macip_addr.ip,
- buf3, sizeof(buf3)), flags, seq,
- inet_ntop(AF_INET, &remote_vtep_ip, buf2,
- sizeof(buf2)));
+ &p->prefix.macip_addr.mac, &p->prefix.macip_addr.ip,
+ flags, seq, &remote_vtep_ip);
return zclient_send_message(zclient);
}
@@ -1319,16 +1312,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
vrf_id_to_name(bgp_vrf->vrf_id), evp);
}
- if (bgp_debug_zebra(NULL)) {
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
-
- zlog_debug("VRF %s type-5 route evp %pFX RMAC %s nexthop %s",
- vrf_id_to_name(bgp_vrf->vrf_id), evp,
- prefix_mac2str(&attr.rmac, buf, sizeof(buf)),
- inet_ntop(AF_INET, &attr.nexthop, buf2,
- INET_ADDRSTRLEN));
- }
+ if (bgp_debug_zebra(NULL))
+ zlog_debug(
+ "VRF %s type-5 route evp %pFX RMAC %pEA nexthop %pI4",
+ vrf_id_to_name(bgp_vrf->vrf_id), evp, &attr.rmac,
+ &attr.nexthop);
attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
@@ -1725,16 +1713,13 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
}
if (bgp_debug_zebra(NULL)) {
- char buf[ETHER_ADDR_STRLEN];
char buf3[ESI_STR_LEN];
zlog_debug(
- "VRF %s vni %u type-2 route evp %pFX RMAC %s nexthop %pI4 esi %s",
+ "VRF %s vni %u type-2 route evp %pFX RMAC %pEA nexthop %pI4 esi %s",
vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id)
: " ",
- vpn->vni, p,
- prefix_mac2str(&attr.rmac, buf, sizeof(buf)),
- &attr.mp_nexthop_global_in,
+ vpn->vni, p, &attr.rmac, &attr.mp_nexthop_global_in,
esi_to_str(esi, buf3, sizeof(buf3)));
}
/* router mac is only needed for type-2 routes here. */
@@ -2004,16 +1989,13 @@ static void bgp_evpn_update_type2_route_entry(struct bgp *bgp,
seq = mac_mobility_seqnum(local_pi->attr);
if (bgp_debug_zebra(NULL)) {
- char buf[ETHER_ADDR_STRLEN];
char buf3[ESI_STR_LEN];
zlog_debug(
- "VRF %s vni %u evp %pFX RMAC %s nexthop %pI4 esi %s esf 0x%x from %s",
+ "VRF %s vni %u evp %pFX RMAC %pEA nexthop %pI4 esi %s esf 0x%x from %s",
vpn->bgp_vrf ? vrf_id_to_name(vpn->bgp_vrf->vrf_id)
: " ",
- vpn->vni, evp,
- prefix_mac2str(&attr.rmac, buf, sizeof(buf)),
- &attr.mp_nexthop_global_in,
+ vpn->vni, evp, &attr.rmac, &attr.mp_nexthop_global_in,
esi_to_str(&attr.esi, buf3, sizeof(buf3)),
attr.es_flags, caller);
}
@@ -5300,18 +5282,14 @@ int bgp_evpn_local_macip_add(struct bgp *bgp, vni_t vni, struct ethaddr *mac,
/* Create EVPN type-2 route and schedule for processing. */
build_evpn_type2_prefix(&p, mac, ip);
if (update_evpn_route(bgp, vpn, &p, flags, seq, esi)) {
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
-
flog_err(
EC_BGP_EVPN_ROUTE_CREATE,
- "%u:Failed to create Type-2 route, VNI %u %s MAC %s IP %s (flags: 0x%x)",
+ "%u:Failed to create Type-2 route, VNI %u %s MAC %pEA IP %pIA (flags: 0x%x)",
bgp->vrf_id, vpn->vni,
CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY)
? "sticky gateway"
: "",
- prefix_mac2str(mac, buf, sizeof(buf)),
- ipaddr2str(ip, buf2, sizeof(buf2)), flags);
+ mac, ip, flags);
return -1;
}
@@ -5396,23 +5374,16 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id,
if (is_zero_mac(&bgp_vrf->evpn_info->pip_rmac_static))
memcpy(&bgp_vrf->evpn_info->pip_rmac, svi_rmac, ETH_ALEN);
- if (bgp_debug_zebra(NULL)) {
- char buf[ETHER_ADDR_STRLEN];
- char buf1[ETHER_ADDR_STRLEN];
- char buf2[ETHER_ADDR_STRLEN];
-
- zlog_debug("VRF %s vni %u pip %s RMAC %s sys RMAC %s static RMAC %s is_anycast_mac %s",
- vrf_id_to_name(bgp_vrf->vrf_id),
- bgp_vrf->l3vni,
- bgp_vrf->evpn_info->advertise_pip ? "enable"
- : "disable",
- prefix_mac2str(&bgp_vrf->rmac, buf, sizeof(buf)),
- prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac,
- buf1, sizeof(buf1)),
- prefix_mac2str(&bgp_vrf->evpn_info->pip_rmac_static,
- buf2, sizeof(buf2)),
- is_anycast_mac ? "Enable" : "Disable");
- }
+ if (bgp_debug_zebra(NULL))
+ zlog_debug(
+ "VRF %s vni %u pip %s RMAC %pEA sys RMAC %pEA static RMAC %pEA is_anycast_mac %s",
+ vrf_id_to_name(bgp_vrf->vrf_id), bgp_vrf->l3vni,
+ bgp_vrf->evpn_info->advertise_pip ? "enable"
+ : "disable",
+ &bgp_vrf->rmac, &bgp_vrf->evpn_info->pip_rmac,
+ &bgp_vrf->evpn_info->pip_rmac_static,
+ is_anycast_mac ? "Enable" : "Disable");
+
/* set the right filter - are we using l3vni only for prefix routes? */
if (filter) {
SET_FLAG(bgp_vrf->vrf_flags, BGP_VRF_L3VNI_PREFIX_ROUTES_ONLY);
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 2dec0863c0..123c46f12f 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -74,6 +74,7 @@ bgp_evpn_es_path_update_on_vtep_chg(struct bgp_evpn_es_vtep *es_vtep,
bool active);
esi_t zero_esi_buf, *zero_esi = &zero_esi_buf;
+static int bgp_evpn_run_consistency_checks(struct thread *t);
/******************************************************************************
* per-ES (Ethernet Segment) routing table
@@ -1621,21 +1622,18 @@ static void bgp_evpn_es_remote_info_re_eval(struct bgp_evpn_es *es)
}
}
-/* Process ES link oper-down by withdrawing ES-EAD and ESR */
-static void bgp_evpn_local_es_down(struct bgp *bgp,
- struct bgp_evpn_es *es)
+static inline bool bgp_evpn_local_es_is_active(struct bgp_evpn_es *es)
+{
+ return (es->flags & BGP_EVPNES_OPER_UP)
+ && !(es->flags & BGP_EVPNES_BYPASS);
+}
+
+static void bgp_evpn_local_es_deactivate(struct bgp *bgp,
+ struct bgp_evpn_es *es)
{
struct prefix_evpn p;
int ret;
- if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP))
- return;
-
- UNSET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
-
- if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("local es %s down", es->esi_str);
-
/* withdraw ESR */
/* Delete and withdraw locally learnt ES route */
build_evpn_type4_prefix(&p, &es->esi, es->originator_ip);
@@ -1661,21 +1659,28 @@ static void bgp_evpn_local_es_down(struct bgp *bgp,
}
}
-/* Process ES link oper-up by generating ES-EAD and ESR */
-static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
- bool regen_esr)
+/* Process ES link oper-down by withdrawing ES-EAD and ESR */
+static void bgp_evpn_local_es_down(struct bgp *bgp, struct bgp_evpn_es *es)
{
- struct prefix_evpn p;
- bool regen_ead = false;
+ bool old_active;
- if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
- if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("local es %s up", es->esi_str);
+ if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP))
+ return;
- SET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
- regen_esr = true;
- regen_ead = true;
- }
+ old_active = bgp_evpn_local_es_is_active(es);
+ UNSET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
+
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("local es %s down", es->esi_str);
+
+ if (old_active)
+ bgp_evpn_local_es_deactivate(bgp, es);
+}
+
+static void bgp_evpn_local_es_activate(struct bgp *bgp, struct bgp_evpn_es *es,
+ bool regen_ead, bool regen_esr)
+{
+ struct prefix_evpn p;
if (regen_esr) {
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
@@ -1697,7 +1702,62 @@ static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
/* generate EAD-ES */
build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG, &es->esi,
es->originator_ip);
- bgp_evpn_type1_route_update(bgp, es, NULL, &p);
+ (void)bgp_evpn_type1_route_update(bgp, es, NULL, &p);
+ }
+}
+
+/* Process ES link oper-up by generating ES-EAD and ESR */
+static void bgp_evpn_local_es_up(struct bgp *bgp, struct bgp_evpn_es *es,
+ bool regen_esr)
+{
+ bool regen_ead = false;
+ bool active = false;
+
+ if (!CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("local es %s up", es->esi_str);
+
+ SET_FLAG(es->flags, BGP_EVPNES_OPER_UP);
+ regen_esr = true;
+ regen_ead = true;
+ }
+
+ active = bgp_evpn_local_es_is_active(es);
+ if (active && (regen_ead || regen_esr))
+ bgp_evpn_local_es_activate(bgp, es, regen_ead, regen_esr);
+}
+
+/* If an ethernet segment is in LACP bypass we cannot advertise
+ * reachability to it i.e. EAD-per-ES and ESR is not advertised in
+ * bypass state.
+ * PS: EAD-per-EVI will continue to be advertised
+ */
+static void bgp_evpn_local_es_bypass_update(struct bgp *bgp,
+ struct bgp_evpn_es *es, bool bypass)
+{
+ bool old_bypass = !!(es->flags & BGP_EVPNES_BYPASS);
+ bool old_active;
+ bool new_active;
+
+ if (bypass == old_bypass)
+ return;
+
+ old_active = bgp_evpn_local_es_is_active(es);
+ if (bypass)
+ SET_FLAG(es->flags, BGP_EVPNES_BYPASS);
+ else
+ UNSET_FLAG(es->flags, BGP_EVPNES_BYPASS);
+
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("local es %s bypass %s", es->esi_str,
+ bypass ? "set" : "clear");
+
+ new_active = bgp_evpn_local_es_is_active(es);
+ if (old_active != new_active) {
+ if (new_active)
+ bgp_evpn_local_es_activate(bgp, es, true, true);
+ else
+ bgp_evpn_local_es_deactivate(bgp, es);
}
}
@@ -1757,7 +1817,7 @@ int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi)
*/
int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
struct in_addr originator_ip, bool oper_up,
- uint16_t df_pref)
+ uint16_t df_pref, bool bypass)
{
char buf[ESI_STR_LEN];
struct bgp_evpn_es *es;
@@ -1780,8 +1840,9 @@ int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
}
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
- zlog_debug("add local es %s orig-ip %pI4 df_pref %u", es->esi_str,
- &originator_ip, df_pref);
+ zlog_debug("add local es %s orig-ip %pI4 df_pref %u %s",
+ es->esi_str, &originator_ip, df_pref,
+ bypass ? "bypass" : "");
es->originator_ip = originator_ip;
if (df_pref != es->df_pref) {
@@ -1802,6 +1863,8 @@ int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
if (bgp_mh_info->ead_evi_adv_for_down_links)
bgp_evpn_local_type1_evi_route_add(bgp, es);
+ bgp_evpn_local_es_bypass_update(bgp, es, bypass);
+
/* If the ES link is operationally up generate EAD-ES. EAD-EVI
* can be generated even if the link is inactive.
*/
@@ -1952,6 +2015,8 @@ static void bgp_evpn_es_show_entry(struct vty *vty,
char vtep_str[ES_VTEP_LIST_STR_SZ + BGP_EVPN_VTEPS_FLAG_STR_SZ];
type_str[0] = '\0';
+ if (es->flags & BGP_EVPNES_BYPASS)
+ strlcat(type_str, "B", sizeof(type_str));
if (es->flags & BGP_EVPNES_LOCAL)
strlcat(type_str, "L", sizeof(type_str));
if (es->flags & BGP_EVPNES_REMOTE)
@@ -1986,13 +2051,17 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
/* Add the "brief" info first */
bgp_evpn_es_show_entry(vty, es, json);
- if (es->flags & (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI)) {
+ if (es->flags
+ & (BGP_EVPNES_OPER_UP | BGP_EVPNES_ADV_EVI
+ | BGP_EVPNES_BYPASS)) {
json_flags = json_object_new_array();
if (es->flags & BGP_EVPNES_OPER_UP)
json_array_string_add(json_flags, "up");
if (es->flags & BGP_EVPNES_ADV_EVI)
json_array_string_add(json_flags,
"advertiseEVI");
+ if (es->flags & BGP_EVPNES_BYPASS)
+ json_array_string_add(json_flags, "bypass");
json_object_object_add(json, "flags", json_flags);
}
json_object_string_add(json, "originator_ip",
@@ -2045,6 +2114,8 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
if (es->flags & BGP_EVPNES_LOCAL)
vty_out(vty, " Local ES DF preference: %u\n",
es->df_pref);
+ if (es->flags & BGP_EVPNES_BYPASS)
+ vty_out(vty, " LACP bypass: on\n");
vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
vty_out(vty, " Remote VNI Count: %d\n",
es->remote_es_evi_cnt);
@@ -2084,7 +2155,7 @@ void bgp_evpn_es_show(struct vty *vty, bool uj, bool detail)
} else {
if (!detail) {
vty_out(vty,
- "ES Flags: L local, R remote, I inconsistent\n");
+ "ES Flags: B - bypass, L local, R remote, I inconsistent\n");
vty_out(vty,
"VTEP Flags: E ESR/Type-4, A active nexthop\n");
vty_out(vty,
@@ -2973,7 +3044,7 @@ static void bgp_evpn_local_es_evi_do_del(struct bgp_evpn_es_evi *es_evi)
if (bgp) {
/* update EAD-ES with new list of VNIs */
- if (CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
+ if (bgp_evpn_local_es_is_active(es)) {
build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG,
&es->esi, es->originator_ip);
if (bgp_evpn_type1_route_update(bgp, es, NULL, &p))
@@ -3098,7 +3169,7 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
/* update EAD-ES */
build_evpn_type1_prefix(&p, BGP_EVPN_AD_ES_ETH_TAG,
&es->esi, es->originator_ip);
- if (CHECK_FLAG(es->flags, BGP_EVPNES_OPER_UP)) {
+ if (bgp_evpn_local_es_is_active(es)) {
if (bgp_evpn_type1_route_update(bgp, es, NULL, &p))
flog_err(EC_BGP_EVPN_ROUTE_CREATE,
"%u: EAD-ES route creation failure for ESI %s VNI %u",
@@ -3508,6 +3579,19 @@ void bgp_evpn_es_evi_show_vni(struct vty *vty, vni_t vni,
* show commands) at this point. A more drastic action can be executed (based
* on user config) in the future.
*/
+static void bgp_evpn_es_cons_checks_timer_start(void)
+{
+ if (!bgp_mh_info->consistency_checking || bgp_mh_info->t_cons_check)
+ return;
+
+ if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
+ zlog_debug("periodic consistency checking started");
+
+ thread_add_timer(bm->master, bgp_evpn_run_consistency_checks, NULL,
+ BGP_EVPN_CONS_CHECK_INTERVAL,
+ &bgp_mh_info->t_cons_check);
+}
+
/* queue up the es for background consistency checks */
static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es)
{
@@ -3519,6 +3603,10 @@ static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es)
/* already queued for consistency checking */
return;
+ /* start the periodic timer for consistency checks if it is not
+ * already running */
+ bgp_evpn_es_cons_checks_timer_start();
+
SET_FLAG(es->flags, BGP_EVPNES_CONS_CHECK_PEND);
listnode_init(&es->pend_es_listnode, es);
listnode_add_after(bgp_mh_info->pend_es_list,
@@ -3737,11 +3825,6 @@ void bgp_evpn_mh_init(void)
bgp_mh_info->install_l3nhg = false;
bgp_mh_info->host_routes_use_l3nhg = BGP_EVPN_MH_USE_ES_L3NHG_DEF;
- if (bgp_mh_info->consistency_checking)
- thread_add_timer(bm->master, bgp_evpn_run_consistency_checks,
- NULL, BGP_EVPN_CONS_CHECK_INTERVAL,
- &bgp_mh_info->t_cons_check);
-
memset(&zero_esi_buf, 0, sizeof(esi_t));
}
@@ -3757,9 +3840,46 @@ void bgp_evpn_mh_finish(void)
es_next) {
bgp_evpn_es_local_info_clear(es);
}
- thread_cancel(&bgp_mh_info->t_cons_check);
+ if (bgp_mh_info->t_cons_check)
+ thread_cancel(&bgp_mh_info->t_cons_check);
list_delete(&bgp_mh_info->local_es_list);
list_delete(&bgp_mh_info->pend_es_list);
XFREE(MTYPE_BGP_EVPN_MH_INFO, bgp_mh_info);
}
+
+/* This function is called when disable-ead-evi-rx knob flaps */
+void bgp_evpn_switch_ead_evi_rx(void)
+{
+ struct bgp *bgp;
+ struct bgp_evpn_es *es;
+ struct bgp_evpn_es_evi *es_evi;
+ struct listnode *evi_node = NULL;
+ struct listnode *evi_next = NULL;
+ struct bgp_evpn_es_evi_vtep *vtep;
+ struct listnode *vtep_node = NULL;
+ struct listnode *vtep_next = NULL;
+
+ bgp = bgp_get_evpn();
+ if (!bgp)
+ return;
+
+ /*
+ * Process all the remote es_evi_vteps and reevaluate if the es_evi_vtep
+ * is active.
+ */
+ RB_FOREACH(es, bgp_es_rb_head, &bgp_mh_info->es_rb_tree) {
+ if (!CHECK_FLAG(es->flags, BGP_EVPNES_REMOTE))
+ continue;
+
+ for (ALL_LIST_ELEMENTS(es->es_evi_list, evi_node, evi_next,
+ es_evi)) {
+ if (!CHECK_FLAG(es_evi->flags, BGP_EVPNES_EVI_REMOTE))
+ continue;
+
+ for (ALL_LIST_ELEMENTS(es_evi->es_evi_vtep_list,
+ vtep_node, vtep_next, vtep))
+ bgp_evpn_es_evi_vtep_re_eval_active(bgp, vtep);
+ }
+ }
+}
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index 6199113e87..e5186619ff 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -29,7 +29,6 @@
#define BGP_EVPN_AD_EVI_ETH_TAG 0
#define BGP_EVPNES_INCONS_STR_SZ 80
-#define BGP_EVPN_FLAG_STR_SZ 5
#define BGP_EVPN_VTEPS_FLAG_STR_SZ (BGP_EVPN_FLAG_STR_SZ * ES_VTEP_MAX_CNT)
#define BGP_EVPN_CONS_CHECK_INTERVAL 60
@@ -62,6 +61,10 @@ struct bgp_evpn_es {
#define BGP_EVPNES_ADV_EVI (1 << 3)
/* consistency checks pending */
#define BGP_EVPNES_CONS_CHECK_PEND (1 << 4)
+ /* ES is in LACP bypass mode - don't advertise EAD-ES or ESR */
+#define BGP_EVPNES_BYPASS (1 << 5)
+ /* bits needed for printing the flags + null */
+#define BGP_EVPN_FLAG_STR_SZ 7
/* memory used for adding the es to bgp->es_rb_tree */
RB_ENTRY(bgp_evpn_es) rb_node;
@@ -340,7 +343,7 @@ int bgp_evpn_type4_route_process(struct peer *peer, afi_t afi, safi_t safi,
uint32_t addpath_id);
extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
struct in_addr originator_ip, bool oper_up,
- uint16_t df_pref);
+ uint16_t df_pref, bool bypass);
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);
@@ -373,5 +376,6 @@ extern bool bgp_evpn_path_es_use_nhg(struct bgp *bgp_vrf,
extern void bgp_evpn_es_vrf_show(struct vty *vty, bool uj,
struct bgp_evpn_es *es);
extern void bgp_evpn_es_vrf_show_esi(struct vty *vty, esi_t *esi, bool uj);
+extern void bgp_evpn_switch_ead_evi_rx(void);
#endif /* _FRR_BGP_EVPN_MH_H */
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index 5b0b3bb6e5..b101589a79 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -3767,7 +3767,12 @@ DEFPY (bgp_evpn_ead_evi_rx_disable,
NO_STR
"Activate PE on EAD-ES even if EAD-EVI is not received\n")
{
- bgp_mh_info->ead_evi_rx = no? true :false;
+ bool ead_evi_rx = no? true :false;
+
+ if (ead_evi_rx != bgp_mh_info->ead_evi_rx) {
+ bgp_mh_info->ead_evi_rx = ead_evi_rx;
+ bgp_evpn_switch_ead_evi_rx();
+ }
return CMD_SUCCESS;
}
@@ -4803,7 +4808,7 @@ DEFPY_HIDDEN(test_es_add,
vtep_ip = bgp->router_id;
ret = bgp_evpn_local_es_add(bgp, &esi, vtep_ip, oper_up,
- EVPN_MH_DF_PREF_MIN);
+ EVPN_MH_DF_PREF_MIN, false);
if (ret == -1) {
vty_out(vty, "%%Failed to add ES\n");
return CMD_WARNING;
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 30e2c3d489..757d76f69e 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -1556,13 +1556,9 @@ static int bgp_connect_success(struct peer *peer)
bgp_reads_on(peer);
if (bgp_debug_neighbor_events(peer)) {
- char buf1[SU_ADDRSTRLEN];
-
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
- zlog_debug("%s open active, local address %s",
- peer->host,
- sockunion2str(peer->su_local, buf1,
- SU_ADDRSTRLEN));
+ zlog_debug("%s open active, local address %pSU",
+ peer->host, peer->su_local);
else
zlog_debug("%s passive open", peer->host);
}
@@ -1598,13 +1594,9 @@ static int bgp_connect_success_w_delayopen(struct peer *peer)
bgp_reads_on(peer);
if (bgp_debug_neighbor_events(peer)) {
- char buf1[SU_ADDRSTRLEN];
-
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER))
- zlog_debug("%s open active, local address %s",
- peer->host,
- sockunion2str(peer->su_local, buf1,
- SU_ADDRSTRLEN));
+ zlog_debug("%s open active, local address %pSU",
+ peer->host, peer->su_local);
else
zlog_debug("%s passive open", peer->host);
}
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index cd464d8c58..bf4966c839 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -31,7 +31,7 @@
#define BGP_TIMER_OFF(T) \
do { \
- THREAD_OFF(T); \
+ THREAD_OFF((T)); \
} while (0)
#define BGP_EVENT_ADD(P, E) \
@@ -44,7 +44,7 @@
#define BGP_EVENT_FLUSH(P) \
do { \
assert(peer); \
- thread_cancel_event(bm->master, (P)); \
+ thread_cancel_event_ready(bm->master, (P)); \
} while (0)
#define BGP_UPDATE_GROUP_TIMER_ON(T, F) \
@@ -53,10 +53,10 @@
PEER_ROUTE_ADV_DELAY(peer)) \
thread_add_timer_msec(bm->master, (F), peer, \
(BGP_DEFAULT_UPDATE_ADVERTISEMENT_TIME * 1000),\
- T); \
+ (T)); \
else \
thread_add_timer_msec(bm->master, (F), peer, \
- 0, T); \
+ 0, (T)); \
} while (0) \
#define BGP_MSEC_JITTER 10
diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index 53fd3b5fe3..7aa489e932 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -45,7 +45,7 @@
/* forward declarations */
static uint16_t bgp_write(struct peer *);
-static uint16_t bgp_read(struct peer *);
+static uint16_t bgp_read(struct peer *peer, int *code_p);
static int bgp_process_writes(struct thread *);
static int bgp_process_reads(struct thread *);
static bool validate_header(struct peer *);
@@ -181,6 +181,7 @@ static int bgp_process_reads(struct thread *thread)
bool fatal = false; // whether fatal error occurred
bool added_pkt = false; // whether we pushed onto ->ibuf
/* clang-format on */
+ int code;
peer = THREAD_ARG(thread);
@@ -190,7 +191,7 @@ static int bgp_process_reads(struct thread *thread)
struct frr_pthread *fpt = bgp_pth_io;
frr_with_mutex(&peer->io_mtx) {
- status = bgp_read(peer);
+ status = bgp_read(peer, &code);
}
/* error checking phase */
@@ -203,6 +204,12 @@ static int bgp_process_reads(struct thread *thread)
/* problem; tear down session */
more = false;
fatal = true;
+
+ /* Handle the error in the main pthread, include the
+ * specific state change from 'bgp_read'.
+ */
+ thread_add_event(bm->master, bgp_packet_process_error,
+ peer, code, NULL);
}
while (more) {
@@ -228,7 +235,7 @@ static int bgp_process_reads(struct thread *thread)
pktsize = ntohs(pktsize);
/* if this fails we are seriously screwed */
- assert(pktsize <= BGP_MAX_PACKET_SIZE);
+ assert(pktsize <= peer->max_packet_size);
/*
* If we have that much data, chuck it into its own
@@ -236,6 +243,7 @@ static int bgp_process_reads(struct thread *thread)
*/
if (ringbuf_remain(ibw) >= pktsize) {
struct stream *pkt = stream_new(pktsize);
+
assert(STREAM_WRITEABLE(pkt) == pktsize);
assert(ringbuf_get(ibw, pkt->data, pktsize) == pktsize);
stream_set_endp(pkt, pktsize);
@@ -255,7 +263,7 @@ static int bgp_process_reads(struct thread *thread)
/* wipe buffer just in case someone screwed up */
ringbuf_wipe(peer->ibuf_work);
} else {
- assert(ringbuf_space(peer->ibuf_work) >= BGP_MAX_PACKET_SIZE);
+ assert(ringbuf_space(peer->ibuf_work) >= peer->max_packet_size);
thread_add_read(fpt->master, bgp_process_reads, peer, peer->fd,
&peer->t_read);
@@ -449,60 +457,39 @@ done : {
*
* @return status flag (see top-of-file)
*/
-static uint16_t bgp_read(struct peer *peer)
+static uint16_t bgp_read(struct peer *peer, int *code_p)
{
- size_t readsize; // how many bytes we want to read
ssize_t nbytes; // how many bytes we actually read
uint16_t status = 0;
- static uint8_t ibw[BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX];
- readsize = MIN(ringbuf_space(peer->ibuf_work), sizeof(ibw));
- nbytes = read(peer->fd, ibw, readsize);
+ nbytes = ringbuf_read(peer->ibuf_work, peer->fd);
/* EAGAIN or EWOULDBLOCK; come back later */
if (nbytes < 0 && ERRNO_IO_RETRY(errno)) {
SET_FLAG(status, BGP_IO_TRANS_ERR);
- /* Fatal error; tear down session */
} else if (nbytes < 0) {
+ /* Fatal error; tear down session */
flog_err(EC_BGP_UPDATE_RCV,
"%s [Error] bgp_read_packet error: %s", peer->host,
safe_strerror(errno));
- if (peer->status == Established) {
- if ((CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
- || CHECK_FLAG(peer->flags,
- PEER_FLAG_GRACEFUL_RESTART_HELPER))
- && CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
- peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
- SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
- } else
- peer->last_reset = PEER_DOWN_CLOSE_SESSION;
- }
+ /* Handle the error in the main pthread. */
+ if (code_p)
+ *code_p = TCP_fatal_error;
- BGP_EVENT_ADD(peer, TCP_fatal_error);
SET_FLAG(status, BGP_IO_FATAL_ERR);
- /* Received EOF / TCP session closed */
+
} else if (nbytes == 0) {
+ /* Received EOF / TCP session closed */
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s [Event] BGP connection closed fd %d",
peer->host, peer->fd);
- if (peer->status == Established) {
- if ((CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
- || CHECK_FLAG(peer->flags,
- PEER_FLAG_GRACEFUL_RESTART_HELPER))
- && CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
- peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
- SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
- } else
- peer->last_reset = PEER_DOWN_CLOSE_SESSION;
- }
+ /* Handle the error in the main pthread. */
+ if (code_p)
+ *code_p = TCP_connection_closed;
- BGP_EVENT_ADD(peer, TCP_connection_closed);
SET_FLAG(status, BGP_IO_FATAL_ERR);
- } else {
- assert(ringbuf_put(peer->ibuf_work, ibw, nbytes)
- == (size_t)nbytes);
}
return status;
@@ -558,7 +545,7 @@ static bool validate_header(struct peer *peer)
}
/* Minimum packet length check. */
- if ((size < BGP_HEADER_SIZE) || (size > BGP_MAX_PACKET_SIZE)
+ if ((size < BGP_HEADER_SIZE) || (size > peer->max_packet_size)
|| (type == BGP_MSG_OPEN && size < BGP_MSG_OPEN_MIN_SIZE)
|| (type == BGP_MSG_UPDATE && size < BGP_MSG_UPDATE_MIN_SIZE)
|| (type == BGP_MSG_NOTIFY && size < BGP_MSG_NOTIFY_MIN_SIZE)
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 5a31bd0243..bdab2ec36a 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -420,27 +420,19 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
/* Check address. */
if (afi == AFI_IP6 && safi == SAFI_LABELED_UNICAST) {
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
- char buf[BUFSIZ];
-
flog_err(
EC_BGP_UPDATE_RCV,
- "%s: IPv6 labeled-unicast NLRI is link-local address %s, ignoring",
- peer->host,
- inet_ntop(AF_INET6, &p.u.prefix6, buf,
- BUFSIZ));
+ "%s: IPv6 labeled-unicast NLRI is link-local address %pI6, ignoring",
+ peer->host, &p.u.prefix6);
continue;
}
if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
- char buf[BUFSIZ];
-
flog_err(
EC_BGP_UPDATE_RCV,
- "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
- peer->host,
- inet_ntop(AF_INET6, &p.u.prefix6, buf,
- BUFSIZ));
+ "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
+ peer->host, &p.u.prefix6);
continue;
}
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index ff5cfe05fb..d5fce115de 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -519,7 +519,6 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
struct listnode *mp_node, *mp_next_node;
struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
int mpath_changed, debug;
- char nh_buf[2][INET6_ADDRSTRLEN];
bool all_paths_lb;
char path_buf[PATH_ADDPATH_STR_BUFFER];
@@ -616,7 +615,8 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
all_paths_lb = false;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pRN: %s is still multipath, cur count %d",
bgp_dest_to_rnode(dest),
@@ -626,16 +626,13 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
mpath_changed = 1;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
- "%pRN: remove mpath %s nexthop %s, cur count %d",
+ "%pRN: remove mpath %s nexthop %pI4, cur count %d",
bgp_dest_to_rnode(dest),
path_buf,
- inet_ntop(AF_INET,
- &cur_mpath->attr
- ->nexthop,
- nh_buf[0],
- sizeof(nh_buf[0])),
+ &cur_mpath->attr->nexthop,
mpath_count);
}
}
@@ -660,14 +657,11 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
mpath_changed = 1;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- cur_mpath, path_buf);
+ cur_mpath, path_buf, sizeof(path_buf));
zlog_debug(
- "%pRN: remove mpath %s nexthop %s, cur count %d",
+ "%pRN: remove mpath %s nexthop %pI4, cur count %d",
bgp_dest_to_rnode(dest), path_buf,
- inet_ntop(AF_INET,
- &cur_mpath->attr->nexthop,
- nh_buf[0], sizeof(nh_buf[0])),
- mpath_count);
+ &cur_mpath->attr->nexthop, mpath_count);
}
cur_mpath = next_mpath;
} else {
@@ -710,16 +704,13 @@ void bgp_path_info_mpath_update(struct bgp_dest *dest,
all_paths_lb = false;
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- new_mpath, path_buf);
+ new_mpath, path_buf,
+ sizeof(path_buf));
zlog_debug(
- "%pRN: add mpath %s nexthop %s, cur count %d",
+ "%pRN: add mpath %s nexthop %pI4, cur count %d",
bgp_dest_to_rnode(dest),
path_buf,
- inet_ntop(AF_INET,
- &new_mpath->attr
- ->nexthop,
- nh_buf[0],
- sizeof(nh_buf[0])),
+ &new_mpath->attr->nexthop,
mpath_count);
}
}
diff --git a/bgpd/bgp_nb_config.c b/bgpd/bgp_nb_config.c
index f2443bd164..721ce5b5c6 100644
--- a/bgpd/bgp_nb_config.c
+++ b/bgpd/bgp_nb_config.c
@@ -69,7 +69,7 @@ int bgp_router_create(struct nb_cb_create_args *args)
{
const struct lyd_node *vrf_dnode;
struct bgp *bgp;
- struct vrf *vrf;
+ const char *vrf_name;
const char *name = NULL;
as_t as;
enum bgp_instance_type inst_type;
@@ -87,12 +87,12 @@ int bgp_router_create(struct nb_cb_create_args *args)
case NB_EV_APPLY:
vrf_dnode = yang_dnode_get_parent(args->dnode,
"control-plane-protocol");
- vrf = nb_running_get_entry(vrf_dnode, NULL, true);
+ vrf_name = yang_dnode_get_string(vrf_dnode, "./vrf");
- if (strmatch(vrf->name, VRF_DEFAULT_NAME)) {
+ if (strmatch(vrf_name, VRF_DEFAULT_NAME)) {
name = NULL;
} else {
- name = vrf->name;
+ name = vrf_name;
inst_type = BGP_INSTANCE_TYPE_VRF;
}
@@ -22977,8 +22977,9 @@ int bgp_neighbors_neighbor_afi_safis_afi_safi_l3vpn_ipv4_unicast_filter_config_p
case NB_EV_VALIDATE:
case NB_EV_PREPARE:
case NB_EV_ABORT:
+ return NB_OK;
case NB_EV_APPLY:
- /* TODO: implement me. */
+ bgp_neighbor_afi_safi_plist_modify(args, FILTER_IN);
break;
}
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index be2c474493..03ff27c7ca 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -233,7 +233,6 @@ int bgp_md5_unset(struct peer *peer)
int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
{
- char buf[INET_ADDRSTRLEN];
int ret = 0;
/* In case of peer is EBGP, we should set TTL for this connection. */
@@ -242,11 +241,8 @@ int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
if (ret) {
flog_err(
EC_LIB_SOCKET,
- "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
- __func__,
- inet_ntop(AF_INET, &peer->remote_id, buf,
- sizeof(buf)),
- errno);
+ "%s: Can't set TxTTL on peer (rtrid %pI4) socket, err = %d",
+ __func__, &peer->remote_id, errno);
return ret;
}
} else if (peer->gtsm_hops) {
@@ -258,11 +254,8 @@ int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
if (ret) {
flog_err(
EC_LIB_SOCKET,
- "%s: Can't set TxTTL on peer (rtrid %s) socket, err = %d",
- __func__,
- inet_ntop(AF_INET, &peer->remote_id, buf,
- sizeof(buf)),
- errno);
+ "%s: Can't set TxTTL on peer (rtrid %pI4) socket, err = %d",
+ __func__, &peer->remote_id, errno);
return ret;
}
ret = sockopt_minttl(peer->su.sa.sa_family, bgp_sock,
@@ -270,11 +263,8 @@ int bgp_set_socket_ttl(struct peer *peer, int bgp_sock)
if (ret) {
flog_err(
EC_LIB_SOCKET,
- "%s: Can't set MinTTL on peer (rtrid %s) socket, err = %d",
- __func__,
- inet_ntop(AF_INET, &peer->remote_id, buf,
- sizeof(buf)),
- errno);
+ "%s: Can't set MinTTL on peer (rtrid %pI4) socket, err = %d",
+ __func__, &peer->remote_id, errno);
return ret;
}
}
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 533518cf93..7642640218 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -538,6 +538,22 @@ static as_t bgp_capability_as4(struct peer *peer, struct capability_header *hdr)
return as4;
}
+static int bgp_capability_ext_message(struct peer *peer,
+ struct capability_header *hdr)
+{
+ if (hdr->length != CAPABILITY_CODE_EXT_MESSAGE_LEN) {
+ flog_err(
+ EC_BGP_PKT_OPEN,
+ "%s: BGP Extended Message capability has incorrect data length %d",
+ peer->host, hdr->length);
+ return -1;
+ }
+
+ SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV);
+
+ return 0;
+}
+
static int bgp_capability_addpath(struct peer *peer,
struct capability_header *hdr)
{
@@ -761,6 +777,7 @@ static const struct message capcode_str[] = {
{CAPABILITY_CODE_ORF_OLD, "ORF (Old)"},
{CAPABILITY_CODE_FQDN, "FQDN"},
{CAPABILITY_CODE_ENHANCED_RR, "Enhanced Route Refresh"},
+ {CAPABILITY_CODE_EXT_MESSAGE, "BGP Extended Message"},
{0}};
/* Minimum sizes for length field of each cap (so not inc. the header) */
@@ -778,6 +795,7 @@ static const size_t cap_minsizes[] = {
[CAPABILITY_CODE_ORF_OLD] = CAPABILITY_CODE_ORF_LEN,
[CAPABILITY_CODE_FQDN] = CAPABILITY_CODE_MIN_FQDN_LEN,
[CAPABILITY_CODE_ENHANCED_RR] = CAPABILITY_CODE_ENHANCED_LEN,
+ [CAPABILITY_CODE_EXT_MESSAGE] = CAPABILITY_CODE_EXT_MESSAGE_LEN,
};
/* value the capability must be a multiple of.
@@ -799,6 +817,7 @@ static const size_t cap_modsizes[] = {
[CAPABILITY_CODE_ORF_OLD] = 1,
[CAPABILITY_CODE_FQDN] = 1,
[CAPABILITY_CODE_ENHANCED_RR] = 1,
+ [CAPABILITY_CODE_EXT_MESSAGE] = 1,
};
/**
@@ -867,6 +886,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
case CAPABILITY_CODE_ENHE:
case CAPABILITY_CODE_FQDN:
case CAPABILITY_CODE_ENHANCED_RR:
+ case CAPABILITY_CODE_EXT_MESSAGE:
/* Check length. */
if (caphdr.length < cap_minsizes[caphdr.code]) {
zlog_info(
@@ -955,6 +975,9 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
case CAPABILITY_CODE_ENHE:
ret = bgp_capability_enhe(peer, &caphdr);
break;
+ case CAPABILITY_CODE_EXT_MESSAGE:
+ ret = bgp_capability_ext_message(peer, &caphdr);
+ break;
case CAPABILITY_CODE_FQDN:
ret = bgp_capability_hostname(peer, &caphdr);
break;
@@ -1191,6 +1214,12 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
}
}
+ /* Extended Message Support */
+ peer->max_packet_size =
+ CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV)
+ ? BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE
+ : BGP_MAX_PACKET_SIZE;
+
/* Check there are no common AFI/SAFIs and send Unsupported Capability
error. */
if (*mp_capability
@@ -1476,6 +1505,13 @@ void bgp_open_capability(struct stream *s, struct peer *peer)
local_as = peer->local_as;
stream_putl(s, local_as);
+ /* Extended Message Support */
+ SET_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_ADV);
+ stream_putc(s, BGP_OPEN_OPT_CAP);
+ stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN + 2);
+ stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE);
+ stream_putc(s, CAPABILITY_CODE_EXT_MESSAGE_LEN);
+
/* AddPath */
FOREACH_AFI_SAFI (afi, safi) {
if (peer->afc[afi][safi]) {
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index 471ac05c7c..bc6eedac85 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -54,6 +54,7 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
#define CAPABILITY_CODE_REFRESH_OLD 128 /* Route Refresh Capability(cisco) */
#define CAPABILITY_CODE_ORF_OLD 130 /* Cooperative Route Filtering Capability(cisco) */
+#define CAPABILITY_CODE_EXT_MESSAGE 6 /* Extended Message Support */
/* Capability Length */
#define CAPABILITY_CODE_MP_LEN 4
@@ -66,6 +67,7 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_MIN_FQDN_LEN 2
#define CAPABILITY_CODE_ENHANCED_LEN 0
#define CAPABILITY_CODE_ORF_LEN 5
+#define CAPABILITY_CODE_EXT_MESSAGE_LEN 0 /* Extended Message Support */
/* Cooperative Route Filtering Capability. */
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index c2e2de1c73..f04b89594e 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -144,7 +144,7 @@ static struct stream *bgp_update_packet_eor(struct peer *peer, afi_t afi,
zlog_debug("send End-of-RIB for %s to %s",
get_afi_safi_str(afi, safi, false), peer->host);
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ s = stream_new(peer->max_packet_size);
/* Make BGP update packet. */
bgp_packet_set_marker(s, BGP_MSG_UPDATE);
@@ -726,7 +726,7 @@ void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
/* ============================================== */
/* Allocate new stream. */
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ s = stream_new(peer->max_packet_size);
/* Make notify packet. */
bgp_packet_set_marker(s, BGP_MSG_NOTIFY);
@@ -864,7 +864,7 @@ void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ s = stream_new(peer->max_packet_size);
/* Make BGP update packet. */
if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
@@ -963,7 +963,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ s = stream_new(peer->max_packet_size);
/* Make BGP update packet. */
bgp_packet_set_marker(s, BGP_MSG_CAPABILITY);
@@ -2699,3 +2699,37 @@ void bgp_send_delayed_eor(struct bgp *bgp)
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
bgp_write_proceed_actions(peer);
}
+
+/*
+ * Task callback to handle socket error encountered in the io pthread. We avoid
+ * having the io pthread try to enqueue fsm events or mess with the peer
+ * struct.
+ */
+int bgp_packet_process_error(struct thread *thread)
+{
+ struct peer *peer;
+ int code;
+
+ peer = THREAD_ARG(thread);
+ code = THREAD_VAL(thread);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s [Event] BGP error %d on fd %d",
+ peer->host, peer->fd, code);
+
+ /* Closed connection or error on the socket */
+ if (peer->status == Established) {
+ if ((CHECK_FLAG(peer->flags, PEER_FLAG_GRACEFUL_RESTART)
+ || CHECK_FLAG(peer->flags,
+ PEER_FLAG_GRACEFUL_RESTART_HELPER))
+ && CHECK_FLAG(peer->sflags, PEER_STATUS_NSF_MODE)) {
+ peer->last_reset = PEER_DOWN_NSF_CLOSE_SESSION;
+ SET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
+ } else
+ peer->last_reset = PEER_DOWN_CLOSE_SESSION;
+ }
+
+ bgp_event_update(peer, code);
+
+ return 0;
+}
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index 525859a2da..d32f091d0c 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -83,4 +83,8 @@ extern int bgp_generate_updgrp_packets(struct thread *);
extern int bgp_process_packet(struct thread *);
extern void bgp_send_delayed_eor(struct bgp *bgp);
+
+/* Task callback to handle socket error encountered in the io pthread */
+int bgp_packet_process_error(struct thread *thread);
+
#endif /* _QUAGGA_BGP_PACKET_H */
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index f9e655b4e7..87fd5f28ca 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -97,6 +97,11 @@ DEFINE_HOOK(bgp_snmp_update_stats,
(struct bgp_node *rn, struct bgp_path_info *pi, bool added),
(rn, pi, added))
+DEFINE_HOOK(bgp_rpki_prefix_status,
+ (struct peer *peer, struct attr *attr,
+ const struct prefix *prefix),
+ (peer, attr, prefix))
+
/* Extern from bgp_dump.c */
extern const char *bgp_origin_str[];
extern const char *bgp_origin_long_str[];
@@ -525,13 +530,14 @@ static uint32_t bgp_med_value(struct attr *attr, struct bgp *bgp)
}
}
-void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf)
+void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
+ size_t buf_len)
{
if (pi->addpath_rx_id)
- sprintf(buf, "path %s (addpath rxid %d)", pi->peer->host,
- pi->addpath_rx_id);
+ snprintf(buf, buf_len, "path %s (addpath rxid %d)",
+ pi->peer->host, pi->addpath_rx_id);
else
- sprintf(buf, "path %s", pi->peer->host);
+ snprintf(buf, buf_len, "path %s", pi->peer->host);
}
/* Compare two bgp route entity. If 'new' is preferable over 'exist' return 1.
@@ -582,7 +588,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug)
- bgp_path_info_path_with_addpath_rx_str(new, new_buf);
+ bgp_path_info_path_with_addpath_rx_str(new, new_buf,
+ sizeof(new_buf));
if (exist == NULL) {
*reason = bgp_path_selection_first;
@@ -593,7 +600,8 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug) {
- bgp_path_info_path_with_addpath_rx_str(exist, exist_buf);
+ bgp_path_info_path_with_addpath_rx_str(exist, exist_buf,
+ sizeof(exist_buf));
zlog_debug("%s: Comparing %s flags 0x%x with %s flags 0x%x",
pfx_buf, new_buf, new->flags, exist_buf,
exist->flags);
@@ -621,10 +629,10 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
prefix2str(
bgp_dest_get_prefix(new->net), pfx_buf,
sizeof(*pfx_buf) * PREFIX2STR_BUFFER);
- bgp_path_info_path_with_addpath_rx_str(new,
- new_buf);
bgp_path_info_path_with_addpath_rx_str(
- exist, exist_buf);
+ new, new_buf, sizeof(new_buf));
+ bgp_path_info_path_with_addpath_rx_str(
+ exist, exist_buf, sizeof(exist_buf));
}
if (newattr->sticky && !existattr->sticky) {
@@ -987,7 +995,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (newm < existm) {
if (debug)
zlog_debug(
- "%s: %s wins over %s due to IGP metric %d < %d",
+ "%s: %s wins over %s due to IGP metric %u < %u",
pfx_buf, new_buf, exist_buf, newm, existm);
ret = 1;
}
@@ -995,7 +1003,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (newm > existm) {
if (debug)
zlog_debug(
- "%s: %s loses to %s due to IGP metric %d > %d",
+ "%s: %s loses to %s due to IGP metric %u > %u",
pfx_buf, new_buf, exist_buf, newm, existm);
ret = 0;
}
@@ -1017,7 +1025,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (newm < existm) {
if (debug)
zlog_debug(
- "%s: %s wins over %s due to CLUSTER_LIST length %d < %d",
+ "%s: %s wins over %s due to CLUSTER_LIST length %u < %u",
pfx_buf, new_buf, exist_buf,
newm, existm);
ret = 1;
@@ -1026,7 +1034,7 @@ static int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
if (newm > existm) {
if (debug)
zlog_debug(
- "%s: %s loses to %s due to CLUSTER_LIST length %d > %d",
+ "%s: %s loses to %s due to CLUSTER_LIST length %u > %u",
pfx_buf, new_buf, exist_buf,
newm, existm);
ret = 0;
@@ -2348,7 +2356,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug) {
bgp_path_info_path_with_addpath_rx_str(
- new_select, path_buf);
+ new_select, path_buf, sizeof(path_buf));
zlog_debug(
"%pBD: %s is the bestpath from AS %u",
dest, path_buf,
@@ -2422,8 +2430,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
*/
if (debug) {
if (new_select)
- bgp_path_info_path_with_addpath_rx_str(new_select,
- path_buf);
+ bgp_path_info_path_with_addpath_rx_str(
+ new_select, path_buf, sizeof(path_buf));
else
snprintf(path_buf, sizeof(path_buf), "NONE");
zlog_debug(
@@ -2438,7 +2446,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug)
bgp_path_info_path_with_addpath_rx_str(
- pi, path_buf);
+ pi, path_buf, sizeof(path_buf));
if (pi == new_select) {
if (debug)
@@ -3594,19 +3602,6 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (has_valid_label)
assert(label != NULL);
- /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
- * condition :
- * Suppress fib is enabled
- * BGP_OPT_NO_FIB is not enabled
- * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
- * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
- */
- if (BGP_SUPPRESS_FIB_ENABLED(bgp) &&
- (sub_type == BGP_ROUTE_NORMAL) &&
- (!bgp_option_check(BGP_OPT_NO_FIB)) &&
- (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
- SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
/* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */
if (!soft_reconfig
@@ -3788,6 +3783,19 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
evpn == NULL ? NULL : &evpn->gw_ip);
}
+ /* The flag BGP_NODE_FIB_INSTALL_PENDING is for the following
+ * condition :
+ * Suppress fib is enabled
+ * BGP_OPT_NO_FIB is not enabled
+ * Route type is BGP_ROUTE_NORMAL (peer learnt routes)
+ * Route is being installed first time (BGP_NODE_FIB_INSTALLED not set)
+ */
+ if (bgp_fibupd_safi(safi) && BGP_SUPPRESS_FIB_ENABLED(bgp)
+ && (sub_type == BGP_ROUTE_NORMAL)
+ && (!bgp_option_check(BGP_OPT_NO_FIB))
+ && (!CHECK_FLAG(dest->flags, BGP_NODE_FIB_INSTALLED)))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
attr_new = bgp_attr_intern(&new_attr);
/* If maximum prefix count is configured and current prefix
@@ -5247,26 +5255,18 @@ int bgp_nlri_parse_ip(struct peer *peer, struct attr *attr,
/* Check address. */
if (afi == AFI_IP6 && safi == SAFI_UNICAST) {
if (IN6_IS_ADDR_LINKLOCAL(&p.u.prefix6)) {
- char buf[BUFSIZ];
-
flog_err(
EC_BGP_UPDATE_RCV,
- "%s: IPv6 unicast NLRI is link-local address %s, ignoring",
- peer->host,
- inet_ntop(AF_INET6, &p.u.prefix6, buf,
- BUFSIZ));
+ "%s: IPv6 unicast NLRI is link-local address %pI6, ignoring",
+ peer->host, &p.u.prefix6);
continue;
}
if (IN6_IS_ADDR_MULTICAST(&p.u.prefix6)) {
- char buf[BUFSIZ];
-
flog_err(
EC_BGP_UPDATE_RCV,
- "%s: IPv6 unicast NLRI is multicast address %s, ignoring",
- peer->host,
- inet_ntop(AF_INET6, &p.u.prefix6, buf,
- BUFSIZ));
+ "%s: IPv6 unicast NLRI is multicast address %pI6, ignoring",
+ peer->host, &p.u.prefix6);
continue;
}
@@ -6389,7 +6389,8 @@ DEFPY_YANG (bgp_network, bgp_network_cmd,
int ret;
ret = netmask_str2prefix_str(address_str, netmask_str,
- addr_prefix_str);
+ addr_prefix_str,
+ sizeof(addr_prefix_str));
if (!ret) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -7550,6 +7551,21 @@ static const char *bgp_origin2str(uint8_t origin)
return "n/a";
}
+static const char *bgp_rpki_validation2str(int v_state)
+{
+ switch (v_state) {
+ case 1:
+ return "valid";
+ case 2:
+ return "not found";
+ case 3:
+ return "invalid";
+ default:
+ break;
+ }
+ return "ERROR";
+}
+
int bgp_aggregate_unset(struct bgp *bgp, struct prefix *prefix, afi_t afi,
safi_t safi, char *errmsg, size_t errmsg_len)
{
@@ -7780,7 +7796,8 @@ DEFPY_YANG(
char prefix_buf[PREFIX2STR_BUFFER];
if (addr_str) {
- if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf)
+ if (netmask_str2prefix_str(addr_str, mask_str, prefix_buf,
+ sizeof(prefix_buf))
== 0) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -9563,6 +9580,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
int i;
char *nexthop_hostname =
bgp_nexthop_hostname(path->peer, path->nexthop);
+ int rpki_validation_state = 0;
if (json_paths) {
json_path = json_object_new_object();
@@ -10161,6 +10179,20 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp,
}
}
+ const struct prefix *p = bgp_dest_get_prefix(bn);
+ if (p->family == AF_INET || p->family == AF_INET6)
+ rpki_validation_state = hook_call(bgp_rpki_prefix_status,
+ path->peer, path->attr, p);
+ if (rpki_validation_state) {
+ if (json_paths)
+ json_object_string_add(
+ json_path, "rpkiValidationState",
+ bgp_rpki_validation2str(rpki_validation_state));
+ else
+ vty_out(vty, ", validation-state: %s",
+ bgp_rpki_validation2str(rpki_validation_state));
+ }
+
if (json_bestpath)
json_object_object_add(json_path, "bestpath", json_bestpath);
@@ -12380,6 +12412,9 @@ static int bgp_table_stats_walker(struct thread *t)
case AFI_IP6:
space = IPV6_MAX_BITLEN;
break;
+ case AFI_L2VPN:
+ space = EVPN_ROUTE_PREFIXLEN;
+ break;
default:
return 0;
}
@@ -14308,6 +14343,21 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
while (pi) {
if (pi->extra && pi->extra->damp_info) {
pi_temp = pi->next;
+ struct bgp_damp_info *bdi =
+ pi->extra->damp_info;
+ if (bdi->lastrecord
+ == BGP_RECORD_UPDATE) {
+ bgp_aggregate_increment(
+ bgp,
+ &bdi->dest->p,
+ bdi->path,
+ bdi->afi,
+ bdi->safi);
+ bgp_process(bgp,
+ bdi->dest,
+ bdi->afi,
+ bdi->safi);
+ }
bgp_damp_info_free(
&pi->extra->damp_info,
&bgp->damp[afi][safi],
@@ -14334,7 +14384,7 @@ DEFUN (clear_ip_bgp_dampening,
"Clear route flap dampening information\n")
{
VTY_DECLVAR_CONTEXT(bgp, bgp);
- bgp_damp_info_clean(&bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
+ bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
SAFI_UNICAST);
return CMD_SUCCESS;
}
@@ -14383,7 +14433,7 @@ DEFUN (clear_ip_bgp_dampening_address_mask,
char prefix_str[BUFSIZ];
ret = netmask_str2prefix_str(argv[idx_ipv4]->arg, argv[idx_ipv4_2]->arg,
- prefix_str);
+ prefix_str, sizeof(prefix_str));
if (!ret) {
vty_out(vty, "%% Inconsistent address and mask\n");
return CMD_WARNING;
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 1060d2e60d..766e5ade92 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -598,7 +598,7 @@ extern void bgp_path_info_set_flag(struct bgp_dest *dest,
extern void bgp_path_info_unset_flag(struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t flag);
extern void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi,
- char *buf);
+ char *buf, size_t buf_len);
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index 3dc2cfbd5c..b7f3289ffc 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -4315,13 +4315,15 @@ DEFUN (match_community,
int idx_comm_list = 2;
int ret;
char *argstr;
+ size_t argstr_len;
if (argc == 4) {
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_comm_list]->arg)
- + strlen("exact-match") + 2);
+ argstr_len = strlen(argv[idx_comm_list]->arg)
+ + strlen("exact-match") + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s exact-match", argv[idx_comm_list]->arg);
+ snprintf(argstr, argstr_len, "%s exact-match",
+ argv[idx_comm_list]->arg);
} else
argstr = argv[idx_comm_list]->arg;
@@ -4362,13 +4364,15 @@ DEFUN (match_lcommunity,
int idx_lcomm_list = 2;
int ret;
char *argstr;
+ size_t argstr_len;
if (argc == 4) {
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_lcomm_list]->arg)
- + strlen("exact-match") + 2);
+ argstr_len = strlen(argv[idx_lcomm_list]->arg)
+ + strlen("exact-match") + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s exact-match", argv[idx_lcomm_list]->arg);
+ snprintf(argstr, argstr_len, "%s exact-match",
+ argv[idx_lcomm_list]->arg);
} else
argstr = argv[idx_lcomm_list]->arg;
@@ -5252,6 +5256,7 @@ DEFUN (set_aggregator_as,
int ret;
struct in_addr address;
char *argstr;
+ size_t argstr_len;
ret = inet_aton(argv[idx_ipv4]->arg, &address);
if (ret == 0) {
@@ -5259,11 +5264,12 @@ DEFUN (set_aggregator_as,
return CMD_WARNING_CONFIG_FAILED;
}
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_number]->arg)
- + strlen(argv[idx_ipv4]->arg) + 2);
+ argstr_len =
+ strlen(argv[idx_number]->arg) + strlen(argv[idx_ipv4]->arg) + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s %s", argv[idx_number]->arg, argv[idx_ipv4]->arg);
+ snprintf(argstr, argstr_len, "%s %s", argv[idx_number]->arg,
+ argv[idx_ipv4]->arg);
ret = generic_set_add(vty, VTY_GET_CONTEXT(route_map_index),
"aggregator as", argstr);
@@ -5289,6 +5295,7 @@ DEFUN (no_set_aggregator_as,
int ret;
struct in_addr address;
char *argstr;
+ size_t argstr_len;
if (argc <= idx_asn)
return generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
@@ -5300,11 +5307,11 @@ DEFUN (no_set_aggregator_as,
return CMD_WARNING_CONFIG_FAILED;
}
- argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED,
- strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg)
- + 2);
+ argstr_len = strlen(argv[idx_asn]->arg) + strlen(argv[idx_ip]->arg) + 2;
+ argstr = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, argstr_len);
- sprintf(argstr, "%s %s", argv[idx_asn]->arg, argv[idx_ip]->arg);
+ snprintf(argstr, argstr_len, "%s %s", argv[idx_asn]->arg,
+ argv[idx_ip]->arg);
ret = generic_set_delete(vty, VTY_GET_CONTEXT(route_map_index),
"aggregator as", argstr);
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 6bb33ff859..42951efb01 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -562,6 +562,7 @@ static int bgp_rpki_module_init(void)
{
lrtr_set_alloc_functions(malloc_wrapper, realloc_wrapper, free_wrapper);
+ hook_register(bgp_rpki_prefix_status, rpki_validate_prefix);
hook_register(frr_late_init, bgp_rpki_init);
hook_register(frr_early_fini, &bgp_rpki_fini);
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 022a6413e2..7e3aa2a48a 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -205,8 +205,14 @@ static ssize_t printfrr_bd(char *buf, size_t bsz, const char *fmt,
int prec, const void *ptr)
{
const struct bgp_dest *dest = ptr;
- const struct prefix *p = bgp_dest_get_prefix(dest);
+ const struct prefix *p;
+
+ if (dest) {
+ p = bgp_dest_get_prefix(dest);
+ prefix2str(p, buf, bsz);
+ } else {
+ strlcpy(buf, "NULL", bsz);
+ }
- prefix2str(p, buf, bsz);
return 2;
}
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index 621a14014f..2600eda42e 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -79,8 +79,11 @@ static void update_subgroup_checkin(struct update_subgroup *subgrp,
subgrp->uptime = bgp_clock();
}
-static void sync_init(struct update_subgroup *subgrp)
+static void sync_init(struct update_subgroup *subgrp,
+ struct update_group *updgrp)
{
+ struct peer *peer = UPDGRP_PEER(updgrp);
+
subgrp->sync =
XCALLOC(MTYPE_BGP_SYNCHRONISE, sizeof(struct bgp_synchronize));
bgp_adv_fifo_init(&subgrp->sync->update);
@@ -91,7 +94,7 @@ static void sync_init(struct update_subgroup *subgrp)
/* We use a larger buffer for subgrp->work in the event that:
* - We RX a BGP_UPDATE where the attributes alone are just
- * under BGP_MAX_PACKET_SIZE
+ * under 4096 or 65535 (if Extended Message capability negotiated).
* - The user configures an outbound route-map that does many as-path
* prepends or adds many communities. At most they can have
* CMD_ARGC_MAX
@@ -103,9 +106,9 @@ static void sync_init(struct update_subgroup *subgrp)
* bounds
* checking for every single attribute as we construct an UPDATE.
*/
- subgrp->work =
- stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
- subgrp->scratch = stream_new(BGP_MAX_PACKET_SIZE);
+ subgrp->work = stream_new(peer->max_packet_size
+ + BGP_MAX_PACKET_SIZE_OVERFLOW);
+ subgrp->scratch = stream_new(peer->max_packet_size);
}
static void sync_delete(struct update_subgroup *subgrp)
@@ -143,6 +146,7 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
dst->flags = src->flags;
dst->af_flags[afi][safi] = src->af_flags[afi][safi];
dst->pmax_out[afi][safi] = src->pmax_out[afi][safi];
+ dst->max_packet_size = src->max_packet_size;
XFREE(MTYPE_BGP_PEER_HOST, dst->host);
dst->host = XSTRDUP(MTYPE_BGP_PEER_HOST, src->host);
@@ -800,7 +804,7 @@ update_subgroup_create(struct update_group *updgrp)
subgrp = XCALLOC(MTYPE_BGP_UPD_SUBGRP, sizeof(struct update_subgroup));
update_subgroup_checkin(subgrp, updgrp);
subgrp->v_coalesce = (UPDGRP_INST(updgrp))->coalesce_time;
- sync_init(subgrp);
+ sync_init(subgrp, updgrp);
bpacket_queue_init(SUBGRP_PKTQ(subgrp));
bpacket_queue_add(SUBGRP_PKTQ(subgrp), NULL, NULL);
TAILQ_INIT(&(subgrp->adjq));
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index a13a5395b4..6418decd16 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -350,8 +350,6 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
struct stream *s = NULL;
bpacket_attr_vec *vec;
struct peer *peer;
- char buf[BUFSIZ];
- char buf2[BUFSIZ];
struct bgp_filter *filter;
s = stream_dup(pkt->buffer);
@@ -568,25 +566,24 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
if (nhlen == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
|| nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
zlog_debug(
- "u%" PRIu64 ":s%" PRIu64" %s send UPDATE w/ mp_nexthops %s, %s%s",
+ "u%" PRIu64 ":s%" PRIu64
+ " %s send UPDATE w/ mp_nexthops %pI6, %pI6%s",
PAF_SUBGRP(paf)->update_group->id,
PAF_SUBGRP(paf)->id, peer->host,
- inet_ntop(AF_INET6, mod_v6nhg, buf,
- BUFSIZ),
- inet_ntop(AF_INET6, mod_v6nhl, buf2,
- BUFSIZ),
+ mod_v6nhg, mod_v6nhl,
(nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL
? " and RD"
: ""));
else
- zlog_debug("u%" PRIu64 ":s%" PRIu64" %s send UPDATE w/ mp_nexthop %s%s",
- PAF_SUBGRP(paf)->update_group->id,
- PAF_SUBGRP(paf)->id, peer->host,
- inet_ntop(AF_INET6, mod_v6nhg, buf,
- BUFSIZ),
- (nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL
- ? " and RD"
- : ""));
+ zlog_debug(
+ "u%" PRIu64 ":s%" PRIu64
+ " %s send UPDATE w/ mp_nexthop %pI6%s",
+ PAF_SUBGRP(paf)->update_group->id,
+ PAF_SUBGRP(paf)->id, peer->host,
+ mod_v6nhg,
+ (nhlen == BGP_ATTR_NHLEN_VPNV6_GLOBAL
+ ? " and RD"
+ : ""));
}
} else if (paf->afi == AFI_L2VPN) {
struct in_addr v4nh, *mod_v4nh;
@@ -898,11 +895,13 @@ next:
packet = stream_dup(s);
bgp_packet_set_size(packet);
if (bgp_debug_update(NULL, NULL, subgrp->update_group, 0))
- zlog_debug("u%" PRIu64 ":s%" PRIu64" send UPDATE len %zd numpfx %d",
- subgrp->update_group->id, subgrp->id,
- (stream_get_endp(packet)
- - stream_get_getp(packet)),
- num_pfx);
+ zlog_debug(
+ "u%" PRIu64 ":s%" PRIu64
+ " send UPDATE len %zd (max message len: %hu) numpfx %d",
+ subgrp->update_group->id, subgrp->id,
+ (stream_get_endp(packet)
+ - stream_get_getp(packet)),
+ peer->max_packet_size, num_pfx);
pkt = bpacket_queue_add(SUBGRP_PKTQ(subgrp), packet, &vecarr);
stream_reset(s);
stream_reset(snlri);
@@ -1128,7 +1127,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
tx_id_buf, attrstr);
}
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ s = stream_new(peer->max_packet_size);
/* Make BGP update packet. */
bgp_packet_set_marker(s, BGP_MSG_UPDATE);
@@ -1206,7 +1205,7 @@ void subgroup_default_withdraw_packet(struct update_subgroup *subgrp)
tx_id_buf);
}
- s = stream_new(BGP_MAX_PACKET_SIZE);
+ s = stream_new(peer->max_packet_size);
/* Make BGP update packet. */
bgp_packet_set_marker(s, BGP_MSG_UPDATE);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index f8ef5e2aa2..a4e56c95c8 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -1483,8 +1483,26 @@ DEFUN_YANG(no_router_bgp,
struct bgp *tmp_bgp;
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) {
- if (tmp_bgp->inst_type
- == BGP_INSTANCE_TYPE_VRF) {
+ if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+ if (CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+ BGP_CONFIG_MPLSVPN_TO_VRF_IMPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_MPLSVPN_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_IP6][SAFI_UNICAST],
+ BGP_CONFIG_VRF_TO_VRF_EXPORT) ||
+ (bgp == bgp_get_evpn() &&
+ (CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV4_UNICAST) ||
+ CHECK_FLAG(tmp_bgp->af_flags[AFI_L2VPN][SAFI_EVPN],
+ BGP_L2VPN_EVPN_ADVERTISE_IPV6_UNICAST))) ||
+ (tmp_bgp->vnihash && hashcount(tmp_bgp->vnihash))) {
vty_out(vty,
"%% Cannot delete default BGP instance. Dependent VRF instances exist\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -12953,6 +12971,28 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
"received");
}
+ /* Extended Message Support */
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV)
+ && CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_RCV))
+ json_object_string_add(
+ json_cap, "extendedMessage",
+ "advertisedAndReceived");
+ else if (CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV))
+ json_object_string_add(
+ json_cap, "extendedMessage",
+ "advertised");
+ else if (CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_RCV))
+ json_object_string_add(
+ json_cap, "extendedMessage",
+ "received");
+
/* AddPath */
if (CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_RCV)
|| CHECK_FLAG(p->cap,
@@ -13431,6 +13471,29 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
vty_out(vty, "\n");
}
+ /* Extended Message Support */
+ if (CHECK_FLAG(p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_RCV)
+ || CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV)) {
+ vty_out(vty, " Extended Message:");
+ if (CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV))
+ vty_out(vty, " advertised");
+ if (CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_RCV))
+ vty_out(vty, " %sreceived",
+ CHECK_FLAG(
+ p->cap,
+ PEER_CAP_EXTENDED_MESSAGE_ADV)
+ ? "and "
+ : "");
+ vty_out(vty, "\n");
+ }
+
/* AddPath */
if (CHECK_FLAG(p->cap, PEER_CAP_ADDPATH_RCV)
|| CHECK_FLAG(p->cap,
@@ -18077,6 +18140,11 @@ void bgp_vty_init(void)
install_element(BGP_EVPN_NODE, &neighbor_attr_unchanged_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_FLOWSPECV4_NODE, &no_neighbor_attr_unchanged_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &neighbor_attr_unchanged_cmd);
+ install_element(BGP_FLOWSPECV6_NODE, &no_neighbor_attr_unchanged_cmd);
+
/* "nexthop-local unchanged" commands */
install_element(BGP_IPV6_NODE, &neighbor_nexthop_local_unchanged_cmd);
install_element(BGP_IPV6_NODE,
@@ -19037,7 +19105,7 @@ static void community_list_perror(struct vty *vty, int ret)
/*community-list standard */
DEFUN (community_list_standard,
bgp_community_list_standard_cmd,
- "bgp community-list <(1-99)|standard WORD> [seq (1-4294967295)] <deny|permit> AA:NN...",
+ "bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
BGP_STR
COMMUNITY_LIST_STR
"Community list number (standard)\n"
@@ -19055,7 +19123,7 @@ DEFUN (community_list_standard,
int style = COMMUNITY_LIST_STANDARD;
int idx = 0;
- argv_find(argv, argc, "(1-4294967295)", &idx);
+ argv_find(argv, argc, "(0-4294967295)", &idx);
if (idx)
seq = argv[idx]->arg;
@@ -19084,7 +19152,7 @@ DEFUN (community_list_standard,
DEFUN (no_community_list_standard_all,
no_bgp_community_list_standard_all_cmd,
- "no bgp community-list <(1-99)|standard WORD> [seq (1-4294967295)] <deny|permit> AA:NN...",
+ "no bgp community-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
NO_STR
BGP_STR
COMMUNITY_LIST_STR
@@ -19104,7 +19172,7 @@ DEFUN (no_community_list_standard_all,
char *seq = NULL;
int idx = 0;
- argv_find(argv, argc, "(1-4294967295)", &idx);
+ argv_find(argv, argc, "(0-4294967295)", &idx);
if (idx)
seq = argv[idx]->arg;
@@ -19150,7 +19218,7 @@ ALIAS(no_community_list_standard_all, no_bgp_community_list_standard_all_list_cm
/*community-list expanded */
DEFUN (community_list_expanded_all,
bgp_community_list_expanded_all_cmd,
- "bgp community-list <(100-500)|expanded WORD> [seq (1-4294967295)] <deny|permit> AA:NN...",
+ "bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
BGP_STR
COMMUNITY_LIST_STR
"Community list number (expanded)\n"
@@ -19168,7 +19236,7 @@ DEFUN (community_list_expanded_all,
int style = COMMUNITY_LIST_EXPANDED;
int idx = 0;
- argv_find(argv, argc, "(1-4294967295)", &idx);
+ argv_find(argv, argc, "(0-4294967295)", &idx);
if (idx)
seq = argv[idx]->arg;
@@ -19198,7 +19266,7 @@ DEFUN (community_list_expanded_all,
DEFUN (no_community_list_expanded_all,
no_bgp_community_list_expanded_all_cmd,
- "no bgp community-list <(100-500)|expanded WORD> [seq (1-4294967295)] <deny|permit> AA:NN...",
+ "no bgp community-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
NO_STR
BGP_STR
COMMUNITY_LIST_STR
@@ -19218,7 +19286,7 @@ DEFUN (no_community_list_expanded_all,
int style = COMMUNITY_LIST_EXPANDED;
int idx = 0;
- argv_find(argv, argc, "(1-4294967295)", &idx);
+ argv_find(argv, argc, "(0-4294967295)", &idx);
if (idx)
seq = argv[idx]->arg;
@@ -19371,7 +19439,7 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc,
char *cl_name;
char *seq = NULL;
- if (argv_find(argv, argc, "(1-4294967295)", &idx))
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
seq = argv[idx]->arg;
idx = 0;
@@ -19420,7 +19488,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc,
int idx = 0;
char *seq = NULL;
- if (argv_find(argv, argc, "(1-4294967295)", &idx))
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
seq = argv[idx]->arg;
idx = 0;
@@ -19468,7 +19536,7 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc,
DEFUN (lcommunity_list_standard,
bgp_lcommunity_list_standard_cmd,
- "bgp large-community-list (1-99) [seq (1-4294967295)] <deny|permit> AA:BB:CC...",
+ "bgp large-community-list (1-99) [seq (0-4294967295)] <deny|permit> AA:BB:CC...",
BGP_STR
LCOMMUNITY_LIST_STR
"Large Community list number (standard)\n"
@@ -19484,7 +19552,7 @@ DEFUN (lcommunity_list_standard,
DEFUN (lcommunity_list_expanded,
bgp_lcommunity_list_expanded_cmd,
- "bgp large-community-list (100-500) [seq (1-4294967295)] <deny|permit> LINE...",
+ "bgp large-community-list (100-500) [seq (0-4294967295)] <deny|permit> LINE...",
BGP_STR
LCOMMUNITY_LIST_STR
"Large Community list number (expanded)\n"
@@ -19500,7 +19568,7 @@ DEFUN (lcommunity_list_expanded,
DEFUN (lcommunity_list_name_standard,
bgp_lcommunity_list_name_standard_cmd,
- "bgp large-community-list standard WORD [seq (1-4294967295)] <deny|permit> AA:BB:CC...",
+ "bgp large-community-list standard WORD [seq (0-4294967295)] <deny|permit> AA:BB:CC...",
BGP_STR
LCOMMUNITY_LIST_STR
"Specify standard large-community-list\n"
@@ -19517,7 +19585,7 @@ DEFUN (lcommunity_list_name_standard,
DEFUN (lcommunity_list_name_expanded,
bgp_lcommunity_list_name_expanded_cmd,
- "bgp large-community-list expanded WORD [seq (1-4294967295)] <deny|permit> LINE...",
+ "bgp large-community-list expanded WORD [seq (0-4294967295)] <deny|permit> LINE...",
BGP_STR
LCOMMUNITY_LIST_STR
"Specify expanded large-community-list\n"
@@ -19574,7 +19642,7 @@ DEFUN (no_lcommunity_list_name_expanded_all,
DEFUN (no_lcommunity_list_standard,
no_bgp_lcommunity_list_standard_cmd,
- "no bgp large-community-list (1-99) [seq (1-4294967295)] <deny|permit> AA:AA:NN...",
+ "no bgp large-community-list (1-99) [seq (0-4294967295)] <deny|permit> AA:AA:NN...",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19591,7 +19659,7 @@ DEFUN (no_lcommunity_list_standard,
DEFUN (no_lcommunity_list_expanded,
no_bgp_lcommunity_list_expanded_cmd,
- "no bgp large-community-list (100-500) [seq (1-4294967295)] <deny|permit> LINE...",
+ "no bgp large-community-list (100-500) [seq (0-4294967295)] <deny|permit> LINE...",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19608,7 +19676,7 @@ DEFUN (no_lcommunity_list_expanded,
DEFUN (no_lcommunity_list_name_standard,
no_bgp_lcommunity_list_name_standard_cmd,
- "no bgp large-community-list standard WORD [seq (1-4294967295)] <deny|permit> AA:AA:NN...",
+ "no bgp large-community-list standard WORD [seq (0-4294967295)] <deny|permit> AA:AA:NN...",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19626,7 +19694,7 @@ DEFUN (no_lcommunity_list_name_standard,
DEFUN (no_lcommunity_list_name_expanded,
no_bgp_lcommunity_list_name_expanded_cmd,
- "no bgp large-community-list expanded WORD [seq (1-4294967295)] <deny|permit> LINE...",
+ "no bgp large-community-list expanded WORD [seq (0-4294967295)] <deny|permit> LINE...",
NO_STR
BGP_STR
LCOMMUNITY_LIST_STR
@@ -19728,7 +19796,7 @@ DEFUN (show_lcommunity_list_arg,
DEFUN (extcommunity_list_standard,
bgp_extcommunity_list_standard_cmd,
- "bgp extcommunity-list <(1-99)|standard WORD> [seq (1-4294967295)] <deny|permit> AA:NN...",
+ "bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
BGP_STR
EXTCOMMUNITY_LIST_STR
"Extended Community list number (standard)\n"
@@ -19751,7 +19819,7 @@ DEFUN (extcommunity_list_standard,
argv_find(argv, argc, "WORD", &idx);
cl_number_or_name = argv[idx]->arg;
- if (argv_find(argv, argc, "(1-4294967295)", &idx))
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
seq = argv[idx]->arg;
direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
@@ -19774,7 +19842,7 @@ DEFUN (extcommunity_list_standard,
DEFUN (extcommunity_list_name_expanded,
bgp_extcommunity_list_name_expanded_cmd,
- "bgp extcommunity-list <(100-500)|expanded WORD> [seq (1-4294967295)] <deny|permit> LINE...",
+ "bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> LINE...",
BGP_STR
EXTCOMMUNITY_LIST_STR
"Extended Community list number (expanded)\n"
@@ -19796,7 +19864,7 @@ DEFUN (extcommunity_list_name_expanded,
argv_find(argv, argc, "WORD", &idx);
cl_number_or_name = argv[idx]->arg;
- if (argv_find(argv, argc, "(1-4294967295)", &idx))
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
seq = argv[idx]->arg;
direct = argv_find(argv, argc, "permit", &idx) ? COMMUNITY_PERMIT
@@ -19819,7 +19887,7 @@ DEFUN (extcommunity_list_name_expanded,
DEFUN (no_extcommunity_list_standard_all,
no_bgp_extcommunity_list_standard_all_cmd,
- "no bgp extcommunity-list <(1-99)|standard WORD> [seq (1-4294967295)] <deny|permit> AA:NN...",
+ "no bgp extcommunity-list <(1-99)|standard WORD> [seq (0-4294967295)] <deny|permit> AA:NN...",
NO_STR
BGP_STR
EXTCOMMUNITY_LIST_STR
@@ -19839,7 +19907,7 @@ DEFUN (no_extcommunity_list_standard_all,
char *seq = NULL;
int idx = 0;
- if (argv_find(argv, argc, "(1-4294967295)", &idx))
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
seq = argv[idx]->arg;
idx = 0;
@@ -19883,7 +19951,7 @@ ALIAS(no_extcommunity_list_standard_all,
DEFUN (no_extcommunity_list_expanded_all,
no_bgp_extcommunity_list_expanded_all_cmd,
- "no bgp extcommunity-list <(100-500)|expanded WORD> [seq (1-4294967295)] <deny|permit> LINE...",
+ "no bgp extcommunity-list <(100-500)|expanded WORD> [seq (0-4294967295)] <deny|permit> LINE...",
NO_STR
BGP_STR
EXTCOMMUNITY_LIST_STR
@@ -19903,7 +19971,7 @@ DEFUN (no_extcommunity_list_expanded_all,
char *seq = NULL;
int idx = 0;
- if (argv_find(argv, argc, "(1-4294967295)", &idx))
+ if (argv_find(argv, argc, "(0-4294967295)", &idx))
seq = argv[idx]->arg;
idx = 0;
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index d397a5241a..c554332255 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -942,12 +942,9 @@ static bool bgp_table_map_apply(struct route_map *map, const struct prefix *p,
if (bgp_debug_zebra(p)) {
if (p->family == AF_INET) {
- char buf[2][INET_ADDRSTRLEN];
zlog_debug(
- "Zebra rmap deny: IPv4 route %pFX nexthop %s",
- p,
- inet_ntop(AF_INET, &path->attr->nexthop, buf[1],
- sizeof(buf[1])));
+ "Zebra rmap deny: IPv4 route %pFX nexthop %pI4",
+ p, &path->attr->nexthop);
}
if (p->family == AF_INET6) {
char buf[2][INET6_ADDRSTRLEN];
@@ -2660,6 +2657,7 @@ static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS)
char buf[ESI_STR_LEN];
struct in_addr originator_ip;
uint8_t active;
+ uint8_t bypass;
uint16_t df_pref;
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -2671,14 +2669,16 @@ static int bgp_zebra_process_local_es_add(ZAPI_CALLBACK_ARGS)
originator_ip.s_addr = stream_get_ipv4(s);
active = stream_getc(s);
df_pref = stream_getw(s);
+ bypass = stream_getc(s);
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug(
- "Rx add ESI %s originator-ip %pI4 active %u df_pref %u",
- esi_to_str(&esi, buf, sizeof(buf)),
- &originator_ip, active, df_pref);
+ "Rx add ESI %s originator-ip %pI4 active %u df_pref %u %s",
+ esi_to_str(&esi, buf, sizeof(buf)), &originator_ip,
+ active, df_pref, bypass ? "bypass" : "");
- bgp_evpn_local_es_add(bgp, &esi, originator_ip, active, df_pref);
+ bgp_evpn_local_es_add(bgp, &esi, originator_ip, active, df_pref,
+ !!bypass);
return 0;
}
@@ -2739,14 +2739,12 @@ static int bgp_zebra_process_local_es_evi(ZAPI_CALLBACK_ARGS)
static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
{
int filter = 0;
- char buf[ETHER_ADDR_STRLEN];
vni_t l3vni = 0;
struct ethaddr svi_rmac, vrr_rmac = {.octet = {0} };
struct in_addr originator_ip;
struct stream *s;
ifindex_t svi_ifindex;
bool is_anycast_mac = false;
- char buf1[ETHER_ADDR_STRLEN];
memset(&svi_rmac, 0, sizeof(struct ethaddr));
memset(&originator_ip, 0, sizeof(struct in_addr));
@@ -2761,13 +2759,12 @@ static int bgp_zebra_process_local_l3vni(ZAPI_CALLBACK_ARGS)
is_anycast_mac = stream_getl(s);
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("Rx L3-VNI ADD VRF %s VNI %u RMAC svi-mac %s vrr-mac %s filter %s svi-if %u",
- vrf_id_to_name(vrf_id), l3vni,
- prefix_mac2str(&svi_rmac, buf, sizeof(buf)),
- prefix_mac2str(&vrr_rmac, buf1,
- sizeof(buf1)),
- filter ? "prefix-routes-only" : "none",
- svi_ifindex);
+ zlog_debug(
+ "Rx L3-VNI ADD VRF %s VNI %u RMAC svi-mac %pEA vrr-mac %pEA filter %s svi-if %u",
+ vrf_id_to_name(vrf_id), l3vni, &svi_rmac,
+ &vrr_rmac,
+ filter ? "prefix-routes-only" : "none",
+ svi_ifindex);
bgp_evpn_local_l3vni_add(l3vni, vrf_id, &svi_rmac, &vrr_rmac,
originator_ip, filter, svi_ifindex,
@@ -2827,8 +2824,6 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)
struct ethaddr mac;
struct ipaddr ip;
int ipa_len;
- char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
uint8_t flags = 0;
uint32_t seqnum = 0;
int state = 0;
@@ -2868,11 +2863,11 @@ static int bgp_zebra_process_local_macip(ZAPI_CALLBACK_ARGS)
return 0;
if (BGP_DEBUG(zebra, ZEBRA))
- zlog_debug("%u:Recv MACIP %s f 0x%x MAC %s IP %s VNI %u seq %u state %d ESI %s",
- vrf_id, (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
- flags, prefix_mac2str(&mac, buf, sizeof(buf)),
- ipaddr2str(&ip, buf1, sizeof(buf1)), vni, seqnum,
- state, esi_to_str(&esi, buf2, sizeof(buf2)));
+ zlog_debug(
+ "%u:Recv MACIP %s f 0x%x MAC %pEA IP %pIA VNI %u seq %u state %d ESI %s",
+ vrf_id, (cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del", flags,
+ &mac, &ip, vni, seqnum, state,
+ esi_to_str(&esi, buf2, sizeof(buf2)));
if (cmd == ZEBRA_MACIP_ADD)
return bgp_evpn_local_macip_add(bgp, vni, &mac, &ip,
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index b11fd5288a..33c8f3c1f0 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1345,6 +1345,7 @@ struct peer *peer_new(struct bgp *bgp)
peer->bgp = bgp_lock(bgp);
peer = peer_lock(peer); /* initial reference */
peer->password = NULL;
+ peer->max_packet_size = BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE;
/* Set default flags. */
FOREACH_AFI_SAFI (afi, safi) {
@@ -1379,7 +1380,7 @@ struct peer *peer_new(struct bgp *bgp)
/* We use a larger buffer for peer->obuf_work in the event that:
* - We RX a BGP_UPDATE where the attributes alone are just
- * under BGP_MAX_PACKET_SIZE
+ * under BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE.
* - The user configures an outbound route-map that does many as-path
* prepends or adds many communities. At most they can have
* CMD_ARGC_MAX args in a route-map so there is a finite limit on how
@@ -1389,12 +1390,12 @@ struct peer *peer_new(struct bgp *bgp)
* bounds checking for every single attribute as we construct an
* UPDATE.
*/
- peer->obuf_work =
- stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
- peer->ibuf_work =
- ringbuf_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
+ peer->obuf_work = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE
+ + BGP_MAX_PACKET_SIZE_OVERFLOW);
+ peer->ibuf_work = ringbuf_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE
+ * BGP_READ_PACKET_MAX);
- peer->scratch = stream_new(BGP_MAX_PACKET_SIZE);
+ peer->scratch = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
bgp_sync_init(peer);
@@ -5246,8 +5247,8 @@ int peer_timers_set(struct peer *peer, uint32_t keepalive, uint32_t holdtime)
/* Set flag and configuration on peer-group member. */
SET_FLAG(member->flags, PEER_FLAG_TIMER);
- PEER_ATTR_INHERIT(peer, peer->group, holdtime);
- PEER_ATTR_INHERIT(peer, peer->group, keepalive);
+ PEER_ATTR_INHERIT(member, peer->group, holdtime);
+ PEER_ATTR_INHERIT(member, peer->group, keepalive);
}
return 0;
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index e79dccdab8..3f5ec07796 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -859,6 +859,7 @@ typedef enum {
#define BGP_MARKER_SIZE 16
#define BGP_HEADER_SIZE 19
#define BGP_MAX_PACKET_SIZE 4096
+#define BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE 65535
#define BGP_MAX_PACKET_SIZE_OVERFLOW 1024
/*
@@ -1122,6 +1123,8 @@ struct peer {
#define PEER_CAP_HOSTNAME_RCV (1U << 16) /* hostname received */
#define PEER_CAP_ENHANCED_RR_ADV (1U << 17) /* enhanced rr advertised */
#define PEER_CAP_ENHANCED_RR_RCV (1U << 18) /* enhanced rr received */
+#define PEER_CAP_EXTENDED_MESSAGE_ADV (1U << 19)
+#define PEER_CAP_EXTENDED_MESSAGE_RCV (1U << 20)
/* Capability flags (reset in bgp_stop) */
uint32_t af_cap[AFI_MAX][SAFI_MAX];
@@ -1564,6 +1567,9 @@ struct peer {
/* Sender side AS path loop detection. */
bool as_path_loop_detection;
+ /* Extended Message Support */
+ uint16_t max_packet_size;
+
/* Conditional advertisement */
bool advmap_config_change[AFI_MAX][SAFI_MAX];
bool advmap_table_change;
@@ -2365,6 +2371,11 @@ DECLARE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp))
DECLARE_HOOK(bgp_snmp_update_stats,
(struct bgp_node *rn, struct bgp_path_info *pi, bool added),
(rn, pi, added))
+DECLARE_HOOK(bgp_rpki_prefix_status,
+ (struct peer * peer, struct attr *attr,
+ const struct prefix *prefix),
+ (peer, attr, prefix))
+
void peer_nsf_stop(struct peer *peer);
#endif /* _QUAGGA_BGPD_H */
diff --git a/configure.ac b/configure.ac
index f3d1f38986..139fca7c42 100755
--- a/configure.ac
+++ b/configure.ac
@@ -794,6 +794,20 @@ fi
#
AS_IF([test "$host" = "$build"], [
+ AC_CHECK_HEADER([gelf.h], [], [
+ AC_MSG_ERROR([libelf headers are required for building clippy. (Host only when cross-compiling.)])
+ ])
+ AC_CHECK_LIB([elf], [elf_memory], [], [
+ AC_MSG_ERROR([libelf is required for building clippy. (Host only when cross-compiling.)])
+ ])
+
+ AC_CHECK_LIB([elf], [elf_getdata_rawchunk], [
+ AC_DEFINE([HAVE_ELF_GETDATA_RAWCHUNK], [1], [Have elf_getdata_rawchunk()])
+ ])
+ AC_CHECK_LIB([elf], [gelf_getnote], [
+ AC_DEFINE([HAVE_GELF_GETNOTE], [1], [Have gelf_getnote()])
+ ])
+
FRR_PYTHON_DEV
], [
FRR_PYTHON
diff --git a/debian/control b/debian/control
index b9e96b55d0..7a08cbbdb0 100644
--- a/debian/control
+++ b/debian/control
@@ -13,6 +13,7 @@ Build-Depends: bison,
install-info,
libc-ares-dev,
libcap-dev,
+ libelf-dev,
libjson-c-dev | libjson0-dev,
libpam0g-dev | libpam-dev,
libpcre3-dev,
diff --git a/doc/developer/building-frr-for-archlinux.rst b/doc/developer/building-frr-for-archlinux.rst
index f62add5963..e589a9f724 100644
--- a/doc/developer/building-frr-for-archlinux.rst
+++ b/doc/developer/building-frr-for-archlinux.rst
@@ -11,7 +11,7 @@ Installing Dependencies
git autoconf automake libtool make cmake pcre readline texinfo \
pkg-config pam json-c bison flex python-pytest \
c-ares python systemd python2-ipaddress python-sphinx \
- systemd-libs net-snmp perl libcap
+ systemd-libs net-snmp perl libcap libelf
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-centos6.rst b/doc/developer/building-frr-for-centos6.rst
index b730a5ee32..5d3be492de 100644
--- a/doc/developer/building-frr-for-centos6.rst
+++ b/doc/developer/building-frr-for-centos6.rst
@@ -45,7 +45,8 @@ Add packages:
sudo yum install git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig \
- json-c-devel pam-devel flex epel-release c-ares-devel libcap-devel
+ json-c-devel pam-devel flex epel-release c-ares-devel libcap-devel \
+ elfutils-libelf-devel
Install newer version of bison (CentOS 6 package source is too old) from CentOS
7:
diff --git a/doc/developer/building-frr-for-centos7.rst b/doc/developer/building-frr-for-centos7.rst
index eb97150d67..8d0aea943c 100644
--- a/doc/developer/building-frr-for-centos7.rst
+++ b/doc/developer/building-frr-for-centos7.rst
@@ -21,7 +21,8 @@ Add packages:
sudo yum install git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig \
json-c-devel pam-devel bison flex pytest c-ares-devel \
- python-devel systemd-devel python-sphinx libcap-devel
+ python-devel systemd-devel python-sphinx libcap-devel \
+ elfutils-libelf-devel
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-centos8.rst b/doc/developer/building-frr-for-centos8.rst
index 75beb53378..77fe489358 100644
--- a/doc/developer/building-frr-for-centos8.rst
+++ b/doc/developer/building-frr-for-centos8.rst
@@ -14,7 +14,8 @@ Add packages:
sudo dnf install --enablerepo=PowerTools git autoconf pcre-devel \
automake libtool make readline-devel texinfo net-snmp-devel pkgconfig \
groff pkgconfig json-c-devel pam-devel bison flex python2-pytest \
- c-ares-devel python2-devel systemd-devel libcap-devel
+ c-ares-devel python2-devel systemd-devel libcap-devel \
+ elfutils-libelf-devel
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-debian8.rst b/doc/developer/building-frr-for-debian8.rst
index c12bf46f8d..51dd07c42a 100644
--- a/doc/developer/building-frr-for-debian8.rst
+++ b/doc/developer/building-frr-for-debian8.rst
@@ -18,7 +18,7 @@ Add packages:
sudo apt-get install git autoconf automake libtool make \
libreadline-dev texinfo libjson-c-dev pkg-config bison flex python3-pip \
libc-ares-dev python3-dev python3-sphinx build-essential libsystemd-dev \
- libsnmp-dev libcap-dev
+ libsnmp-dev libcap-dev libelf-dev
Install newer pytest (>3.0) from pip
diff --git a/doc/developer/building-frr-for-debian9.rst b/doc/developer/building-frr-for-debian9.rst
index f976b9f49a..919b010314 100644
--- a/doc/developer/building-frr-for-debian9.rst
+++ b/doc/developer/building-frr-for-debian9.rst
@@ -11,7 +11,7 @@ Add packages:
sudo apt-get install git autoconf automake libtool make \
libreadline-dev texinfo libjson-c-dev pkg-config bison flex \
libc-ares-dev python3-dev python3-pytest python3-sphinx build-essential \
- libsnmp-dev libsystemd-dev libcap-dev
+ libsnmp-dev libsystemd-dev libcap-dev libelf-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-fedora.rst b/doc/developer/building-frr-for-fedora.rst
index 4ab59490fd..5fecd8a826 100644
--- a/doc/developer/building-frr-for-fedora.rst
+++ b/doc/developer/building-frr-for-fedora.rst
@@ -14,7 +14,8 @@ Installing Dependencies
sudo dnf install git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig json-c-devel \
pam-devel python3-pytest bison flex c-ares-devel python3-devel \
- python3-sphinx perl-core patch systemd-devel libcap-devel
+ python3-sphinx perl-core patch systemd-devel libcap-devel \
+ elfutils-libelf-devel
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-opensuse.rst b/doc/developer/building-frr-for-opensuse.rst
index 5ed714a67e..4e886e9c25 100644
--- a/doc/developer/building-frr-for-opensuse.rst
+++ b/doc/developer/building-frr-for-opensuse.rst
@@ -13,7 +13,8 @@ Installing Dependencies
zypper in git autoconf automake libtool make \
readline-devel texinfo net-snmp-devel groff pkgconfig libjson-c-devel\
pam-devel python3-pytest bison flex c-ares-devel python3-devel\
- python3-Sphinx perl patch systemd-devel libcap-devel libyang-devel
+ python3-Sphinx perl patch systemd-devel libcap-devel libyang-devel \
+ libelf-devel
Building & Installing FRR
-------------------------
diff --git a/doc/developer/building-frr-for-ubuntu1404.rst b/doc/developer/building-frr-for-ubuntu1404.rst
index cc54415266..2711e92b6f 100644
--- a/doc/developer/building-frr-for-ubuntu1404.rst
+++ b/doc/developer/building-frr-for-ubuntu1404.rst
@@ -14,7 +14,7 @@ Installing Dependencies
git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev python3-sphinx install-info build-essential \
- libsnmp-dev perl libcap-dev
+ libsnmp-dev perl libcap-dev libelf-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-ubuntu1604.rst b/doc/developer/building-frr-for-ubuntu1604.rst
index 63c6f8648c..2cb9536f9b 100644
--- a/doc/developer/building-frr-for-ubuntu1604.rst
+++ b/doc/developer/building-frr-for-ubuntu1604.rst
@@ -14,7 +14,8 @@ Installing Dependencies
git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
- install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev
+ install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev \
+ libelf-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-ubuntu1804.rst b/doc/developer/building-frr-for-ubuntu1804.rst
index 9d85957d88..eb3991c139 100644
--- a/doc/developer/building-frr-for-ubuntu1804.rst
+++ b/doc/developer/building-frr-for-ubuntu1804.rst
@@ -14,7 +14,8 @@ Installing Dependencies
git autoconf automake libtool make libreadline-dev texinfo \
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
- install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev
+ install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev \
+ libelf-dev
.. include:: building-libyang.rst
diff --git a/doc/developer/building-frr-for-ubuntu2004.rst b/doc/developer/building-frr-for-ubuntu2004.rst
index f7f8c63e5b..ffc05a6841 100644
--- a/doc/developer/building-frr-for-ubuntu2004.rst
+++ b/doc/developer/building-frr-for-ubuntu2004.rst
@@ -15,7 +15,7 @@ Installing Dependencies
pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
install-info build-essential libsystemd-dev libsnmp-dev perl \
- libcap-dev python2
+ libcap-dev python2 libelf-dev
Note that Ubuntu 20 no longer installs python 2.x, so it must be
installed explicitly. Ensure that your system has a symlink named
@@ -27,7 +27,7 @@ ubuntu apt repositories; in order to install it:
.. code-block:: shell
- curl https://bootstrap.pypa.io/get-pip.py --output get-pip.py
+ curl https://bootstrap.pypa.io/2.7/get-pip.py --output get-pip.py
sudo python2 ./get-pip.py
# And verify the installation
diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst
index cf3aa8d17f..a35e60619c 100644
--- a/doc/developer/logging.rst
+++ b/doc/developer/logging.rst
@@ -71,6 +71,10 @@ Extensions
+-----------+--------------------------+----------------------------------------------+
| ``%pI6`` | ``struct in6_addr *`` | ``fe80::1234`` |
+-----------+--------------------------+----------------------------------------------+
+| ``%pIA`` | ``struct ipaddr *`` | ``1.2.3.4`` |
+| | | |
+| | | ``fe80::1234`` |
++-----------+--------------------------+----------------------------------------------+
| ``%pFX`` | ``struct prefix *`` | ``fe80::1234/64`` |
+-----------+--------------------------+----------------------------------------------+
| ``%pSG4`` | ``struct prefix_sg *`` | ``(*,1.2.3.4)`` |
diff --git a/doc/developer/tracing.rst b/doc/developer/tracing.rst
index c194ae1270..ae4d621a8e 100644
--- a/doc/developer/tracing.rst
+++ b/doc/developer/tracing.rst
@@ -62,117 +62,189 @@ use your tracer as usual.
To see available USDT probes::
- readelf -n /usr/lib/frr/bgpd
+ readelf -n /usr/lib/frr/bgpd
Example::
- root@host ~> readelf -n /usr/lib/frr/bgpd
-
- Displaying notes found in: .note.ABI-tag
- Owner Data size Description
- GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
- OS: Linux, ABI: 3.2.0
-
- Displaying notes found in: .note.gnu.build-id
- Owner Data size Description
- GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
- Build ID: 4f42933a69dcb42a519bc459b2105177c8adf55d
-
- Displaying notes found in: .note.stapsdt
- Owner Data size Description
- stapsdt 0x00000045 NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: packet_read
- Location: 0x000000000045ee48, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-96(%rbp) 8@-104(%rbp)
- stapsdt 0x00000047 NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: open_process
- Location: 0x000000000047c43b, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-224(%rbp) 2@-226(%rbp)
- stapsdt 0x00000049 NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: update_process
- Location: 0x000000000047c4bf, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-208(%rbp) 2@-210(%rbp)
- stapsdt 0x0000004f NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: notification_process
- Location: 0x000000000047c557, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-192(%rbp) 2@-194(%rbp)
- stapsdt 0x0000004c NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: keepalive_process
- Location: 0x000000000047c5db, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-176(%rbp) 2@-178(%rbp)
- stapsdt 0x0000004a NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: refresh_process
- Location: 0x000000000047c673, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-160(%rbp) 2@-162(%rbp)
- stapsdt 0x0000004d NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: capability_process
- Location: 0x000000000047c6f7, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-144(%rbp) 2@-146(%rbp)
- stapsdt 0x0000006f NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: output_filter
- Location: 0x000000000048e33a, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-144(%rbp) 8@-152(%rbp) 4@-156(%rbp) 4@-160(%rbp) 8@-168(%rbp)
- stapsdt 0x0000007d NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: process_update
- Location: 0x0000000000491f10, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-800(%rbp) 8@-808(%rbp) 4@-812(%rbp) 4@-816(%rbp) 4@-820(%rbp) 8@-832(%rbp)
- stapsdt 0x0000006e NT_STAPSDT (SystemTap probe descriptors)
- Provider: frr_bgp
- Name: input_filter
- Location: 0x00000000004940ed, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
- Arguments: 8@-144(%rbp) 8@-152(%rbp) 4@-156(%rbp) 4@-160(%rbp) 8@-168(%rbp)
+ root@host ~> readelf -n /usr/lib/frr/bgpd
+
+ Displaying notes found in: .note.ABI-tag
+ Owner Data size Description
+ GNU 0x00000010 NT_GNU_ABI_TAG (ABI version tag)
+ OS: Linux, ABI: 3.2.0
+
+ Displaying notes found in: .note.gnu.build-id
+ Owner Data size Description
+ GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
+ Build ID: 4f42933a69dcb42a519bc459b2105177c8adf55d
+
+ Displaying notes found in: .note.stapsdt
+ Owner Data size Description
+ stapsdt 0x00000045 NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: packet_read
+ Location: 0x000000000045ee48, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-96(%rbp) 8@-104(%rbp)
+ stapsdt 0x00000047 NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: open_process
+ Location: 0x000000000047c43b, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-224(%rbp) 2@-226(%rbp)
+ stapsdt 0x00000049 NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: update_process
+ Location: 0x000000000047c4bf, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-208(%rbp) 2@-210(%rbp)
+ stapsdt 0x0000004f NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: notification_process
+ Location: 0x000000000047c557, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-192(%rbp) 2@-194(%rbp)
+ stapsdt 0x0000004c NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: keepalive_process
+ Location: 0x000000000047c5db, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-176(%rbp) 2@-178(%rbp)
+ stapsdt 0x0000004a NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: refresh_process
+ Location: 0x000000000047c673, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-160(%rbp) 2@-162(%rbp)
+ stapsdt 0x0000004d NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: capability_process
+ Location: 0x000000000047c6f7, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-144(%rbp) 2@-146(%rbp)
+ stapsdt 0x0000006f NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: output_filter
+ Location: 0x000000000048e33a, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-144(%rbp) 8@-152(%rbp) 4@-156(%rbp) 4@-160(%rbp) 8@-168(%rbp)
+ stapsdt 0x0000007d NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: process_update
+ Location: 0x0000000000491f10, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-800(%rbp) 8@-808(%rbp) 4@-812(%rbp) 4@-816(%rbp) 4@-820(%rbp) 8@-832(%rbp)
+ stapsdt 0x0000006e NT_STAPSDT (SystemTap probe descriptors)
+ Provider: frr_bgp
+ Name: input_filter
+ Location: 0x00000000004940ed, Base: 0x00000000005a09d2, Semaphore: 0x0000000000000000
+ Arguments: 8@-144(%rbp) 8@-152(%rbp) 4@-156(%rbp) 4@-160(%rbp) 8@-168(%rbp)
To see available LTTng probes, run the target, create a session and then::
- lttng list --userspace | grep frr
+ lttng list --userspace | grep frr
Example::
- root@host ~> lttng list --userspace | grep frr
- PID: 11157 - Name: /usr/lib/frr/bgpd
- frr_libfrr:route_node_get (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:list_sort (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:list_delete_node (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:list_remove (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:list_add (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:memfree (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:memalloc (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:frr_pthread_stop (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:frr_pthread_run (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
- frr_libfrr:thread_call (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:thread_cancel_async (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:thread_cancel (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:schedule_write (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:schedule_read (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:schedule_event (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:schedule_timer (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:hash_release (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:hash_insert (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_libfrr:hash_get (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:output_filter (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:input_filter (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:process_update (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:packet_read (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:refresh_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:capability_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:notification_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:update_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:keepalive_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
- frr_bgp:open_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ root@host ~> lttng list --userspace | grep frr
+ PID: 11157 - Name: /usr/lib/frr/bgpd
+ frr_libfrr:route_node_get (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:list_sort (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:list_delete_node (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:list_remove (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:list_add (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:memfree (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:memalloc (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:frr_pthread_stop (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:frr_pthread_run (loglevel: TRACE_DEBUG_LINE (13)) (type: tracepoint)
+ frr_libfrr:thread_call (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:thread_cancel_async (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:thread_cancel (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:schedule_write (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:schedule_read (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:schedule_event (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:schedule_timer (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:hash_release (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:hash_insert (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_libfrr:hash_get (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:output_filter (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:input_filter (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:process_update (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:packet_read (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:refresh_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:capability_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:notification_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:update_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:keepalive_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
+ frr_bgp:open_process (loglevel: TRACE_INFO (6)) (type: tracepoint)
When using LTTng, you can also get zlogs as trace events by enabling
the ``lttng_ust_tracelog:*`` event class.
+To see available SystemTap USDT probes, run::
+
+ stap -L 'process("/usr/lib/frr/bgpd").mark("*")'
+
+Example::
+
+ root@host ~> stap -L 'process("/usr/lib/frr/bgpd").mark("*")'
+ process("/usr/lib/frr/bgpd").mark("capability_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("input_filter") $arg1:long $arg2:long $arg3:long $arg4:long $arg5:long
+ process("/usr/lib/frr/bgpd").mark("keepalive_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("notification_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("open_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("output_filter") $arg1:long $arg2:long $arg3:long $arg4:long $arg5:long
+ process("/usr/lib/frr/bgpd").mark("packet_read") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("process_update") $arg1:long $arg2:long $arg3:long $arg4:long $arg5:long $arg6:long
+ process("/usr/lib/frr/bgpd").mark("refresh_process") $arg1:long $arg2:long
+ process("/usr/lib/frr/bgpd").mark("update_process") $arg1:long $arg2:long
+
+When using SystemTap, you can also easily attach to an existing function::
+
+ stap -L 'process("/usr/lib/frr/bgpd").function("bgp_update_receive")'
+
+Example::
+
+ root@host ~> stap -L 'process("/usr/lib/frr/bgpd").function("bgp_update_receive")'
+ process("/usr/lib/frr/bgpd").function("bgp_update_receive@bgpd/bgp_packet.c:1531") $peer:struct peer* $size:bgp_size_t $attr:struct attr $restart:_Bool $nlris:struct bgp_nlri[] $__func__:char const[] const
+
+Complete ``bgp.stp`` example using SystemTap to show BGP peer, prefix and aspath
+using ``process_update`` USDT::
+
+ global pkt_size;
+ probe begin
+ {
+ ansi_clear_screen();
+ println("Starting...");
+ }
+ probe process("/usr/lib/frr/bgpd").function("bgp_update_receive")
+ {
+ pkt_size <<< $size;
+ }
+ probe process("/usr/lib/frr/bgpd").mark("process_update")
+ {
+ aspath = @cast($arg6, "attr")->aspath;
+ printf("> %s via %s (%s)\n",
+ user_string($arg2),
+ user_string(@cast($arg1, "peer")->host),
+ user_string(@cast(aspath, "aspath")->str));
+ }
+ probe end
+ {
+ if (@count(pkt_size))
+ print(@hist_linear(pkt_size, 0, 20, 2));
+ }
+
+Output::
+
+ Starting...
+ > 192.168.0.0/24 via 192.168.0.1 (65534)
+ > 192.168.100.1/32 via 192.168.0.1 (65534)
+ > 172.16.16.1/32 via 192.168.0.1 (65534 65030)
+ ^Cvalue |-------------------------------------------------- count
+ 0 | 0
+ 2 | 0
+ 4 |@ 1
+ 6 | 0
+ 8 | 0
+ ~
+ 18 | 0
+ 20 | 0
+ >20 |@@@@@ 5
+
+
Concepts
--------
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index 861d87b998..abdbea5a9c 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -563,7 +563,7 @@ In general, code submitted into FRR will be rejected if it uses unsafe
programming practices. While there is no enforced overall ruleset, the
following requirements have achieved consensus:
-- ``strcpy``, ``strcat`` and ``sprintf`` are inacceptable without exception.
+- ``strcpy``, ``strcat`` and ``sprintf`` are unacceptable without exception.
Use ``strlcpy``, ``strlcat`` and ``snprintf`` instead. (Rationale: even if
you know the operation cannot overflow the buffer, a future code change may
inadvertedly introduce an overflow.)
@@ -1229,9 +1229,9 @@ towards making documentation easier to use, write and maintain.
CLI Commands
^^^^^^^^^^^^
-When documenting CLI please use a combination of the ``.. index::`` and
-``.. clicmd::`` directives. For example, the command :clicmd:`show pony` would
-be documented as follows:
+When documenting CLI please use the ``.. clicmd::`` directive. This directive
+will format the command and generate index entries automatically. For example,
+the command :clicmd:`show pony` would be documented as follows:
.. code-block:: rest
@@ -1252,6 +1252,7 @@ be documented as follows:
hjw |_>|> /_] //
/_] /_]
+
When documented this way, CLI commands can be cross referenced with the
``:clicmd:`` inline markup like so:
@@ -1262,8 +1263,27 @@ When documented this way, CLI commands can be cross referenced with the
This is very helpful for users who want to quickly remind themselves what a
particular command does.
-When documenting a cli that has a ``no`` form, please do not include
-the ``no`` in the ``.. index::`` line.
+When documenting a cli that has a ``no`` form, please do not include the ``no``
+form. I.e. ``no show pony`` would not be documented anywhere. Since most
+commands have ``no`` forms, users should be able to infer these or get help
+from vtysh's completions.
+
+When documenting commands that have lots of possible variants, just document
+the single command in summary rather than enumerating each possible variant.
+E.g. for ``show pony [foo|bar]``, do not:
+
+.. code-block:: rest
+
+ .. clicmd:: show pony
+ .. clicmd:: show pony foo
+ .. clicmd:: show pony bar
+
+Do:
+
+.. code-block:: rest
+
+ .. clicmd:: show pony [foo|bar]
+
Configuration Snippets
^^^^^^^^^^^^^^^^^^^^^^
diff --git a/doc/developer/xrefs.rst b/doc/developer/xrefs.rst
index 6a0794d41b..e8e07dfe1d 100644
--- a/doc/developer/xrefs.rst
+++ b/doc/developer/xrefs.rst
@@ -20,8 +20,6 @@ To verify xrefs have been included in a binary or dynamic library, run
``readelf -n binary``. For individual object files, it's
``readelf -S object.o | grep xref_array`` instead.
-An extraction tool will be added in a future commit.
-
Structure and contents
----------------------
@@ -168,3 +166,50 @@ entry point.
for C++ code when compiled by GCC. A workaround is present for runtime
functionality, but to extract the xrefs from a C++ source file, it needs
to be built with clang (or a future fixed version of GCC) instead.
+
+Extraction tool
+---------------
+
+The FRR source contains a matching tool to extract xref data from compiled ELF
+binaries in ``python/xrelfo.py``. This tool uses CPython extensions
+implemented in ``clippy`` and must therefore be executed with that.
+
+``xrelfo.py`` processes input from one or more ELF file (.o, .so, executable),
+libtool object (.lo, .la, executable wrapper script) or JSON (output from
+``xrelfo.py``) and generates an output JSON file. During standard FRR build,
+it is invoked on all binaries and libraries and the result is combined into
+``frr.json``.
+
+ELF files from any operating system, CPU architecture and endianness can be
+processed on any host. Any issues with this are bugs in ``xrelfo.py``
+(or clippy's ELF code.)
+
+``xrelfo.py`` also performs some sanity checking, particularly on log
+messages. The following options are available:
+
+.. option:: -o OUTPUT
+
+ Filename to write JSON output to. As a convention, a ``.xref`` filename
+ extension is used.
+
+.. option:: -Wlog-format
+
+ Performs extra checks on log message format strings, particularly checks
+ for ``\t`` and ``\n`` characters (which should not be used in log messages).
+
+.. option:: -Wlog-args
+
+ Generates cleanup hints for format string arguments where
+ :c:func:`printfrr()` extensions could be used, e.g. replacing ``inet_ntoa``
+ with ``%pI4``.
+
+.. option:: --profile
+
+ Runs the Python profiler to identify hotspots in the ``xrelfo.py`` code.
+
+``xrelfo.py`` uses information about C structure definitions saved in
+``python/xrefstructs.json``. This file is included with the FRR sources and
+only needs to be regenerated when some of the ``struct xref_*`` definitions
+are changed (which should be almost never). The file is written by
+``python/tiabwarfo.py``, which uses ``pahole`` to extract the necessary data
+from DWARF information.
diff --git a/doc/user/babeld.rst b/doc/user/babeld.rst
index 62d50d5d65..e6d4aa5c97 100644
--- a/doc/user/babeld.rst
+++ b/doc/user/babeld.rst
@@ -34,26 +34,17 @@ Configuration of *babeld* is done in its configuration file
Babel configuration
===================
-.. index:: router babel
-.. clicmd:: [no] router babel
+.. clicmd:: router babel
Enable or disable Babel routing.
-.. index:: babel resend-delay (20-655340)
-.. clicmd:: [no] babel resend-delay (20-655340)
-
- Specifies the time after which important messages are resent when
- avoiding a black-hole. The default is 2000 ms.
-
-.. index:: babel diversity
-.. clicmd:: [no] babel diversity
+.. clicmd:: babel diversity
Enable or disable routing using radio frequency diversity. This is
highly recommended in networks with many wireless nodes.
If you enable this, you will probably want to set `babel
diversity-factor` and `babel channel` below.
-.. index:: babel diversity-factor (1-256)
.. clicmd:: babel diversity-factor (1-256)
@@ -63,12 +54,10 @@ Babel configuration
no role in route selection; you will probably want to set that to 128
or less on nodes with multiple independent radios.
-.. index:: network IFNAME
-.. clicmd:: [no] network IFNAME
+.. clicmd:: network IFNAME
Enable or disable Babel on the given interface.
-.. index:: babel <wired|wireless>
.. clicmd:: babel <wired|wireless>
@@ -77,8 +66,7 @@ Babel configuration
Specifying `wireless` (the default) is always correct, but may
cause slower convergence and extra routing traffic.
-.. index:: babel split-horizon
-.. clicmd:: [no] babel split-horizon
+.. clicmd:: babel split-horizon
Specifies whether to perform split-horizon on the interface. Specifying
``no babel split-horizon`` is always correct, while ``babel
@@ -88,7 +76,6 @@ Babel configuration
interfaces. This flag is reset when the wired/wireless status of an
interface is changed.
-.. index:: babel hello-interval (20-655340)
.. clicmd:: babel hello-interval (20-655340)
@@ -97,7 +84,6 @@ Babel configuration
on wireless links, the link quality value is reestimated at every
hello interval. The default is 4000 ms.
-.. index:: babel update-interval (20-655340)
.. clicmd:: babel update-interval (20-655340)
@@ -105,7 +91,6 @@ Babel configuration
Babel makes extensive use of triggered updates, this can be set to fairly
high values on links with little packet loss. The default is 20000 ms.
-.. index:: babel channel
.. clicmd:: babel channel (1-254)
.. clicmd:: babel channel interfering
@@ -121,7 +106,6 @@ Babel configuration
interfaces. This is reset when the wired/wireless status of an interface is
changed.
-.. index:: babel rxcost (1-65534)
.. clicmd:: babel rxcost (1-65534)
@@ -136,7 +120,6 @@ Babel configuration
networks, acting directly on the cost using route maps is a better
technique.
-.. index:: babel rtt-decay (1-256)
.. clicmd:: babel rtt-decay (1-256)
@@ -144,7 +127,6 @@ Babel configuration
RTT samples, in units of 1/256. Higher values discard old samples
faster. The default is 42.
-.. index:: babel rtt-min (1-65535)
.. clicmd:: babel rtt-min (1-65535)
@@ -152,14 +134,12 @@ Babel configuration
increase the cost to a neighbour. The additional cost is linear in
(rtt - rtt-min). The default is 100 ms.
-.. index:: babel rtt-max (1-65535)
.. clicmd:: babel rtt-max (1-65535)
This specifies the maximum RTT, in milliseconds, above which we don't
increase the cost to a neighbour. The default is 120 ms.
-.. index:: babel max-rtt-penalty (0-65535)
.. clicmd:: babel max-rtt-penalty (0-65535)
@@ -167,14 +147,12 @@ Babel configuration
when the RTT is higher or equal than rtt-max. The default is 0, which
effectively disables the use of a RTT-based cost.
-.. index:: babel enable-timestamps
-.. clicmd:: [no] babel enable-timestamps
+.. clicmd:: babel enable-timestamps
Enable or disable sending timestamps with each Hello and IHU message in
order to compute RTT values. The default is `no babel enable-timestamps`.
-.. index:: babel resend-delay (20-655340)
.. clicmd:: babel resend-delay (20-655340)
@@ -182,7 +160,6 @@ Babel configuration
update will be resent. The default is 2000 ms. You probably don't want to
tweak this value.
-.. index:: babel smoothing-half-life (0-65534)
.. clicmd:: babel smoothing-half-life (0-65534)
@@ -196,9 +173,8 @@ Babel configuration
Babel redistribution
====================
-.. index:: redistribute <ipv4|ipv6> KIND
-.. clicmd:: [no] redistribute <ipv4|ipv6> KIND
+.. clicmd:: redistribute <ipv4|ipv6> KIND
Specify which kind of routes should be redistributed into Babel.
@@ -209,50 +185,40 @@ Show Babel information
These commands dump various parts of *babeld*'s internal state.
-.. index:: show babel route
.. clicmd:: show babel route
-.. index:: show babel route A.B.C.D
.. clicmd:: show babel route A.B.C.D
-.. index:: show babel route X:X::X:X
.. clicmd:: show babel route X:X::X:X
-.. index:: show babel route A.B.C.D/M
.. clicmd:: show babel route A.B.C.D/M
-.. index:: show babel route X:X::X:X/M
.. clicmd:: show babel route X:X::X:X/M
-.. index:: show babel interface
.. clicmd:: show babel interface
-.. index:: show babel interface IFNAME
.. clicmd:: show babel interface IFNAME
-.. index:: show babel neighbor
.. clicmd:: show babel neighbor
-.. index:: show babel parameters
.. clicmd:: show babel parameters
Babel debugging commands
========================
-.. index::
simple: debug babel KIND
simple: no debug babel KIND
-.. clicmd:: [no] debug babel KIND
+.. clicmd:: debug babel KIND
Enable or disable debugging messages of a given kind. ``KIND`` can
be one of:
diff --git a/doc/user/basic.rst b/doc/user/basic.rst
index 1ca3ca3cf2..5cbd3692dc 100644
--- a/doc/user/basic.rst
+++ b/doc/user/basic.rst
@@ -11,13 +11,9 @@ The following sections discuss commands common to all the routing daemons.
Config Commands
===============
-.. index:: Configuration files for running the software
-.. index:: Files for running configurations
-.. index:: Modifying the herd's behavior
-.. index:: Getting the herd running
In a config file, you can write the debugging options, a vty's password,
routing daemon configurations, a log file name, and so forth. This information
@@ -60,25 +56,21 @@ If desired, you can specify a config file using the :option:`-f` or
Basic Config Commands
---------------------
-.. index:: hostname HOSTNAME
.. clicmd:: hostname HOSTNAME
Set hostname of the router.
-.. index:: password PASSWORD
-.. clicmd:: [no] password PASSWORD
+.. clicmd:: password PASSWORD
Set password for vty interface. The ``no`` form of the command deletes the
password. If there is no password, a vty won't accept connections.
-.. index:: enable password PASSWORD
-.. clicmd:: [no] enable password PASSWORD
+.. clicmd:: enable password PASSWORD
Set enable password. The ``no`` form of the command deletes the enable
password.
-.. index:: log trap LEVEL
-.. clicmd:: [no] log trap LEVEL
+.. clicmd:: log trap LEVEL
These commands are deprecated and are present only for historical
compatibility. The log trap command sets the current logging level for all
@@ -88,9 +80,8 @@ Basic Config Commands
future logging commands to debugging, but it does not change the logging
level of existing logging destinations.
-.. index:: log stdout [LEVEL]
-.. clicmd:: [no] log stdout LEVEL
+.. clicmd:: log stdout LEVEL
Enable logging output to stdout. If the optional second argument specifying
the logging level is not present, the default logging level (typically
@@ -109,8 +100,7 @@ Basic Config Commands
terminal output. Use a log file and ``tail -f`` if this rare chance is
inacceptable to your setup.
-.. index:: log file FILENAME [LEVEL]
-.. clicmd:: [no] log file [FILENAME [LEVEL]]
+.. clicmd:: log file [FILENAME [LEVEL]]
If you want to log into a file, please specify ``filename`` as
in this example:
@@ -124,16 +114,14 @@ Basic Config Commands
deprecated ``log trap`` command) will be used. The ``no`` form of the command
disables logging to a file.
-.. index:: log syslog [LEVEL]
-.. clicmd:: [no] log syslog [LEVEL]
+.. clicmd:: log syslog [LEVEL]
Enable logging output to syslog. If the optional second argument specifying
the logging level is not present, the default logging level (typically
debugging, but can be changed using the deprecated ``log trap`` command) will
be used. The ``no`` form of the command disables logging to syslog.
-.. index:: log monitor [LEVEL]
-.. clicmd:: [no] log monitor [LEVEL]
+.. clicmd:: log monitor [LEVEL]
Enable logging output to vty terminals that have enabled logging using the
``terminal monitor`` command. By default, monitor logging is enabled at the
@@ -143,15 +131,13 @@ Basic Config Commands
level (typically debugging) will be used. The ``no`` form of the command
disables logging to terminal monitors.
-.. index:: log facility [FACILITY]
-.. clicmd:: [no] log facility [FACILITY]
+.. clicmd:: log facility [FACILITY]
This command changes the facility used in syslog messages. The default
facility is ``daemon``. The ``no`` form of the command resets the facility
to the default ``daemon`` facility.
-.. index:: log record-priority
-.. clicmd:: [no] log record-priority
+.. clicmd:: log record-priority
To include the severity in all messages logged to a file, to stdout, or to
a terminal monitor (i.e. anything except syslog),
@@ -161,8 +147,7 @@ Basic Config Commands
versions of syslogd can be configured to include the facility and
level in the messages emitted.
-.. index:: log timestamp precision (0-6)
-.. clicmd:: [no] log timestamp precision [(0-6)]
+.. clicmd:: log timestamp precision [(0-6)]
This command sets the precision of log message timestamps to the given
number of digits after the decimal point. Currently, the value must be in
@@ -177,8 +162,7 @@ Basic Config Commands
In this example, the precision is set to provide timestamps with
millisecond accuracy.
-.. index:: log commands
-.. clicmd:: [no] log commands
+.. clicmd:: log commands
This command enables the logging of all commands typed by a user to all
enabled log destinations. The note that logging includes full command lines,
@@ -186,8 +170,7 @@ Basic Config Commands
is used to start the daemon then this command is turned on by default
and cannot be turned off and the [no] form of the command is dissallowed.
-.. index:: log-filter WORD [DAEMON]
-.. clicmd:: [no] log-filter WORD [DAEMON]
+.. clicmd:: log-filter WORD [DAEMON]
This command forces logs to be filtered on a specific string. A log message
will only be printed if it matches on one of the filters in the log-filter
@@ -200,55 +183,41 @@ Basic Config Commands
Log filters prevent this but you should still expect a small performance
hit due to filtering each of all those logs.
-.. index:: log-filter clear [DAEMON]
.. clicmd:: log-filter clear [DAEMON]
This command clears all current filters in the log-filter table. Can be
daemon independent.
-.. index:: service password-encryption
.. clicmd:: service password-encryption
Encrypt password.
-.. index:: service advanced-vty
.. clicmd:: service advanced-vty
Enable advanced mode VTY.
-.. index:: service terminal-length (0-512)
.. clicmd:: service terminal-length (0-512)
Set system wide line configuration. This configuration command applies to
all VTY interfaces.
-.. index:: line vty
.. clicmd:: line vty
Enter vty configuration mode.
-.. index:: banner motd default
.. clicmd:: banner motd default
Set default motd string.
-.. index:: banner motd file FILE
.. clicmd:: banner motd file FILE
Set motd string from file. The file must be in directory specified
under ``--sysconfdir``.
-.. index:: banner motd line LINE
.. clicmd:: banner motd line LINE
Set motd string from an input.
-.. index:: banner motd
-.. clicmd:: no banner motd
-
- No motd banner string will be printed.
-
-.. index:: exec-timeout MINUTE [SECOND]
.. clicmd:: exec-timeout MINUTE [SECOND]
Set VTY connection timeout value. When only one argument is specified
@@ -256,13 +225,9 @@ Basic Config Commands
used for timeout value in seconds. Default timeout value is 10 minutes.
When timeout value is zero, it means no timeout.
-.. index:: exec-timeout
-.. clicmd:: no exec-timeout
-
- Do not perform timeout at all. This command is as same as
- ``exec-timeout 0 0``.
+ Not setting this, or setting the values to 0 0, means a timeout will not be
+ enabled.
-.. index:: access-class ACCESS-LIST
.. clicmd:: access-class ACCESS-LIST
Restrict vty connections with an access list.
@@ -440,55 +405,45 @@ Puppet, etc.), upgrade considerations differ somewhat:
Terminal Mode Commands
======================
-.. index:: write terminal
.. clicmd:: write terminal
Displays the current configuration to the vty interface.
-.. index:: write file
.. clicmd:: write file
Write current configuration to configuration file.
-.. index:: configure [terminal]
.. clicmd:: configure [terminal]
Change to configuration mode. This command is the first step to
configuration.
-.. index:: terminal length (0-512)
.. clicmd:: terminal length (0-512)
Set terminal display length to ``(0-512)``. If length is 0, no display
control is performed.
-.. index:: who
.. clicmd:: who
Show a list of currently connected vty sessions.
-.. index:: list
.. clicmd:: list
List all available commands.
-.. index:: show version
.. clicmd:: show version
Show the current version of |PACKAGE_NAME| and its build host information.
-.. index:: show logging
.. clicmd:: show logging
Shows the current configuration of the logging system. This includes the
status of all logging destinations.
-.. index:: show log-filter
.. clicmd:: show log-filter
Shows the current log filters applied to each daemon.
-.. index:: show memory
.. clicmd:: show memory
Show information on how much memory is used for which specific things in
@@ -549,18 +504,15 @@ Terminal Mode Commands
When executing this command from ``vtysh``, each of the daemons' memory
usage is printed sequentially.
-.. index:: show history
.. clicmd:: show history
Dump the vtysh cli history.
-.. index:: logmsg LEVEL MESSAGE
.. clicmd:: logmsg LEVEL MESSAGE
Send a message to all logging destinations that are enabled for messages of
the given severity.
-.. index:: find COMMAND...
.. clicmd:: find COMMAND...
This command performs a simple substring search across all defined commands
@@ -589,7 +541,6 @@ Terminal Mode Commands
.. _common-show-commands:
-.. index:: show thread cpu
.. clicmd:: show thread cpu [r|w|t|e|x]
This command displays system run statistics for all the different event
@@ -598,7 +549,6 @@ Terminal Mode Commands
(e)vent and e(x)ecute thread event types. If you have compiled with
disable-cpu-time then this command will not show up.
-.. index:: show thread poll
.. clicmd:: show thread poll
This command displays FRR's poll data. It allows a glimpse into how
diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst
index 6c83ffa19a..b8f749b740 100644
--- a/doc/user/bfd.rst
+++ b/doc/user/bfd.rst
@@ -90,12 +90,10 @@ may also be specified (:ref:`common-invocation-options`).
BFDd Commands
=============
-.. index:: bfd
.. clicmd:: bfd
Opens the BFD daemon configuration node.
-.. index:: peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]
.. clicmd:: peer <A.B.C.D|X:X::X:X> [{multihop|local-address <A.B.C.D|X:X::X:X>|interface IFNAME|vrf NAME}]
Creates and configures a new BFD peer to listen and talk to.
@@ -113,41 +111,27 @@ BFDd Commands
`vrf` selects which domain we want to use.
-.. index:: peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrf_name}]
-.. clicmd:: no peer <A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname|vrf NAME$vrf_name}]
- Stops and removes the selected peer.
-
-
-.. index:: profile WORD
.. clicmd:: profile WORD
Creates a peer profile that can be configured in multiple peers.
+ Deleting the profile will cause all peers using it to reset to the default
+ values.
-.. index:: profile WORD
-.. clicmd:: no profile WORD
-
- Deletes a peer profile. Any peer using the profile will have their
- configurations reset to the default values.
-
-.. index:: show bfd [vrf NAME] peers [json]
.. clicmd:: show bfd [vrf NAME] peers [json]
Show all configured BFD peers information and current status.
-.. index:: show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
.. clicmd:: show bfd [vrf NAME$vrf_name] peer <WORD$label|<A.B.C.D|X:X::X:X>$peer [{multihop|local-address <A.B.C.D|X:X::X:X>$local|interface IFNAME$ifname}]> [json]
Show status for a specific BFD peer.
-.. index:: show bfd [vrf NAME] peers brief [json]
.. clicmd:: show bfd [vrf NAME] peers brief [json]
Show all configured BFD peers information and current status in brief.
-.. index:: show bfd distributed
.. clicmd:: show bfd distributed
Show the BFD data plane (distributed BFD) statistics.
@@ -160,7 +144,6 @@ Peer / Profile Configuration
BFD peers and profiles share the same BFD session configuration commands.
-.. index:: detect-multiplier (2-255)
.. clicmd:: detect-multiplier (2-255)
Configures the detection multiplier to determine packet loss. The
@@ -173,26 +156,22 @@ BFD peers and profiles share the same BFD session configuration commands.
detect failures only after 900 milliseconds without receiving
packets.
-.. index:: receive-interval (10-60000)
.. clicmd:: receive-interval (10-60000)
Configures the minimum interval that this system is capable of
receiving control packets. The default value is 300 milliseconds.
-.. index:: transmit-interval (10-60000)
.. clicmd:: transmit-interval (10-60000)
The minimum transmission interval (less jitter) that this system
wants to use to send BFD control packets. Defaults to 300ms.
-.. index:: echo-interval (10-60000)
.. clicmd:: echo-interval (10-60000)
Configures the minimal echo receive transmission interval that this
system is capable of handling.
-.. index:: echo-mode
-.. clicmd:: [no] echo-mode
+.. clicmd:: echo-mode
Enables or disables the echo transmission mode. This mode is disabled
by default.
@@ -204,15 +183,13 @@ BFD peers and profiles share the same BFD session configuration commands.
Echo mode is not supported on multi-hop setups (see :rfc:`5883`
section 3).
-.. index:: shutdown
-.. clicmd:: [no] shutdown
+.. clicmd:: shutdown
Enables or disables the peer. When the peer is disabled an
'administrative down' message is sent to the remote peer.
-.. index:: passive-mode
-.. clicmd:: [no] passive-mode
+.. clicmd:: passive-mode
Mark session as passive: a passive session will not attempt to start
the connection and will wait for control packets from peer before it
@@ -224,8 +201,7 @@ BFD peers and profiles share the same BFD session configuration commands.
The default is active-mode (or ``no passive-mode``).
-.. index:: minimum-ttl (1-254)
-.. clicmd:: [no] minimum-ttl (1-254)
+.. clicmd:: minimum-ttl (1-254)
For multi hop sessions only: configure the minimum expected TTL for
an incoming BFD control packet.
@@ -241,14 +217,12 @@ BFD peers and profiles share the same BFD session configuration commands.
BFD Peer Specific Commands
--------------------------
-.. index:: label WORD
.. clicmd:: label WORD
Labels a peer with the provided word. This word can be referenced
later on other daemons to refer to a specific peer.
-.. index:: profile BFDPROF
.. clicmd:: profile BFDPROF
Configure peer to use the profile configurations.
@@ -270,7 +244,6 @@ BGP BFD Configuration
The following commands are available inside the BGP configuration node.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd
Listen for BFD events registered on the same target as this BGP
@@ -278,12 +251,7 @@ The following commands are available inside the BGP configuration node.
the connection with its neighbor and, when it goes back up, notify
BGP to try to connect to it.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd
-.. clicmd:: no neighbor <A.B.C.D|X:X::X:X|WORD> bfd
-
- Removes any notification registration for this neighbor.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
Allow to write CBIT independence in BFD outgoing packets. Also allow to
@@ -293,26 +261,16 @@ The following commands are available inside the BGP configuration node.
This is the case when graceful restart is enabled, and it is wished to
ignore the BD event while waiting for the remote router to restart.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
-.. clicmd:: no neighbor <A.B.C.D|X:X::X:X|WORD> bfd check-control-plane-failure
+ Disabling this disables presence of CBIT independence in BFD outgoing
+ packets and pays attention to BFD down notifications. This is the default.
- Disallow to write CBIT independence in BFD outgoing packets. Also disallow
- to ignore BFD down notification. This is the default behaviour.
-
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF
Same as command ``neighbor <A.B.C.D|X:X::X:X|WORD> bfd``, but applies the
BFD profile to the sessions it creates or that already exist.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF
-.. clicmd:: no neighbor <A.B.C.D|X:X::X:X|WORD> bfd profile BFDPROF
-
- Removes the BFD profile configuration from peer session(s).
-
-
.. _bfd-isis-peer-config:
IS-IS BFD Configuration
@@ -320,31 +278,20 @@ IS-IS BFD Configuration
The following commands are available inside the interface configuration node.
-.. index:: isis bfd
.. clicmd:: isis bfd
Listen for BFD events on peers created on the interface. Every time
a new neighbor is found a BFD peer is created to monitor the link
status for fast convergence.
-.. index:: isis bfd
-.. clicmd:: no isis bfd
-
- Removes any notification registration for this interface peers.
-
Note that there will be just one BFD session per interface. In case both
IPv4 and IPv6 support are configured then just a IPv6 based session is
created.
-.. index:: isis bfd profile BFDPROF
.. clicmd:: isis bfd profile BFDPROF
Use a BFD profile BFDPROF as provided in the BFD configuration.
-.. index:: isis bfd profile BFDPROF
-.. clicmd:: no isis bfd profile BFDPROF
-
- Removes any BFD profile if present.
.. _bfd-ospf-peer-config:
@@ -353,18 +300,12 @@ OSPF BFD Configuration
The following commands are available inside the interface configuration node.
-.. index:: ip ospf bfd
.. clicmd:: ip ospf bfd
Listen for BFD events on peers created on the interface. Every time
a new neighbor is found a BFD peer is created to monitor the link
status for fast convergence.
-.. index:: ip ospf bfd
-.. clicmd:: no ip ospf bfd
-
- Removes any notification registration for this interface peers.
-
.. _bfd-ospf6-peer-config:
@@ -373,18 +314,12 @@ OSPF6 BFD Configuration
The following commands are available inside the interface configuration node.
-.. index:: ipv6 ospf6 bfd
.. clicmd:: ipv6 ospf6 bfd
Listen for BFD events on peers created on the interface. Every time
a new neighbor is found a BFD peer is created to monitor the link
status for fast convergence.
-.. index:: ipv6 ospf6 bfd
-.. clicmd:: no ipv6 ospf6 bfd
-
- Removes any notification registration for this interface peers.
-
.. _bfd-pim-peer-config:
@@ -393,18 +328,12 @@ PIM BFD Configuration
The following commands are available inside the interface configuration node.
-.. index:: ip pim bfd
.. clicmd:: ip pim bfd
Listen for BFD events on peers created on the interface. Every time
a new neighbor is found a BFD peer is created to monitor the link
status for fast convergence.
-.. index:: ip pim bfd
-.. clicmd:: no ip pim bfd
-
- Removes any notification registration for this interface peers.
-
.. _bfd-configuration:
@@ -721,8 +650,7 @@ sure you have `debugging` level enabled:
You may also fine tune the debug messages by selecting one or more of the
debug levels:
-.. index:: debug bfd distributed
-.. clicmd:: [no] debug bfd distributed
+.. clicmd:: debug bfd distributed
Toggle BFD data plane (distributed BFD) debugging.
@@ -731,20 +659,17 @@ debug levels:
* Data plane received / send messages
* Connection events
-.. index:: debug bfd network
-.. clicmd:: [no] debug bfd network
+.. clicmd:: debug bfd network
Toggle network events: show messages about socket failures and unexpected
BFD messages that may not belong to registered peers.
-.. index:: debug bfd peer
-.. clicmd:: [no] debug bfd peer
+.. clicmd:: debug bfd peer
Toggle peer event log messages: show messages about peer creation/removal
and state changes.
-.. index:: debug bfd zebra
-.. clicmd:: [no] debug bfd zebra
+.. clicmd:: debug bfd zebra
Toggle zebra message events: show messages about interfaces, local
addresses, VRF and daemon peer registrations.
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index cb97ee22df..da6c0d9824 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -252,18 +252,11 @@ command. The AS number is an identifier for the autonomous system. The BGP
protocol uses the AS number for detecting whether the BGP connection is
internal or external.
-.. index:: router bgp ASN
.. clicmd:: router bgp ASN
Enable a BGP protocol process with the specified ASN. After
this statement you can input any `BGP Commands`.
-.. index:: router bgp ASN
-.. clicmd:: no router bgp ASN
-
- Destroy a BGP protocol process with the specified ASN.
-
-.. index:: bgp router-id A.B.C.D
.. clicmd:: bgp router-id A.B.C.D
This command specifies the router-ID. If *bgpd* connects to *zebra* it gets
@@ -301,7 +294,6 @@ However, the same AS can be used with different VRFs.
Configuration of additional autonomous systems, or of a router that targets a
specific VRF, is accomplished with the following command:
-.. index:: router bgp ASN vrf VRFNAME
.. clicmd:: router bgp ASN vrf VRFNAME
``VRFNAME`` is matched against VRFs configured in the kernel. When ``vrf
@@ -344,7 +336,6 @@ via BGP. Multiple views can be supported, and BGP view information is always
independent from other routing protocols and Zebra/kernel routes. BGP views use
the core instance (i.e., default VRF) for communication with peers.
-.. index:: router bgp AS-NUMBER view NAME
.. clicmd:: router bgp AS-NUMBER view NAME
Make a new BGP view. You can use an arbitrary word for the ``NAME``. Routes
@@ -363,7 +354,6 @@ the core instance (i.e., default VRF) for communication with peers.
neighbor 10.0.0.3 remote-as 4
neighbor 10.0.0.4 remote-as 5
-.. index:: show [ip] bgp view NAME
.. clicmd:: show [ip] bgp view NAME
Display the routing table of BGP view ``NAME``.
@@ -372,14 +362,12 @@ the core instance (i.e., default VRF) for communication with peers.
Route Selection
---------------
-.. index:: bgp bestpath as-path confed
.. clicmd:: bgp bestpath as-path confed
This command specifies that the length of confederation path sets and
sequences should should be taken into account during the BGP best path
decision process.
-.. index:: bgp bestpath as-path multipath-relax
.. clicmd:: bgp bestpath as-path multipath-relax
This command specifies that BGP decision process should consider paths
@@ -411,17 +399,14 @@ Route Selection
Administrative Distance Metrics
-------------------------------
-.. index:: distance bgp (1-255) (1-255) (1-255)
.. clicmd:: distance bgp (1-255) (1-255) (1-255)
This command change distance value of BGP. The arguments are the distance
values for for external routes, internal routes and local routes
respectively.
-.. index:: distance (1-255) A.B.C.D/M
.. clicmd:: distance (1-255) A.B.C.D/M
-.. index:: distance (1-255) A.B.C.D/M WORD
.. clicmd:: distance (1-255) A.B.C.D/M WORD
Sets the administrative distance for a particular route.
@@ -431,8 +416,7 @@ Administrative Distance Metrics
Require policy on EBGP
-------------------------------
-.. index:: bgp ebgp-requires-policy
-.. clicmd:: [no] bgp ebgp-requires-policy
+.. clicmd:: bgp ebgp-requires-policy
This command requires incoming and outgoing filters to be applied
for eBGP sessions as part of RFC-8212 compliance. Without the incoming
@@ -480,16 +464,14 @@ Require policy on EBGP
Reject routes with AS_SET or AS_CONFED_SET types
------------------------------------------------
-.. index:: bgp reject-as-sets
-.. clicmd:: [no] bgp reject-as-sets
+.. clicmd:: bgp reject-as-sets
This command enables rejection of incoming and outgoing routes having AS_SET or AS_CONFED_SET type.
Suppress duplicate updates
--------------------------
-.. index:: bgp suppress-duplicates
-.. clicmd:: [no] bgp suppress-duplicates
+.. clicmd:: bgp suppress-duplicates
For example, BGP routers can generate multiple identical announcements with
empty community attributes if stripped at egress. This is an undesired behavior.
@@ -499,8 +481,7 @@ Suppress duplicate updates
Disable checking if nexthop is connected on EBGP sessions
---------------------------------------------------------
-.. index:: bgp disable-ebgp-connected-route-check
-.. clicmd:: [no] bgp disable-ebgp-connected-route-check
+.. clicmd:: bgp disable-ebgp-connected-route-check
This command is used to disable the connection verification process for EBGP peering sessions
that are reachable by a single hop but are configured on a loopback interface or otherwise
@@ -511,20 +492,17 @@ Disable checking if nexthop is connected on EBGP sessions
Route Flap Dampening
--------------------
-.. index:: [no] bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
-.. clicmd:: [no] bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
+.. clicmd:: bgp dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
This command enables (with optionally specified dampening parameters) or
disables route-flap dampening for all routes of a BGP instance.
-.. index:: [no] neighbor PEER dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
-.. clicmd:: [no] neighbor PEER dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
+.. clicmd:: neighbor PEER dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
This command enables (with optionally specified dampening parameters) or
disables route-flap dampening for all routes learned from a BGP peer.
-.. index:: [no] neighbor GROUP dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
-.. clicmd:: [no] neighbor GROUP dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
+.. clicmd:: neighbor GROUP dampening [(1-45) [(1-20000) (1-20000) (1-255)]]
This command enables (with optionally specified dampening parameters) or
disables route-flap dampening for all routes learned from peers of a peer
@@ -769,7 +747,6 @@ topologies are at cross-purposes with each other - see the Flavel and Roughan
paper above for an example. Hence the guideline that the iBGP topology should
follow the IGP topology.
-.. index:: bgp deterministic-med
.. clicmd:: bgp deterministic-med
Carry out route-selection in way that produces deterministic answers
@@ -789,7 +766,6 @@ Note that there are other sources of indeterminism in the route selection
process, specifically, the preference for older and already selected routes
from eBGP peers, :ref:`bgp-route-selection`.
-.. index:: bgp always-compare-med
.. clicmd:: bgp always-compare-med
Always compare the MED on routes, even when they were received from
@@ -893,7 +869,6 @@ forwarding state has been preserved.
The remaining bits are reserved and MUST be set to zero by the sender and
ignored by the receiver.
-.. index:: bgp graceful-restart preserve-fw-state
.. clicmd:: bgp graceful-restart preserve-fw-state
FRR gives us the option to enable/disable the "F" flag using this specific
@@ -943,18 +918,15 @@ However, it MUST defer route selection for an address family until it either.
that do not advertise the graceful restart capability).
2. The Selection_Deferral_Timer timeout.
-.. index:: bgp graceful-restart select-defer-time (0-3600)
.. clicmd:: bgp graceful-restart select-defer-time (0-3600)
This is command, will set deferral time to value specified.
-.. index:: bgp graceful-restart rib-stale-time (1-3600)
.. clicmd:: bgp graceful-restart rib-stale-time (1-3600)
This is command, will set the time for which stale routes are kept in RIB.
-.. index:: bgp graceful-restart stalepath-time (1-4095)
.. clicmd:: bgp graceful-restart stalepath-time (1-4095)
This is command, will set the max time (in seconds) to hold onto
@@ -988,13 +960,11 @@ override the global mode.
BGP GR Global Mode Commands
^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: bgp graceful-restart
.. clicmd:: bgp graceful-restart
This command will enable BGP graceful restart ifunctionality at the global
level.
-.. index:: bgp graceful-restart disable
.. clicmd:: bgp graceful-restart disable
This command will disable both the functionality graceful restart and helper
@@ -1006,19 +976,16 @@ BGP GR Global Mode Commands
BGP GR Peer Mode Commands
^^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: neighbor A.B.C.D graceful-restart
.. clicmd:: neighbor A.B.C.D graceful-restart
This command will enable BGP graceful restart ifunctionality at the peer
level.
-.. index:: neighbor A.B.C.D graceful-restart-helper
.. clicmd:: neighbor A.B.C.D graceful-restart-helper
This command will enable BGP graceful restart helper only functionality
at the peer level.
-.. index:: neighbor A.B.C.D graceful-restart-disable
.. clicmd:: neighbor A.B.C.D graceful-restart-disable
This command will disable the entire BGP graceful restart functionality
@@ -1030,8 +997,7 @@ BGP GR Peer Mode Commands
Administrative Shutdown
-----------------------
-.. index:: bgp shutdown [message MSG...]
-.. clicmd:: [no] bgp shutdown [message MSG...]
+.. clicmd:: bgp shutdown [message MSG...]
Administrative shutdown of all peers of a bgp instance. Drop all BGP peers,
but preserve their configurations. The peers are notified in accordance with
@@ -1049,7 +1015,6 @@ Administrative Shutdown
Networks
--------
-.. index:: network A.B.C.D/M
.. clicmd:: network A.B.C.D/M
This command adds the announcement network.
@@ -1066,11 +1031,8 @@ Networks
routes if they aren't present in their IGP routing tables; `bgpd`
doesn't care about IGP routes when announcing its routes.
-.. index:: network A.B.C.D/M
-.. clicmd:: no network A.B.C.D/M
-.. index:: bgp network import-check
-.. clicmd:: [no] bgp network import-check
+.. clicmd:: bgp network import-check
This configuration modifies the behavior of the network statement.
If you have this configured the underlying network must exist in
@@ -1085,8 +1047,7 @@ Networks
IPv6 Support
------------
-.. index:: neighbor A.B.C.D activate
-.. clicmd:: [no] neighbor A.B.C.D activate
+.. clicmd:: neighbor A.B.C.D activate
This configuration modifies whether to enable an address family for a
specific neighbor. By default only the IPv4 unicast address family is
@@ -1137,53 +1098,41 @@ Route Aggregation
Route Aggregation-IPv4 Address Family
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: aggregate-address A.B.C.D/M
.. clicmd:: aggregate-address A.B.C.D/M
This command specifies an aggregate address.
-.. index:: aggregate-address A.B.C.D/M route-map NAME
.. clicmd:: aggregate-address A.B.C.D/M route-map NAME
Apply a route-map for an aggregated prefix.
-.. index:: aggregate-address A.B.C.D/M origin <egp|igp|incomplete>
.. clicmd:: aggregate-address A.B.C.D/M origin <egp|igp|incomplete>
Override ORIGIN for an aggregated prefix.
-.. index:: aggregate-address A.B.C.D/M as-set
.. clicmd:: aggregate-address A.B.C.D/M as-set
This command specifies an aggregate address. Resulting routes include
AS set.
-.. index:: aggregate-address A.B.C.D/M summary-only
.. clicmd:: aggregate-address A.B.C.D/M summary-only
This command specifies an aggregate address. Aggregated routes will
not be announced.
-.. index:: aggregate-address A.B.C.D/M matching-MED-only
.. clicmd:: aggregate-address A.B.C.D/M matching-MED-only
Configure the aggregated address to only be created when the routes MED
match, otherwise no aggregated route will be created.
-.. index:: aggregate-address A.B.C.D/M suppress-map NAME
.. clicmd:: aggregate-address A.B.C.D/M suppress-map NAME
Similar to `summary-only`, but will only suppress more specific routes that
are matched by the selected route-map.
-.. index:: aggregate-address A.B.C.D/M
-.. clicmd:: no aggregate-address A.B.C.D/M
-
- This command removes an aggregate address.
-
- This configuration example setup the aggregate-address under
- ipv4 address-family.
+ This configuration example sets up an ``aggregate-address`` under the ipv4
+ address-family.
.. code-block:: frr
@@ -1201,53 +1150,41 @@ Route Aggregation-IPv4 Address Family
Route Aggregation-IPv6 Address Family
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: aggregate-address X:X::X:X/M
.. clicmd:: aggregate-address X:X::X:X/M
This command specifies an aggregate address.
-.. index:: aggregate-address X:X::X:X/M route-map NAME
.. clicmd:: aggregate-address X:X::X:X/M route-map NAME
Apply a route-map for an aggregated prefix.
-.. index:: aggregate-address X:X::X:X/M origin <egp|igp|incomplete>
.. clicmd:: aggregate-address X:X::X:X/M origin <egp|igp|incomplete>
Override ORIGIN for an aggregated prefix.
-.. index:: aggregate-address X:X::X:X/M as-set
.. clicmd:: aggregate-address X:X::X:X/M as-set
This command specifies an aggregate address. Resulting routes include
AS set.
-.. index:: aggregate-address X:X::X:X/M summary-only
.. clicmd:: aggregate-address X:X::X:X/M summary-only
This command specifies an aggregate address. Aggregated routes will
not be announced.
-.. index:: aggregate-address X:X::X:X/M matching-MED-only
.. clicmd:: aggregate-address X:X::X:X/M matching-MED-only
Configure the aggregated address to only be created when the routes MED
match, otherwise no aggregated route will be created.
-.. index:: aggregate-address X:X::X:X/M suppress-map NAME
.. clicmd:: aggregate-address X:X::X:X/M suppress-map NAME
Similar to `summary-only`, but will only suppress more specific routes that
are matched by the selected route-map.
-.. index:: aggregate-address X:X::X:X/M
-.. clicmd:: no aggregate-address X:X::X:X/M
-
- This command removes an aggregate address.
-
- This configuration example setup the aggregate-address under
- ipv6 address-family.
+ This configuration example sets up an ``aggregate-address`` under the ipv6
+ address-family.
.. code-block:: frr
@@ -1259,50 +1196,27 @@ Route Aggregation-IPv6 Address Family
aggregate-address 50::0/64 route-map aggr-rmap
exit-address-family
+
.. _bgp-redistribute-to-bgp:
Redistribution
--------------
-.. index:: redistribute kernel
-.. clicmd:: redistribute kernel
-
- Redistribute kernel route to BGP process.
-
-.. index:: redistribute static
-.. clicmd:: redistribute static
+Redistribution configuration should be placed under the ``address-family``
+section for the specific AF to redistribute into. Protocol availability for
+redistribution is determined by BGP AF; for example, you cannot redistribute
+OSPFv3 into ``address-family ipv4 unicast`` as OSPFv3 supports IPv6.
- Redistribute static route to BGP process.
+.. clicmd:: redistribute <babel|connected|eigrp|isis|kernel|openfabric|ospf|ospf6|rip|ripng|sharp|static|table> [metric (0-4294967295)] [route-map WORD]
-.. index:: redistribute connected
-.. clicmd:: redistribute connected
+Redistribute routes from other protocols into BGP.
- Redistribute connected route to BGP process.
-
-.. index:: redistribute rip
-.. clicmd:: redistribute rip
-
- Redistribute RIP route to BGP process.
-
-.. index:: redistribute ospf
-.. clicmd:: redistribute ospf
-
- Redistribute OSPF route to BGP process.
-
-.. index:: redistribute vnc
-.. clicmd:: redistribute vnc
-
- Redistribute VNC routes to BGP process.
-
-.. index:: redistribute vnc-direct
.. clicmd:: redistribute vnc-direct
Redistribute VNC direct (not via zebra) routes to BGP process.
-.. index:: bgp update-delay MAX-DELAY
.. clicmd:: bgp update-delay MAX-DELAY
-.. index:: bgp update-delay MAX-DELAY ESTABLISH-WAIT
.. clicmd:: bgp update-delay MAX-DELAY ESTABLISH-WAIT
This feature is used to enable read-only mode on BGP process restart or when
@@ -1334,10 +1248,8 @@ Redistribution
Default max-delay is 0, i.e. the feature is off by default.
-.. index:: update-delay MAX-DELAY
.. clicmd:: update-delay MAX-DELAY
-.. index:: update-delay MAX-DELAY ESTABLISH-WAIT
.. clicmd:: update-delay MAX-DELAY ESTABLISH-WAIT
This feature is used to enable read-only mode on BGP process restart or when
@@ -1368,7 +1280,6 @@ Redistribution
Default max-delay is 0, i.e. the feature is off by default.
-.. index:: table-map ROUTE-MAP-NAME
.. clicmd:: table-map ROUTE-MAP-NAME
This feature is used to apply a route-map on route updates from BGP to
@@ -1390,7 +1301,6 @@ Peers
Defining Peers
^^^^^^^^^^^^^^
-.. index:: neighbor PEER remote-as ASN
.. clicmd:: neighbor PEER remote-as ASN
Creates a new neighbor whose remote-as is ASN. PEER can be an IPv4 address
@@ -1408,22 +1318,19 @@ Defining Peers
can't find neighbor 10.0.0.1
-.. index:: neighbor PEER remote-as internal
.. clicmd:: neighbor PEER remote-as internal
Create a peer as you would when you specify an ASN, except that if the
peers ASN is different than mine as specified under the :clicmd:`router bgp ASN`
command the connection will be denied.
-.. index:: neighbor PEER remote-as external
.. clicmd:: neighbor PEER remote-as external
Create a peer as you would when you specify an ASN, except that if the
peers ASN is the same as mine as specified under the :clicmd:`router bgp ASN`
command the connection will be denied.
-.. index:: bgp listen range <A.B.C.D/M|X:X::X:X/M> peer-group PGNAME
-.. clicmd:: [no] bgp listen range <A.B.C.D/M|X:X::X:X/M> peer-group PGNAME
+.. clicmd:: bgp listen range <A.B.C.D/M|X:X::X:X/M> peer-group PGNAME
Accept connections from any peers in the specified prefix. Configuration
from the specified peer-group is used to configure these peers.
@@ -1446,8 +1353,7 @@ Defining Peers
``net.core.optmem_max`` to allow the kernel to allocate the necessary option
memory.
-.. index:: coalesce-time (0-4294967295)
-.. clicmd:: [no] coalesce-time (0-4294967295)
+.. clicmd:: coalesce-time (0-4294967295)
The time in milliseconds that BGP will delay before deciding what peers
can be put into an update-group together in order to generate a single
@@ -1458,8 +1364,7 @@ Defining Peers
Configuring Peers
^^^^^^^^^^^^^^^^^
-.. index:: neighbor PEER shutdown [message MSG...] [rtt (1-65535) [count (1-255)]]
-.. clicmd:: [no] neighbor PEER shutdown [message MSG...] [rtt (1-65535) [count (1-255)]]
+.. clicmd:: neighbor PEER shutdown [message MSG...] [rtt (1-65535) [count (1-255)]]
Shutdown the peer. We can delete the neighbor's configuration by
``no neighbor PEER remote-as ASN`` but all configuration of the neighbor
@@ -1474,14 +1379,12 @@ Configuring Peers
Additional ``count`` parameter is the number of keepalive messages to count
before shutdown the peer if round-trip-time becomes higher than defined.
-.. index:: neighbor PEER disable-connected-check
-.. clicmd:: [no] neighbor PEER disable-connected-check
+.. clicmd:: neighbor PEER disable-connected-check
Allow peerings between directly connected eBGP peers using loopback
addresses.
-.. index:: neighbor PEER ebgp-multihop
-.. clicmd:: [no] neighbor PEER ebgp-multihop
+.. clicmd:: neighbor PEER ebgp-multihop
Specifying ``ebgp-multihop`` allows sessions with eBGP neighbors to
establish when they are multiple hops away. When the neighbor is not
@@ -1491,13 +1394,11 @@ Configuring Peers
If the peer's IP address is not in the RIB and is reachable via the
default route, then you have to enable ``ip nht resolve-via-default``.
-.. index:: neighbor PEER description ...
-.. clicmd:: [no] neighbor PEER description ...
+.. clicmd:: neighbor PEER description ...
Set description of the peer.
-.. index:: neighbor PEER version VERSION
-.. clicmd:: [no] neighbor PEER version VERSION
+.. clicmd:: neighbor PEER version VERSION
Set up the neighbor's BGP version. `version` can be `4`, `4+` or `4-`. BGP
version `4` is the default value used for BGP peering. BGP version `4+`
@@ -1506,8 +1407,7 @@ Configuring Peers
revision 00's Multiprotocol Extensions for BGP-4. Some routing software is
still using this version.
-.. index:: neighbor PEER interface IFNAME
-.. clicmd:: [no] neighbor PEER interface IFNAME
+.. clicmd:: neighbor PEER interface IFNAME
When you connect to a BGP peer over an IPv6 link-local address, you have to
specify the IFNAME of the interface used for the connection. To specify
@@ -1517,15 +1417,13 @@ Configuring Peers
This command is deprecated and may be removed in a future release. Its use
should be avoided.
-.. index:: neighbor PEER next-hop-self [all]
-.. clicmd:: [no] neighbor PEER next-hop-self [all]
+.. clicmd:: neighbor PEER next-hop-self [all]
This command specifies an announced route's nexthop as being equivalent to
the address of the bgp router if it is learned via eBGP. If the optional
keyword `all` is specified the modification is done also for routes learned
via iBGP.
-.. index:: neighbor PEER attribute-unchanged [{as-path|next-hop|med}]
.. clicmd:: neighbor PEER attribute-unchanged [{as-path|next-hop|med}]
This command specifies attributes to be left unchanged for advertisements
@@ -1533,8 +1431,7 @@ Configuring Peers
configurations, as the route-map directive to leave the next-hop unchanged
is only available for ipv4.
-.. index:: neighbor PEER update-source <IFNAME|ADDRESS>
-.. clicmd:: [no] neighbor PEER update-source <IFNAME|ADDRESS>
+.. clicmd:: neighbor PEER update-source <IFNAME|ADDRESS>
Specify the IPv4 source address to use for the :abbr:`BGP` session to this
neighbour, may be specified as either an IPv4 address directly or as an
@@ -1548,18 +1445,15 @@ Configuring Peers
neighbor bar update-source lo0
-.. index:: neighbor PEER default-originate
-.. clicmd:: [no] neighbor PEER default-originate
+.. clicmd:: neighbor PEER default-originate
*bgpd*'s default is to not announce the default route (0.0.0.0/0) even if it
is in routing table. When you want to announce default routes to the peer,
use this command.
-.. index:: neighbor PEER port PORT
.. clicmd:: neighbor PEER port PORT
-.. index:: neighbor PEER password PASSWORD
-.. clicmd:: [no] neighbor PEER password PASSWORD
+.. clicmd:: neighbor PEER password PASSWORD
Set a MD5 password to be used with the tcp socket that is being used
to connect to the remote peer. Please note if you are using this
@@ -1567,16 +1461,13 @@ Configuring Peers
modifying the `net.core.optmem_max` sysctl to a larger value to
avoid out of memory errors from the linux kernel.
-.. index:: neighbor PEER send-community
.. clicmd:: neighbor PEER send-community
-.. index:: neighbor PEER weight WEIGHT
-.. clicmd:: [no] neighbor PEER weight WEIGHT
+.. clicmd:: neighbor PEER weight WEIGHT
This command specifies a default `weight` value for the neighbor's routes.
-.. index:: neighbor PEER maximum-prefix NUMBER [force]
-.. clicmd:: [no] neighbor PEER maximum-prefix NUMBER [force]
+.. clicmd:: neighbor PEER maximum-prefix NUMBER [force]
Sets a maximum number of prefixes we can receive from a given peer. If this
number is exceeded, the BGP session will be destroyed.
@@ -1593,16 +1484,14 @@ Configuring Peers
but you want maximum-prefix to act on ALL (including filtered) prefixes. This
option requires `soft-reconfiguration inbound` to be enabled for the peer.
-.. index:: neighbor PEER maximum-prefix-out NUMBER
-.. clicmd:: [no] neighbor PEER maximum-prefix-out NUMBER
+.. clicmd:: neighbor PEER maximum-prefix-out NUMBER
Sets a maximum number of prefixes we can send to a given peer.
Since sent prefix count is managed by update-groups, this option
creates a separate update-group for outgoing updates.
-.. index:: neighbor PEER local-as AS-NUMBER [no-prepend] [replace-as]
-.. clicmd:: [no] neighbor PEER local-as AS-NUMBER [no-prepend] [replace-as]
+.. clicmd:: neighbor PEER local-as AS-NUMBER [no-prepend] [replace-as]
Specify an alternate AS for this BGP process when interacting with the
specified peer. With no modifiers, the specified local-as is prepended to
@@ -1620,8 +1509,7 @@ Configuring Peers
This command is only allowed for eBGP peers.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> as-override
-.. clicmd:: [no] neighbor <A.B.C.D|X:X::X:X|WORD> as-override
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> as-override
Override AS number of the originating router with the local AS number.
@@ -1633,8 +1521,7 @@ Configuring Peers
This command is only allowed for eBGP peers.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]
-.. clicmd:: [no] neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> allowas-in [<(1-10)|origin>]
Accept incoming routes with AS path containing AS number with the same value
as the current system AS.
@@ -1651,28 +1538,24 @@ Configuring Peers
This command is only allowed for eBGP peers.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths
-.. clicmd:: [no] neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-all-paths
Configure BGP to send all known paths to neighbor in order to preserve multi
path capabilities inside a network.
-.. index:: neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-bestpath-per-AS
-.. clicmd:: [no] neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-bestpath-per-AS
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> addpath-tx-bestpath-per-AS
Configure BGP to send best known paths to neighbor in order to preserve multi
path capabilities inside a network.
-.. index:: neighbor PEER ttl-security hops NUMBER
-.. clicmd:: [no] neighbor PEER ttl-security hops NUMBER
+.. clicmd:: neighbor PEER ttl-security hops NUMBER
This command enforces Generalized TTL Security Mechanism (GTSM), as
specified in RFC 5082. With this command, only neighbors that are the
specified number of hops away will be allowed to become neighbors. This
command is mutually exclusive with *ebgp-multihop*.
-.. index:: neighbor PEER capability extended-nexthop
-.. clicmd:: [no] neighbor PEER capability extended-nexthop
+.. clicmd:: neighbor PEER capability extended-nexthop
Allow bgp to negotiate the extended-nexthop capability with it's peer.
If you are peering over a v6 LL address then this capability is turned
@@ -1680,43 +1563,37 @@ Configuring Peers
turning on this command will allow BGP to install v4 routes with
v6 nexthops if you do not have v4 configured on interfaces.
-.. index:: bgp fast-external-failover
-.. clicmd:: [no] bgp fast-external-failover
+.. clicmd:: bgp fast-external-failover
This command causes bgp to not take down ebgp peers immediately
when a link flaps. `bgp fast-external-failover` is the default
and will not be displayed as part of a `show run`. The no form
of the command turns off this ability.
-.. index:: bgp default ipv4-unicast
-.. clicmd:: [no] bgp default ipv4-unicast
+.. clicmd:: bgp default ipv4-unicast
This command allows the user to specify that v4 peering is turned
on by default or not. This command defaults to on and is not displayed.
The `no bgp default ipv4-unicast` form of the command is displayed.
-.. index:: bgp default show-hostname
-.. clicmd:: [no] bgp default show-hostname
+.. clicmd:: bgp default show-hostname
This command shows the hostname of the peer in certain BGP commands
outputs. It's easier to troubleshoot if you have a number of BGP peers.
-.. index:: bgp default show-nexthop-hostname
-.. clicmd:: [no] bgp default show-nexthop-hostname
+.. clicmd:: bgp default show-nexthop-hostname
This command shows the hostname of the next-hop in certain BGP commands
outputs. It's easier to troubleshoot if you have a number of BGP peers
and a number of routes to check.
-.. index:: neighbor PEER advertisement-interval (0-600)
-.. clicmd:: [no] neighbor PEER advertisement-interval (0-600)
+.. clicmd:: neighbor PEER advertisement-interval (0-600)
Setup the minimum route advertisement interval(mrai) for the
peer in question. This number is between 0 and 600 seconds,
with the default advertisement interval being 0.
-.. index:: neighbor PEER timers delayopen (1-240)
-.. clicmd:: [no] neighbor PEER timers delayopen (1-240)
+.. clicmd:: neighbor PEER timers delayopen (1-240)
This command allows the user enable the
`RFC 4271 <https://tools.ietf.org/html/rfc4271/>` DelayOpenTimer with the
@@ -1727,7 +1604,6 @@ Configuring Peers
Displaying Information about Peers
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: show bgp <afi> <safi> neighbors WORD bestpath-routes [json] [wide]
.. clicmd:: show bgp <afi> <safi> neighbors WORD bestpath-routes [json] [wide]
For the given neighbor, WORD, that is specified list the routes selected
@@ -1738,32 +1614,26 @@ Displaying Information about Peers
Peer Filtering
^^^^^^^^^^^^^^
-.. index:: neighbor PEER distribute-list NAME [in|out]
.. clicmd:: neighbor PEER distribute-list NAME [in|out]
This command specifies a distribute-list for the peer. `direct` is
``in`` or ``out``.
-.. index:: neighbor PEER prefix-list NAME [in|out]
.. clicmd:: neighbor PEER prefix-list NAME [in|out]
-.. index:: neighbor PEER filter-list NAME [in|out]
.. clicmd:: neighbor PEER filter-list NAME [in|out]
-.. index:: neighbor PEER route-map NAME [in|out]
.. clicmd:: neighbor PEER route-map NAME [in|out]
Apply a route-map on the neighbor. `direct` must be `in` or `out`.
-.. index:: bgp route-reflector allow-outbound-policy
.. clicmd:: bgp route-reflector allow-outbound-policy
By default, attribute modification via route-map policy out is not reflected
on reflected routes. This option allows the modifications to be reflected as
well. Once enabled, it affects all reflected routes.
-.. index:: neighbor PEER sender-as-path-loop-detection
-.. clicmd:: [no] neighbor PEER sender-as-path-loop-detection
+.. clicmd:: neighbor PEER sender-as-path-loop-detection
Enable the detection of sender side AS path loops and filter the
bad routes before they are sent.
@@ -1783,17 +1653,14 @@ indicated the originating peer. All peers not associated with a
specific peer group are treated as belonging to a default peer group,
and will share updates.
-.. index:: neighbor WORD peer-group
.. clicmd:: neighbor WORD peer-group
This command defines a new peer group.
-.. index:: neighbor PEER peer-group PGNAME
.. clicmd:: neighbor PEER peer-group PGNAME
This command bind specific peer to peer group WORD.
-.. index:: neighbor PEER solo
.. clicmd:: neighbor PEER solo
This command is used to indicate that routes advertised by the peer
@@ -1803,11 +1670,8 @@ and will share updates.
Capability Negotiation
^^^^^^^^^^^^^^^^^^^^^^
-.. index:: neighbor PEER strict-capability-match
.. clicmd:: neighbor PEER strict-capability-match
-.. index:: neighbor PEER strict-capability-match
-.. clicmd:: no neighbor PEER strict-capability-match
Strictly compares remote capabilities and local capabilities. If
capabilities are different, send Unsupported Capability error then reset
@@ -1818,8 +1682,7 @@ Capability Negotiation
Negotiation. Please use *dont-capability-negotiate* command to disable the
feature.
-.. index:: neighbor PEER dont-capability-negotiate
-.. clicmd:: [no] neighbor PEER dont-capability-negotiate
+.. clicmd:: neighbor PEER dont-capability-negotiate
Suppress sending Capability Negotiation as OPEN message optional parameter
to the peer. This command only affects the peer is configured other than
@@ -1839,11 +1702,8 @@ Capability Negotiation
hostname support, AS4, Addpath, Route Refresh, ORF, Dynamic Capabilities,
and graceful restart.
-.. index:: neighbor PEER override-capability
.. clicmd:: neighbor PEER override-capability
-.. index:: neighbor PEER override-capability
-.. clicmd:: no neighbor PEER override-capability
Override the result of Capability Negotiation with local configuration.
Ignore remote peer's capability value.
@@ -1855,16 +1715,11 @@ AS Path Access Lists
AS path access list is user defined AS path.
-.. index:: bgp as-path access-list WORD permit|deny LINE
.. clicmd:: bgp as-path access-list WORD permit|deny LINE
This command defines a new AS path access list.
-.. index:: bgp as-path access-list WORD
-.. clicmd:: no bgp as-path access-list WORD
-.. index:: bgp as-path access-list WORD permit|deny LINE
-.. clicmd:: no bgp as-path access-list WORD permit|deny LINE
.. _bgp-bogon-filter-example:
@@ -1882,21 +1737,18 @@ Bogon ASN filter policy configuration example
Using AS Path in Route Map
--------------------------
-.. index:: match as-path WORD
-.. clicmd:: [no] match as-path WORD
+.. clicmd:: match as-path WORD
For a given as-path, WORD, match it on the BGP as-path given for the prefix
and if it matches do normal route-map actions. The no form of the command
removes this match from the route-map.
-.. index:: set as-path prepend AS-PATH
-.. clicmd:: [no] set as-path prepend AS-PATH
+.. clicmd:: set as-path prepend AS-PATH
Prepend the given string of AS numbers to the AS_PATH of the BGP path's NLRI.
The no form of this command removes this set operation from the route-map.
-.. index:: set as-path prepend last-as NUM
-.. clicmd:: [no] set as-path prepend last-as NUM
+.. clicmd:: set as-path prepend last-as NUM
Prepend the existing last AS number (the leftmost ASN) to the AS_PATH.
The no form of this command removes this set operation from the route-map.
@@ -2042,7 +1894,6 @@ expanded
interpreted on each use expanded community lists are slower than standard
lists.
-.. index:: bgp community-list standard NAME permit|deny COMMUNITY
.. clicmd:: bgp community-list standard NAME permit|deny COMMUNITY
This command defines a new standard community list. ``COMMUNITY`` is
@@ -2053,7 +1904,6 @@ expanded
community list definition. When there is no matched entry, deny will be
returned. When ``COMMUNITY`` is empty it matches to any routes.
-.. index:: bgp community-list expanded NAME permit|deny COMMUNITY
.. clicmd:: bgp community-list expanded NAME permit|deny COMMUNITY
This command defines a new expanded community list. ``COMMUNITY`` is a
@@ -2065,7 +1915,6 @@ expanded
.. deprecated:: 5.0
It is recommended to use the more explicit versions of this command.
-.. index:: bgp community-list NAME permit|deny COMMUNITY
.. clicmd:: bgp community-list NAME permit|deny COMMUNITY
When the community list type is not specified, the community list type is
@@ -2074,15 +1923,10 @@ expanded
Otherwise it is defined as an expanded community list. This feature is left
for backward compatibility. Use of this feature is not recommended.
+ Note that all community lists share the same namespace, so it's not
+ necessary to specify ``standard`` or ``expanded``; these modifiers are
+ purely aesthetic.
-.. index:: bgp community-list [standard|expanded] NAME
-.. clicmd:: no bgp community-list [standard|expanded] NAME
-
- Deletes the community list specified by ``NAME``. All community lists share
- the same namespace, so it's not necessary to specify ``standard`` or
- ``expanded``; these modifiers are purely aesthetic.
-
-.. index:: show bgp community-list [NAME detail]
.. clicmd:: show bgp community-list [NAME detail]
Displays community list information. When ``NAME`` is specified the
@@ -2115,13 +1959,11 @@ to 199 is expanded community list. These community lists are called
as numbered community lists. On the other hand normal community lists
is called as named community lists.
-.. index:: bgp community-list (1-99) permit|deny COMMUNITY
.. clicmd:: bgp community-list (1-99) permit|deny COMMUNITY
This command defines a new community list. The argument to (1-99) defines
the list identifier.
-.. index:: bgp community-list (100-199) permit|deny COMMUNITY
.. clicmd:: bgp community-list (100-199) permit|deny COMMUNITY
This command defines a new expanded community list. The argument to
@@ -2138,7 +1980,6 @@ communities attribute.
The following commands can be used in route maps:
-.. index:: match community WORD exact-match [exact-match]
.. clicmd:: match community WORD exact-match [exact-match]
This command perform match to BGP updates using community list WORD. When
@@ -2147,7 +1988,6 @@ The following commands can be used in route maps:
happen only when BGP updates have completely same communities value
specified in the community list.
-.. index:: set community <none|COMMUNITY> additive
.. clicmd:: set community <none|COMMUNITY> additive
This command sets the community value in BGP updates. If the attribute is
@@ -2160,7 +2000,6 @@ The following commands can be used in route maps:
It is not possible to set an expanded community list.
-.. index:: set comm-list WORD delete
.. clicmd:: set comm-list WORD delete
This command remove communities value from BGP communities attribute. The
@@ -2337,7 +2176,6 @@ the other is IP address based format.
Extended Community Lists
^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: bgp extcommunity-list standard NAME permit|deny EXTCOMMUNITY
.. clicmd:: bgp extcommunity-list standard NAME permit|deny EXTCOMMUNITY
This command defines a new standard extcommunity-list. `extcommunity` is
@@ -2349,7 +2187,6 @@ Extended Community Lists
there is no matched entry, deny will be returned. When `extcommunity` is
empty it matches to any routes.
-.. index:: bgp extcommunity-list expanded NAME permit|deny LINE
.. clicmd:: bgp extcommunity-list expanded NAME permit|deny LINE
This command defines a new expanded extcommunity-list. `line` is a string
@@ -2357,29 +2194,13 @@ Extended Community Lists
expression (:ref:`bgp-regular-expressions`) to match an extended communities
attribute in BGP updates.
-.. index:: bgp extcommunity-list NAME
-.. clicmd:: no bgp extcommunity-list NAME
-
-.. index:: bgp extcommunity-list standard NAME
-.. clicmd:: no bgp extcommunity-list standard NAME
+ Note that all extended community lists shares a single name space, so it's
+ not necessary to specify their type when creating or destroying them.
-.. index:: bgp extcommunity-list expanded NAME
-.. clicmd:: no bgp extcommunity-list expanded NAME
-
- These commands delete extended community lists specified by `name`. All of
- extended community lists shares a single name space. So extended community
- lists can be removed simply specifying the name.
-
-.. index:: show bgp extcommunity-list
-.. clicmd:: show bgp extcommunity-list
-
-.. index:: show bgp extcommunity-list NAME detail
-.. clicmd:: show bgp extcommunity-list NAME detail
+.. clicmd:: show bgp extcommunity-list [NAME detail]
This command displays current extcommunity-list information. When `name` is
- specified the community list's information is shown.::
-
- # show bgp extcommunity-list
+ specified the community list's information is shown.
.. _bgp-extended-communities-in-route-map:
@@ -2387,20 +2208,16 @@ Extended Community Lists
BGP Extended Communities in Route Map
"""""""""""""""""""""""""""""""""""""
-.. index:: match extcommunity WORD
.. clicmd:: match extcommunity WORD
-.. index:: set extcommunity rt EXTCOMMUNITY
.. clicmd:: set extcommunity rt EXTCOMMUNITY
This command set Route Target value.
-.. index:: set extcommunity soo EXTCOMMUNITY
.. clicmd:: set extcommunity soo EXTCOMMUNITY
This command set Site of Origin value.
-.. index:: set extcommunity bandwidth <(1-25600) | cumulative | num-multipaths> [non-transitive]
.. clicmd:: set extcommunity bandwidth <(1-25600) | cumulative | num-multipaths> [non-transitive]
This command sets the BGP link-bandwidth extended community for the prefix
@@ -2452,7 +2269,6 @@ Large Community Lists
Two types of large community lists are supported, namely `standard` and
`expanded`.
-.. index:: bgp large-community-list standard NAME permit|deny LARGE-COMMUNITY
.. clicmd:: bgp large-community-list standard NAME permit|deny LARGE-COMMUNITY
This command defines a new standard large-community-list. `large-community`
@@ -2463,7 +2279,6 @@ Two types of large community lists are supported, namely `standard` and
definition. When there is no matched entry, a deny will be returned. When
`large-community` is empty it matches any routes.
-.. index:: bgp large-community-list expanded NAME permit|deny LINE
.. clicmd:: bgp large-community-list expanded NAME permit|deny LINE
This command defines a new expanded large-community-list. Where `line` is a
@@ -2472,29 +2287,17 @@ Two types of large community lists are supported, namely `standard` and
lowest to highest. `line` can also be a regular expression which matches
this Large Community attribute.
-.. index:: bgp large-community-list NAME
-.. clicmd:: no bgp large-community-list NAME
-
-.. index:: bgp large-community-list standard NAME
-.. clicmd:: no bgp large-community-list standard NAME
-
-.. index:: bgp large-community-list expanded NAME
-.. clicmd:: no bgp large-community-list expanded NAME
+ Note that all community lists share the same namespace, so it's not
+ necessary to specify ``standard`` or ``expanded``; these modifiers are
+ purely aesthetic.
- These commands delete Large Community lists specified by `name`. All Large
- Community lists share a single namespace. This means Large Community lists
- can be removed by simply specifying the name.
-
-.. index:: show bgp large-community-list
.. clicmd:: show bgp large-community-list
-.. index:: show bgp large-community-list NAME detail
.. clicmd:: show bgp large-community-list NAME detail
This command display current large-community-list information. When
`name` is specified the community list information is shown.
-.. index:: show ip bgp large-community-info
.. clicmd:: show ip bgp large-community-info
This command displays the current large communities in use.
@@ -2504,7 +2307,6 @@ Two types of large community lists are supported, namely `standard` and
Large Communities in Route Map
""""""""""""""""""""""""""""""
-.. index:: match large-community LINE [exact-match]
.. clicmd:: match large-community LINE [exact-match]
Where `line` can be a simple string to match, or a regular expression. It
@@ -2514,13 +2316,10 @@ Large Communities in Route Map
happen only when BGP updates have completely same large communities value
specified in the large community list.
-.. index:: set large-community LARGE-COMMUNITY
.. clicmd:: set large-community LARGE-COMMUNITY
-.. index:: set large-community LARGE-COMMUNITY LARGE-COMMUNITY
.. clicmd:: set large-community LARGE-COMMUNITY LARGE-COMMUNITY
-.. index:: set large-community LARGE-COMMUNITY additive
.. clicmd:: set large-community LARGE-COMMUNITY additive
These commands are used for setting large-community values. The first
@@ -2602,18 +2401,11 @@ Configuration of route leaking between a unicast VRF RIB and the VPN SAFI RIB
of the default VRF is accomplished via commands in the context of a VRF
address-family:
-.. index:: rd vpn export AS:NN|IP:nn
.. clicmd:: rd vpn export AS:NN|IP:nn
Specifies the route distinguisher to be added to a route exported from the
current unicast VRF to VPN.
-.. index:: rd vpn export [AS:NN|IP:nn]
-.. clicmd:: no rd vpn export [AS:NN|IP:nn]
-
- Deletes any previously-configured export route distinguisher.
-
-.. index:: rt vpn import|export|both RTLIST...
.. clicmd:: rt vpn import|export|both RTLIST...
Specifies the route-target list to be attached to a route (export) or the
@@ -2624,12 +2416,6 @@ address-family:
extended community values as described in
:ref:`bgp-extended-communities-attribute`.
-.. index:: rt vpn import|export|both [RTLIST...]
-.. clicmd:: no rt vpn import|export|both [RTLIST...]
-
- Deletes any previously-configured import or export route-target list.
-
-.. index:: label vpn export (0..1048575)|auto
.. clicmd:: label vpn export (0..1048575)|auto
Enables an MPLS label to be attached to a route exported from the current
@@ -2638,45 +2424,21 @@ address-family:
is not running, or if this command is not configured, automatic label
assignment will not complete, which will block corresponding route export.
-.. index:: label vpn export [(0..1048575)|auto]
-.. clicmd:: no label vpn export [(0..1048575)|auto]
-
- Deletes any previously-configured export label.
-
-.. index:: nexthop vpn export A.B.C.D|X:X::X:X
.. clicmd:: nexthop vpn export A.B.C.D|X:X::X:X
Specifies an optional nexthop value to be assigned to a route exported from
the current unicast VRF to VPN. If left unspecified, the nexthop will be set
to 0.0.0.0 or 0:0::0:0 (self).
-.. index:: nexthop vpn export [A.B.C.D|X:X::X:X]
-.. clicmd:: no nexthop vpn export [A.B.C.D|X:X::X:X]
-
- Deletes any previously-configured export nexthop.
-
-.. index:: route-map vpn import|export MAP
.. clicmd:: route-map vpn import|export MAP
Specifies an optional route-map to be applied to routes imported or exported
between the current unicast VRF and VPN.
-.. index:: route-map vpn import|export [MAP]
-.. clicmd:: no route-map vpn import|export [MAP]
-
- Deletes any previously-configured import or export route-map.
-
-.. index:: import|export vpn
.. clicmd:: import|export vpn
Enables import or export of routes between the current unicast VRF and VPN.
-.. index:: import|export vpn
-.. clicmd:: no import|export vpn
-
- Disables import or export of routes between the current unicast VRF and VPN.
-
-.. index:: import vrf VRFNAME
.. clicmd:: import vrf VRFNAME
Shortcut syntax for specifying automatic leaking from vrf VRFNAME to
@@ -2689,12 +2451,6 @@ address-family:
The CLI will disallow attempts to configure incompatible leaking
modes.
-.. index:: import vrf VRFNAME
-.. clicmd:: no import vrf VRFNAME
-
- Disables automatic leaking from vrf VRFNAME to the current VRF using
- the VPN RIB as intermediary.
-
.. _bgp-evpn:
@@ -2745,8 +2501,7 @@ disable the feature via configuration CLI. Once the feature is disable under
bgp vrf instance or MAC-VLAN interface is not configured, all the routes follow
the same behavior of using same next-hop and RMAC values.
-.. index:: advertise-pip [ip <addr> [mac <addr>]]
-.. clicmd:: [no] advertise-pip [ip <addr> [mac <addr>]]
+.. clicmd:: advertise-pip [ip <addr> [mac <addr>]]
Enables or disables advertise-pip feature, specifiy system-IP and/or system-MAC
parameters.
@@ -2763,11 +2518,9 @@ Ethernet Segments
An Ethernet Segment can be configured by specifying a system-MAC and a
local discriminatior against the bond interface on the PE (via zebra) -
-.. index:: evpn mh es-id (1-16777215)
-.. clicmd:: [no] evpn mh es-id (1-16777215)
+.. clicmd:: evpn mh es-id (1-16777215)
-.. index:: evpn mh es-sys-mac X:X:X:X:X:X
-.. clicmd:: [no] evpn mh es-sys-mac X:X:X:X:X:X
+.. clicmd:: evpn mh es-sys-mac X:X:X:X:X:X
The sys-mac and local discriminator are used for generating a 10-byte,
Type-3 Ethernet Segment ID.
@@ -2790,8 +2543,7 @@ forward BUM traffic received via the overlay network. This implementation
uses a preference based DF election specified by draft-ietf-bess-evpn-pref-df.
The DF preference is configurable per-ES (via zebra) -
-.. index:: evpn mh es-df-pref (1-16777215)
-.. clicmd:: [no] evpn mh es-df-pref (1-16777215)
+.. clicmd:: evpn mh es-df-pref (1-16777215)
BUM traffic is rxed via the overlay by all PEs attached to a server but
only the DF can forward the de-capsulated traffic to the access port. To
@@ -2809,11 +2561,9 @@ ES-PE based on just the EAD-per-ES route.
Note that by default we advertise and expect EAD-per-EVI routes.
-.. index:: disable-ead-evi-rx
-.. clicmd:: [no] disable-ead-evi-rx
+.. clicmd:: disable-ead-evi-rx
-.. index:: disable-ead-evi-tx
-.. clicmd:: [no] disable-ead-evi-tx
+.. clicmd:: disable-ead-evi-tx
Fast failover
"""""""""""""
@@ -2827,15 +2577,13 @@ been introduced for the express purpose of efficient ES failovers.
On dataplanes that support layer3 nexthop groups the feature can be turned
on via the following BGP config -
-.. index:: use-es-l3nhg
-.. clicmd:: [no] use-es-l3nhg
+.. clicmd:: use-es-l3nhg
- Local ES (MAC/Neigh) failover via ES-redirect.
On dataplanes that do not have support for ES-redirect the feature can be
turned off via the following zebra config -
-.. index:: evpn mh redirect-off
-.. clicmd:: [no] evpn mh redirect-off
+.. clicmd:: evpn mh redirect-off
Uplink/Core tracking
""""""""""""""""""""
@@ -2844,8 +2592,7 @@ When all the underlay links go down the PE no longer has access to the VxLAN
protodowned on the PE. A link can be setup for uplink tracking via the
following zebra configuration -
-.. index:: evpn mh uplink
-.. clicmd:: [no] evpn mh uplink
+.. clicmd:: evpn mh uplink
Proxy advertisements
""""""""""""""""""""
@@ -2856,11 +2603,9 @@ the ES peer (PE2) goes down PE1 continues to advertise hosts learnt from PE2
for a holdtime during which it attempts to establish local reachability of
the host. This holdtime is configurable via the following zebra commands -
-.. index:: evpn mh neigh-holdtime (0-86400)
-.. clicmd:: [no] evpn mh neigh-holdtime (0-86400)
+.. clicmd:: evpn mh neigh-holdtime (0-86400)
-.. index:: evpn mh mac-holdtime (0-86400)
-.. clicmd:: [no] evpn mh mac-holdtime (0-86400)
+.. clicmd:: evpn mh mac-holdtime (0-86400)
Startup delay
"""""""""""""
@@ -2869,8 +2614,7 @@ and EVPN network to converge before enabling the ESs. For this duration the
ES bonds are held protodown. The startup delay is configurable via the
following zebra command -
-.. index:: evpn mh startup-delay (0-3600)
-.. clicmd:: [no] evpn mh startup-delay (0-3600)
+.. clicmd:: evpn mh startup-delay (0-3600)
+Support with VRF network namespace backend
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -2928,8 +2672,7 @@ advertisement to take effect is 60 seconds. The conditional advertisement can ta
effect depending on when the tracked route is removed from the BGP table and
when the next instance of the BGP scanner occurs.
-.. index:: neighbor A.B.C.D advertise-map NAME [exist-map|non-exist-map] NAME
-.. clicmd:: [no] neighbor A.B.C.D advertise-map NAME [exist-map|non-exist-map] NAME
+.. clicmd:: neighbor A.B.C.D advertise-map NAME [exist-map|non-exist-map] NAME
This command enables BGP scanner process to monitor routes specified by
exist-map or non-exist-map command in BGP table and conditionally advertises
@@ -3086,70 +2829,57 @@ When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2
Debugging
---------
-.. index:: show debug
.. clicmd:: show debug
Show all enabled debugs.
-.. index:: show bgp listeners
.. clicmd:: show bgp listeners
Display Listen sockets and the vrf that created them. Useful for debugging of when
listen is not working and this is considered a developer debug statement.
-.. index:: debug bgp neighbor-events
-.. clicmd:: [no] debug bgp neighbor-events
+.. clicmd:: debug bgp neighbor-events
Enable or disable debugging for neighbor events. This provides general
information on BGP events such as peer connection / disconnection, session
establishment / teardown, and capability negotiation.
-.. index:: debug bgp updates
-.. clicmd:: [no] debug bgp updates
+.. clicmd:: debug bgp updates
Enable or disable debugging for BGP updates. This provides information on
BGP UPDATE messages transmitted and received between local and remote
instances.
-.. index:: debug bgp keepalives
-.. clicmd:: [no] debug bgp keepalives
+.. clicmd:: debug bgp keepalives
Enable or disable debugging for BGP keepalives. This provides information on
BGP KEEPALIVE messages transmitted and received between local and remote
instances.
-.. index:: debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>
-.. clicmd:: [no] debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>
+.. clicmd:: debug bgp bestpath <A.B.C.D/M|X:X::X:X/M>
Enable or disable debugging for bestpath selection on the specified prefix.
-.. index:: debug bgp nht
-.. clicmd:: [no] debug bgp nht
+.. clicmd:: debug bgp nht
Enable or disable debugging of BGP nexthop tracking.
-.. index:: debug bgp update-groups
-.. clicmd:: [no] debug bgp update-groups
+.. clicmd:: debug bgp update-groups
Enable or disable debugging of dynamic update groups. This provides general
information on group creation, deletion, join and prune events.
-.. index:: debug bgp zebra
-.. clicmd:: [no] debug bgp zebra
+.. clicmd:: debug bgp zebra
Enable or disable debugging of communications between *bgpd* and *zebra*.
Dumping Messages and Routing Tables
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: dump bgp all PATH [INTERVAL]
.. clicmd:: dump bgp all PATH [INTERVAL]
-.. index:: dump bgp all-et PATH [INTERVAL]
.. clicmd:: dump bgp all-et PATH [INTERVAL]
-.. index:: dump bgp all [PATH] [INTERVAL]
-.. clicmd:: no dump bgp all [PATH] [INTERVAL]
Dump all BGP packet and events to `path` file.
If `interval` is set, a new file will be created for echo `interval` of
@@ -3157,14 +2887,10 @@ Dumping Messages and Routing Tables
(strftime). The type ‘all-et’ enables support for Extended Timestamp Header
(:ref:`packet-binary-dump-format`).
-.. index:: dump bgp updates PATH [INTERVAL]
.. clicmd:: dump bgp updates PATH [INTERVAL]
-.. index:: dump bgp updates-et PATH [INTERVAL]
.. clicmd:: dump bgp updates-et PATH [INTERVAL]
-.. index:: dump bgp updates [PATH] [INTERVAL]
-.. clicmd:: no dump bgp updates [PATH] [INTERVAL]
Dump only BGP updates messages to `path` file.
If `interval` is set, a new file will be created for echo `interval` of
@@ -3172,14 +2898,10 @@ Dumping Messages and Routing Tables
(strftime). The type ‘updates-et’ enables support for Extended Timestamp
Header (:ref:`packet-binary-dump-format`).
-.. index:: dump bgp routes-mrt PATH
.. clicmd:: dump bgp routes-mrt PATH
-.. index:: dump bgp routes-mrt PATH INTERVAL
.. clicmd:: dump bgp routes-mrt PATH INTERVAL
-.. index:: dump bgp route-mrt [PATH] [INTERVAL]
-.. clicmd:: no dump bgp route-mrt [PATH] [INTERVAL]
Dump whole BGP routing table to `path`. This is heavy process. The path
`path` can be set with date and time formatting (strftime). If `interval` is
@@ -3195,44 +2917,36 @@ Other BGP Commands
The following are available in the top level *enable* mode:
-.. index:: clear bgp \*
.. clicmd:: clear bgp \*
Clear all peers.
-.. index:: clear bgp ipv4|ipv6 \*
.. clicmd:: clear bgp ipv4|ipv6 \*
Clear all peers with this address-family activated.
-.. index:: clear bgp ipv4|ipv6 unicast \*
.. clicmd:: clear bgp ipv4|ipv6 unicast \*
Clear all peers with this address-family and sub-address-family activated.
-.. index:: clear bgp ipv4|ipv6 PEER
.. clicmd:: clear bgp ipv4|ipv6 PEER
Clear peers with address of X.X.X.X and this address-family activated.
-.. index:: clear bgp ipv4|ipv6 unicast PEER
.. clicmd:: clear bgp ipv4|ipv6 unicast PEER
Clear peer with address of X.X.X.X and this address-family and sub-address-family activated.
-.. index:: clear bgp ipv4|ipv6 PEER soft|in|out
.. clicmd:: clear bgp ipv4|ipv6 PEER soft|in|out
Clear peer using soft reconfiguration in this address-family.
-.. index:: clear bgp ipv4|ipv6 unicast PEER soft|in|out
.. clicmd:: clear bgp ipv4|ipv6 unicast PEER soft|in|out
Clear peer using soft reconfiguration in this address-family and sub-address-family.
The following are available in the ``router bgp`` mode:
-.. index:: write-quanta (1-64)
.. clicmd:: write-quanta (1-64)
BGP message Tx I/O is vectored. This means that multiple packets are written
@@ -3242,7 +2956,6 @@ The following are available in the ``router bgp`` mode:
less 'bursty'. In practice, leave this settings on the default (64) unless
you truly know what you are doing.
-.. index:: read-quanta (1-10)
.. clicmd:: read-quanta (1-10)
Unlike Tx, BGP Rx traffic is not vectored. Packets are read off the wire one
@@ -3252,7 +2965,6 @@ The following are available in the ``router bgp`` mode:
The following command is available in ``config`` mode as well as in the
``router bgp`` mode:
-.. index:: bgp graceful-shutdown
.. clicmd:: bgp graceful-shutdown
The purpose of this command is to initiate BGP Graceful Shutdown which
@@ -3287,16 +2999,12 @@ daemon project, while :clicmd:`show bgp` command is the new format. The choice
has been done to keep old format with IPv4 routing table, while new format
displays IPv6 routing table.
-.. index:: show ip bgp [all] [wide|json]
.. clicmd:: show ip bgp [all] [wide|json]
-.. index:: show ip bgp A.B.C.D [json]
.. clicmd:: show ip bgp A.B.C.D [json]
-.. index:: show bgp [all] [wide|json]
.. clicmd:: show bgp [all] [wide|json]
-.. index:: show bgp X:X::X:X [json]
.. clicmd:: show bgp X:X::X:X [json]
These commands display BGP routes. When no route is specified, the default
@@ -3326,13 +3034,11 @@ displays IPv6 routing table.
Some other commands provide additional options for filtering the output.
-.. index:: show [ip] bgp regexp LINE
.. clicmd:: show [ip] bgp regexp LINE
This command displays BGP routes using AS path regular expression
(:ref:`bgp-regular-expressions`).
-.. index:: show [ip] bgp [all] summary [wide] [json]
.. clicmd:: show [ip] bgp [all] summary [wide] [json]
Show a bgp peer summary for the specified address family.
@@ -3361,10 +3067,8 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
Total number of neighbors 1
exit1#
-.. index:: show bgp [afi] [safi] [all] [wide|json]
.. clicmd:: show bgp [afi] [safi] [all] [wide|json]
-.. index:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast>
.. clicmd:: show bgp <ipv4|ipv6> <unicast|multicast|vpn|labeled-unicast>
These commands display BGP routes for the specific routing table indicated by
@@ -3373,62 +3077,51 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
For EVPN prefixes, you can display the full BGP table for this AFI/SAFI
using the standard `show bgp [afi] [safi]` syntax.
-.. index:: show bgp l2vpn evpn route [type <macip|2|multicast|3|es|4|prefix|5>]
.. clicmd:: show bgp l2vpn evpn route [type <macip|2|multicast|3|es|4|prefix|5>]
Additionally, you can also filter this output by route type.
-.. index:: show bgp [afi] [safi] [all] summary [json]
.. clicmd:: show bgp [afi] [safi] [all] summary [json]
Show a bgp peer summary for the specified address family, and subsequent
address-family.
-.. index:: show bgp [afi] [safi] [all] summary failed [json]
.. clicmd:: show bgp [afi] [safi] [all] summary failed [json]
Show a bgp peer summary for peers that are not succesfully exchanging routes
for the specified address family, and subsequent address-family.
-.. index:: show bgp [afi] [safi] [all] summary established [json]
.. clicmd:: show bgp [afi] [safi] [all] summary established [json]
Show a bgp peer summary for peers that are succesfully exchanging routes
for the specified address family, and subsequent address-family.
-.. index:: show bgp [afi] [safi] neighbor [PEER]
.. clicmd:: show bgp [afi] [safi] neighbor [PEER]
This command shows information on a specific BGP peer of the relevant
afi and safi selected.
-.. index:: show bgp [afi] [safi] [all] dampening dampened-paths [wide|json]
.. clicmd:: show bgp [afi] [safi] [all] dampening dampened-paths [wide|json]
Display paths suppressed due to dampening of the selected afi and safi
selected.
-.. index:: show bgp [afi] [safi] [all] dampening flap-statistics [wide|json]
.. clicmd:: show bgp [afi] [safi] [all] dampening flap-statistics [wide|json]
Display flap statistics of routes of the selected afi and safi selected.
-.. index:: show bgp [afi] [safi] statistics
.. clicmd:: show bgp [afi] [safi] statistics
Display statistics of routes of the selected afi and safi.
-.. index:: show bgp statistics-all
.. clicmd:: show bgp statistics-all
Display statistics of routes of all the afi and safi.
-.. index:: show [ip] bgp [afi] [safi] [all] cidr-only [wide|json]
.. clicmd:: show [ip] bgp [afi] [safi] [all] cidr-only [wide|json]
Display routes with non-natural netmasks.
-.. index:: show [ip] bgp [afi] [safi] [all] neighbors A.B.C.D [advertised-routes|received-routes|filtered-routes] [json|wide]
.. clicmd:: show [ip] bgp [afi] [safi] [all] neighbors A.B.C.D [advertised-routes|received-routes|filtered-routes] [json|wide]
Display the routes advertised to a BGP neighbor or received routes
@@ -3456,13 +3149,10 @@ Displaying Routes by Community Attribute
The following commands allow displaying routes based on their community
attribute.
-.. index:: show [ip] bgp <ipv4|ipv6> [all] community [wide|json]
.. clicmd:: show [ip] bgp <ipv4|ipv6> [all] community [wide|json]
-.. index:: show [ip] bgp <ipv4|ipv6> [all] community COMMUNITY [wide|json]
.. clicmd:: show [ip] bgp <ipv4|ipv6> [all] community COMMUNITY [wide|json]
-.. index:: show [ip] bgp <ipv4|ipv6> [all] community COMMUNITY exact-match [wide|json]
.. clicmd:: show [ip] bgp <ipv4|ipv6> [all] community COMMUNITY exact-match [wide|json]
These commands display BGP routes which have the community attribute.
@@ -3470,10 +3160,8 @@ attribute.
community are displayed. When `exact-match` is specified, it display only
routes that have an exact match.
-.. index:: show [ip] bgp <ipv4|ipv6> community-list WORD
.. clicmd:: show [ip] bgp <ipv4|ipv6> community-list WORD
-.. index:: show [ip] bgp <ipv4|ipv6> community-list WORD exact-match
.. clicmd:: show [ip] bgp <ipv4|ipv6> community-list WORD exact-match
These commands display BGP routes for the address family specified that
@@ -3493,7 +3181,6 @@ attribute.
If ``json`` option is specified, output is displayed in JSON format.
-.. index:: show bgp labelpool <chunks|inuse|ledger|requests|summary> [json]
.. clicmd:: show bgp labelpool <chunks|inuse|ledger|requests|summary> [json]
These commands display information about the BGP labelpool used for
@@ -3527,16 +3214,12 @@ Displaying Routes by Large Community Attribute
The following commands allow displaying routes based on their
large community attribute.
-.. index:: show [ip] bgp <ipv4|ipv6> large-community
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community
-.. index:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY
-.. index:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY exact-match
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY exact-match
-.. index:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY json
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community LARGE-COMMUNITY json
These commands display BGP routes which have the large community attribute.
@@ -3545,13 +3228,10 @@ large community attribute.
only routes that have an exact match. When `json` is specified, it display
routes in json format.
-.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD
-.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD exact-match
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD exact-match
-.. index:: show [ip] bgp <ipv4|ipv6> large-community-list WORD json
.. clicmd:: show [ip] bgp <ipv4|ipv6> large-community-list WORD json
These commands display BGP routes for the address family specified that
@@ -3565,24 +3245,19 @@ large community attribute.
Displaying Routes by AS Path
----------------------------
-.. index:: show bgp ipv4|ipv6 regexp LINE
.. clicmd:: show bgp ipv4|ipv6 regexp LINE
This commands displays BGP routes that matches a regular
expression `line` (:ref:`bgp-regular-expressions`).
-.. index:: show [ip] bgp ipv4 vpn
.. clicmd:: show [ip] bgp ipv4 vpn
-.. index:: show [ip] bgp ipv6 vpn
.. clicmd:: show [ip] bgp ipv6 vpn
Print active IPV4 or IPV6 routes advertised via the VPN SAFI.
-.. index:: show bgp ipv4 vpn summary
.. clicmd:: show bgp ipv4 vpn summary
-.. index:: show bgp ipv6 vpn summary
.. clicmd:: show bgp ipv6 vpn summary
Print a summary of neighbor connections for the specified AFI/SAFI combination.
@@ -3590,7 +3265,6 @@ Displaying Routes by AS Path
Displaying Update Group Information
-----------------------------------
-.. index:: show bgp update-groups SUBGROUP-ID [advertise-queue|advertised-routes|packet-queue]
.. clicmd:: show bgp update-groups [advertise-queue|advertised-routes|packet-queue]
Display Information about each individual update-group being used.
@@ -3600,7 +3274,6 @@ Displaying Update Group Information
the list of routes we have sent to the peers in the update-group and
packet-queue specifies the list of packets in the queue to be sent.
-.. index:: show bgp update-groups statistics
.. clicmd:: show bgp update-groups statistics
Display Information about update-group events in FRR.
@@ -3620,22 +3293,17 @@ When route reflectors are configured, these will reflect the routes announced
by the peers configured as clients. A route reflector client is configured
with:
-.. index:: neighbor PEER route-reflector-client
.. clicmd:: neighbor PEER route-reflector-client
-.. index:: neighbor PEER route-reflector-client
-.. clicmd:: no neighbor PEER route-reflector-client
To avoid single points of failure, multiple route reflectors can be configured.
A cluster is a collection of route reflectors and their clients, and is used
by route reflectors to avoid looping.
-.. index:: bgp cluster-id A.B.C.D
.. clicmd:: bgp cluster-id A.B.C.D
-.. index:: bgp no-rib
-.. clicmd:: [no] bgp no-rib
+.. clicmd:: bgp no-rib
To set and unset the BGP daemon ``-n`` / ``--no_kernel`` options during runtime
to disable BGP route installation to the RIB (Zebra), the ``[no] bgp no-rib``
@@ -3648,8 +3316,7 @@ starting the daemon and the configuration gets saved, the option will persist
unless removed from the configuration with the negating command prior to the
configuration write operation.
-.. index:: bgp send-extra-data zebra
-.. clicmd:: [no] bgp send-extra-data zebra
+.. clicmd:: bgp send-extra-data zebra
This Command turns off the ability of BGP to send extra data to zebra.
In this case it's the AS-Path being used for the path. The default behavior
@@ -3698,8 +3365,7 @@ status in FIB:
7. If the route which is already installed in dataplane is removed for some
reason, sending withdraw message to peers is not currently supported.
-.. index:: bgp suppress-fib-pending
-.. clicmd:: [no] bgp suppress-fib-pending
+.. clicmd:: bgp suppress-fib-pending
This command is applicable at the global level and at an individual
bgp level. If applied at the global level all bgp instances will
diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst
index 061800c14e..f925910d45 100644
--- a/doc/user/bmp.rst
+++ b/doc/user/bmp.rst
@@ -73,8 +73,7 @@ setup.
There is one option that applies to the BGP instance as a whole:
-.. index:: bmp mirror buffer-limit(0-4294967294)
-.. clicmd:: [no] bmp mirror buffer-limit(0-4294967294)
+.. clicmd:: bmp mirror buffer-limit(0-4294967294)
This sets the maximum amount of memory used for buffering BGP messages
(updates, keepalives, ...) for sending in BMP Route Mirroring.
@@ -94,8 +93,7 @@ There is one option that applies to the BGP instance as a whole:
All other configuration is managed per targets:
-.. index:: bmp targets NAME
-.. clicmd:: [no] bmp targets NAME
+.. clicmd:: bmp targets NAME
Create/delete a targets group. As implied by the plural name, targets may
cover multiple outbound active BMP sessions as well as inbound passive
@@ -110,8 +108,7 @@ BMP session configuration
Inside a ``bmp targets`` block, the following commands control session
establishment:
-.. index:: bmp connect HOSTNAME port (1-65535) {min-retry MSEC|max-retry MSEC}
-.. clicmd:: [no] bmp connect HOSTNAME port (1-65535) {min-retry MSEC|max-retry MSEC}
+.. clicmd:: bmp connect HOSTNAME port (1-65535) {min-retry MSEC|max-retry MSEC}
Add/remove an active outbound BMP session. HOSTNAME is resolved via DNS,
if multiple addresses are returned they are tried in nondeterministic
@@ -124,14 +121,13 @@ establishment:
``ip access-list`` and ``ipv6 access-list`` are checked for outbound
connections resulting from ``bmp connect`` statements.
-.. index:: bmp listener <X:X::X:X|A.B.C.D> port (1-65535)
-.. clicmd:: [no] bmp listener <X:X::X:X|A.B.C.D> port (1-65535)
+.. clicmd:: bmp listener <X:X::X:X|A.B.C.D> port (1-65535)
Accept incoming BMP sessions on the specified address and port. You can
use ``0.0.0.0`` and ``::`` to listen on all IPv4/IPv6 addresses.
-.. clicmd:: [no] ip access-list NAME
-.. clicmd:: [no] ipv6 access-list NAME
+.. clicmd:: ip access-list NAME
+.. clicmd:: ipv6 access-list NAME
Restrict BMP sessions to the addresses allowed by the respective access
lists. The access lists are checked for both passive and active BMP
@@ -143,14 +139,12 @@ BMP data feed configuration
The following commands configure what BMP messages are sent on sessions
associated with a particular ``bmp targets``:
-.. index:: bmp stats [interval (100-86400000)]
-.. clicmd:: [no] bmp stats [interval (100-86400000)]
+.. clicmd:: bmp stats [interval (100-86400000)]
Send BMP Statistics (counter) messages at the specified interval (in
milliseconds.)
-.. index:: bmp monitor AFI SAFI <pre-policy|post-policy>
-.. clicmd:: [no] bmp monitor AFI SAFI <pre-policy|post-policy>
+.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy>
Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and
IPv6 are currently valid for AFI, and only unicast and multicast are valid
@@ -159,8 +153,7 @@ associated with a particular ``bmp targets``:
All BGP neighbors are included in Route Monitoring. Options to select
a subset of BGP sessions may be added in the future.
-.. index:: bmp mirror
-.. clicmd:: [no] bmp mirror
+.. clicmd:: bmp mirror
Perform Route Mirroring for all BGP neighbors. Since this provides a
direct feed of BGP messages, there are no AFI/SAFI options to be
diff --git a/doc/user/bugs.rst b/doc/user/bugs.rst
index 2bd632e3a5..2af9e317a0 100644
--- a/doc/user/bugs.rst
+++ b/doc/user/bugs.rst
@@ -1,5 +1,5 @@
-.. index:: Bug Reports
-.. index:: Reporting bugs
+.. index::
+ pair: bug reports; contact
.. _bug-reports:
diff --git a/doc/user/conf.py b/doc/user/conf.py
index 79b37e7850..e0aec40443 100644
--- a/doc/user/conf.py
+++ b/doc/user/conf.py
@@ -384,7 +384,7 @@ def vparse(s):
def setup(app):
# object type for FRR CLI commands, can be extended to document parent CLI
# node later on
- app.add_object_type("clicmd", "clicmd")
+ app.add_object_type("clicmd", "clicmd", indextemplate="pair: %s; configuration command")
# css overrides for HTML theme
# Note sphinx version differences
diff --git a/doc/user/eigrpd.rst b/doc/user/eigrpd.rst
index 4ce2e280c7..88d289d27e 100644
--- a/doc/user/eigrpd.rst
+++ b/doc/user/eigrpd.rst
@@ -65,7 +65,6 @@ Certain signals have special meanings to *eigrpd*.
EIGRP Configuration
===================
-.. index:: router eigrp (1-65535) [vrf NAME]
.. clicmd:: router eigrp (1-65535) [vrf NAME]
The `router eigrp` command is necessary to enable EIGRP. To disable EIGRP,
@@ -73,17 +72,8 @@ EIGRP Configuration
carrying out any of the EIGRP commands. Specify vrf NAME if you want
eigrp to work within the specified vrf.
-.. index:: router eigrp (1-65535) [vrf NAME]
-.. clicmd:: no router eigrp (1-65535) [vrf NAME]
-
- Disable EIGRP.
-
-.. index:: network NETWORK
.. clicmd:: network NETWORK
-.. index:: network NETWORK
-.. clicmd:: no network NETWORK
-
Set the EIGRP enable interface by `network`. The interfaces which
have addresses matching with `network` are enabled.
@@ -104,11 +94,8 @@ EIGRP Configuration
!
-.. index:: passive-interface (IFNAME|default)
.. clicmd:: passive-interface (IFNAME|default)
-.. index:: passive-interface IFNAME
-.. clicmd:: no passive-interface IFNAME
This command sets the specified interface to passive mode. On passive mode
interface, all receiving packets are ignored and eigrpd does not send either
@@ -123,74 +110,26 @@ EIGRP Configuration
How to Announce EIGRP route
===========================
-.. index:: redistribute kernel
-.. clicmd:: redistribute kernel
-
-.. index:: redistribute kernel metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-.. clicmd:: redistribute kernel metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-
-.. index:: redistribute kernel
-.. clicmd:: no redistribute kernel
-
- `redistribute kernel` redistributes routing information from kernel route
- entries into the EIGRP tables. `no redistribute kernel` disables the routes.
-
-.. index:: redistribute static
-.. clicmd:: redistribute static
-
-.. index:: redistribute static metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-.. clicmd:: redistribute static metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-
-.. index:: redistribute static
-.. clicmd:: no redistribute static
-
- `redistribute static` redistributes routing information from static route
- entries into the EIGRP tables. `no redistribute static` disables the routes.
-
-.. index:: redistribute connected
-.. clicmd:: redistribute connected
-
-.. index:: redistribute connected metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-.. clicmd:: redistribute connected metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-
-.. index:: redistribute connected
-.. clicmd:: no redistribute connected
-
- Redistribute connected routes into the EIGRP tables. `no redistribute
- connected` disables the connected routes in the EIGRP tables. This command
- redistribute connected of the interface which EIGRP disabled. The connected
- route on EIGRP enabled interface is announced by default.
-
-.. index:: redistribute ospf
-.. clicmd:: redistribute ospf
-
-.. index:: redistribute ospf metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-.. clicmd:: redistribute ospf metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-
-.. index:: redistribute ospf
-.. clicmd:: no redistribute ospf
+Redistribute routes into EIGRP:
- `redistribute ospf` redistributes routing information from ospf route
- entries into the EIGRP tables. `no redistribute ospf` disables the routes.
+.. clicmd:: redistribute <babel|bgp|connected|isis|kernel|openfabric|ospf|rip|sharp|static|table> [metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)]
-.. index:: redistribute bgp
-.. clicmd:: redistribute bgp
+ The ``redistribute`` family of commands imports routing information from
+ other sources into EIGRP's tables. Redistribution may be disabled with the
+ ``no`` form of the commands.
-.. index:: redistribute bgp metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
-.. clicmd:: redistribute bgp metric (1-4294967295) (0-4294967295) (0-255) (1-255) (1-65535)
+ Note that connected routes on interfaces EIGRP is enabled on are announced
+ by default.
-.. index:: redistribute bgp
-.. clicmd:: no redistribute bgp
+ Optionally, various EIGRP metrics may be specified. These metrics will be
+ applied to the imported routes.
- `redistribute bgp` redistributes routing information from bgp route entries
- into the EIGRP tables. `no redistribute bgp` disables the routes.
.. _show-eigrp-information:
Show EIGRP Information
======================
-.. index:: show ip eigrp [vrf NAME] topology
.. clicmd:: show ip eigrp [vrf NAME] topology
Display current EIGRP status.
@@ -208,7 +147,6 @@ Show EIGRP Information
P 10.0.2.0/24, 1 successors, FD is 256256, serno: 0
via Connected, enp0s3
-.. index:: show ip eigrp [vrf NAME] interface
.. clicmd:: show ip eigrp [vrf NAME] interface
Display the list of interfaces associated with a particular eigrp
@@ -225,14 +163,12 @@ EIGRP Debug Commands
Debug for EIGRP protocol.
-.. index:: debug eigrp packets
.. clicmd:: debug eigrp packets
Debug eigrp packets
``debug eigrp`` will show EIGRP packets that are sent and received.
-.. index:: debug eigrp transmit
.. clicmd:: debug eigrp transmit
Debug eigrp transmit events
@@ -240,7 +176,6 @@ Debug for EIGRP protocol.
``debug eigrp transmit`` will display detailed information about the EIGRP
transmit events.
-.. index:: show debugging eigrp
.. clicmd:: show debugging eigrp
Display *eigrpd*'s debugging option.
diff --git a/doc/user/fabricd.rst b/doc/user/fabricd.rst
index 17a51ccb3c..611bc1caaa 100644
--- a/doc/user/fabricd.rst
+++ b/doc/user/fabricd.rst
@@ -32,37 +32,21 @@ OpenFabric router
To enable the OpenFabric routing protocol, an OpenFabric router needs to be created
in the configuration:
-.. index:: router openfabric WORD
.. clicmd:: router openfabric WORD
-.. index:: router openfabric WORD
-.. clicmd:: no router openfabric WORD
-
Enable or disable the OpenFabric process by specifying the OpenFabric domain with
'WORD'.
-.. index:: net XX.XXXX. ... .XXX.XX
.. clicmd:: net XX.XXXX. ... .XXX.XX
-.. index:: net XX.XXXX. ... .XXX.XX
-.. clicmd:: no net XX.XXXX. ... .XXX.XX
-
Set/Unset network entity title (NET) provided in ISO format.
-.. index:: domain-password [clear | md5] <password>
.. clicmd:: domain-password [clear | md5] <password>
-.. index:: domain-password
-.. clicmd:: no domain-password
-
Configure the authentication password for a domain, as clear text or md5 one.
-.. index:: attached-bit [receive ignore | send]
.. clicmd:: attached-bit [receive ignore | send]
-.. index:: attached-bit
-.. clicmd:: no attached-bit
-
Set attached bit for inter-area traffic:
- receive
@@ -70,35 +54,22 @@ in the configuration:
- send
If L1|L2 router, set attached bit in LSP sent to L1 router
-.. index:: log-adjacency-changes
.. clicmd:: log-adjacency-changes
-.. index:: log-adjacency-changes
-.. clicmd:: no log-adjacency-changes
-
Log changes in adjacency state.
-.. index:: set-overload-bit
.. clicmd:: set-overload-bit
-.. index:: set-overload-bit
-.. clicmd:: no set-overload-bit
Set overload bit to avoid any transit traffic.
-.. index:: purge-originator
.. clicmd:: purge-originator
-.. index:: purge-originator
-.. clicmd:: no purge-originator
Enable or disable :rfc:`6232` purge originator identification.
-.. index:: fabric-tier (0-14)
.. clicmd:: fabric-tier (0-14)
-.. index:: fabric-tier
-.. clicmd:: no fabric-tier
Configure a static tier number to advertise as location in the fabric
@@ -107,35 +78,23 @@ in the configuration:
OpenFabric Timer
================
-.. index:: lsp-gen-interval (1-120)
.. clicmd:: lsp-gen-interval (1-120)
-.. index:: lsp-gen-interval
-.. clicmd:: no lsp-gen-interval
Set minimum interval in seconds between regenerating same LSP.
-.. index:: lsp-refresh-interval (1-65235)
.. clicmd:: lsp-refresh-interval (1-65235)
-.. index:: lsp-refresh-interval
-.. clicmd:: no lsp-refresh-interval
Set LSP refresh interval in seconds.
-.. index:: max-lsp-lifetime (360-65535)
.. clicmd:: max-lsp-lifetime (360-65535)
-.. index:: max-lsp-lifetime
-.. clicmd:: no max-lsp-lifetime
Set LSP maximum LSP lifetime in seconds.
-.. index:: spf-interval (1-120)
.. clicmd:: spf-interval (1-120)
-.. index:: spf-interval
-.. clicmd:: no spf-interval
Set minimum interval between consecutive SPF calculations in seconds.
@@ -144,11 +103,8 @@ OpenFabric Timer
OpenFabric interface
====================
-.. index:: ip router openfabric WORD
.. clicmd:: ip router openfabric WORD
-.. index:: ip router openfabric WORD
-.. clicmd:: no ip router openfabric WORD
.. _ip-router-openfabric-word:
@@ -156,60 +112,39 @@ OpenFabric interface
of OpenFabric instance must be the same as the one used to configure the
routing process (see command :clicmd:`router openfabric WORD`).
-.. index:: openfabric csnp-interval (1-600)
.. clicmd:: openfabric csnp-interval (1-600)
-.. index:: openfabric csnp-interval
-.. clicmd:: no openfabric csnp-interval
Set CSNP interval in seconds.
-.. index:: openfabric hello-interval (1-600)
.. clicmd:: openfabric hello-interval (1-600)
-.. index:: openfabric hello-interval
-.. clicmd:: no openfabric hello-interval
Set Hello interval in seconds.
-.. index:: openfabric hello-multiplier (2-100)
.. clicmd:: openfabric hello-multiplier (2-100)
-.. index:: openfabric hello-multiplier
-.. clicmd:: no openfabric hello-multiplier
Set multiplier for Hello holding time.
-.. index:: openfabric metric (0-16777215)
.. clicmd:: openfabric metric (0-16777215)
-.. index:: openfabric metric
-.. clicmd:: no openfabric metric
Set interface metric value.
-.. index:: openfabric passive
.. clicmd:: openfabric passive
-.. index:: openfabric passive
-.. clicmd:: no openfabric passive
Configure the passive mode for this interface.
-.. index:: openfabric password [clear | md5] <password>
.. clicmd:: openfabric password [clear | md5] <password>
-.. index:: openfabric password
-.. clicmd:: no openfabric password
Configure the authentication password (clear or encoded text) for the
interface.
-.. index:: openfabric psnp-interval (1-120)
.. clicmd:: openfabric psnp-interval (1-120)
-.. index:: openfabric psnp-interval
-.. clicmd:: no openfabric psnp-interval
Set PSNP interval in seconds.
@@ -218,56 +153,43 @@ OpenFabric interface
Showing OpenFabric information
==============================
-.. index:: show openfabric summary
.. clicmd:: show openfabric summary
Show summary information about OpenFabric.
-.. index:: show openfabric hostname
.. clicmd:: show openfabric hostname
Show which hostnames are associated with which OpenFabric system ids.
-.. index:: show openfabric interface
.. clicmd:: show openfabric interface
-.. index:: show openfabric interface detail
.. clicmd:: show openfabric interface detail
-.. index:: show openfabric interface <interface name>
.. clicmd:: show openfabric interface <interface name>
Show state and configuration of specified OpenFabric interface, or all interfaces
if no interface is given with or without details.
-.. index:: show openfabric neighbor
.. clicmd:: show openfabric neighbor
-.. index:: show openfabric neighbor <System Id>
.. clicmd:: show openfabric neighbor <System Id>
-.. index:: show openfabric neighbor detail
.. clicmd:: show openfabric neighbor detail
Show state and information of specified OpenFabric neighbor, or all neighbors if
no system id is given with or without details.
-.. index:: show openfabric database
.. clicmd:: show openfabric database
-.. index:: show openfabric database [detail]
.. clicmd:: show openfabric database [detail]
-.. index:: show openfabric database <LSP id> [detail]
.. clicmd:: show openfabric database <LSP id> [detail]
-.. index:: show openfabric database detail <LSP id>
.. clicmd:: show openfabric database detail <LSP id>
Show the OpenFabric database globally, for a specific LSP id without or with
details.
-.. index:: show openfabric topology
.. clicmd:: show openfabric topology
Show calculated OpenFabric paths and associated topology information.
@@ -277,120 +199,64 @@ Showing OpenFabric information
Debugging OpenFabric
====================
-.. index:: debug openfabric adj-packets
.. clicmd:: debug openfabric adj-packets
-.. index:: debug openfabric adj-packets
-.. clicmd:: no debug openfabric adj-packets
+ OpenFabric Adjacency related packets.
-OpenFabric Adjacency related packets.
-
-.. index:: debug openfabric checksum-errors
.. clicmd:: debug openfabric checksum-errors
-.. index:: debug openfabric checksum-errors
-.. clicmd:: no debug openfabric checksum-errors
-
-OpenFabric LSP checksum errors.
+ OpenFabric LSP checksum errors.
-.. index:: debug openfabric events
.. clicmd:: debug openfabric events
-.. index:: debug openfabric events
-.. clicmd:: no debug openfabric events
-
-OpenFabric Events.
+ OpenFabric Events.
-.. index:: debug openfabric local-updates
.. clicmd:: debug openfabric local-updates
-.. index:: debug openfabric local-updates
-.. clicmd:: no debug openfabric local-updates
+ OpenFabric local update packets.
-OpenFabric local update packets.
-
-.. index:: debug openfabric lsp-gen
.. clicmd:: debug openfabric lsp-gen
-.. index:: debug openfabric lsp-gen
-.. clicmd:: no debug openfabric lsp-gen
-
-Generation of own LSPs.
+ Generation of own LSPs.
-.. index:: debug openfabric lsp-sched
.. clicmd:: debug openfabric lsp-sched
-.. index:: debug openfabric lsp-sched
-.. clicmd:: no debug openfabric lsp-sched
+ Debug scheduling of generation of own LSPs.
-Debug scheduling of generation of own LSPs.
-
-.. index:: debug openfabric packet-dump
.. clicmd:: debug openfabric packet-dump
-.. index:: debug openfabric packet-dump
-.. clicmd:: no debug openfabric packet-dump
-
-OpenFabric packet dump.
+ OpenFabric packet dump.
-.. index:: debug openfabric protocol-errors
.. clicmd:: debug openfabric protocol-errors
-.. index:: debug openfabric protocol-errors
-.. clicmd:: no debug openfabric protocol-errors
-
-OpenFabric LSP protocol errors.
+ OpenFabric LSP protocol errors.
-.. index:: debug openfabric route-events
.. clicmd:: debug openfabric route-events
-.. index:: debug openfabric route-events
-.. clicmd:: no debug openfabric route-events
+ OpenFabric Route related events.
-OpenFabric Route related events.
-
-.. index:: debug openfabric snp-packets
.. clicmd:: debug openfabric snp-packets
-.. index:: debug openfabric snp-packets
-.. clicmd:: no debug openfabric snp-packets
-
-OpenFabric CSNP/PSNP packets.
+ OpenFabric CSNP/PSNP packets.
-.. index:: debug openfabric spf-events
.. clicmd:: debug openfabric spf-events
-.. index:: debug openfabric spf-statistics
.. clicmd:: debug openfabric spf-statistics
-.. index:: debug openfabric spf-triggers
.. clicmd:: debug openfabric spf-triggers
-.. index:: debug openfabric spf-events
-.. clicmd:: no debug openfabric spf-events
+ OpenFabric Shortest Path First Events, Timing and Statistic Data and
+ triggering events.
-.. index:: debug openfabric spf-statistics
-.. clicmd:: no debug openfabric spf-statistics
-
-.. index:: debug openfabric spf-triggers
-.. clicmd:: no debug openfabric spf-triggers
-
-OpenFabric Shortest Path First Events, Timing and Statistic Data and triggering
-events.
-
-.. index:: debug openfabric update-packets
.. clicmd:: debug openfabric update-packets
-.. index:: debug openfabric update-packets
-.. clicmd:: no debug openfabric update-packets
+ Update-related packets.
-Update related packets.
-
-.. index:: show debugging openfabric
.. clicmd:: show debugging openfabric
Print which OpenFabric debug levels are active.
+
OpenFabric configuration example
================================
diff --git a/doc/user/filter.rst b/doc/user/filter.rst
index 910da7246d..78043e779b 100644
--- a/doc/user/filter.rst
+++ b/doc/user/filter.rst
@@ -9,10 +9,8 @@ defined, it can be applied in any direction.
IP Access List
==============
-.. index:: access-list NAME [seq (1-4294967295)] permit IPV4-NETWORK
.. clicmd:: access-list NAME [seq (1-4294967295)] permit IPV4-NETWORK
-.. index:: access-list NAME [seq (1-4294967295)] deny IPV4-NETWORK
.. clicmd:: access-list NAME [seq (1-4294967295)] deny IPV4-NETWORK
seq
@@ -50,10 +48,8 @@ filters to arbitrary points of prefix-list using sequential number specification
If no ip prefix-list is specified, it acts as permit. If *ip prefix-list*
is defined, and no match is found, default deny is applied.
-.. index:: ip prefix-list NAME (permit|deny) PREFIX [le LEN] [ge LEN]
.. clicmd:: ip prefix-list NAME (permit|deny) PREFIX [le LEN] [ge LEN]
-.. index:: ip prefix-list NAME seq NUMBER (permit|deny) PREFIX [le LEN] [ge LEN]
.. clicmd:: ip prefix-list NAME seq NUMBER (permit|deny) PREFIX [le LEN] [ge LEN]
You can create *ip prefix-list* using above commands.
@@ -98,88 +94,63 @@ is defined, and no match is found, default deny is applied.
In the case of no le or ge command, the prefix length must match exactly the
length specified in the prefix list.
-.. index:: ip prefix-list NAME
-.. clicmd:: no ip prefix-list NAME
.. _ip-prefix-list-description:
ip prefix-list description
--------------------------
-.. index:: ip prefix-list NAME description DESC
.. clicmd:: ip prefix-list NAME description DESC
Descriptions may be added to prefix lists. This command adds a
description to the prefix list.
-.. index:: ip prefix-list NAME description [DESC]
-.. clicmd:: no ip prefix-list NAME description [DESC]
-
- Deletes the description from a prefix list. It is possible to use the
- command without the full description.
.. _ip-prefix-list-sequential-number-control:
ip prefix-list sequential number control
----------------------------------------
-.. index:: ip prefix-list sequence-number
.. clicmd:: ip prefix-list sequence-number
With this command, the IP prefix list sequential number is displayed.
This is the default behavior.
-.. index:: ip prefix-list sequence-number
-.. clicmd:: no ip prefix-list sequence-number
-
- With this command, the IP prefix list sequential number is not
- displayed.
.. _showing-ip-prefix-list:
Showing ip prefix-list
----------------------
-.. index:: show ip prefix-list
.. clicmd:: show ip prefix-list
Display all IP prefix lists.
-.. index:: show ip prefix-list NAME
.. clicmd:: show ip prefix-list NAME
Show IP prefix list can be used with a prefix list name.
-.. index:: show ip prefix-list NAME seq NUM
.. clicmd:: show ip prefix-list NAME seq NUM
Show IP prefix list can be used with a prefix list name and sequential
number.
-.. index:: show ip prefix-list NAME A.B.C.D/M
.. clicmd:: show ip prefix-list NAME A.B.C.D/M
If the command longer is used, all prefix lists with prefix lengths equal to
or longer than the specified length will be displayed. If the command first
match is used, the first prefix length match will be displayed.
-.. index:: show ip prefix-list NAME A.B.C.D/M longer
.. clicmd:: show ip prefix-list NAME A.B.C.D/M longer
-.. index:: show ip prefix-list NAME A.B.C.D/M first-match
.. clicmd:: show ip prefix-list NAME A.B.C.D/M first-match
-.. index:: show ip prefix-list summary
.. clicmd:: show ip prefix-list summary
-.. index:: show ip prefix-list summary NAME
.. clicmd:: show ip prefix-list summary NAME
-.. index:: show ip prefix-list detail
.. clicmd:: show ip prefix-list detail
-.. index:: show ip prefix-list detail NAME
.. clicmd:: show ip prefix-list detail NAME
Clear counter of ip prefix-list
-------------------------------
-.. index:: clear ip prefix-list [NAME [A.B.C.D/M]]
.. clicmd:: clear ip prefix-list [NAME [A.B.C.D/M]]
Clears the counters of all IP prefix lists. Clear IP Prefix List can be used
diff --git a/doc/user/flowspec.rst b/doc/user/flowspec.rst
index c303ebdba4..faf5973460 100644
--- a/doc/user/flowspec.rst
+++ b/doc/user/flowspec.rst
@@ -123,10 +123,8 @@ As of today, it is only possible to configure Flowspec on the default VRF.
You can see Flowspec entries, by using one of the following show commands:
-.. index:: show bgp ipv4 flowspec [detail | A.B.C.D]
.. clicmd:: show bgp ipv4 flowspec [detail | A.B.C.D]
-.. index:: show bgp ipv6 flowspec [detail | A:B::C:D]
.. clicmd:: show bgp ipv6 flowspec [detail | A:B::C:D]
Per-interface configuration
@@ -141,8 +139,7 @@ twice the traffic, or slow down the traffic (filtering costs). To limit
Flowspec to one specific interface, use the following command, under
`flowspec address-family` node.
-.. index:: local-install <IFNAME | any>
-.. clicmd:: [no] local-install <IFNAME | any>
+.. clicmd:: local-install <IFNAME | any>
By default, Flowspec is activated on all interfaces. Installing it to a named
interface will result in allowing only this interface. Conversely, enabling any
@@ -168,8 +165,7 @@ following:
- The first VRF with the matching Route Target will be selected to route traffic
to. Use the following command under ipv4 unicast address-family node
-.. index:: rt redirect import RTLIST...
-.. clicmd:: [no] rt redirect import RTLIST...
+.. clicmd:: rt redirect import RTLIST...
In order to illustrate, if the Route Target configured in the Flowspec entry is
``E.F.G.H:II``, then a BGP VRF instance with the same Route Target will be set
@@ -223,7 +219,6 @@ Those command rely on the filtering contexts configured from BGP, and get the
statistics information retrieved from the underlying system. In other words,
those statistics are retrieved from ``Netfilter``.
-.. index:: show pbr ipset IPSETNAME | iptable
.. clicmd:: show pbr ipset IPSETNAME | iptable
``IPSETNAME`` is the policy routing object name created by ``ipset``. About
@@ -235,21 +230,18 @@ match.
.. code-block:: frr
-.. index:: show ip route table TABLEID
.. clicmd:: show ip route table TABLEID
``TABLEID`` is the table number identifier referencing the non standard
routing table used in this example.
-.. index:: debug bgp flowspec
-.. clicmd:: [no] debug bgp flowspec
+.. clicmd:: debug bgp flowspec
You can troubleshoot Flowspec, or BGP policy based routing. For instance, if
you encounter some issues when decoding a Flowspec entry, you should enable
:clicmd:`debug bgp flowspec`.
-.. index:: debug bgp pbr [error]
-.. clicmd:: [no] debug bgp pbr [error]
+.. clicmd:: debug bgp pbr [error]
If you fail to apply the flowspec entry into *zebra*, there should be some
relationship with policy routing mechanism. Here,
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index a13e6ce43b..dbd95aca40 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -1,16 +1,16 @@
+.. index::
+ single: How to install FRR
+ single: Installing FRR
+ single: Building FRR
+
.. _installation:
Installation
============
-.. index:: How to install FRR
-.. index:: Installation
-.. index:: Installing FRR
-.. index:: Building the system
-.. index:: Making FRR
-
This section covers the basics of building, installing and setting up FRR.
+
From Packages
-------------
@@ -55,14 +55,18 @@ is the release version.
In addition, release tarballs are published on the GitHub releases page
`here <https://github.com/FRRouting/frr/releases>`_.
-Configuration
-^^^^^^^^^^^^^
-.. index:: Configuration options
-.. index:: Options for configuring
-.. index:: Build options
-.. index:: Distribution configuration
-.. index:: Options to `./configure`
+.. index::
+ single: Configuration options
+ single: Options for configuring
+ single: Build options
+ single: Distribution configuration
+ single: Options to `./configure`
+
+.. _build-configuration:
+
+Build Configuration
+^^^^^^^^^^^^^^^^^^^
FRR has an excellent configure script which automatically detects most host
configurations. There are several additional configure options to customize the
@@ -420,14 +424,15 @@ The `sphinx` and `pytest` dependencies can be avoided by not building
documentation / not running ``make check``, but the CPython dependency is a
hard dependency of the FRR build process (for the `clippy` tool.)
+.. index::
+ single: FRR Least-Privileges
+ single: FRR Privileges
+
.. _least-privilege-support:
Least-Privilege Support
"""""""""""""""""""""""
-.. index:: FRR Least-Privileges
-.. index:: FRR Privileges
-
Additionally, you may configure zebra to drop its elevated privileges
shortly after startup and switch to another user. The configure script will
automatically try to configure this support. There are three configure
@@ -460,12 +465,14 @@ only Linux), FRR will retain only minimal capabilities required and will only
raise these capabilities for brief periods. On systems without libcap, FRR will
run as the user specified and only raise its UID to 0 for brief periods.
+
+.. index::
+ pair: building; Linux
+ pair: configuration; Linux
+
Linux Notes
"""""""""""
-.. index:: Building on Linux boxes
-.. index:: Linux configurations
-
There are several options available only to GNU/Linux systems. If you use
GNU/Linux, make sure that the current kernel configuration is what you want.
FRR will run with any kernel configuration but some recommendations do exist.
diff --git a/doc/user/ipv6.rst b/doc/user/ipv6.rst
index 26341f04f1..089fae39b1 100644
--- a/doc/user/ipv6.rst
+++ b/doc/user/ipv6.rst
@@ -17,17 +17,11 @@ no longer possible.
Router Advertisement
====================
-.. index:: ipv6 nd suppress-ra
-.. clicmd:: no ipv6 nd suppress-ra
-
- Send router advertisement messages.
-
-.. index:: ipv6 nd suppress-ra
.. clicmd:: ipv6 nd suppress-ra
- Don't send router advertisement messages.
+ Don't send router advertisement messages. The ``no`` form of this command
+ enables sending RA messages.
-.. index:: ipv6 nd prefix ipv6prefix [valid-lifetime] [preferred-lifetime] [off-link] [no-autoconfig] [router-address]
.. clicmd:: ipv6 nd prefix ipv6prefix [valid-lifetime] [preferred-lifetime] [off-link] [no-autoconfig] [router-address]
Configuring the IPv6 prefix to include in router advertisements. Several prefix
@@ -57,22 +51,19 @@ Router Advertisement
Default: not set, i.e. hosts do not assume a complete IP address is placed.
-.. index:: ipv6 nd ra-interval [(1-1800)]
-.. clicmd:: [no] ipv6 nd ra-interval [(1-1800)]
+.. clicmd:: ipv6 nd ra-interval [(1-1800)]
The maximum time allowed between sending unsolicited multicast router
advertisements from the interface, in seconds.
Default: ``600``
-.. index:: ipv6 nd ra-interval msec (70-1800000)
-.. clicmd:: [no] ipv6 nd ra-interval [msec (70-1800000)]
+.. clicmd:: ipv6 nd ra-interval [msec (70-1800000)]
The maximum time allowed between sending unsolicited multicast router
advertisements from the interface, in milliseconds.
Default: ``600000``
-.. index:: ipv6 nd ra-fast-retrans
-.. clicmd:: [no] ipv6 nd ra-fast-retrans
+.. clicmd:: ipv6 nd ra-fast-retrans
RFC4861 states that consecutive RA packets should be sent no more
frequently than three seconds apart. FRR by default allows faster
@@ -83,8 +74,7 @@ Router Advertisement
and neighbor establishment.
Default: enabled
-.. index:: ipv6 nd ra-retrans-interval (0-4294967295)
-.. clicmd:: [no] ipv6 nd ra-retrans-interval [(0-4294967295)]
+.. clicmd:: ipv6 nd ra-retrans-interval [(0-4294967295)]
The value to be placed in the retrans timer field of router advertisements
sent from the interface, in msec. Indicates the interval between router
@@ -93,8 +83,7 @@ Router Advertisement
msec.
Default: ``0``
-.. index:: ipv6 nd ra-hop-limit (0-255)
-.. clicmd:: [no] ipv6 nd ra-hop-limit [(0-255)]
+.. clicmd:: ipv6 nd ra-hop-limit [(0-255)]
The value to be placed in the hop count field of router advertisements sent
from the interface, in hops. Indicates the maximum diameter of the network.
@@ -102,8 +91,7 @@ Router Advertisement
router. Must be between zero or 255 hops.
Default: ``64``
-.. index:: ipv6 nd ra-lifetime (0-9000)
-.. clicmd:: [no] ipv6 nd ra-lifetime [(0-9000)]
+.. clicmd:: ipv6 nd ra-lifetime [(0-9000)]
The value to be placed in the Router Lifetime field of router advertisements
sent from the interface, in seconds. Indicates the usefulness of the router
@@ -113,8 +101,7 @@ Router Advertisement
(or default) and 9000 seconds.
Default: ``1800``
-.. index:: ipv6 nd reachable-time (1-3600000)
-.. clicmd:: [no] ipv6 nd reachable-time [(1-3600000)]
+.. clicmd:: ipv6 nd reachable-time [(1-3600000)]
The value to be placed in the Reachable Time field in the Router
Advertisement messages sent by the router, in milliseconds. The configured
@@ -122,8 +109,7 @@ Router Advertisement
means unspecified (by this router).
Default: ``0``
-.. index:: ipv6 nd managed-config-flag
-.. clicmd:: [no] ipv6 nd managed-config-flag
+.. clicmd:: ipv6 nd managed-config-flag
Set/unset flag in IPv6 router advertisements which indicates to hosts that
they should use managed (stateful) protocol for addresses autoconfiguration
@@ -131,33 +117,28 @@ Router Advertisement
autoconfiguration.
Default: not set
-.. index:: ipv6 nd other-config-flag
-.. clicmd:: [no] ipv6 nd other-config-flag
+.. clicmd:: ipv6 nd other-config-flag
Set/unset flag in IPv6 router advertisements which indicates to hosts that
they should use administered (stateful) protocol to obtain autoconfiguration
information other than addresses.
Default: not set
-.. index:: ipv6 nd home-agent-config-flag
-.. clicmd:: [no] ipv6 nd home-agent-config-flag
+.. clicmd:: ipv6 nd home-agent-config-flag
Set/unset flag in IPv6 router advertisements which indicates to hosts that
the router acts as a Home Agent and includes a Home Agent Option.
Default: not set
-.. index:: ipv6 nd home-agent-preference (0-65535)
-.. index:: ipv6 nd home-agent-preference (0-65535)
-.. clicmd:: [no] ipv6 nd home-agent-preference [(0-65535)]
+.. clicmd:: ipv6 nd home-agent-preference [(0-65535)]
The value to be placed in Home Agent Option, when Home Agent config flag is
set, which indicates to hosts Home Agent preference. The default value of 0
stands for the lowest preference possible.
Default: ``0``
-.. index:: ipv6 nd home-agent-lifetime (0-65520)
-.. clicmd:: [no] ipv6 nd home-agent-lifetime [(0-65520)]
+.. clicmd:: ipv6 nd home-agent-lifetime [(0-65520)]
The value to be placed in Home Agent Option, when Home Agent config flag is set,
which indicates to hosts Home Agent Lifetime. The default value of 0 means to
@@ -165,21 +146,18 @@ Router Advertisement
Default: ``0``
-.. index:: ipv6 nd adv-interval-option
-.. clicmd:: [no] ipv6 nd adv-interval-option
+.. clicmd:: ipv6 nd adv-interval-option
Include an Advertisement Interval option which indicates to hosts the maximum time,
in milliseconds, between successive unsolicited Router Advertisements.
Default: not set
-.. index:: ipv6 nd router-preference (high|medium|low)
-.. clicmd:: [no] ipv6 nd router-preference [(high|medium|low)]
+.. clicmd:: ipv6 nd router-preference [(high|medium|low)]
Set default router preference in IPv6 router advertisements per RFC4191.
Default: medium
-.. index:: ipv6 nd mtu (1-65535)
-.. clicmd:: [no] ipv6 nd mtu [(1-65535)]
+.. clicmd:: ipv6 nd mtu [(1-65535)]
Include an MTU (type 5) option in each RA packet to assist the attached
hosts in proper interface configuration. The announced value is not verified
@@ -187,8 +165,7 @@ Router Advertisement
Default: don't advertise any MTU option.
-.. index:: ipv6 nd rdnss ipv6address [lifetime]
-.. clicmd:: [no] ipv6 nd rdnss ipv6address [lifetime]
+.. clicmd:: ipv6 nd rdnss ipv6address [lifetime]
Recursive DNS server address to advertise using the RDNSS (type 25) option
described in RFC8106. Can be specified more than once to advertise multiple
@@ -205,8 +182,7 @@ Router Advertisement
Default: do not emit RDNSS option
-.. index:: ipv6 nd dnssl domain-name-suffix [lifetime]
-.. clicmd:: [no] ipv6 nd dnssl domain-name-suffix [lifetime]
+.. clicmd:: ipv6 nd dnssl domain-name-suffix [lifetime]
Advertise DNS search list using the DNSSL (type 31) option described in
RFC8106. Specify more than once to advertise multiple domain name suffixes.
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index 352701728d..ef2bf16166 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -33,51 +33,30 @@ ISIS router
To start the ISIS process you have to specify the ISIS router. As of this
writing, *isisd* does not support multiple ISIS processes.
-.. index:: router isis WORD [vrf NAME]
-.. clicmd:: [no] router isis WORD [vrf NAME]
+.. clicmd:: router isis WORD [vrf NAME]
Enable or disable the ISIS process by specifying the ISIS domain with
'WORD'. *isisd* does not yet support multiple ISIS processes but you must
specify the name of ISIS process. The ISIS process name 'WORD' is then used
for interface (see command :clicmd:`ip router isis WORD`).
-.. index:: net XX.XXXX. ... .XXX.XX
.. clicmd:: net XX.XXXX. ... .XXX.XX
-.. index:: net XX.XXXX. ... .XXX.XX
-.. clicmd:: no net XX.XXXX. ... .XXX.XX
-
Set/Unset network entity title (NET) provided in ISO format.
-.. index:: hostname dynamic
.. clicmd:: hostname dynamic
-.. index:: hostname dynamic
-.. clicmd:: no hostname dynamic
-
Enable support for dynamic hostname.
-.. index:: area-password [clear | md5] <password>
.. clicmd:: area-password [clear | md5] <password>
-.. index:: domain-password [clear | md5] <password>
.. clicmd:: domain-password [clear | md5] <password>
-.. index:: area-password
-.. clicmd:: no area-password
-
-.. index:: domain-password
-.. clicmd:: no domain-password
-
Configure the authentication password for an area, respectively a domain, as
clear text or md5 one.
-.. index:: attached-bit [receive ignore | send]
.. clicmd:: attached-bit [receive ignore | send]
-.. index:: attached-bit
-.. clicmd:: no attached-bit
-
Set attached bit for inter-area traffic:
- receive
@@ -85,20 +64,12 @@ writing, *isisd* does not support multiple ISIS processes.
- send
If L1|L2 router, set attached bit in LSP sent to L1 router
-.. index:: log-adjacency-changes
.. clicmd:: log-adjacency-changes
-.. index:: log-adjacency-changes
-.. clicmd:: no log-adjacency-changes
-
Log changes in adjacency state.
-.. index:: metric-style [narrow | transition | wide]
.. clicmd:: metric-style [narrow | transition | wide]
-.. index:: metric-style
-.. clicmd:: no metric-style
-
Set old-style (ISO 10589) or new-style packet formats:
- narrow
@@ -108,24 +79,15 @@ writing, *isisd* does not support multiple ISIS processes.
- wide
Use new style of TLVs to carry wider metric
-.. index:: set-overload-bit
.. clicmd:: set-overload-bit
-.. index:: set-overload-bit
-.. clicmd:: no set-overload-bit
-
Set overload bit to avoid any transit traffic.
-.. index:: purge-originator
.. clicmd:: purge-originator
-.. index:: purge-originator
-.. clicmd:: no purge-originator
-
Enable or disable :rfc:`6232` purge originator identification.
-.. index:: lsp-mtu (128-4352)
-.. clicmd:: [no] lsp-mtu (128-4352)
+.. clicmd:: lsp-mtu (128-4352)
Configure the maximum size of generated LSPs, in bytes.
@@ -135,57 +97,23 @@ writing, *isisd* does not support multiple ISIS processes.
ISIS Timer
==========
-.. index:: lsp-gen-interval (1-120)
-.. clicmd:: lsp-gen-interval (1-120)
-
-.. index:: lsp-gen-interval [level-1 | level-2] (1-120)
.. clicmd:: lsp-gen-interval [level-1 | level-2] (1-120)
-.. index:: lsp-gen-interval
-.. clicmd:: no lsp-gen-interval
-
-.. index:: lsp-gen-interval [level-1 | level-2]
-.. clicmd:: no lsp-gen-interval [level-1 | level-2]
-
Set minimum interval in seconds between regenerating same LSP,
globally, for an area (level-1) or a domain (level-2).
-.. index:: lsp-refresh-interval [level-1 | level-2] (1-65235)
.. clicmd:: lsp-refresh-interval [level-1 | level-2] (1-65235)
-.. index:: lsp-refresh-interval [level-1 | level-2]
-.. clicmd:: no lsp-refresh-interval [level-1 | level-2]
-
Set LSP refresh interval in seconds, globally, for an area (level-1) or a
domain (level-2).
-.. index:: max-lsp-lifetime (360-65535)
-.. clicmd:: max-lsp-lifetime (360-65535)
-
-.. index:: max-lsp-lifetime [level-1 | level-2] (360-65535)
.. clicmd:: max-lsp-lifetime [level-1 | level-2] (360-65535)
-.. index:: max-lsp-lifetime
-.. clicmd:: no max-lsp-lifetime
-
-.. index:: max-lsp-lifetime [level-1 | level-2]
-.. clicmd:: no max-lsp-lifetime [level-1 | level-2]
-
Set LSP maximum LSP lifetime in seconds, globally, for an area (level-1) or
a domain (level-2).
-.. index:: spf-interval (1-120)
-.. clicmd:: spf-interval (1-120)
-
-.. index:: spf-interval [level-1 | level-2] (1-120)
.. clicmd:: spf-interval [level-1 | level-2] (1-120)
-.. index:: spf-interval
-.. clicmd:: no spf-interval
-
-.. index:: spf-interval [level-1 | level-2]
-.. clicmd:: no spf-interval [level-1 | level-2]
-
Set minimum interval between consecutive SPF calculations in seconds.
.. _isis-fast-reroute:
@@ -193,47 +121,41 @@ ISIS Timer
ISIS Fast-Reroute
=================
-.. index:: spf prefix-priority [critical | high | medium] WORD
-.. clicmd:: spf prefix-priority [critical | high | medium] WORD
+Unless stated otherwise, commands in this section apply to all LFA
+flavors (local LFA, Remote LFA and TI-LFA).
-.. index:: spf prefix-priority [critical | high | medium] WORD
-.. clicmd:: no spf prefix-priority [critical | high | medium] [WORD]
+.. clicmd:: spf prefix-priority [critical | high | medium] WORD
Assign a priority to the prefixes that match the specified access-list.
-.. index:: fast-reroute priority-limit [critical | high | medium] [level-1 | level-2]
-.. clicmd:: [no] fast-reroute priority-limit [critical | high | medium] [level-1 | level-2]
+ By default loopback prefixes have medium priority and non-loopback prefixes
+ have low priority.
+
+.. clicmd:: fast-reroute priority-limit [critical | high | medium] [level-1 | level-2]
Limit LFA backup computation up to the specified prefix priority.
-.. index:: fast-reroute lfa tiebreaker [downstream | lowest-backup-metric | node-protecting] index (1-255) [level-1 | level-2]
-.. clicmd:: [no] fast-reroute lfa tiebreaker [downstream | lowest-backup-metric | node-protecting] index (1-255) [level-1 | level-2]
+.. clicmd:: fast-reroute lfa tiebreaker [downstream | lowest-backup-metric | node-protecting] index (1-255) [level-1 | level-2]
- Configure a tie-breaker for multiple LFA backups. Lower indexes are processed
- first.
+ Configure a tie-breaker for multiple local LFA backups. Lower indexes are
+ processed first.
-.. index:: fast-reroute load-sharing disable [level-1 | level-2]
-.. clicmd:: [no] fast-reroute load-sharing disable [level-1 | level-2]
+.. clicmd:: fast-reroute load-sharing disable [level-1 | level-2]
Disable load sharing across multiple LFA backups.
-.. index:: fast-reroute remote-lfa prefix-list WORD [level-1 | level-2]
-.. clicmd:: [no] fast-reroute remote-lfa prefix-list [WORD] [level-1 | level-2]
+.. clicmd:: fast-reroute remote-lfa prefix-list [WORD] [level-1 | level-2]
- Configure a prefix-list to select eligible PQ nodes (valid for all protected
- interfaces).
+ Configure a prefix-list to select eligible PQ nodes for remote LFA
+ backups (valid for all protected interfaces).
.. _isis-region:
ISIS region
===========
-.. index:: is-type [level-1 | level-1-2 | level-2-only]
.. clicmd:: is-type [level-1 | level-1-2 | level-2-only]
-.. index:: is-type
-.. clicmd:: no is-type
-
Define the ISIS router behavior:
- level-1
@@ -250,21 +172,15 @@ ISIS interface
.. _ip-router-isis-word:
-.. index:: ip router isis WORD [vrf NAME]
-.. index:: ipv6 router isis WORD [vrf NAME]
-.. clicmd:: [no] <ip|ipv6> router isis WORD [vrf NAME]
+.. clicmd:: <ip|ipv6> router isis WORD [vrf NAME]
Activate ISIS adjacency on this interface. Note that the name of ISIS
instance must be the same as the one used to configure the ISIS process (see
command :clicmd:`router isis WORD`). To enable IPv4, issue ``ip router isis
WORD``; to enable IPv6, issue ``ipv6 router isis WORD``.
-.. index:: isis circuit-type [level-1 | level-1-2 | level-2]
.. clicmd:: isis circuit-type [level-1 | level-1-2 | level-2]
-.. index:: isis circuit-type
-.. clicmd:: no isis circuit-type
-
Configure circuit type for interface:
- level-1
@@ -274,238 +190,126 @@ ISIS interface
- level-2-only
Level-2 only adjacencies are formed
-.. index:: isis csnp-interval (1-600)
-.. clicmd:: isis csnp-interval (1-600)
-
-.. index:: isis csnp-interval (1-600) [level-1 | level-2]
.. clicmd:: isis csnp-interval (1-600) [level-1 | level-2]
-.. index:: isis csnp-interval
-.. clicmd:: no isis csnp-interval
-
-.. index:: isis csnp-interval [level-1 | level-2]
-.. clicmd:: no isis csnp-interval [level-1 | level-2]
-
Set CSNP interval in seconds globally, for an area (level-1) or a domain
(level-2).
-.. index:: isis hello padding
.. clicmd:: isis hello padding
Add padding to IS-IS hello packets.
-.. index:: isis hello-interval (1-600)
-.. clicmd:: isis hello-interval (1-600)
-
-.. index:: isis hello-interval (1-600) [level-1 | level-2]
.. clicmd:: isis hello-interval (1-600) [level-1 | level-2]
-.. index:: isis hello-interval
-.. clicmd:: no isis hello-interval
-
-.. index:: isis hello-interval [level-1 | level-2]
-.. clicmd:: no isis hello-interval [level-1 | level-2]
-
Set Hello interval in seconds globally, for an area (level-1) or a domain
(level-2).
-.. index:: isis hello-multiplier (2-100)
-.. clicmd:: isis hello-multiplier (2-100)
-
-.. index:: isis hello-multiplier (2-100) [level-1 | level-2]
.. clicmd:: isis hello-multiplier (2-100) [level-1 | level-2]
-.. index:: isis hello-multiplier
-.. clicmd:: no isis hello-multiplier
-
-.. index:: isis hello-multiplier [level-1 | level-2]
-.. clicmd:: no isis hello-multiplier [level-1 | level-2]
-
Set multiplier for Hello holding time globally, for an area (level-1) or a
domain (level-2).
-.. index:: isis metric [(0-255) | (0-16777215)]
-.. clicmd:: isis metric [(0-255) | (0-16777215)]
-
-.. index:: isis metric [(0-255) | (0-16777215)] [level-1 | level-2]
.. clicmd:: isis metric [(0-255) | (0-16777215)] [level-1 | level-2]
-.. index:: isis metric
-.. clicmd:: no isis metric
-
-.. index:: isis metric [level-1 | level-2]
-.. clicmd:: no isis metric [level-1 | level-2]
-
Set default metric value globally, for an area (level-1) or a domain
(level-2). Max value depend if metric support narrow or wide value (see
command :clicmd:`metric-style [narrow | transition | wide]`).
-.. index:: isis network point-to-point
.. clicmd:: isis network point-to-point
-.. index:: isis network point-to-point
-.. clicmd:: no isis network point-to-point
-
Set network type to 'Point-to-Point' (broadcast by default).
-.. index:: isis passive
.. clicmd:: isis passive
-.. index:: isis passive
-.. clicmd:: no isis passive
-
Configure the passive mode for this interface.
-.. index:: isis password [clear | md5] <password>
.. clicmd:: isis password [clear | md5] <password>
-.. index:: isis password
-.. clicmd:: no isis password
-
Configure the authentication password (clear or encoded text) for the
interface.
-.. index:: isis priority (0-127)
-.. clicmd:: isis priority (0-127)
-
-.. index:: isis priority (0-127) [level-1 | level-2]
.. clicmd:: isis priority (0-127) [level-1 | level-2]
-.. index:: isis priority
-.. clicmd:: no isis priority
-
-.. index:: isis priority [level-1 | level-2]
-.. clicmd:: no isis priority [level-1 | level-2]
-
Set priority for Designated Router election, globally, for the area
(level-1) or the domain (level-2).
-.. index:: isis psnp-interval (1-120)
-.. clicmd:: isis psnp-interval (1-120)
-
-.. index:: isis psnp-interval (1-120) [level-1 | level-2]
.. clicmd:: isis psnp-interval (1-120) [level-1 | level-2]
-.. index:: isis psnp-interval
-.. clicmd:: no isis psnp-interval
-
-.. index:: isis psnp-interval [level-1 | level-2]
-.. clicmd:: no isis psnp-interval [level-1 | level-2]
-
Set PSNP interval in seconds globally, for an area (level-1) or a domain
(level-2).
-.. index:: isis three-way-handshake
.. clicmd:: isis three-way-handshake
-.. index:: isis three-way-handshake
-.. clicmd:: no isis three-way-handshake
-
Enable or disable :rfc:`5303` Three-Way Handshake for P2P adjacencies.
Three-Way Handshake is enabled by default.
-.. index:: isis fast-reroute lfa [level-1 | level-2]
-.. clicmd:: [no] isis fast-reroute lfa [level-1 | level-2]
-
- Enable per-prefix LFA fast reroute link protection.
+.. clicmd:: isis fast-reroute lfa [level-1 | level-2]
-.. index:: isis fast-reroute lfa [level-1 | level-2] exclude interface IFNAME
-.. clicmd:: [no] isis fast-reroute lfa [level-1 | level-2] exclude interface IFNAME
+ Enable per-prefix local LFA fast reroute link protection.
- Exclude an interface from the LFA backup nexthop computation.
+.. clicmd:: isis fast-reroute lfa [level-1 | level-2] exclude interface IFNAME
-.. index:: isis fast-reroute ti-lfa [level-1|level-2] [node-protection]
-.. clicmd:: [no] isis fast-reroute ti-lfa [level-1|level-2] [node-protection]
+ Exclude an interface from the local LFA backup nexthop computation.
- Enable per-prefix TI-LFA fast reroute link or node protection.
-
-.. index:: isis fast-reroute remote-lfa tunnel mpls-ldp [level-1 | level-2]
-.. clicmd:: [no] isis fast-reroute remote-lfa tunnel mpls-ldp [level-1 | level-2]
+.. clicmd:: isis fast-reroute remote-lfa tunnel mpls-ldp [level-1 | level-2]
Enable per-prefix Remote LFA fast reroute link protection. Note that other
routers in the network need to be configured to accept LDP targeted hello
messages in order for RLFA to work.
-.. index:: isis fast-reroute remote-lfa maximum-metric (1-16777215) [level-1 | level-2]
-.. clicmd:: [no] isis fast-reroute remote-lfa maximum-metric (1-16777215) [level-1 | level-2]
+.. clicmd:: isis fast-reroute remote-lfa maximum-metric (1-16777215) [level-1 | level-2]
Limit Remote LFA PQ node selection within the specified metric.
+.. clicmd:: isis fast-reroute ti-lfa [level-1|level-2] [node-protection]
+
+ Enable per-prefix TI-LFA fast reroute link or node protection.
+
+
.. _showing-isis-information:
Showing ISIS information
========================
-.. index:: show isis summary
.. clicmd:: show isis summary
Show summary information about ISIS.
-.. index:: show isis hostname
.. clicmd:: show isis hostname
Show information about ISIS node.
-.. index:: show isis interface
-.. clicmd:: show isis interface
-
-.. index:: show isis interface detail
-.. clicmd:: show isis interface detail
-
-.. index:: show isis interface <interface name>
-.. clicmd:: show isis interface <interface name>
+.. clicmd:: show isis interface [detail] [IFNAME]
Show state and configuration of ISIS specified interface, or all interfaces
if no interface is given with or without details.
-.. index:: show isis neighbor
-.. clicmd:: show isis neighbor
-
-.. index:: show isis neighbor <System Id>
-.. clicmd:: show isis neighbor <System Id>
-
-.. index:: show isis neighbor detail
-.. clicmd:: show isis neighbor detail
+.. clicmd:: show isis neighbor [detail] [SYSTEMID]
Show state and information of ISIS specified neighbor, or all neighbors if
no system id is given with or without details.
-.. index:: show isis database
-.. clicmd:: show isis database
-
-.. index:: show isis database [detail]
-.. clicmd:: show isis database [detail]
-
-.. index:: show isis database <LSP id> [detail]
-.. clicmd:: show isis database <LSP id> [detail]
-
-.. index:: show isis database detail <LSP id>
-.. clicmd:: show isis database detail <LSP id>
+.. clicmd:: show isis database [detail] [LSPID]
Show the ISIS database globally, for a specific LSP id without or with
details.
-.. index:: show isis topology
-.. clicmd:: show isis topology
-
-.. index:: show isis topology [level-1|level-2]
.. clicmd:: show isis topology [level-1|level-2]
Show topology IS-IS paths to Intermediate Systems, globally, in area
(level-1) or domain (level-2).
-.. index:: show isis route [level-1|level-2] [prefix-sid|backup]
.. clicmd:: show isis route [level-1|level-2] [prefix-sid|backup]
Show the ISIS routing table, as determined by the most recent SPF
calculation.
-.. index:: show isis fast-reroute summary [level-1|level-2]
.. clicmd:: show isis fast-reroute summary [level-1|level-2]
Show information about the number of prefixes having LFA protection,
and network-wide LFA coverage.
+
.. _isis-traffic-engineering:
Traffic Engineering
@@ -513,35 +317,24 @@ Traffic Engineering
.. note::
- At this time, FRR offers partial support for some of the routing
- protocol extensions that can be used with MPLS-TE. FRR does not
- support a complete RSVP-TE solution currently.
+ At this time, FRR offers partial support for some of the routing protocol
+ extensions that can be used with MPLS-TE. FRR does not currently support a
+ complete RSVP-TE solution.
-.. index:: mpls-te on
.. clicmd:: mpls-te on
-.. index:: mpls-te
-.. clicmd:: no mpls-te
-
Enable Traffic Engineering LSP flooding.
-.. index:: mpls-te router-address <A.B.C.D>
.. clicmd:: mpls-te router-address <A.B.C.D>
-.. index:: mpls-te router-address
-.. clicmd:: no mpls-te router-address
-
Configure stable IP address for MPLS-TE.
-.. index:: show isis mpls-te interface
.. clicmd:: show isis mpls-te interface
-.. index:: show isis mpls-te interface INTERFACE
.. clicmd:: show isis mpls-te interface INTERFACE
Show MPLS Traffic Engineering parameters for all or specified interface.
-.. index:: show isis mpls-te router
.. clicmd:: show isis mpls-te router
Show Traffic Engineering router parameters.
@@ -550,6 +343,7 @@ Traffic Engineering
:ref:`ospf-traffic-engineering`
+
.. _debugging-isis:
Segment Routing
@@ -566,36 +360,32 @@ Known limitations:
- No support for SRLB
- Only one SRGB and default SPF Algorithm is supported
-.. index:: segment-routing on
-.. clicmd:: [no] segment-routing on
+.. clicmd:: segment-routing on
Enable Segment Routing.
-.. index:: segment-routing global-block (0-1048575) (0-1048575)
-.. clicmd:: [no] segment-routing global-block (0-1048575) (0-1048575)
+.. clicmd:: segment-routing global-block (16-1048575) (16-1048575) [local-block (16-1048575) (16-1048575)]
Set the Segment Routing Global Block i.e. the label range used by MPLS
to store label in the MPLS FIB for Prefix SID. Note that the block size
- may not exceed 65535.
+ may not exceed 65535. Optionally sets also the Segment Routing Local Block.
+ The negative command always unsets both.
-.. index:: segment-routing local-block (0-1048575) (0-1048575)
-.. clicmd:: [no] segment-routing local-block (0-1048575) (0-1048575)
+.. clicmd:: segment-routing local-block (16-1048575) (16-1048575)
Set the Segment Routing Local Block i.e. the label range used by MPLS
to store label in the MPLS FIB for Adjacency SID. Note that the block size
- may not exceed 65535.
+ may not exceed 65535. This command is deprecated in favor of the combined
+ 'segment-routing global-block A B local-block C D' command.
-.. index:: segment-routing node-msd (1-16)
-.. clicmd:: [no] segment-routing node-msd (1-16)
+.. clicmd:: segment-routing node-msd (1-16)
Set the Maximum Stack Depth supported by the router. The value depend of the
MPLS dataplane. E.g. for Linux kernel, since version 4.13 the maximum value
is 32.
-.. index:: segment-routing prefix <A.B.C.D/M|X:X::X:X/M> <absolute (16-1048575)|index (0-65535)> [no-php-flag|explicit-null] [n-flag-clear]
-.. clicmd:: [no] segment-routing prefix <A.B.C.D/M|X:X::X:X/M> <absolute (16-1048575)|index (0-65535) [no-php-flag|explicit-null] [n-flag-clear]
+.. clicmd:: segment-routing prefix <A.B.C.D/M|X:X::X:X/M> <absolute (16-1048575)|index (0-65535) [no-php-flag|explicit-null] [n-flag-clear]
- Set the Segment Routing index or absolute label value for the specified
prefix. The 'no-php-flag' means NO Penultimate Hop Popping that allows SR
node to request to its neighbor to not pop the label. The 'explicit-null'
flag allows SR node to request to its neighbor to send IP packet with the
@@ -603,12 +393,10 @@ Known limitations:
clear the Node flag that is set by default for Prefix-SIDs associated to
loopback addresses. This option is necessary to configure Anycast-SIDs.
-.. index:: show isis segment-routing prefix-sids
.. clicmd:: show isis segment-routing prefix-sids
Show detailed information about all learned Segment Routing Prefix-SIDs.
-.. index:: show isis segment-routing nodes
.. clicmd:: show isis segment-routing nodes
Show detailed information about all learned Segment Routing Nodes.
@@ -616,120 +404,66 @@ Known limitations:
Debugging ISIS
==============
-.. index:: debug isis adj-packets
.. clicmd:: debug isis adj-packets
-.. index:: debug isis adj-packets
-.. clicmd:: no debug isis adj-packets
-
IS-IS Adjacency related packets.
-.. index:: debug isis checksum-errors
.. clicmd:: debug isis checksum-errors
-.. index:: debug isis checksum-errors
-.. clicmd:: no debug isis checksum-errors
-
IS-IS LSP checksum errors.
-.. index:: debug isis events
.. clicmd:: debug isis events
-.. index:: debug isis events
-.. clicmd:: no debug isis events
-
IS-IS Events.
-.. index:: debug isis local-updates
.. clicmd:: debug isis local-updates
-.. index:: debug isis local-updates
-.. clicmd:: no debug isis local-updates
-
IS-IS local update packets.
-.. index:: debug isis packet-dump
.. clicmd:: debug isis packet-dump
-.. index:: debug isis packet-dump
-.. clicmd:: no debug isis packet-dump
-
IS-IS packet dump.
-.. index:: debug isis protocol-errors
.. clicmd:: debug isis protocol-errors
-.. index:: debug isis protocol-errors
-.. clicmd:: no debug isis protocol-errors
-
IS-IS LSP protocol errors.
-.. index:: debug isis route-events
.. clicmd:: debug isis route-events
-.. index:: debug isis route-events
-.. clicmd:: no debug isis route-events
-
IS-IS Route related events.
-.. index:: debug isis snp-packets
.. clicmd:: debug isis snp-packets
-.. index:: debug isis snp-packets
-.. clicmd:: no debug isis snp-packets
-
IS-IS CSNP/PSNP packets.
-.. index:: debug isis spf-events
.. clicmd:: debug isis spf-events
-
-.. index:: debug isis spf-statistics
.. clicmd:: debug isis spf-statistics
-
-.. index:: debug isis spf-triggers
.. clicmd:: debug isis spf-triggers
-.. index:: debug isis spf-events
-.. clicmd:: no debug isis spf-events
-
-.. index:: debug isis spf-statistics
-.. clicmd:: no debug isis spf-statistics
-
-.. index:: debug isis spf-triggers
-.. clicmd:: no debug isis spf-triggers
-
IS-IS Shortest Path First Events, Timing and Statistic Data and triggering
events.
-.. index:: debug isis update-packets
.. clicmd:: debug isis update-packets
-.. index:: debug isis update-packets
-.. clicmd:: no debug isis update-packets
Update related packets.
-.. index:: debug isis sr-events
.. clicmd:: debug isis sr-events
-.. index:: debug isis sr-events
-.. clicmd:: no debug isis sr-events
IS-IS Segment Routing events.
-.. index:: debug isis lfa
.. clicmd:: debug isis lfa
-.. index:: debug isis lfa
-.. clicmd:: no debug isis lfa
IS-IS LFA events.
-.. index:: show debugging isis
.. clicmd:: show debugging isis
Print which ISIS debug level is activate.
+.. _isis-config-examples:
+
ISIS Configuration Examples
===========================
@@ -843,6 +577,9 @@ A Segment Routing configuration, with IPv4, IPv6, SRGB and MSD configuration.
segment-routing prefix 2001:db8:1000::1/128 index 101 explicit-null
!
+
+.. _isis-vrf-config-examples:
+
ISIS Vrf Configuration Examples
===============================
@@ -860,5 +597,3 @@ A simple vrf example:
net 47.0023.0000.0000.0000.0000.0000.0000.1900.0004.00
metric-style wide
is-type level-2-only
-
-
diff --git a/doc/user/ldpd.rst b/doc/user/ldpd.rst
index 375842f2ba..3e662b14d8 100644
--- a/doc/user/ldpd.rst
+++ b/doc/user/ldpd.rst
@@ -97,53 +97,45 @@ implementation.
LDP Configuration
===================
-.. index:: mpls ldp
-.. clicmd:: [no] mpls ldp
+.. clicmd:: mpls ldp
Enable or disable LDP daemon
-.. index:: router-id A.B.C.D
-.. clicmd:: [no] router-id A.B.C.D
+.. clicmd:: router-id A.B.C.D
The following command located under MPLS router node configures the MPLS
router-id of the local device.
-.. index:: ordered-control
-.. clicmd:: [no] ordered-control
+.. clicmd:: ordered-control
Configure LDP Ordered Label Distribution Control.
-.. index:: address-family [ipv4 | ipv6]
-.. clicmd:: [no] address-family [ipv4 | ipv6]
+.. clicmd:: address-family [ipv4 | ipv6]
Configure LDP for IPv4 or IPv6 address-family. Located under MPLS route node,
this subnode permits configuring the LDP neighbors.
-.. index:: interface IFACE
-.. clicmd:: [no] interface IFACE
+.. clicmd:: interface IFACE
Located under MPLS address-family node, use this command to enable or disable
LDP discovery per interface. IFACE stands for the interface name where LDP is
enabled. By default it is disabled. Once this command executed, the
address-family interface node is configured.
-.. index:: discovery transport-address A.B.C.D | A:B::C:D
-.. clicmd:: [no] discovery transport-address A.B.C.D | A:B::C:D
+.. clicmd:: discovery transport-address A.B.C.D | A:B::C:D
Located under mpls address-family interface node, use this command to set
the IPv4 or IPv6 transport-address used by the LDP protocol to talk on this
interface.
-.. index:: neighbor A.B.C.D password PASSWORD
-.. clicmd:: [no] neighbor A.B.C.D password PASSWORD
+.. clicmd:: neighbor A.B.C.D password PASSWORD
The following command located under MPLS router node configures the router
of a LDP device. This device, if found, will have to comply with the
configured password. PASSWORD is a clear text password wit its digest sent
through the network.
-.. index:: neighbor A.B.C.D holdtime HOLDTIME
-.. clicmd:: [no] neighbor A.B.C.D holdtime HOLDTIME
+.. clicmd:: neighbor A.B.C.D holdtime HOLDTIME
The following command located under MPLS router node configures the holdtime
value in seconds of the LDP neighbor ID. Configuring it triggers a keepalive
@@ -151,19 +143,16 @@ LDP Configuration
this time of non response, the LDP established session will be considered as
set to down. By default, no holdtime is configured for the LDP devices.
-.. index:: discovery hello holdtime HOLDTIME
-.. clicmd:: [no] discovery hello holdtime HOLDTIME
+.. clicmd:: discovery hello holdtime HOLDTIME
-.. index:: discovery hello interval INTERVAL
-.. clicmd:: [no] discovery hello interval INTERVAL
+.. clicmd:: discovery hello interval INTERVAL
INTERVAL value ranges from 1 to 65535 seconds. Default value is 5 seconds.
This is the value between each hello timer message sent.
HOLDTIME value ranges from 1 to 65535 seconds. Default value is 15 seconds.
That value is added as a TLV in the LDP messages.
-.. index:: dual-stack transport-connection prefer ipv4
-.. clicmd:: [no] dual-stack transport-connection prefer ipv4
+.. clicmd:: dual-stack transport-connection prefer ipv4
When *ldpd* is configured for dual-stack operation, the transport connection
preference is IPv6 by default (as specified by :rfc:`7552`). On such
@@ -179,7 +168,6 @@ Show LDP Information
These commands dump various parts of *ldpd*.
-.. index:: show mpls ldp neighbor [A.B.C.D]
.. clicmd:: show mpls ldp neighbor [A.B.C.D]
This command dumps the various neighbors discovered. Below example shows that
@@ -192,29 +180,22 @@ These commands dump various parts of *ldpd*.
ipv4 1.1.1.1 OPERATIONAL 1.1.1.1 00:01:37
west-vm#
-.. index:: show mpls ldp neighbor [A.B.C.D] capabilities
.. clicmd:: show mpls ldp neighbor [A.B.C.D] capabilities
-.. index:: show mpls ldp neighbor [A.B.C.D] detail
.. clicmd:: show mpls ldp neighbor [A.B.C.D] detail
Above commands dump other neighbor information.
-.. index:: show mpls ldp discovery [detail]
.. clicmd:: show mpls ldp discovery [detail]
-.. index:: show mpls ldp ipv4 discovery [detail]
.. clicmd:: show mpls ldp ipv4 discovery [detail]
-.. index:: show mpls ldp ipv6 discovery [detail]
.. clicmd:: show mpls ldp ipv6 discovery [detail]
Above commands dump discovery information.
-.. index:: show mpls ldp ipv4 interface
.. clicmd:: show mpls ldp ipv4 interface
-.. index:: show mpls ldp ipv6 interface
.. clicmd:: show mpls ldp ipv6 interface
Above command dumps the IPv4 or IPv6 interface per where LDP is enabled.
@@ -228,7 +209,6 @@ These commands dump various parts of *ldpd*.
ipv4 eth3 ACTIVE 00:08:35 5/15 1
-.. index:: show mpls ldp ipv4|ipv6 binding
.. clicmd:: show mpls ldp ipv4|ipv6 binding
Above command dumps the binding obtained through MPLS exchanges with LDP.
@@ -245,14 +225,12 @@ These commands dump various parts of *ldpd*.
ipv4 10.200.0.0/24 1.1.1.1 17 imp-null yes
west-vm#
+
LDP debugging commands
========================
-.. index::
- simple: debug mpls ldp KIND
- simple: no debug mpls ldp KIND
-.. clicmd:: [no] debug mpls ldp KIND
+.. clicmd:: debug mpls ldp KIND
Enable or disable debugging messages of a given kind. ``KIND`` can
be one of:
diff --git a/doc/user/nhrpd.rst b/doc/user/nhrpd.rst
index 65645c519d..b02e761acc 100644
--- a/doc/user/nhrpd.rst
+++ b/doc/user/nhrpd.rst
@@ -77,7 +77,6 @@ command defines the GRE subnet):
Configuring NHRP
================
-.. index:: ip nhrp holdtime (1-65000)
.. clicmd:: ip nhrp holdtime (1-65000)
Holdtime is the number of seconds that have to pass before stopping to
@@ -85,12 +84,10 @@ Configuring NHRP
registration requests are sent. By default registrations are sent every one
third of the holdtime.
-.. index:: ip nhrp map A.B.C.D|X:X::X:X A.B.C.D|local
.. clicmd:: ip nhrp map A.B.C.D|X:X::X:X A.B.C.D|local
Map an IP address of a station to the station's NBMA address.
-.. index:: ip nhrp network-id (1-4294967295)
.. clicmd:: ip nhrp network-id (1-4294967295)
Enable NHRP on this interface and set the interface's network ID. The
@@ -101,30 +98,25 @@ Configuring NHRP
different nodes do not need to match. When NHRP packets are received on an
interface they are assigned to the local NHRP domain for that interface.
-.. index:: ip nhrp nhs A.B.C.D nbma A.B.C.D|FQDN
.. clicmd:: ip nhrp nhs A.B.C.D nbma A.B.C.D|FQDN
Configure the Next Hop Server address and its NBMA address.
-.. index:: ip nhrp nhs dynamic nbma A.B.C.D
.. clicmd:: ip nhrp nhs dynamic nbma A.B.C.D
Configure the Next Hop Server to have a dynamic address and set its NBMA
address.
-.. index:: ip nhrp registration no-unique
.. clicmd:: ip nhrp registration no-unique
Allow the client to not set the unique flag in the NHRP packets. This is
useful when a station has a dynamic IP address that could change over time.
-.. index:: ip nhrp shortcut
.. clicmd:: ip nhrp shortcut
Enable shortcut (spoke-to-spoke) tunnels to allow NHC to talk to each others
directly after establishing a connection without going through the hub.
-.. index:: ip nhrp mtu
.. clicmd:: ip nhrp mtu
Configure NHRP advertised MTU.
@@ -159,13 +151,11 @@ However, the above should be good in most cases.
This kernel NFLOG target's nflog-group is configured in global nhrp config
with:
-.. index:: nhrp nflog-group (1-65535)
.. clicmd:: nhrp nflog-group (1-65535)
To start sending these traffic notices out from hubs, use the nhrp
per-interface directive:
-.. index:: ip nhrp redirect
.. clicmd:: ip nhrp redirect
This enable redirect replies on the NHS similar to ICMP redirects except this
@@ -195,7 +185,6 @@ https://gitlab.alpinelinux.org/alpine/aports/-/tree/master/main/strongswan
NHRP Events
===========
-.. index:: nhrp event socket SOCKET
.. clicmd:: nhrp event socket SOCKET
Configure the Unix path for the event socket.
@@ -205,22 +194,18 @@ NHRP Events
Show NHRP
==========
-.. index:: show [ip|ipv6] nhrp cache [json]
.. clicmd:: show [ip|ipv6] nhrp cache [json]
Dump the cache entries.
-.. index:: show [ip|ipv6] nhrp opennhrp [json]
.. clicmd:: show [ip|ipv6] nhrp opennhrp [json]
Dump the cache entries with opennhrp format.
-.. index:: show [ip|ipv6] nhrp nhs [json]
.. clicmd:: show [ip|ipv6] nhrp nhs [json]
Dump the hub context.
-.. index:: show dmvpn [json]
.. clicmd:: show dmvpn [json]
Dump the security contexts.
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index 99119bb7e5..00571487d7 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -12,28 +12,20 @@ described in :rfc:`2740`.
OSPF6 router
============
-.. index:: router ospf6
.. clicmd:: router ospf6
-.. index:: ospf6 router-id A.B.C.D
.. clicmd:: ospf6 router-id A.B.C.D
Set router's Router-ID.
-.. index:: interface IFNAME area (0-4294967295)
.. clicmd:: interface IFNAME area (0-4294967295)
-.. index:: interface IFNAME area A.B.C.D
.. clicmd:: interface IFNAME area A.B.C.D
Bind interface to specified area, and start sending OSPF packets. `area` can
be specified as 0.
-.. index:: timers throttle spf DELAY INITIAL-HOLDTIME MAX-HOLDTIME
-.. clicmd:: timers throttle spf DELAY INITIAL-HOLDTIME MAX-HOLDTIME
-
-.. index:: timers throttle spf
-.. clicmd:: no timers throttle spf
+.. clicmd:: timers throttle spf (0-600000) (0-600000) (0-600000)
This command sets the initial `delay`, the `initial-holdtime`
and the `maximum-holdtime` between when SPF is calculated and the
@@ -68,11 +60,8 @@ OSPF6 router
time an SPF-triggering event occurs within the hold-time of the previous
SPF calculation.
-.. index:: auto-cost reference-bandwidth COST
.. clicmd:: auto-cost reference-bandwidth COST
-.. index:: auto-cost reference-bandwidth
-.. clicmd:: no auto-cost reference-bandwidth
This sets the reference bandwidth for cost calculations, where this
bandwidth is considered equivalent to an OSPF cost of 1, specified in
@@ -83,12 +72,12 @@ OSPF6 router
This configuration setting MUST be consistent across all routers
within the OSPF domain.
-.. index:: maximum-paths (1-64)
-.. clicmd::[no] maximum-paths (1-64)
+.. clicmd:: maximum-paths (1-64)
Use this command to control the maximum number of parallel routes that
OSPFv3 can support. The default is 64.
+
.. _ospf6-area:
OSPF6 area
@@ -101,38 +90,31 @@ Area support for OSPFv3 is not yet implemented.
OSPF6 interface
===============
-.. index:: ipv6 ospf6 cost COST
.. clicmd:: ipv6 ospf6 cost COST
Sets interface's output cost. Default value depends on the interface
bandwidth and on the auto-cost reference bandwidth.
-.. index:: ipv6 ospf6 hello-interval HELLOINTERVAL
.. clicmd:: ipv6 ospf6 hello-interval HELLOINTERVAL
Sets interface's Hello Interval. Default 10
-.. index:: ipv6 ospf6 dead-interval DEADINTERVAL
.. clicmd:: ipv6 ospf6 dead-interval DEADINTERVAL
Sets interface's Router Dead Interval. Default value is 40.
-.. index:: ipv6 ospf6 retransmit-interval RETRANSMITINTERVAL
.. clicmd:: ipv6 ospf6 retransmit-interval RETRANSMITINTERVAL
Sets interface's Rxmt Interval. Default value is 5.
-.. index:: ipv6 ospf6 priority PRIORITY
.. clicmd:: ipv6 ospf6 priority PRIORITY
Sets interface's Router Priority. Default value is 1.
-.. index:: ipv6 ospf6 transmit-delay TRANSMITDELAY
.. clicmd:: ipv6 ospf6 transmit-delay TRANSMITDELAY
Sets interface's Inf-Trans-Delay. Default value is 1.
-.. index:: ipv6 ospf6 network (broadcast|point-to-point)
.. clicmd:: ipv6 ospf6 network (broadcast|point-to-point)
Set explicitly network type for specified interface.
@@ -142,7 +124,6 @@ OSPF6 route-map
Usage of *ospfd6*'s route-map support.
-.. index:: set metric [+|-](0-4294967295)
.. clicmd:: set metric [+|-](0-4294967295)
Set a metric for matched route when sending announcement. Use plus (+) sign
@@ -154,14 +135,9 @@ Usage of *ospfd6*'s route-map support.
Redistribute routes to OSPF6
============================
-.. index:: redistribute static
-.. clicmd:: redistribute static
+.. clicmd:: redistribute <babel|bgp|connected|isis|kernel|openfabric|ripng|sharp|static|table> [route-map WORD]
-.. index:: redistribute connected
-.. clicmd:: redistribute connected
-
-.. index:: redistribute ripng
-.. clicmd:: redistribute ripng
+ Redistribute routes from other protocols into OSPFv3.
.. _showing-ospf6-information:
@@ -169,14 +145,12 @@ Redistribute routes to OSPF6
Showing OSPF6 information
=========================
-.. index:: show ipv6 ospf6 [INSTANCE_ID] [json]
.. clicmd:: show ipv6 ospf6 [INSTANCE_ID] [json]
INSTANCE_ID is an optional OSPF instance ID. To see router ID and OSPF
instance ID, simply type "show ipv6 ospf6 <cr>". JSON output can be
obtained by appending 'json' to the end of command.
-.. index:: show ipv6 ospf6 database [<detail|dump|internal>] [json]
.. clicmd:: show ipv6 ospf6 database [<detail|dump|internal>] [json]
This command shows LSAs present in the LSDB. There are three view options.
@@ -184,14 +158,12 @@ Showing OSPF6 information
can be obtained by appending 'json' to the end of command. JSON option is
not applicable with 'dump' option.
-.. index:: show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [json]
.. clicmd:: show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [json]
These options filters out the LSA based on its type. The three views options
works here as well. JSON output can be obtained by appending 'json' to the
end of command.
-.. index:: show ipv6 ospf6 database adv-router A.B.C.D linkstate-id A.B.C.D [json]
.. clicmd:: show ipv6 ospf6 database adv-router A.B.C.D linkstate-id A.B.C.D [json]
The LSAs additinally can also be filtered with the linkstate-id and
@@ -199,54 +171,45 @@ Showing OSPF6 information
this command as well and visa-versa. JSON output can be obtained by
appending 'json' to the end of command.
-.. index:: show ipv6 ospf6 database self-originated [json]
.. clicmd:: show ipv6 ospf6 database self-originated [json]
This command is used to filter the LSAs which are originated by the present
router. All the other filters are applicable here as well.
-.. index:: show ipv6 ospf6 interface [json]
.. clicmd:: show ipv6 ospf6 interface [json]
To see OSPF interface configuration like costs. JSON output can be
obtained by appending "json" in the end.
-.. index:: show ipv6 ospf6 neighbor [json]
.. clicmd:: show ipv6 ospf6 neighbor [json]
Shows state and chosen (Backup) DR of neighbor. JSON output can be
obtained by appending 'json' at the end.
-.. index:: show ipv6 ospf6 interface traffic [json]
.. clicmd:: show ipv6 ospf6 interface traffic [json]
Shows counts of different packets that have been recieved and transmitted
by the interfaces. JSON output can be obtained by appending "json" at the
end.
-.. index:: show ipv6 ospf6 request-list A.B.C.D
.. clicmd:: show ipv6 ospf6 request-list A.B.C.D
Shows requestlist of neighbor.
-.. index:: show ipv6 route ospf6
.. clicmd:: show ipv6 route ospf6
This command shows internal routing table.
-.. index:: show ipv6 ospf6 zebra [json]
.. clicmd:: show ipv6 ospf6 zebra [json]
Shows state about what is being redistributed between zebra and OSPF6.
JSON output can be obtained by appending "json" at the end.
-.. index:: show ipv6 ospf6 redistribute [json]
.. clicmd:: show ipv6 ospf6 redistribute [json]
Shows the routes which are redistributed by the router. JSON output can
be obtained by appending 'json' at the end.
-.. index:: show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]
.. clicmd:: show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]
This command displays the ospfv3 routing table as determined by the most
@@ -255,19 +218,26 @@ Showing OSPF6 information
and summary. JSON output can be obtained by appending 'json' to the end of
command.
-.. index:: show ipv6 ospf6 route X:X::X:X/M match [detail] [json]
.. clicmd:: show ipv6 ospf6 route X:X::X:X/M match [detail] [json]
The additional match option will match the given address to the destination
of the routes, and return the result accordingly.
-.. index:: show ipv6 ospf6 interface [IFNAME] prefix [detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]] [json]
.. clicmd:: show ipv6 ospf6 interface [IFNAME] prefix [detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]] [json]
This command shows the prefixes present in the interface routing table.
Interface name can also be given. JSON output can be obtained by appending
'json' to the end of command.
+.. index:: show ipv6 ospf6 spf tree [json]
+.. clicmd:: show ipv6 ospf6 spf tree [json]
+
+ This commands shows the spf tree from the recent spf calculation with the
+ calling router as the root. If json is appended in the end, we can get the
+ tree in JSON format. Each area that the router belongs to has it's own
+ JSON object, with each router having "cost", "isLeafNode" and "children" as
+ arguments.
+
OSPF6 Configuration Examples
============================
diff --git a/doc/user/ospf_fundamentals.rst b/doc/user/ospf_fundamentals.rst
index b0eb018107..38c18e5526 100644
--- a/doc/user/ospf_fundamentals.rst
+++ b/doc/user/ospf_fundamentals.rst
@@ -3,8 +3,10 @@
OSPF Fundamentals
=================
-.. index:: Link-state routing protocol
-.. index:: Distance-vector routing protocol
+.. index::
+ pair: Link-state routing protocol; OSPF
+ pair: Distance-vector routing protocol; OSPF
+
:abbr:`OSPF` is, mostly, a link-state routing protocol. In contrast to
:term:`distance-vector` protocols, such as :abbr:`RIP` or :abbr:`BGP`, where
@@ -12,10 +14,12 @@ 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.
-.. index:: Link State Announcement
-.. index:: Link State Advertisement
-.. index:: LSA flooding
-.. index:: Link State Database
+.. index::
+ single: Link State Announcement
+ single: Link State Advertisement
+ single: LSA flooding
+ single: Link State Database
+
Each router describes their link-state information in a message known as an
:abbr:`LSA (Link State Advertisement)`, which is then propagated through to all
@@ -27,7 +31,8 @@ metric, by using an algorithm such as
`Edsger Dijkstra's <http://www.cs.utexas.edu/users/EWD/>`_
:abbr:`SPF (Shortest Path First)` algorithm.
-.. index:: Link-state routing protocol advantages
+.. index::
+ pair: Link-state routing protocol; advantages
By describing connectivity of a network in this way, in terms of
routers and links rather than in terms of the paths through a network,
@@ -39,7 +44,8 @@ reconverge on the best paths through the network. In contrast, distance
vector protocols can require a progression of different path update
messages from a series of different routers in order to converge.
-.. index:: Link-state routing protocol disadvantages
+.. index::
+ pair: Link-state routing protocol; disadvantages
The disadvantage to a link-state protocol is that the process of
computing the best paths can be relatively intensive when compared to
@@ -64,7 +70,8 @@ will nearly all be covered in greater detail further on. They may be
broadly classed as:
-.. index:: OSPF Hello Protocol
+.. index::
+ pair: Hello protocol; OSPF
The Hello Protocol
^^^^^^^^^^^^^^^^^^
@@ -86,7 +93,10 @@ sharing a link, for example:
The Hello protocol is comparatively trivial and will not be explored in more
detail.
-.. index:: OSPF LSA overview
+
+.. index::
+ pair: LSA; OSPF
+
.. _ospf-lsas:
LSAs
@@ -120,7 +130,9 @@ OSPF defines several related mechanisms, used to manage synchronisation of
:abbr:`LSDB` s between neighbours as neighbours form adjacencies and the
propagation, or `flooding` of new or updated :abbr:`LSA` s.
-.. index:: OSPF Areas overview
+
+.. index::
+ pair: Area; OSPF
.. _ospf-areas:
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index ee02a9dae5..8689bc4ccb 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -80,19 +80,13 @@ Routers
To start OSPF process you have to specify the OSPF router.
-.. index:: router ospf [(1-65535)] vrf NAME
.. clicmd:: router ospf [(1-65535)] vrf NAME
-.. index:: router ospf [(1-65535)] vrf NAME
-.. clicmd:: no router ospf [(1-65535)] vrf NAME
Enable or disable the OSPF process.
-.. index:: ospf router-id A.B.C.D
.. clicmd:: ospf router-id A.B.C.D
-.. index:: ospf router-id [A.B.C.D]
-.. clicmd:: no ospf router-id [A.B.C.D]
This sets the router-ID of the OSPF process. The router-ID may be an IP
address of the router, but need not be - it can be any arbitrary 32bit
@@ -101,11 +95,8 @@ To start OSPF process you have to specify the OSPF router.
with the same router-ID! If one is not specified then *ospfd* will obtain a
router-ID automatically from *zebra*.
-.. index:: ospf abr-type TYPE
.. clicmd:: ospf abr-type TYPE
-.. index:: ospf abr-type TYPE
-.. clicmd:: no ospf abr-type TYPE
`type` can be cisco|ibm|shortcut|standard. The "Cisco" and "IBM" types
are equivalent.
@@ -137,11 +128,8 @@ To start OSPF process you have to specify the OSPF router.
OSPF domain, is dropped. This document describes alternative ABR
behaviors implemented in Cisco and IBM routers."
-.. index:: ospf rfc1583compatibility
.. clicmd:: ospf rfc1583compatibility
-.. index:: ospf rfc1583compatibility
-.. clicmd:: no ospf rfc1583compatibility
:rfc:`2328`, the successor to :rfc:`1583`, suggests according
to section G.2 (changes) in section 16.4 a change to the path
@@ -152,21 +140,15 @@ To start OSPF process you have to specify the OSPF router.
This command should NOT be set normally.
-.. index:: log-adjacency-changes [detail]
.. clicmd:: log-adjacency-changes [detail]
-.. index:: log-adjacency-changes [detail]
-.. clicmd:: no log-adjacency-changes [detail]
Configures ospfd to log changes in adjacency. With the optional
detail argument, all changes in adjacency status are shown. Without detail,
only changes to full or regressions are shown.
-.. index:: passive-interface INTERFACE
.. clicmd:: passive-interface INTERFACE
-.. index:: passive-interface INTERFACE
-.. clicmd:: no passive-interface INTERFACE
Do not speak OSPF interface on the
given interface, but do advertise the interface as a stub link in the
@@ -177,12 +159,8 @@ To start OSPF process you have to specify the OSPF router.
OSPF (:ref:`redistribute-routes-to-ospf`). This is the only way to
advertise non-OSPF links into stub areas.
-.. index:: timers throttle spf (0-600000) (0-600000) (0-600000)
.. clicmd:: timers throttle spf (0-600000) (0-600000) (0-600000)
-.. index:: timers throttle spf
-.. clicmd:: no timers throttle spf
-
This command sets the initial `delay`, the `initial-holdtime`
and the `maximum-holdtime` between when SPF is calculated and the
event which triggered the calculation. The times are specified in
@@ -221,14 +199,10 @@ To start OSPF process you have to specify the OSPF router.
This command supersedes the *timers spf* command in previous FRR
releases.
-.. index:: max-metric router-lsa [on-startup|on-shutdown] (5-86400)
.. clicmd:: max-metric router-lsa [on-startup|on-shutdown] (5-86400)
-.. index:: max-metric router-lsa administrative
.. clicmd:: max-metric router-lsa administrative
-.. index:: max-metric router-lsa [on-startup|on-shutdown|administrative]
-.. clicmd:: no max-metric router-lsa [on-startup|on-shutdown|administrative]
This enables :rfc:`3137` support, where the OSPF process describes its
transit links in its router-LSA as having infinite distance so that other
@@ -257,11 +231,8 @@ To start OSPF process you have to specify the OSPF router.
number of second remaining till on-startup or on-shutdown ends, can be
viewed with the :clicmd:`show ip ospf` command.
-.. index:: auto-cost reference-bandwidth (1-4294967)
.. clicmd:: auto-cost reference-bandwidth (1-4294967)
-.. index:: auto-cost reference-bandwidth
-.. clicmd:: no auto-cost reference-bandwidth
This sets the reference
bandwidth for cost calculations, where this bandwidth is considered
@@ -273,17 +244,11 @@ To start OSPF process you have to specify the OSPF router.
This configuration setting MUST be consistent across all routers within the
OSPF domain.
-.. index:: network A.B.C.D/M area A.B.C.D
.. clicmd:: network A.B.C.D/M area A.B.C.D
-.. index:: network A.B.C.D/M area (0-4294967295)
.. clicmd:: network A.B.C.D/M area (0-4294967295)
-.. index:: network A.B.C.D/M area A.B.C.D
-.. clicmd:: no network A.B.C.D/M area A.B.C.D
-.. index:: network A.B.C.D/M area (0-4294967295)
-.. clicmd:: no network A.B.C.D/M area (0-4294967295)
This command specifies the OSPF enabled interface(s). If the interface has
an address from range 192.168.1.0/24 then the command below enables ospf
@@ -310,11 +275,8 @@ To start OSPF process you have to specify the OSPF router.
In some cases it may be more convenient to enable OSPF on a per
interface/subnet basis (:clicmd:`ip ospf area AREA [ADDR]`).
-.. index:: proactive-arp
.. clicmd:: proactive-arp
-.. index:: proactive-arp
-.. clicmd:: no proactive-arp
This command enables or disables sending ARP requests to update neighbor
table entries. It speeds up convergence for /32 networks on a P2P
@@ -322,7 +284,6 @@ To start OSPF process you have to specify the OSPF router.
This feature is enabled by default.
-.. index:: clear ip ospf [(1-65535)] process
.. clicmd:: clear ip ospf [(1-65535)] process
This command can be used to clear the ospf process data structures. This
@@ -331,7 +292,6 @@ To start OSPF process you have to specify the OSPF router.
in router-id and if user wants the router-id change to take effect, user can
use this cli instead of restarting the ospfd daemon.
-.. index:: clear ip ospf [(1-65535)] neighbor
.. clicmd:: clear ip ospf [(1-65535)] neighbor
This command can be used to clear the ospf neighbor data structures. This
@@ -344,17 +304,11 @@ To start OSPF process you have to specify the OSPF router.
Areas
-----
-.. index:: area A.B.C.D range A.B.C.D/M
.. clicmd:: area A.B.C.D range A.B.C.D/M
-.. index:: area (0-4294967295) range A.B.C.D/M
.. clicmd:: area (0-4294967295) range A.B.C.D/M
-.. index:: area A.B.C.D range A.B.C.D/M
-.. clicmd:: no area A.B.C.D range A.B.C.D/M
-.. index:: area (0-4294967295) range A.B.C.D/M
-.. clicmd:: no area (0-4294967295) range A.B.C.D/M
Summarize intra area paths from specified area into one Type-3 summary-LSA
announced to other areas. This command can be used only in ABR and ONLY
@@ -374,21 +328,15 @@ Areas
announced into backbone area if area 0.0.0.10 contains at least one intra-area
network (i.e. described with router or network LSA) from this range.
-.. index:: area A.B.C.D range IPV4_PREFIX not-advertise
.. clicmd:: area A.B.C.D range IPV4_PREFIX not-advertise
-.. index:: area A.B.C.D range IPV4_PREFIX not-advertise
-.. clicmd:: no area A.B.C.D range IPV4_PREFIX not-advertise
Instead of summarizing intra area paths filter them - i.e. intra area paths from this
range are not advertised into other areas.
This command makes sense in ABR only.
-.. index:: area A.B.C.D range IPV4_PREFIX substitute IPV4_PREFIX
.. clicmd:: area A.B.C.D range IPV4_PREFIX substitute IPV4_PREFIX
-.. index:: area A.B.C.D range IPV4_PREFIX substitute IPV4_PREFIX
-.. clicmd:: no area A.B.C.D range IPV4_PREFIX substitute IPV4_PREFIX
Substitute summarized prefix with another prefix.
@@ -405,44 +353,26 @@ Areas
network-LSA) from range 10.0.0.0/8.
This command makes sense in ABR only.
-.. index:: area A.B.C.D virtual-link A.B.C.D
.. clicmd:: area A.B.C.D virtual-link A.B.C.D
-.. index:: area (0-4294967295) virtual-link A.B.C.D
.. clicmd:: area (0-4294967295) virtual-link A.B.C.D
-.. index:: area A.B.C.D virtual-link A.B.C.D
-.. clicmd:: no area A.B.C.D virtual-link A.B.C.D
-.. index:: area (0-4294967295) virtual-link A.B.C.D
-.. clicmd:: no area (0-4294967295) virtual-link A.B.C.D
-.. index:: area A.B.C.D shortcut
.. clicmd:: area A.B.C.D shortcut
-.. index:: area (0-4294967295) shortcut
.. clicmd:: area (0-4294967295) shortcut
-.. index:: area A.B.C.D shortcut
-.. clicmd:: no area A.B.C.D shortcut
-.. index:: area (0-4294967295) shortcut
-.. clicmd:: no area (0-4294967295) shortcut
Configure the area as Shortcut capable. See :rfc:`3509`. This requires
that the 'abr-type' be set to 'shortcut'.
-.. index:: area A.B.C.D stub
.. clicmd:: area A.B.C.D stub
-.. index:: area (0-4294967295) stub
.. clicmd:: area (0-4294967295) stub
-.. index:: area A.B.C.D stub
-.. clicmd:: no area A.B.C.D stub
-.. index:: area (0-4294967295) stub
-.. clicmd:: no area (0-4294967295) stub
Configure the area to be a stub area. That is, an area where no router
originates routes external to OSPF and hence an area where all external
@@ -451,40 +381,25 @@ Areas
area. They need only pass Network-Summary (type-3) LSAs into such an area,
along with a default-route summary.
-.. index:: area A.B.C.D stub no-summary
.. clicmd:: area A.B.C.D stub no-summary
-.. index:: area (0-4294967295) stub no-summary
.. clicmd:: area (0-4294967295) stub no-summary
-.. index:: area A.B.C.D stub no-summary
-.. clicmd:: no area A.B.C.D stub no-summary
-.. index:: area (0-4294967295) stub no-summary
-.. clicmd:: no area (0-4294967295) stub no-summary
Prevents an *ospfd* ABR from injecting inter-area
summaries into the specified stub area.
-.. index:: area A.B.C.D default-cost (0-16777215)
.. clicmd:: area A.B.C.D default-cost (0-16777215)
-.. index:: area A.B.C.D default-cost (0-16777215)
-.. clicmd:: no area A.B.C.D default-cost (0-16777215)
Set the cost of default-summary LSAs announced to stubby areas.
-.. index:: area A.B.C.D export-list NAME
.. clicmd:: area A.B.C.D export-list NAME
-.. index:: area (0-4294967295) export-list NAME
.. clicmd:: area (0-4294967295) export-list NAME
-.. index:: area A.B.C.D export-list NAME
-.. clicmd:: no area A.B.C.D export-list NAME
-.. index:: area (0-4294967295) export-list NAME
-.. clicmd:: no area (0-4294967295) export-list NAME
Filter Type-3 summary-LSAs announced to other areas originated from intra-
area paths from specified area.
@@ -507,67 +422,41 @@ Areas
This command is only relevant if the router is an ABR for the specified
area.
-.. index:: area A.B.C.D import-list NAME
.. clicmd:: area A.B.C.D import-list NAME
-.. index:: area (0-4294967295) import-list NAME
.. clicmd:: area (0-4294967295) import-list NAME
-.. index:: area A.B.C.D import-list NAME
-.. clicmd:: no area A.B.C.D import-list NAME
-.. index:: area (0-4294967295) import-list NAME
-.. clicmd:: no area (0-4294967295) import-list NAME
Same as export-list, but it applies to paths announced into specified area
as Type-3 summary-LSAs.
-.. index:: area A.B.C.D filter-list prefix NAME in
.. clicmd:: area A.B.C.D filter-list prefix NAME in
-.. index:: area A.B.C.D filter-list prefix NAME out
.. clicmd:: area A.B.C.D filter-list prefix NAME out
-.. index:: area (0-4294967295) filter-list prefix NAME in
.. clicmd:: area (0-4294967295) filter-list prefix NAME in
-.. index:: area (0-4294967295) filter-list prefix NAME out
.. clicmd:: area (0-4294967295) filter-list prefix NAME out
-.. index:: area A.B.C.D filter-list prefix NAME in
-.. clicmd:: no area A.B.C.D filter-list prefix NAME in
-.. index:: area A.B.C.D filter-list prefix NAME out
-.. clicmd:: no area A.B.C.D filter-list prefix NAME out
-.. index:: area (0-4294967295) filter-list prefix NAME in
-.. clicmd:: no area (0-4294967295) filter-list prefix NAME in
-.. index:: area (0-4294967295) filter-list prefix NAME out
-.. clicmd:: no area (0-4294967295) filter-list prefix NAME out
Filtering Type-3 summary-LSAs to/from area using prefix lists. This command
makes sense in ABR only.
-.. index:: area A.B.C.D authentication
.. clicmd:: area A.B.C.D authentication
-.. index:: area (0-4294967295) authentication
.. clicmd:: area (0-4294967295) authentication
-.. index:: area A.B.C.D authentication
-.. clicmd:: no area A.B.C.D authentication
-.. index:: area (0-4294967295) authentication
-.. clicmd:: no area (0-4294967295) authentication
Specify that simple password authentication should be used for the given
area.
-.. index:: area A.B.C.D authentication message-digest
.. clicmd:: area A.B.C.D authentication message-digest
-.. index:: area (0-4294967295) authentication message-digest
.. clicmd:: area (0-4294967295) authentication message-digest
Specify that OSPF packets must be authenticated with MD5 HMACs within the
@@ -583,11 +472,8 @@ Areas
Interfaces
----------
-.. index:: ip ospf area AREA [ADDR]
.. clicmd:: ip ospf area AREA [ADDR]
-.. index:: ip ospf area [ADDR]
-.. clicmd:: no ip ospf area [ADDR]
Enable OSPF on the interface, optionally restricted to just the IP address
given by `ADDR`, putting it in the `AREA` area. Per interface area settings
@@ -597,11 +483,8 @@ Interfaces
If you have a lot of interfaces, and/or a lot of subnets, then enabling OSPF
via this command may result in a slight performance improvement.
-.. index:: ip ospf authentication-key AUTH_KEY
.. clicmd:: ip ospf authentication-key AUTH_KEY
-.. index:: ip ospf authentication-key
-.. clicmd:: no ip ospf authentication-key
Set OSPF authentication key to a simple password. After setting `AUTH_KEY`,
all OSPF packets are authenticated. `AUTH_KEY` has length up to 8 chars.
@@ -609,7 +492,6 @@ Interfaces
Simple text password authentication is insecure and deprecated in favour of
MD5 HMAC authentication.
-.. index:: ip ospf authentication message-digest
.. clicmd:: ip ospf authentication message-digest
Specify that MD5 HMAC authentication must be used on this interface. MD5
@@ -626,11 +508,8 @@ Interfaces
non-volatile storage and restored at boot if MD5 authentication is to be
expected to work reliably.
-.. index:: ip ospf message-digest-key KEYID md5 KEY
.. clicmd:: ip ospf message-digest-key KEYID md5 KEY
-.. index:: ip ospf message-digest-key
-.. clicmd:: no ip ospf message-digest-key
Set OSPF authentication key to a cryptographic password. The cryptographic
algorithm is MD5.
@@ -641,23 +520,16 @@ Interfaces
KEY is the actual message digest key, of up to 16 chars (larger strings will
be truncated), and is associated with the given KEYID.
-.. index:: ip ospf cost (1-65535)
.. clicmd:: ip ospf cost (1-65535)
-.. index:: ip ospf cost
-.. clicmd:: no ip ospf cost
Set link cost for the specified interface. The cost value is set to
router-LSA's metric field and used for SPF calculation.
-.. index:: ip ospf dead-interval (1-65535)
.. clicmd:: ip ospf dead-interval (1-65535)
-.. index:: ip ospf dead-interval minimal hello-multiplier (2-20)
.. clicmd:: ip ospf dead-interval minimal hello-multiplier (2-20)
-.. index:: ip ospf dead-interval
-.. clicmd:: no ip ospf dead-interval
Set number of seconds for RouterDeadInterval timer value used for Wait Timer
and Inactivity Timer. This value must be the same for all routers attached
@@ -672,11 +544,8 @@ Interfaces
hello-multiplier need NOT be the same across multiple routers on a common
link.
-.. index:: ip ospf hello-interval (1-65535)
.. clicmd:: ip ospf hello-interval (1-65535)
-.. index:: ip ospf hello-interval
-.. clicmd:: no ip ospf hello-interval
Set number of seconds for HelloInterval timer value. Setting this value,
Hello packet will be sent every timer value seconds on the specified interface.
@@ -687,7 +556,6 @@ Interfaces
:clicmd:`ip ospf dead-interval minimal hello-multiplier (2-20)` is also
specified for the interface.
-.. index:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)
.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)
When configuring a point-to-point network on an interface and the interface
@@ -696,45 +564,31 @@ Interfaces
net.ipv4.conf.<interface name>.rp_filter value to 0. In order for
the ospf multicast packets to be delivered by the kernel.
-.. index:: ip ospf network
-.. clicmd:: no ip ospf network
Set explicitly network type for specified interface.
-.. index:: ip ospf priority (0-255)
.. clicmd:: ip ospf priority (0-255)
-.. index:: ip ospf priority
-.. clicmd:: no ip ospf priority
Set RouterPriority integer value. The router with the highest priority will
be more eligible to become Designated Router. Setting the value to 0, makes
the router ineligible to become Designated Router. The default value is 1.
-.. index:: ip ospf retransmit-interval (1-65535)
.. clicmd:: ip ospf retransmit-interval (1-65535)
-.. index:: ip ospf retransmit interval
-.. clicmd:: no ip ospf retransmit interval
Set number of seconds for RxmtInterval timer value. This value is used when
retransmitting Database Description and Link State Request packets. The
default value is 5 seconds.
-.. index:: ip ospf transmit-delay (1-65535) [A.B.C.D]
.. clicmd:: ip ospf transmit-delay (1-65535) [A.B.C.D]
-.. index:: ip ospf transmit-delay [(1-65535)] [A.B.C.D]
-.. clicmd:: no ip ospf transmit-delay [(1-65535)] [A.B.C.D]
Set number of seconds for InfTransDelay value. LSAs' age should be
incremented by this value when transmitting. The default value is 1 second.
-.. index:: ip ospf area (A.B.C.D|(0-4294967295))
.. clicmd:: ip ospf area (A.B.C.D|(0-4294967295))
-.. index:: ip ospf area
-.. clicmd:: no ip ospf area
Enable ospf on an interface and set associated area.
@@ -743,7 +597,6 @@ OSPF route-map
Usage of *ospfd*'s route-map support.
-.. index:: set metric [+|-](0-4294967295)
.. clicmd:: set metric [+|-](0-4294967295)
Set a metric for matched route when sending announcement. Use plus (+) sign
@@ -755,35 +608,10 @@ Usage of *ospfd*'s route-map support.
Redistribution
--------------
-.. index:: redistribute (kernel|connected|static|rip|bgp)
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp)
-
-.. index:: redistribute (kernel|connected|static|rip|bgp) ROUTE-MAP
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp) ROUTE-MAP
-
-.. index:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2)
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2)
-
-.. index:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) route-map WORD
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) route-map WORD
-
-.. index:: redistribute (kernel|connected|static|rip|bgp) metric (0-16777214)
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp) metric (0-16777214)
-
-.. index:: redistribute (kernel|connected|static|rip|bgp) metric (0-16777214) route-map WORD
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp) metric (0-16777214) route-map WORD
-
-.. index:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric (0-16777214)
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric (0-16777214)
-
-.. index:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric (0-16777214) route-map WORD
-.. clicmd:: redistribute (kernel|connected|static|rip|bgp) metric-type (1|2) metric (0-16777214) route-map WORD
-
-.. index:: redistribute (kernel|connected|static|rip|bgp)
-.. clicmd:: no redistribute (kernel|connected|static|rip|bgp)
-
.. _ospf-redistribute:
+.. clicmd:: redistribute <babel|bgp|connected|eigrp|isis|kernel|openfabric|ospf|rip|sharp|static|table> [metric-type (1-2)] [metric (0-16777214)] [route-map WORD]
+
Redistribute routes of the specified protocol or kind into OSPF, with the
metric type and metric set if specified, filtering the routes using the
given route-map if specified. Redistributed routes may also be filtered
@@ -802,43 +630,30 @@ Redistribution
clicmd:`passive-interface INTERFACE`.
-.. index:: default-information originate
.. clicmd:: default-information originate
-.. index:: default-information originate metric (0-16777214)
.. clicmd:: default-information originate metric (0-16777214)
-.. index:: default-information originate metric (0-16777214) metric-type (1|2)
.. clicmd:: default-information originate metric (0-16777214) metric-type (1|2)
-.. index:: default-information originate metric (0-16777214) metric-type (1|2) route-map WORD
.. clicmd:: default-information originate metric (0-16777214) metric-type (1|2) route-map WORD
-.. index:: default-information originate always
.. clicmd:: default-information originate always
-.. index:: default-information originate always metric (0-16777214)
.. clicmd:: default-information originate always metric (0-16777214)
-.. index:: default-information originate always metric (0-16777214) metric-type (1|2)
.. clicmd:: default-information originate always metric (0-16777214) metric-type (1|2)
-.. index:: default-information originate always metric (0-16777214) metric-type (1|2) route-map WORD
.. clicmd:: default-information originate always metric (0-16777214) metric-type (1|2) route-map WORD
-.. index:: default-information originate
-.. clicmd:: no default-information originate
Originate an AS-External (type-5) LSA describing a default route into all
external-routing capable areas, of the specified metric and metric type. If
the 'always' keyword is given then the default is always advertised, even
when there is no default present in the routing table.
-.. index:: distribute-list NAME out (kernel|connected|static|rip|ospf
.. clicmd:: distribute-list NAME out (kernel|connected|static|rip|ospf
-.. index:: distribute-list NAME out (kernel|connected|static|rip|ospf
-.. clicmd:: no distribute-list NAME out (kernel|connected|static|rip|ospf
.. _ospf-distribute-list:
@@ -846,38 +661,21 @@ Redistribution
type before allowing the routes to redistributed into OSPF
(:ref:`ospf redistribution <ospf-redistribute>`).
-.. index:: default-metric (0-16777214)
.. clicmd:: default-metric (0-16777214)
-.. index:: default-metric
-.. clicmd:: no default-metric
-.. index:: distance (1-255)
.. clicmd:: distance (1-255)
-.. index:: distance (1-255)
-.. clicmd:: no distance (1-255)
-.. index:: distance ospf (intra-area|inter-area|external) (1-255)
.. clicmd:: distance ospf (intra-area|inter-area|external) (1-255)
-.. index:: distance ospf
-.. clicmd:: no distance ospf
-
-.. index:: router zebra
-.. clicmd:: router zebra
-.. index:: router zebra
-.. clicmd:: no router zebra
Graceful Restart Helper
=======================
-.. index:: graceful-restart helper-only [A.B.C.D]
.. clicmd:: graceful-restart helper-only [A.B.C.D]
-.. index:: graceful-restart helper-only [A.B.C.D]
-.. clicmd:: no graceful-restart helper-only [A.B.C.D]
Configure Graceful Restart (RFC 3623) helper support.
By default, helper support is disabled for all neighbours.
@@ -886,30 +684,21 @@ Graceful Restart Helper
To enable/disable helper support for a specific
neighbour, the router-id (A.B.C.D) has to be specified.
-.. index:: graceful-restart helper strict-lsa-checking
.. clicmd:: graceful-restart helper strict-lsa-checking
-.. index:: graceful-restart helper strict-lsa-checking
-.. clicmd:: no graceful-restart helper strict-lsa-checking
If 'strict-lsa-checking' is configured then the helper will
abort the Graceful Restart when a LSA change occurs which
affects the restarting router.
By default 'strict-lsa-checking' is enabled"
-.. index:: graceful-restart helper supported-grace-time
.. clicmd:: graceful-restart helper supported-grace-time
-.. index:: graceful-restart helper supported-grace-time
-.. clicmd:: no graceful-restart helper supported-grace-time
Supports as HELPER for configured grace period.
-.. index:: graceful-restart helper planned-only
.. clicmd:: graceful-restart helper planned-only
-.. index:: graceful-restart helper planned-only
-.. clicmd:: no graceful-restart helper planned-only
It helps to support as HELPER only for planned
restarts. By default, it supports both planned and
@@ -922,68 +711,51 @@ Showing Information
.. _show-ip-ospf:
-.. index:: show ip ospf [json]
.. clicmd:: show ip ospf [json]
Show information on a variety of general OSPF and area state and
configuration information.
-.. index:: show ip ospf interface [INTERFACE] [json]
.. clicmd:: show ip ospf interface [INTERFACE] [json]
Show state and configuration of OSPF the specified interface, or all
interfaces if no interface is given.
-.. index:: show ip ospf neighbor [json]
.. clicmd:: show ip ospf neighbor [json]
-.. index:: show ip ospf neighbor INTERFACE [json]
.. clicmd:: show ip ospf neighbor INTERFACE [json]
-.. index:: show ip ospf neighbor detail [json]
.. clicmd:: show ip ospf neighbor detail [json]
-.. index:: show ip ospf neighbor INTERFACE detail [json]
.. clicmd:: show ip ospf neighbor INTERFACE detail [json]
Display lsa information of LSDB.
Json o/p of this command covers base route information
i.e all LSAs except opaque lsa info.
-.. index:: show ip ospf database [json]
.. clicmd:: show ip ospf database [json]
-.. index:: show ip ospf database (asbr-summary|external|network|router|summary) [json]
.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) [json]
-.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID [json]
.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID [json]
-.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID adv-router ADV-ROUTER [json]
.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID adv-router ADV-ROUTER [json]
-.. index:: show ip ospf database (asbr-summary|external|network|router|summary) adv-router ADV-ROUTER [json]
.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) adv-router ADV-ROUTER [json]
-.. index:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID self-originate [json]
.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) LINK-STATE-ID self-originate [json]
-.. index:: show ip ospf database (asbr-summary|external|network|router|summary) self-originate [json]
.. clicmd:: show ip ospf database (asbr-summary|external|network|router|summary) self-originate [json]
-.. index:: show ip ospf database max-age [json]
.. clicmd:: show ip ospf database max-age [json]
-.. index:: show ip ospf database self-originate [json]
.. clicmd:: show ip ospf database self-originate [json]
-.. index:: show ip ospf route [json]
.. clicmd:: show ip ospf route [json]
Show the OSPF routing table, as determined by the most recent SPF
calculation.
-.. index:: show ip ospf graceful-restart helper [detail] [json]
.. clicmd:: show ip ospf graceful-restart helper [detail] [json]
Displays the Grcaeful Restart Helper details including helper
@@ -994,17 +766,11 @@ Showing Information
Opaque LSA
==========
-.. index:: ospf opaque-lsa
.. clicmd:: ospf opaque-lsa
-.. index:: capability opaque
.. clicmd:: capability opaque
-.. index:: ospf opaque-lsa
-.. clicmd:: no ospf opaque-lsa
-.. index:: capability opaque
-.. clicmd:: no capability opaque
*ospfd* supports Opaque LSA (:rfc:`2370`) as partial support for
MPLS Traffic Engineering LSAs. The opaque-lsa capability must be
@@ -1014,22 +780,16 @@ Opaque LSA
extensions that are used with MPLS-TE; it does not support a
complete RSVP-TE solution.
-.. index:: show ip ospf database (opaque-link|opaque-area|opaque-external)
.. clicmd:: show ip ospf database (opaque-link|opaque-area|opaque-external)
-.. index:: show ip ospf database (opaque-link|opaque-area|opaque-external) LINK-STATE-ID
.. clicmd:: show ip ospf database (opaque-link|opaque-area|opaque-external) LINK-STATE-ID
-.. index:: show ip ospf database (opaque-link|opaque-area|opaque-external) LINK-STATE-ID adv-router ADV-ROUTER
.. clicmd:: show ip ospf database (opaque-link|opaque-area|opaque-external) LINK-STATE-ID adv-router ADV-ROUTER
-.. index:: show ip ospf database (opaque-link|opaque-area|opaque-external) adv-router ADV-ROUTER
.. clicmd:: show ip ospf database (opaque-link|opaque-area|opaque-external) adv-router ADV-ROUTER
-.. index:: show ip ospf database (opaque-link|opaque-area|opaque-external) LINK-STATE-ID self-originate
.. clicmd:: show ip ospf database (opaque-link|opaque-area|opaque-external) LINK-STATE-ID self-originate
-.. index:: show ip ospf database (opaque-link|opaque-area|opaque-external) self-originate
.. clicmd:: show ip ospf database (opaque-link|opaque-area|opaque-external) self-originate
Show Opaque LSA from the database.
@@ -1045,40 +805,30 @@ Traffic Engineering
protocol extensions that can be used with MPLS-TE. FRR does not
support a complete RSVP-TE solution currently.
-.. index:: mpls-te on
.. clicmd:: mpls-te on
-.. index:: mpls-te
-.. clicmd:: no mpls-te
Enable Traffic Engineering LSA flooding.
-.. index:: mpls-te router-address <A.B.C.D>
.. clicmd:: mpls-te router-address <A.B.C.D>
Configure stable IP address for MPLS-TE. This IP address is then advertise
in Opaque LSA Type-10 TLV=1 (TE) option 1 (Router-Address).
-.. index:: mpls-te inter-as area <area-id>|as
.. clicmd:: mpls-te inter-as area <area-id>|as
-.. index:: mpls-te inter-as
-.. clicmd:: no mpls-te inter-as
Enable :rfc:`5392` support - Inter-AS TE v2 - to flood Traffic Engineering
parameters of Inter-AS link. 2 modes are supported: AREA and AS; LSA are
flood in AREA <area-id> with Opaque Type-10, respectively in AS with Opaque
Type-11. In all case, Opaque-LSA TLV=6.
-.. index:: show ip ospf mpls-te interface
.. clicmd:: show ip ospf mpls-te interface
-.. index:: show ip ospf mpls-te interface INTERFACE
.. clicmd:: show ip ospf mpls-te interface INTERFACE
Show MPLS Traffic Engineering parameters for all or specified interface.
-.. index:: show ip ospf mpls-te router
.. clicmd:: show ip ospf mpls-te router
Show Traffic Engineering router parameters.
@@ -1088,11 +838,8 @@ Traffic Engineering
Router Information
==================
-.. index:: router-info [as | area]
.. clicmd:: router-info [as | area]
-.. index:: router-info
-.. clicmd:: no router-info
Enable Router Information (:rfc:`4970`) LSA advertisement with AS scope
(default) or Area scope flooding when area is specified. Old syntax
@@ -1100,35 +847,20 @@ Router Information
as the area ID is no more necessary. Indeed, router information support
multi-area and detect automatically the areas.
-.. index:: pce address <A.B.C.D>
.. clicmd:: pce address <A.B.C.D>
-.. index:: pce address
-.. clicmd:: no pce address
-.. index:: pce domain as (0-65535)
.. clicmd:: pce domain as (0-65535)
-.. index:: pce domain as (0-65535)
-.. clicmd:: no pce domain as (0-65535)
-.. index:: pce neighbor as (0-65535)
.. clicmd:: pce neighbor as (0-65535)
-.. index:: pce neighbor as (0-65535)
-.. clicmd:: no pce neighbor as (0-65535)
-.. index:: pce flag BITPATTERN
.. clicmd:: pce flag BITPATTERN
-.. index:: pce flag
-.. clicmd:: no pce flag
-.. index:: pce scope BITPATTERN
.. clicmd:: pce scope BITPATTERN
-.. index:: pce scope
-.. clicmd:: no pce scope
The commands are conform to :rfc:`5088` and allow OSPF router announce Path
Computation Element (PCE) capabilities through the Router Information (RI)
@@ -1138,12 +870,10 @@ Router Information
refer to :rfc`5088` for the BITPATTERN recognition. Multiple 'pce neighbor'
command could be specified in order to specify all PCE neighbours.
-.. index:: show ip ospf router-info
.. clicmd:: show ip ospf router-info
Show Router Capabilities flag.
-.. index:: show ip ospf router-info pce
.. clicmd:: show ip ospf router-info pce
Show Router Capabilities PCE parameters.
@@ -1156,42 +886,35 @@ Segment Routing
This is an EXPERIMENTAL support of Segment Routing as per `RFC 8665` for MPLS
dataplane.
-.. index:: segment-routing on
-.. clicmd:: [no] segment-routing on
+.. clicmd:: segment-routing on
Enable Segment Routing. Even if this also activate routing information
support, it is preferable to also activate routing information, and set
accordingly the Area or AS flooding.
-.. index:: segment-routing global-block (0-1048575) (0-1048575)
-.. clicmd:: [no] segment-routing global-block (0-1048575) (0-1048575)
+.. clicmd:: segment-routing global-block (0-1048575) (0-1048575)
Fix the Segment Routing Global Block i.e. the label range used by MPLS to
store label in the MPLS FIB for Prefix SID.
-.. index:: segment-routing local-block (0-1048575) (0-1048575)
-.. clicmd:: [no] segment-routing local-block (0-1048575) (0-1048575)
+.. clicmd:: segment-routing local-block (0-1048575) (0-1048575)
Fix the Segment Routing Local Block i.e. the label range used by MPLS to
store label in the MPLS FIB for Adjacency SID.
-.. index:: segment-routing node-msd (1-16)
-.. clicmd:: [no] segment-routing node-msd (1-16)
+.. clicmd:: segment-routing node-msd (1-16)
Fix the Maximum Stack Depth supported by the router. The value depend of the
MPLS dataplane. E.g. for Linux kernel, since version 4.13 it is 32.
-.. index:: segment-routing prefix A.B.C.D/M index (0-65535) [no-php-flag|explicit-null]
-.. clicmd:: [no] segment-routing prefix A.B.C.D/M [index (0-65535)|no-php-flag|explicit-null]
+.. clicmd:: segment-routing prefix A.B.C.D/M [index (0-65535)|no-php-flag|explicit-null]
- Set the Segment Routing index for the specified prefix. Note that, only
prefix with /32 corresponding to a loopback interface are currently
supported. The 'no-php-flag' means NO Penultimate Hop Popping that allows SR
node to request to its neighbor to not pop the label. The 'explicit-null' means that
neighbor nodes must swap the incoming label by the MPLS Explicit Null label
before delivering the packet.
-.. index:: show ip ospf database segment-routing <adv-router ADVROUTER|self-originate> [json]
.. clicmd:: show ip ospf database segment-routing <adv-router ADVROUTER|self-originate> [json]
Show Segment Routing Data Base, all SR nodes, specific advertised router or
@@ -1203,31 +926,25 @@ External Route Summarisation
This feature summarises originated external LSAs(Type-5 and Type-7).
Summary Route will be originated on-behalf of all matched external LSAs.
-.. index:: summary-address A.B.C.D/M [tag (1-4294967295)]
-.. clicmd:: [no] summary-address A.B.C.D/M [tag (1-4294967295)]
+.. clicmd:: summary-address A.B.C.D/M [tag (1-4294967295)]
This command enable/disables summarisation for the configured address
range. Tag is the optional parameter. If tag configured Summary route
will be originated with the configured tag.
-.. index:: summary-address A.B.C.D/M no-advertise
-.. clicmd:: [no] summary-address A.B.C.D/M no-advertise
+.. clicmd:: summary-address A.B.C.D/M no-advertise
This command to ensure not advertise the summary lsa for the matched
external LSAs.
-.. index:: aggregation timer (5-1800)
.. clicmd:: aggregation timer (5-1800)
Configure aggregation delay timer interval. Summarisation starts only after
this delay timer expiry. By default, delay interval is 5 secs.
-.. index:: aggregation timer
-.. clicmd:: no aggregation timer
Resetting the aggregation delay interval to default value.
-.. index:: show ip ospf [vrf <NAME|all>] summary-address [detail] [json]
.. clicmd:: show ip ospf [vrf <NAME|all>] summary-address [detail] [json]
Show configuration for display all configured summary routes with
@@ -1240,7 +957,6 @@ Experimental support for Topology Independent LFA (Loop-Free Alternate), see
for example 'draft-bashandy-rtgwg-segment-routing-ti-lfa-05'. Note that
TI-LFA requires a proper Segment Routing configuration.
-.. index:: fast-reroute ti-lfa [node-protection]
.. clicmd:: fast-reroute ti-lfa [node-protection]
Configured on the router level. Activates TI-LFA for all interfaces.
@@ -1250,107 +966,66 @@ TI-LFA requires a proper Segment Routing configuration.
Debugging OSPF
==============
-.. index:: debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
.. clicmd:: debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
-.. index:: debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
-.. clicmd:: no debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
Dump Packet for debugging
-.. index:: debug ospf ism
.. clicmd:: debug ospf ism
-.. index:: debug ospf ism (status|events|timers)
.. clicmd:: debug ospf ism (status|events|timers)
-.. index:: debug ospf ism
-.. clicmd:: no debug ospf ism
-.. index:: debug ospf ism (status|events|timers)
-.. clicmd:: no debug ospf ism (status|events|timers)
Show debug information of Interface State Machine
-.. index:: debug ospf nsm
.. clicmd:: debug ospf nsm
-.. index:: debug ospf nsm (status|events|timers)
.. clicmd:: debug ospf nsm (status|events|timers)
-.. index:: debug ospf nsm
-.. clicmd:: no debug ospf nsm
-.. index:: debug ospf nsm (status|events|timers)
-.. clicmd:: no debug ospf nsm (status|events|timers)
Show debug information of Network State Machine
-.. index:: debug ospf event
.. clicmd:: debug ospf event
-.. index:: debug ospf event
-.. clicmd:: no debug ospf event
Show debug information of OSPF event
-.. index:: debug ospf nssa
.. clicmd:: debug ospf nssa
-.. index:: debug ospf nssa
-.. clicmd:: no debug ospf nssa
Show debug information about Not So Stub Area
-.. index:: debug ospf lsa
.. clicmd:: debug ospf lsa
-.. index:: debug ospf lsa (generate|flooding|refresh)
.. clicmd:: debug ospf lsa (generate|flooding|refresh)
-.. index:: debug ospf lsa
-.. clicmd:: no debug ospf lsa
-.. index:: debug ospf lsa (generate|flooding|refresh)
-.. clicmd:: no debug ospf lsa (generate|flooding|refresh)
Show debug detail of Link State messages
-.. index:: debug ospf te
.. clicmd:: debug ospf te
-.. index:: debug ospf te
-.. clicmd:: no debug ospf te
Show debug information about Traffic Engineering LSA
-.. index:: debug ospf zebra
.. clicmd:: debug ospf zebra
-.. index:: debug ospf zebra (interface|redistribute)
.. clicmd:: debug ospf zebra (interface|redistribute)
-.. index:: debug ospf zebra
-.. clicmd:: no debug ospf zebra
-.. index:: debug ospf zebra (interface|redistribute)
-.. clicmd:: no debug ospf zebra (interface|redistribute)
Show debug information of ZEBRA API
-.. index:: debug ospf graceful-restart helper
.. clicmd:: debug ospf graceful-restart helper
-.. index:: debug ospf graceful-restart helper
-.. clicmd:: no debug ospf graceful-restart helper
Enable/disable debug information for OSPF Graceful Restart Helper
-.. index:: show debugging ospf
.. clicmd:: show debugging ospf
-.. index:: debug ospf lsa aggregate
-.. clicmd:: [no] debug ospf lsa aggregate
+.. clicmd:: debug ospf lsa aggregate
Debug commnd to enable/disable external route summarisation specific debugs.
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index f67698e404..b4f56260c9 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -62,9 +62,8 @@ Feature support varies by platform; see the :ref:`feature-matrix`.
System Architecture
-------------------
-.. index:: System architecture
-.. index:: Software architecture
-.. index:: Software internals
+.. index::
+ pair: architecture; FRR
Traditional routing software is made as a one process program which provides
all of the routing protocol functionalities. FRR takes a different approach.
@@ -114,15 +113,15 @@ data models. When this work is completed, FRR will be a fully programmable
routing stack.
+.. index::
+ pair: platforms; FRR
+ pair: operating systems; FRR
+
.. _supported-platforms:
Supported Platforms
-------------------
-.. index:: Supported platforms
-.. index:: FRR on other systems
-.. index:: Compatibility with other systems
-.. index:: Operating systems that support FRR
Currently FRR supports GNU/Linux and BSD. Porting FRR to other platforms is not
too difficult as platform dependent code should be mostly limited to the
@@ -149,11 +148,9 @@ Recent versions of the following compilers are well tested:
.. _unsupported-platforms:
-UnSupported Platforms
+Unsupported Platforms
---------------------
-.. index:: UnSupported platforms
-
In General if the platform you are attempting to use is not listed above then
FRR does not support being run on that platform. The only caveat here is that
version 7.5 and before Solaris was supported in a limited fashion.
@@ -264,6 +261,10 @@ Known Kernel Issues
especially becomes apparent if the route is being transformed from one ECMP
path to another.
+
+.. index::
+ pair: rfcs; FRR
+
.. _supported-rfcs:
Supported RFCs
@@ -341,6 +342,8 @@ BGP
:t:`Default External BGP (EBGP) Route Propagation Behavior without Policies. J. Mauch, J. Snijders, G. Hankins. July 2017`
- :rfc:`8277`
:t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017`
+- :rfc:`8654`
+ :t:`Extended Message Support for BGP. R. Bush, K. Patel, D. Ward. October 2019`
OSPF
@@ -439,13 +442,14 @@ SNMP
- :rfc:`2741`
:t:`Agent Extensibility (AgentX) Protocol. M. Daniele, B. Wijnen. January 2000.`
-Mailing Lists
-=============
-.. index:: How to get in touch with FRR
-.. index:: Contact information
-.. index:: Mailing lists
+.. index::
+ pair: mailing lists; contact
+.. _mailing-lists:
+
+Mailing Lists
+=============
Italicized lists are private.
@@ -471,6 +475,7 @@ results of such discussions are reflected in updates, as appropriate, to code
changes, updates to the Development list and either this file or information
posted at `FRR`_.
+
Bug Reports
===========
diff --git a/doc/user/pathd.rst b/doc/user/pathd.rst
index 0815a6c414..fe50a5e7eb 100644
--- a/doc/user/pathd.rst
+++ b/doc/user/pathd.rst
@@ -105,72 +105,59 @@ Example:
Configuration Commands
----------------------
-.. index:: segment-routing
.. clicmd:: segment-routing
Configure segment routing.
-.. index:: traffic-eng
.. clicmd:: traffic-eng
Configure segment routing traffic engineering.
-.. index:: segment-list NAME
-.. clicmd:: [no] segment-list NAME
+.. clicmd:: segment-list NAME
Delete or start a segment list definition.
-
-.. index:: index INDEX mpls label LABEL [nai node ADDRESS]
-.. clicmd:: [no] index INDEX mpls label LABEL [nai node ADDRESS]
+.. clicmd:: index INDEX mpls label LABEL [nai node ADDRESS]
Delete or specify a segment in a segment list definition.
-.. index:: policy color COLOR endpoint ENDPOINT
-.. clicmd:: [no] policy color COLOR endpoint ENDPOINT
+.. clicmd:: policy color COLOR endpoint ENDPOINT
Delete or start a policy definition.
-.. index:: name NAME
.. clicmd:: name NAME
Specify the policy name.
-.. index:: binding-sid LABEL
.. clicmd:: binding-sid LABEL
Specify the policy SID.
-.. index:: candidate-path preference PREFERENCE name NAME explicit segment-list SEGMENT-LIST-NAME
-.. clicmd:: [no] candidate-path preference PREFERENCE name NAME explicit segment-list SEGMENT-LIST-NAME
+.. clicmd:: candidate-path preference PREFERENCE name NAME explicit segment-list SEGMENT-LIST-NAME
Delete or define an explicit candidate path.
-.. index:: candidate-path preference PREFERENCE name NAME dynamic
-.. clicmd:: [no] candidate-path preference PREFERENCE name NAME dynamic
+.. clicmd:: candidate-path preference PREFERENCE name NAME dynamic
Delete or start a dynamic candidate path definition.
-.. index:: affinity {exclude-any|include-any|include-all} BITPATTERN
-.. clicmd:: [no] affinity {exclude-any|include-any|include-all} BITPATTERN
+.. clicmd:: affinity {exclude-any|include-any|include-all} BITPATTERN
Delete or specify an affinity constraint for a dynamic candidate path.
-.. index:: bandwidth BANDWIDTH [required]
-.. clicmd:: [no] bandwidth BANDWIDTH [required]
+.. clicmd:: bandwidth BANDWIDTH [required]
Delete or specify a bandwidth constraint for a dynamic candidate path.
-.. index:: metric [bound] METRIC VALUE [required]
-.. clicmd:: [no] metric [bound] METRIC VALUE [required]
+.. clicmd:: metric [bound] METRIC VALUE [required]
Delete or specify a metric constraint for a dynamic candidate path.
@@ -198,8 +185,7 @@ Configuration Commands
- bnc: Border Node Count metric
-.. index:: objective-function OBJFUN1 [required]
-.. clicmd:: [no] objective-function OBJFUN1 [required]
+.. clicmd:: objective-function OBJFUN1 [required]
Delete or specify a PCEP objective function constraint for a dynamic
candidate path.
@@ -224,8 +210,7 @@ Configuration Commands
- msn: Minimize the number of Shared Nodes [RFC8800]
-.. index:: debug pathd pcep [basic|path|message|pceplib]
-.. clicmd:: [no] debug pathd pcep [basic|path|message|pceplib]
+.. clicmd:: debug pathd pcep [basic|path|message|pceplib]
Enable or disable debugging for the pcep module:
@@ -235,33 +220,28 @@ Configuration Commands
- pceplib: Enable pceplib logging
-.. index:: pcep
.. clicmd:: pcep
Configure PCEP support.
-.. index:: cep-config NAME
-.. clicmd:: [no] pce-config NAME
+.. clicmd:: pce-config NAME
Define a shared PCE configuration that can be used in multiple PCE
declarations.
-.. index:: pce NAME
-.. clicmd:: [no] pce NAME
+.. clicmd:: pce NAME
Define or delete a PCE definition.
-.. index:: config WORD
.. clicmd:: config WORD
Select a shared configuration. If not defined, the default
configuration will be used.
-.. index:: address <ip A.B.C.D | ipv6 X:X::X:X> [port (1024-65535)]
.. clicmd:: address <ip A.B.C.D | ipv6 X:X::X:X> [port (1024-65535)]
Define the address and port of the PCE.
@@ -271,7 +251,6 @@ Configuration Commands
This should be specified in the PCC peer definition.
-.. index:: source-address [ip A.B.C.D | ipv6 X:X::X:X] [port PORT]
.. clicmd:: source-address [ip A.B.C.D | ipv6 X:X::X:X] [port PORT]
Define the address and/or port of the PCC as seen by the PCE.
@@ -284,7 +263,6 @@ Configuration Commands
configuration group.
-.. index:: tcp-md5-auth WORD
.. clicmd:: tcp-md5-auth WORD
Enable TCP MD5 security with the given secret.
@@ -293,7 +271,6 @@ Configuration Commands
configuration group.
-.. index:: sr-draft07
.. clicmd:: sr-draft07
Specify if a PCE only support segment routing draft 7, this flag will limit
@@ -303,7 +280,6 @@ Configuration Commands
configuration group.
-.. index:: pce-initiated
.. clicmd:: pce-initiated
Specify if PCE-initiated LSP should be allowed for this PCE.
@@ -312,7 +288,6 @@ Configuration Commands
configuration group.
-.. index:: timer [keep-alive (1-63)] [min-peer-keep-alive (1-255)] [max-peer-keep-alive (1-255)] [dead-timer (4-255)] [min-peer-dead-timer (4-255)] [max-peer-dead-timer (4-255)] [pcep-request (1-120)] [session-timeout-interval (1-120)] [delegation-timeout (1-60)]
.. clicmd:: timer [keep-alive (1-63)] [min-peer-keep-alive (1-255)] [max-peer-keep-alive (1-255)] [dead-timer (4-255)] [min-peer-dead-timer (4-255)] [max-peer-dead-timer (4-255)] [pcep-request (1-120)] [session-timeout-interval (1-120)] [delegation-timeout (1-60)]
Specify the PCEP timers.
@@ -321,20 +296,17 @@ Configuration Commands
configuration group.
-.. index:: pcc
-.. clicmd:: [no] pcc
+.. clicmd:: pcc
Disable or start the definition of a PCC.
-.. index:: msd (1-32)
.. clicmd:: msd (1-32)
Specify the maximum SID depth in a PCC definition.
-.. index:: peer WORD [precedence (1-255)]
-.. clicmd:: [no] peer WORD [precedence (1-255)]
+.. clicmd:: peer WORD [precedence (1-255)]
Specify a peer and its precedence in a PCC definition.
@@ -342,7 +314,6 @@ Configuration Commands
Introspection Commands
----------------------
-.. index:: show sr-te policy [detail]
.. clicmd:: show sr-te policy [detail]
Display the segment routing policies.
@@ -368,38 +339,22 @@ The asterisk (*) marks the best, e.g. active, candidate path. Note that for segm
retrieved via PCEP a random number based name is generated.
-.. index:: show debugging pathd
-.. clicmd:: show debugging pathd
-
- Display the current status of the pathd debugging.
-
-
-.. index:: show debugging pathd-pcep
-.. clicmd:: show debugging pathd-pcep
-
- Display the current status of the pcep module debugging.
-
-
-.. index:: show sr-te pcep counters
.. clicmd:: show sr-te pcep counters
Display the counters from pceplib.
-.. index:: show sr-te pcep pce-config [NAME]
.. clicmd:: show sr-te pcep pce-config [NAME]
Display a shared configuration. if no name is specified, the default
configuration will be displayed.
-.. index:: show sr-te pcep pcc
.. clicmd:: show sr-te pcep pcc
Display PCC information.
-.. index:: show sr-te pcep session [NAME]
.. clicmd:: show sr-te pcep session [NAME]
Display the information of a PCEP session, if not name is specified all the
@@ -409,7 +364,6 @@ retrieved via PCEP a random number based name is generated.
Utility Commands
----------------
-.. index:: clear sr-te pcep session [NAME]
.. clicmd:: clear sr-te pcep session [NAME]
Reset the pcep session by disconnecting from the PCE and performing the
diff --git a/doc/user/pbr.rst b/doc/user/pbr.rst
index 5cec7cbe62..14a05a69d7 100644
--- a/doc/user/pbr.rst
+++ b/doc/user/pbr.rst
@@ -45,7 +45,7 @@ listing of ECMP nexthops used to forward packets for when a pbr-map is matched.
are used to are allowed here. The syntax was intentionally kept the same as
creating nexthops as you would for static routes.
-.. clicmd:: [no] pbr table range (10000-4294966272) (10000-4294966272)
+.. clicmd:: pbr table range (10000-4294966272) (10000-4294966272)
Set or unset the range used to assign numeric table ID's to new
nexthop-group tables. Existing tables will not be modified to fit in this
@@ -220,6 +220,10 @@ end destination.
| installedInternally | Do we think this group is installed? | Integer |
+---------------------+--------------------------------------+---------+
+
+.. index::
+ pair: policy; PBR
+
.. _pbr-policy:
PBR Policy
@@ -229,7 +233,6 @@ After you have specified a PBR map, in order for it to be turned on, you must
apply the PBR map to an interface. This policy application to an interface
causes the policy to be installed into the kernel.
-.. index:: pbr-policy
.. clicmd:: pbr-policy NAME
This command is available under interface sub-mode. This turns
@@ -263,12 +266,10 @@ causes the policy to be installed into the kernel.
PBR Debugs
===========
-.. index:: debug pbr
.. clicmd:: debug pbr events|map|nht|zebra
Debug pbr in pbrd daemon. You specify what types of debugs to turn on.
-.. index:: debug zebra pbr
.. clicmd:: debug zebra pbr
Debug pbr in zebra daemon.
@@ -281,12 +282,10 @@ PBR Details
Under the covers a PBR map is translated into two separate constructs in the
Linux kernel.
-.. index:: PBR Rules
The PBR map specified creates a `ip rule ...` that is inserted into the Linux
kernel that points to a table to use for forwarding once the rule matches.
-.. index:: PBR Tables
The creation of a nexthop or nexthop-group is translated to a default route in a
table with the nexthops specified as the nexthops for the default route.
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index 201fe2f9ed..86716b49a4 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -56,7 +56,6 @@ Certain signals have special meanings to *pimd*.
*pimd* invocation options. Common options that can be specified
(:ref:`common-invocation-options`).
-.. index:: ip pim rp A.B.C.D A.B.C.D/M
.. clicmd:: ip pim rp A.B.C.D A.B.C.D/M
In order to use pim, it is necessary to configure a RP for join messages to
@@ -66,7 +65,6 @@ Certain signals have special meanings to *pimd*.
prefix of group ranges covered. This command is vrf aware, to configure for
a vrf, enter the vrf submode.
-.. index:: ip pim register-accept-list PLIST
.. clicmd:: ip pim register-accept-list PLIST
When pim receives a register packet the source of the packet will be compared
@@ -74,14 +72,12 @@ Certain signals have special meanings to *pimd*.
processing continues. If a deny is returned for the source address of the
register packet a register stop message is sent to the source.
-.. index:: ip pim spt-switchover infinity-and-beyond
.. clicmd:: ip pim spt-switchover infinity-and-beyond
On the last hop router if it is desired to not switch over to the SPT tree.
Configure this command. This command is vrf aware, to configure for a vrf,
enter the vrf submode.
-.. index:: ip pim ecmp
.. clicmd:: ip pim ecmp
If pim has the a choice of ECMP nexthops for a particular RPF, pim will
@@ -89,7 +85,6 @@ Certain signals have special meanings to *pimd*.
not specified then the first nexthop found will be used. This command is vrf
aware, to configure for a vrf, enter the vrf submode.
-.. index:: ip pim ecmp rebalance
.. clicmd:: ip pim ecmp rebalance
If pim is using ECMP and an interface goes down, cause pim to rebalance all
@@ -98,14 +93,12 @@ Certain signals have special meanings to *pimd*.
down. This command is vrf aware, to configure for a vrf, enter the vrf
submode.
-.. index:: ip pim join-prune-interval (60-600)
.. clicmd:: ip pim join-prune-interval (60-600)
Modify the join/prune interval that pim uses to the new value. Time is
specified in seconds. This command is vrf aware, to configure for a vrf,
enter the vrf submode.
-.. index:: ip pim keep-alive-timer (31-60000)
.. clicmd:: ip pim keep-alive-timer (31-60000)
Modify the time out value for a S,G flow from 31-60000 seconds. 31 seconds
@@ -113,7 +106,6 @@ Certain signals have special meanings to *pimd*.
flowing in better than 30 second chunks. This command is vrf aware, to
configure for a vrf, enter the vrf submode.
-.. index:: ip pim packets (1-100)
.. clicmd:: ip pim packets (1-100)
When processing packets from a neighbor process the number of packets
@@ -122,14 +114,12 @@ Certain signals have special meanings to *pimd*.
a large number of pim control packets flowing. This command is vrf aware, to
configure for a vrf, enter the vrf submode.
-.. index:: ip pim register-suppress-time (5-60000)
.. clicmd:: ip pim register-suppress-time (5-60000)
Modify the time that pim will register suppress a FHR will send register
notifications to the kernel. This command is vrf aware, to configure for a
vrf, enter the vrf submode.
-.. index:: ip pim send-v6-secondary
.. clicmd:: ip pim send-v6-secondary
When sending pim hello packets tell pim to send any v6 secondary addresses
@@ -137,14 +127,12 @@ Certain signals have special meanings to *pimd*.
in it's decision for RPF lookup. This command is vrf aware, to configure for
a vrf, enter the vrf submode.
-.. index:: ip pim ssm prefix-list WORD
.. clicmd:: ip pim ssm prefix-list WORD
Specify a range of group addresses via a prefix-list that forces pim to
never do SM over. This command is vrf aware, to configure for a vrf, enter
the vrf submode.
-.. index:: ip multicast rpf-lookup-mode WORD
.. clicmd:: ip multicast rpf-lookup-mode WORD
Modify how PIM does RPF lookups in the zebra routing table. You can use
@@ -166,32 +154,27 @@ Certain signals have special meanings to *pimd*.
urib-only
Lookup in the Unicast Rib only.
-.. index:: ip msdp mesh-group [WORD]
-.. clicmd:: [no] ip msdp mesh-group [WORD]
+.. clicmd:: ip msdp mesh-group [WORD]
Create or Delete a multicast source discovery protocol mesh-group using
[WORD] as the group name.
-.. index:: ip msdp mesh-group WORD member A.B.C.D
-.. clicmd:: [no] ip msdp mesh-group WORD member A.B.C.D
+.. clicmd:: ip msdp mesh-group WORD member A.B.C.D
Attach or Delete A.B.C.D to the MSDP mesh group WORD specified.
-.. index:: ip msdp mesh-group WORD source A.B.C.D
-.. clicmd:: [no] ip msdp mesh-group WORD source A.B.C.D
+.. clicmd:: ip msdp mesh-group WORD source A.B.C.D
For the address specified A.B.C.D use that as the source address for
mesh group packets being sent.
-.. index:: ip igmp generate-query-once [version (2-3)]
.. clicmd:: ip igmp generate-query-once [version (2-3)]
Generate IGMP query (v2/v3) on user requirement. This will not depend on
the existing IGMP general query timer.If no version is provided in the cli,
it will be considered as default v2 query.This is a hidden command.
-.. index:: ip igmp watermark-warn (10-60000)
-.. clicmd:: [no] ip igmp watermark-warn (10-60000)
+.. clicmd:: ip igmp watermark-warn (10-60000)
Configure watermark warning generation for an igmp group limit. Generates
warning once the configured group limit is reached while adding new groups.
@@ -207,44 +190,33 @@ PIM interface commands allow you to configure an interface as either a Receiver
or a interface that you would like to form pim neighbors on. If the interface
is in a vrf, enter the interface command with the vrf keyword at the end.
-.. index:: ip pim active-active
.. clicmd:: ip pim active-active
Turn on pim active-active configuration for a Vxlan interface. This
command will not do anything if you do not have the underlying ability
of a mlag implementation.
-.. index:: ip pim bfd
-.. clicmd:: ip pim bfd
-
- Turns on BFD support for PIM for this interface.
-
-.. index:: ip pim bsm
.. clicmd:: ip pim bsm
Tell pim that we would like to use this interface to process bootstrap
messages. This is enabled by default. 'no' form of this command is used to
restrict bsm messages on this interface.
-.. index:: ip pim unicast-bsm
.. clicmd:: ip pim unicast-bsm
Tell pim that we would like to allow interface to process unicast bootstrap
messages. This is enabled by default. 'no' form of this command is used to
restrict processing of unicast bsm messages on this interface.
-.. index:: ip pim drpriority (1-4294967295)
.. clicmd:: ip pim drpriority (1-4294967295)
Set the DR Priority for the interface. This command is useful to allow the
user to influence what node becomes the DR for a lan segment.
-.. index:: ip pim hello (1-180) (1-180)
.. clicmd:: ip pim hello (1-180) (1-180)
Set the pim hello and hold interval for a interface.
-.. index:: ip pim
.. clicmd:: ip pim
Tell pim that we would like to use this interface to form pim neighbors
@@ -252,67 +224,63 @@ is in a vrf, enter the interface command with the vrf keyword at the end.
reports on the interface. Refer to the next `ip igmp` command for IGMP
management.
-.. index:: ip pim use-source A.B.C.D
-.. clicmd:: [no] ip pim use-source A.B.C.D
+.. clicmd:: ip pim use-source A.B.C.D
If you have multiple addresses configured on a particular interface
and would like pim to use a specific source address associated with
that interface.
-.. index:: ip igmp
.. clicmd:: ip igmp
Tell pim to receive IGMP reports and Query on this interface. The default
version is v3. This command is useful on a LHR.
-.. index:: ip igmp join A.B.C.D [A.B.C.D]
.. clicmd:: ip igmp join A.B.C.D [A.B.C.D]
Join multicast group or source-group on an interface.
-.. index:: ip igmp query-interval (1-1800)
.. clicmd:: ip igmp query-interval (1-1800)
Set the IGMP query interval that PIM will use.
-.. index:: ip igmp query-max-response-time (10-250)
.. clicmd:: ip igmp query-max-response-time (10-250)
Set the IGMP query response timeout value. If an report is not returned in
the specified time we will assume the S,G or \*,G has timed out.
-.. index:: ip igmp version (2-3)
.. clicmd:: ip igmp version (2-3)
Set the IGMP version used on this interface. The default value is 3.
-.. index:: ip multicast boundary oil WORD
.. clicmd:: ip multicast boundary oil WORD
Set a pim multicast boundary, based upon the WORD prefix-list. If a pim join
or IGMP report is received on this interface and the Group is denied by the
prefix-list, PIM will ignore the join or report.
-.. index:: ip igmp last-member-query-count (1-7)
.. clicmd:: ip igmp last-member-query-count (1-7)
Set the IGMP last member query count. The default value is 2. 'no' form of
this command is used to to configure back to the default value.
-.. index:: ip igmp last-member-query-interval (1-255)
.. clicmd:: ip igmp last-member-query-interval (1-255)
Set the IGMP last member query interval in deciseconds. The default value is
10 deciseconds. 'no' form of this command is used to to configure back to the
default value.
-.. index:: ip mroute INTERFACE A.B.C.D [A.B.C.D]
.. clicmd:: ip mroute INTERFACE A.B.C.D [A.B.C.D]
Set a static multicast route for a traffic coming on the current interface to
be forwarded on the given interface if the traffic matches the group address
and optionally the source address.
+
+.. seealso::
+
+ :ref:`bfd-pim-peer-config`
+
+
.. _pim-multicast-rib-insertion:
PIM Multicast RIB insertion:
@@ -325,13 +293,11 @@ into the kernel *or* for normal rib processing. As such it is
possible to create weird states with these commands. Use with
caution. Most of the time this will not be necessary.
-.. index:: ip mroute A.B.C.D/M A.B.C.D (1-255)
.. clicmd:: ip mroute A.B.C.D/M A.B.C.D (1-255)
Insert into the Multicast Rib Route A.B.C.D/M with specified nexthop. The
distance can be specified as well if desired.
-.. index:: ip mroute A.B.C.D/M INTERFACE (1-255)
.. clicmd:: ip mroute A.B.C.D/M INTERFACE (1-255)
Insert into the Multicast Rib Route A.B.C.D/M using the specified INTERFACE.
@@ -342,34 +308,25 @@ caution. Most of the time this will not be necessary.
Multicast Source Discovery Protocol (MSDP) Configuration
========================================================
-.. index:: ip msdp mesh-group [WORD] member A.B.C.D
.. clicmd:: ip msdp mesh-group [WORD] member A.B.C.D
Include a MSDP peer as a member of a MSDP mesh-group.
-.. index:: ip msdp mesh-group [WORD] source A.B.C.D
.. clicmd:: ip msdp mesh-group [WORD] source A.B.C.D
Create a MSDP mesh-group, defining a name for it and an associated local source
address.
-.. index:: ip msdp peer A.B.C.D source A.B.C.D
.. clicmd:: ip msdp peer A.B.C.D source A.B.C.D
Establish a MSDP connection with a peer.
-.. index:: ip msdp mesh-group [WORD] member A.B.C.D
-.. clicmd:: no ip msdp mesh-group [WORD] member A.B.C.D
Remove a MSDP peer member from a MSDP mesh-group.
-.. index:: ip msdp mesh-group [WORD] source A.B.C.D
-.. clicmd:: no ip msdp mesh-group [WORD] source A.B.C.D
Delete a MSDP mesh-group.
-.. index:: ip msdp peer A.B.C.D
-.. clicmd:: no ip msdp peer A.B.C.D
Delete a MSDP peer connection.
@@ -384,48 +341,39 @@ vrf is specified then the default vrf is assumed. Finally the special keyword
'all' allows you to look at all vrfs for the command. Naming a vrf 'all' will
cause great confusion.
-.. index:: show ip igmp interface
.. clicmd:: show ip igmp interface
Display IGMP interface information.
-.. index:: show ip igmp [vrf NAME] join [json]
.. clicmd:: show ip igmp [vrf NAME] join [json]
Display IGMP static join information for a specific vrf.
If "vrf all" is provided, it displays information for all the vrfs present.
-.. index:: show ip igmp groups
.. clicmd:: show ip igmp groups
Display IGMP groups information.
-.. index:: show ip igmp groups retransmissions
.. clicmd:: show ip igmp groups retransmissions
Display IGMP group retransmission information.
-.. index:: show ip igmp sources
.. clicmd:: show ip igmp sources
Display IGMP sources information.
-.. index:: show ip igmp sources retransmissions
.. clicmd:: show ip igmp sources retransmissions
Display IGMP source retransmission information.
-.. index:: show ip igmp statistics
.. clicmd:: show ip igmp statistics
Display IGMP statistics information.
-.. index:: show ip multicast
.. clicmd:: show ip multicast
Display various information about the interfaces used in this pim instance.
-.. index:: show ip mroute [vrf NAME] [A.B.C.D [A.B.C.D]] [fill] [json]
.. clicmd:: show ip mroute [vrf NAME] [A.B.C.D [A.B.C.D]] [fill] [json]
Display information about installed into the kernel S,G mroutes. If
@@ -434,200 +382,167 @@ cause great confusion.
Source Group. The keyword `fill` says to fill in all assumed data
for test/data gathering purposes.
-.. index:: show ip mroute [vrf NAME] count [json]
.. clicmd:: show ip mroute [vrf NAME] count [json]
Display information about installed into the kernel S,G mroutes and in
addition display data about packet flow for the mroutes for a specific
vrf.
-.. index:: show ip mroute vrf all count [json]
.. clicmd:: show ip mroute vrf all count [json]
Display information about installed into the kernel S,G mroutes and in
addition display data about packet flow for the mroutes for all vrfs.
-.. index:: show ip mroute [vrf NAME] summary [json]
.. clicmd:: show ip mroute [vrf NAME] summary [json]
Display total number of S,G mroutes and number of S,G mroutes installed
into the kernel for a specific vrf.
-.. index:: show ip mroute vrf all summary [json]
.. clicmd:: show ip mroute vrf all summary [json]
Display total number of S,G mroutes and number of S,G mroutes
installed into the kernel for all vrfs.
-.. index:: show ip msdp mesh-group
.. clicmd:: show ip msdp mesh-group
Display the configured mesh-groups, the local address associated with each
mesh-group, the peer members included in each mesh-group, and their status.
-.. index:: show ip msdp peer
.. clicmd:: show ip msdp peer
Display information about the MSDP peers. That includes the peer address,
the local address used to establish the connection to the peer, the
connection status, and the number of active sources.
-.. index:: show ip pim assert
.. clicmd:: show ip pim assert
Display information about asserts in the PIM system for S,G mroutes.
-.. index:: show ip pim assert-internal
.. clicmd:: show ip pim assert-internal
Display internal assert state for S,G mroutes
-.. index:: show ip pim assert-metric
.. clicmd:: show ip pim assert-metric
Display metric information about assert state for S,G mroutes
-.. index:: show ip pim assert-winner-metric
.. clicmd:: show ip pim assert-winner-metric
Display winner metric for assert state for S,G mroutes
-.. index:: show ip pim group-type
.. clicmd:: show ip pim group-type
Display SSM group ranges.
-.. index:: show ip pim interface
.. clicmd:: show ip pim interface
Display information about interfaces PIM is using.
-.. index:: show ip pim mlag [vrf NAME] interface [detail|WORD] [json]
.. clicmd:: show ip pim mlag [vrf NAME|all] interface [detail|WORD] [json]
Display mlag interface information.
-.. index:: show ip pim [vrf NAME] join [A.B.C.D [A.B.C.D]] [json]
.. clicmd:: show ip pim join
Display information about PIM joins received. If one address is specified
then we assume it is the Group we are interested in displaying data on.
If the second address is specified then it is Source Group.
-.. index:: show ip pim local-membership
.. clicmd:: show ip pim local-membership
Display information about PIM interface local-membership.
-.. index:: show ip pim mlag summary [json]
.. clicmd:: show ip pim mlag summary [json]
Display mlag information state that PIM is keeping track of.
-.. index:: show ip pim neighbor
.. clicmd:: show ip pim neighbor
Display information about PIM neighbors.
-.. index:: show ip pim nexthop
.. clicmd:: show ip pim nexthop
Display information about pim nexthops that are being used.
-.. index:: show ip pim nexthop-lookup
.. clicmd:: show ip pim nexthop-lookup
Display information about a S,G pair and how the RPF would be chosen. This
is especially useful if there are ECMP's available from the RPF lookup.
-.. index:: show ip pim rp-info
.. clicmd:: show ip pim rp-info
Display information about RP's that are configured on this router.
-.. index:: show ip pim rpf
.. clicmd:: show ip pim rpf
Display information about currently being used S,G's and their RPF lookup
information. Additionally display some statistics about what has been
happening on the router.
-.. index:: show ip pim secondary
.. clicmd:: show ip pim secondary
Display information about an interface and all the secondary addresses
associated with it.
-.. index:: show ip pim state
.. clicmd:: show ip pim state
Display information about known S,G's and incoming interface as well as the
OIL and how they were chosen.
-.. index:: show ip pim [vrf NAME] upstream [A.B.C.D [A.B.C.D]] [json]
-.. clicmd:: show ip pim upstream
+.. clicmd:: show ip pim [vrf NAME] upstream [A.B.C.D [A.B.C.D]] [json]
Display upstream information about a S,G mroute. Allow the user to
specify sub Source and Groups that we are only interested in.
-.. index:: show ip pim upstream-join-desired
.. clicmd:: show ip pim upstream-join-desired
Display upstream information for S,G's and if we desire to
join the multicast tree
-.. index:: show ip pim upstream-rpf
.. clicmd:: show ip pim upstream-rpf
Display upstream information for S,G's and the RPF data associated with them.
-.. index:: show ip pim [vrf NAME] mlag upstream [A.B.C.D [A.B.C.D]] [json]
-.. clicmd:: show ip pim mlag upstream
+.. clicmd:: show ip pim [vrf NAME] mlag upstream [A.B.C.D [A.B.C.D]] [json]
Display upstream entries that are synced across MLAG switches.
Allow the user to specify sub Source and Groups address filters.
-.. index:: show ip pim mlag summary
.. clicmd:: show ip pim mlag summary
Display PIM MLAG (multi-chassis link aggregation) session status and
control message statistics.
-.. index:: show ip pim bsr
.. clicmd:: show ip pim bsr
Display current bsr, its uptime and last received bsm age.
-.. index:: show ip pim bsrp-info
.. clicmd:: show ip pim bsrp-info
Display group-to-rp mappings received from E-BSR.
-.. index:: show ip pim bsm-database
.. clicmd:: show ip pim bsm-database
Display all fragments ofstored bootstrap message in user readable format.
-.. index:: show ip rpf
-.. clicmd:: show ip rpf
-
- Display the multicast RIB created in zebra.
-
-.. index:: mtrace A.B.C.D [A.B.C.D]
.. clicmd:: mtrace A.B.C.D [A.B.C.D]
Display multicast traceroute towards source, optionally for particular group.
-.. index:: show ip multicast count [vrf NAME] [json]
.. clicmd:: show ip multicast count [vrf NAME] [json]
Display multicast data packets count per interface for a vrf.
-.. index:: show ip multicast count vrf all [json]
.. clicmd:: show ip multicast count vrf all [json]
Display multicast data packets count per interface for all vrf.
+
+.. seealso::
+
+ :ref:`multicast-rib-commands`
+
+
PIM Debug Commands
==================
@@ -637,56 +552,46 @@ configure CLI mode. If you specify debug commands in the configuration cli
mode, the debug commands can be persistent across restarts of the FRR pimd if
the config was written out.
-.. index:: debug igmp
.. clicmd:: debug igmp
This turns on debugging for IGMP protocol activity.
-.. index:: debug mtrace
.. clicmd:: debug mtrace
This turns on debugging for mtrace protocol activity.
-.. index:: debug mroute
.. clicmd:: debug mroute
This turns on debugging for PIM interaction with kernel MFC cache.
-.. index:: debug pim events
.. clicmd:: debug pim events
This turns on debugging for PIM system events. Especially timers.
-.. index:: debug pim nht
.. clicmd:: debug pim nht
This turns on debugging for PIM nexthop tracking. It will display
information about RPF lookups and information about when a nexthop changes.
-.. index:: debug pim packet-dump
.. clicmd:: debug pim packet-dump
This turns on an extraordinary amount of data. Each pim packet sent and
received is dumped for debugging purposes. This should be considered a
developer only command.
-.. index:: debug pim packets
.. clicmd:: debug pim packets
This turns on information about packet generation for sending and about
packet handling from a received packet.
-.. index:: debug pim trace
.. clicmd:: debug pim trace
This traces pim code and how it is running.
-.. index:: debug pim bsm
.. clicmd:: debug pim bsm
This turns on debugging for BSR message processing.
-.. index:: debug pim zebra
.. clicmd:: debug pim zebra
This gathers data about events from zebra that come up through the ZAPI.
@@ -695,39 +600,32 @@ PIM Clear Commands
==================
Clear commands reset various variables.
-.. index:: clear ip interfaces
.. clicmd:: clear ip interfaces
Reset interfaces.
-.. index:: clear ip igmp interfaces
.. clicmd:: clear ip igmp interfaces
Reset IGMP interfaces.
-.. index:: clear ip mroute
.. clicmd:: clear ip mroute
Reset multicast routes.
-.. index:: clear ip mroute [vrf NAME] count
.. clicmd:: clear ip mroute [vrf NAME] count
When this command is issued, reset the counts of data shown for
packet count, byte count and wrong interface to 0 and start count
up from this spot.
-.. index:: clear ip pim interfaces
.. clicmd:: clear ip pim interfaces
Reset PIM interfaces.
-.. index:: clear ip pim oil
.. clicmd:: clear ip pim oil
Rescan PIM OIL (output interface list).
-.. index:: clear ip pim [vrf NAME] bsr-data
.. clicmd:: clear ip pim [vrf NAME] bsr-data
This command will clear the BSM scope data struct. This command also
diff --git a/doc/user/ripd.rst b/doc/user/ripd.rst
index e83b505a19..cba93e0d84 100644
--- a/doc/user/ripd.rst
+++ b/doc/user/ripd.rst
@@ -87,23 +87,17 @@ multipath routing.
RIP Configuration
=================
-.. index:: router rip
.. clicmd:: router rip
The `router rip` command is necessary to enable RIP. To disable RIP, use the
`no router rip` command. RIP must be enabled before carrying out any of the
RIP commands.
-.. index:: router rip
-.. clicmd:: no router rip
Disable RIP.
-.. index:: network NETWORK
.. clicmd:: network NETWORK
-.. index:: network NETWORK
-.. clicmd:: no network NETWORK
Set the RIP enable interface by NETWORK. The interfaces which have addresses
matching with NETWORK are enabled.
@@ -114,22 +108,16 @@ RIP Configuration
10.0.0.0 to 10.0.0.255 being enabled for RIP. The `no network` command will
disable RIP for the specified network.
-.. index:: network IFNAME
.. clicmd:: network IFNAME
-.. index:: network IFNAME
-.. clicmd:: no network IFNAME
Set a RIP enabled interface by IFNAME. Both the sending and
receiving of RIP packets will be enabled on the port specified in the
`network ifname` command. The `no network ifname` command will disable
RIP on the specified interface.
-.. index:: neighbor A.B.C.D
.. clicmd:: neighbor A.B.C.D
-.. index:: neighbor A.B.C.D
-.. clicmd:: no neighbor A.B.C.D
Specify RIP neighbor. When a neighbor doesn't understand multicast, this
command is used to specify neighbors. In some cases, not all routers will be
@@ -152,11 +140,8 @@ RIP Configuration
!
-.. index:: passive-interface (IFNAME|default)
.. clicmd:: passive-interface (IFNAME|default)
-.. index:: passive-interface IFNAME
-.. clicmd:: no passive-interface IFNAME
This command sets the specified interface to passive mode. On passive mode
interface, all receiving packets are processed as normal and ripd does not
@@ -166,11 +151,8 @@ RIP Configuration
The default is to be passive on all interfaces.
-.. index:: ip split-horizon
.. clicmd:: ip split-horizon
-.. index:: ip split-horizon
-.. clicmd:: no ip split-horizon
Control split-horizon on the interface. Default is `ip split-horizon`. If
you don't perform split-horizon on the interface, please specify `no ip
@@ -192,7 +174,6 @@ is enabled then RIP will reply to REQUEST packets, sending the state of its RIP
routing table to any remote routers that ask on demand. For a more detailed
discussion on the security implications of RIPv1 see :ref:`rip-authentication`.
-.. index:: version VERSION
.. clicmd:: version VERSION
Set RIP version to accept for reads and send. ``VERSION`` can be either 1 or
@@ -203,12 +184,6 @@ discussion on the security implications of RIPv1 see :ref:`rip-authentication`.
Default: Send Version 2, and accept either version.
-.. index:: version
-.. clicmd:: no version
-
- Reset the global version setting back to the default.
-
-.. index:: ip rip send version VERSION
.. clicmd:: ip rip send version VERSION
VERSION can be ``1``, ``2``, or ``1 2``.
@@ -221,7 +196,6 @@ discussion on the security implications of RIPv1 see :ref:`rip-authentication`.
Default: Send packets according to the global version (version 2)
-.. index:: ip rip receive version VERSION
.. clicmd:: ip rip receive version VERSION
VERSION can be ``1``, ``2``, or ``1 2``.
@@ -232,98 +206,22 @@ discussion on the security implications of RIPv1 see :ref:`rip-authentication`.
Default: Accept packets according to the global setting (both 1 and 2).
+
.. _how-to-announce-rip-route:
How to Announce RIP route
=========================
-.. index:: redistribute kernel
-.. clicmd:: redistribute kernel
-
-.. index:: redistribute kernel metric (0-16)
-.. clicmd:: redistribute kernel metric (0-16)
-
-.. index:: redistribute kernel route-map ROUTE-MAP
-.. clicmd:: redistribute kernel route-map ROUTE-MAP
-
-.. index:: redistribute kernel
-.. clicmd:: no redistribute kernel
-
- `redistribute kernel` redistributes routing information from kernel route
- entries into the RIP tables. `no redistribute kernel` disables the routes.
-
-.. index:: redistribute static
-.. clicmd:: redistribute static
-
-.. index:: redistribute static metric (0-16)
-.. clicmd:: redistribute static metric (0-16)
-
-.. index:: redistribute static route-map ROUTE-MAP
-.. clicmd:: redistribute static route-map ROUTE-MAP
-
-.. index:: redistribute static
-.. clicmd:: no redistribute static
-
- `redistribute static` redistributes routing information from static route
- entries into the RIP tables. `no redistribute static` disables the routes.
-
-.. index:: redistribute connected
-.. clicmd:: redistribute connected
-
-.. index:: redistribute connected metric (0-16)
-.. clicmd:: redistribute connected metric (0-16)
+.. clicmd:: redistribute <babel|bgp|connected|eigrp|isis|kernel|openfabric|ospf|sharp|static|table> [metric (0-16)] [route-map WORD]
-.. index:: redistribute connected route-map ROUTE-MAP
-.. clicmd:: redistribute connected route-map ROUTE-MAP
+ Redistribute routes from other sources into RIP.
-.. index:: redistribute connected
-.. clicmd:: no redistribute connected
+If you want to specify RIP only static routes:
- Redistribute connected routes into the RIP tables. `no redistribute
- connected` disables the connected routes in the RIP tables. This command
- redistribute connected of the interface which RIP disabled. The connected
- route on RIP enabled interface is announced by default.
-
-.. index:: redistribute ospf
-.. clicmd:: redistribute ospf
-
-.. index:: redistribute ospf metric (0-16)
-.. clicmd:: redistribute ospf metric (0-16)
-
-.. index:: redistribute ospf route-map ROUTE-MAP
-.. clicmd:: redistribute ospf route-map ROUTE-MAP
-
-.. index:: redistribute ospf
-.. clicmd:: no redistribute ospf
-
- `redistribute ospf` redistributes routing information from ospf route
- entries into the RIP tables. `no redistribute ospf` disables the routes.
-
-.. index:: redistribute bgp
-.. clicmd:: redistribute bgp
-
-.. index:: redistribute bgp metric (0-16)
-.. clicmd:: redistribute bgp metric (0-16)
-
-.. index:: redistribute bgp route-map ROUTE-MAP
-.. clicmd:: redistribute bgp route-map ROUTE-MAP
-
-.. index:: redistribute bgp
-.. clicmd:: no redistribute bgp
-
- `redistribute bgp` redistributes routing information from bgp route entries
- into the RIP tables. `no redistribute bgp` disables the routes.
-
- If you want to specify RIP only static routes:
-
-.. index:: default-information originate
.. clicmd:: default-information originate
-.. index:: route A.B.C.D/M
.. clicmd:: route A.B.C.D/M
-.. index:: route A.B.C.D/M
-.. clicmd:: no route A.B.C.D/M
This command is specific to FRR. The `route` command makes a static route
only inside RIP. This command should be used only by advanced users who are
@@ -338,7 +236,6 @@ Filtering RIP Routes
RIP routes can be filtered by a distribute-list.
-.. index:: distribute-list ACCESS_LIST DIRECT IFNAME
.. clicmd:: distribute-list ACCESS_LIST DIRECT IFNAME
You can apply access lists to the interface with a `distribute-list` command.
@@ -364,7 +261,6 @@ RIP routes can be filtered by a distribute-list.
`distribute-list` can be applied to both incoming and outgoing data.
-.. index:: distribute-list prefix PREFIX_LIST (in|out) IFNAME
.. clicmd:: distribute-list prefix PREFIX_LIST (in|out) IFNAME
You can apply prefix lists to the interface with a `distribute-list`
@@ -381,11 +277,8 @@ RIP metric is a value for distance for the network. Usually
*ripd* increment the metric when the network information is
received. Redistributed routes' metric is set to 1.
-.. index:: default-metric (1-16)
.. clicmd:: default-metric (1-16)
-.. index:: default-metric (1-16)
-.. clicmd:: no default-metric (1-16)
This command modifies the default metric value for redistributed routes.
The default value is 1. This command does not affect connected route even if
@@ -393,10 +286,8 @@ received. Redistributed routes' metric is set to 1.
metric value, please use ``redistribute connected metric`` or *route-map*.
*offset-list* also affects connected routes.
-.. index:: offset-list ACCESS-LIST (in|out)
.. clicmd:: offset-list ACCESS-LIST (in|out)
-.. index:: offset-list ACCESS-LIST (in|out) IFNAME
.. clicmd:: offset-list ACCESS-LIST (in|out) IFNAME
@@ -407,28 +298,19 @@ RIP distance
Distance value is used in zebra daemon. Default RIP distance is 120.
-.. index:: distance (1-255)
.. clicmd:: distance (1-255)
-.. index:: distance (1-255)
-.. clicmd:: no distance (1-255)
Set default RIP distance to specified value.
-.. index:: distance (1-255) A.B.C.D/M
.. clicmd:: distance (1-255) A.B.C.D/M
-.. index:: distance (1-255) A.B.C.D/M
-.. clicmd:: no distance (1-255) A.B.C.D/M
Set default RIP distance to specified value when the route's source IP
address matches the specified prefix.
-.. index:: distance (1-255) A.B.C.D/M ACCESS-LIST
.. clicmd:: distance (1-255) A.B.C.D/M ACCESS-LIST
-.. index:: distance (1-255) A.B.C.D/M ACCESS-LIST
-.. clicmd:: no distance (1-255) A.B.C.D/M ACCESS-LIST
Set default RIP distance to specified value when the route's source IP
address matches the specified prefix and the specified access-list.
@@ -459,7 +341,6 @@ it may be changed at future.
Route-map statement (:ref:`route-map`) is needed to use route-map
functionality.
-.. index:: match interface WORD
.. clicmd:: match interface WORD
This command match to incoming interface. Notation of this match is
@@ -471,37 +352,30 @@ functionality.
sends to different interfaces must be different. Maybe it'd be better to
made new matches - say "match interface-out NAME" or something like that.
-.. index:: match ip address WORD
.. clicmd:: match ip address WORD
-.. index:: match ip address prefix-list WORD
.. clicmd:: match ip address prefix-list WORD
Match if route destination is permitted by access-list.
-.. index:: match ip next-hop WORD
.. clicmd:: match ip next-hop WORD
-.. index:: match ip next-hop prefix-list WORD
.. clicmd:: match ip next-hop prefix-list WORD
Match if route next-hop (meaning next-hop listed in the rip route-table as
displayed by "show ip rip") is permitted by access-list.
-.. index:: match metric (0-4294967295)
.. clicmd:: match metric (0-4294967295)
This command match to the metric value of RIP updates. For other protocol
compatibility metric range is shown as (0-4294967295). But for RIP protocol
only the value range (0-16) make sense.
-.. index:: set ip next-hop A.B.C.D
.. clicmd:: set ip next-hop A.B.C.D
This command set next hop value in RIPv2 protocol. This command does not
affect RIPv1 because there is no next hop field in the packet.
-.. index:: set metric (0-4294967295)
.. clicmd:: set metric (0-4294967295)
Set a metric for matched route when sending announcement. The metric value
@@ -536,36 +410,24 @@ on the internet, via RIPv1.
To prevent such unauthenticated querying of routes disable RIPv1,
:ref:`rip-version-control`.
-.. index:: ip rip authentication mode md5
.. clicmd:: ip rip authentication mode md5
-.. index:: ip rip authentication mode md5
-.. clicmd:: no ip rip authentication mode md5
Set the interface with RIPv2 MD5 authentication.
-.. index:: ip rip authentication mode text
.. clicmd:: ip rip authentication mode text
-.. index:: ip rip authentication mode text
-.. clicmd:: no ip rip authentication mode text
Set the interface with RIPv2 simple password authentication.
-.. index:: ip rip authentication string STRING
.. clicmd:: ip rip authentication string STRING
-.. index:: ip rip authentication string STRING
-.. clicmd:: no ip rip authentication string STRING
RIP version 2 has simple text authentication. This command sets
authentication string. The string must be shorter than 16 characters.
-.. index:: ip rip authentication key-chain KEY-CHAIN
.. clicmd:: ip rip authentication key-chain KEY-CHAIN
-.. index:: ip rip authentication key-chain KEY-CHAIN
-.. clicmd:: no ip rip authentication key-chain KEY-CHAIN
Specify Keyed MD5 chain.
@@ -587,7 +449,6 @@ To prevent such unauthenticated querying of routes disable RIPv1,
RIP Timers
==========
-.. index:: timers basic UPDATE TIMEOUT GARBAGE
.. clicmd:: timers basic UPDATE TIMEOUT GARBAGE
@@ -610,11 +471,6 @@ RIP Timers
The ``timers basic`` command allows the the default values of the timers
listed above to be changed.
-.. index:: timers basic
-.. clicmd:: no timers basic
-
- The `no timers basic` command will reset the timers to the default settings
- listed above.
.. _show-rip-information:
@@ -623,7 +479,6 @@ Show RIP Information
To display RIP routes.
-.. index:: show ip rip
.. clicmd:: show ip rip
Show RIP routes.
@@ -633,7 +488,6 @@ through RIP, this command will display the time the packet was sent and
the tag information. This command will also display this information
for routes redistributed into RIP.
-.. index:: show ip rip status
.. clicmd:: show ip rip status
The command displays current RIP status. It includes RIP timer,
@@ -665,26 +519,22 @@ RIP Debug Commands
Debug for RIP protocol.
-.. index:: debug rip events
.. clicmd:: debug rip events
Shows RIP events. Sending and receiving packets, timers, and changes in
interfaces are events shown with *ripd*.
-.. index:: debug rip packet
.. clicmd:: debug rip packet
Shows display detailed information about the RIP packets. The origin and
port number of the packet as well as a packet dump is shown.
-.. index:: debug rip zebra
.. clicmd:: debug rip zebra
This command will show the communication between *ripd* and *zebra*. The
main information will include addition and deletion of paths to the kernel
and the sending and receiving of interface information.
-.. index:: show debugging rip
.. clicmd:: show debugging rip
Shows all information currently set for ripd debug.
diff --git a/doc/user/ripngd.rst b/doc/user/ripngd.rst
index ae2400f0bb..0387e36305 100644
--- a/doc/user/ripngd.rst
+++ b/doc/user/ripngd.rst
@@ -22,62 +22,46 @@ ripngd Configuration
Currently ripngd supports the following commands:
-.. index:: router ripng
.. clicmd:: router ripng
Enable RIPng.
-.. index:: flush_timer TIME
.. clicmd:: flush_timer TIME
Set flush timer.
-.. index:: network NETWORK
.. clicmd:: network NETWORK
Set RIPng enabled interface by NETWORK.
-.. index:: network IFNAME
.. clicmd:: network IFNAME
Set RIPng enabled interface by IFNAME.
-.. index:: route NETWORK
.. clicmd:: route NETWORK
Set RIPng static routing announcement of NETWORK.
-.. index:: router zebra
-.. clicmd:: router zebra
-
- This command is the default and does not appear in the configuration. With
- this statement, RIPng routes go to the *zebra* daemon.
.. _ripngd-terminal-mode-commands:
ripngd Terminal Mode Commands
=============================
-.. index:: show ip ripng
.. clicmd:: show ip ripng
-.. index:: show debugging ripng
.. clicmd:: show debugging ripng
-.. index:: debug ripng events
.. clicmd:: debug ripng events
-.. index:: debug ripng packet
.. clicmd:: debug ripng packet
-.. index:: debug ripng zebra
.. clicmd:: debug ripng zebra
ripngd Filtering Commands
=========================
-.. index:: distribute-list ACCESS_LIST (in|out) IFNAME
.. clicmd:: distribute-list ACCESS_LIST (in|out) IFNAME
You can apply an access-list to the interface using the `distribute-list`
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index fa8eee815d..7f357b0925 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -90,7 +90,6 @@ cont
.. _route-map-show-command:
-.. index:: show route-map [WORD]
.. clicmd:: show route-map [WORD]
Display data about each daemons knowledge of individual route-maps.
@@ -98,7 +97,6 @@ cont
.. _route-map-clear-counter-command:
-.. index:: clear route-map counter [WORD]
.. clicmd:: clear route-map counter [WORD]
Clear counters that are being stored about the route-map utilization
@@ -110,7 +108,6 @@ cont
Route Map Command
=================
-.. index:: route-map ROUTE-MAP-NAME (permit|deny) ORDER
.. clicmd:: route-map ROUTE-MAP-NAME (permit|deny) ORDER
Configure the `order`'th entry in `route-map-name` with ``Match Policy`` of
@@ -121,98 +118,80 @@ Route Map Command
Route Map Match Command
=======================
-.. index:: match ip address ACCESS_LIST
.. clicmd:: match ip address ACCESS_LIST
Matches the specified `access_list`
-.. index:: match ip address prefix-list PREFIX_LIST
.. clicmd:: match ip address prefix-list PREFIX_LIST
Matches the specified `PREFIX_LIST`
-.. index:: match ip address prefix-len 0-32
.. clicmd:: match ip address prefix-len 0-32
Matches the specified `prefix-len`. This is a Zebra specific command.
-.. index:: match ipv6 address ACCESS_LIST
.. clicmd:: match ipv6 address ACCESS_LIST
Matches the specified `access_list`
-.. index:: match ipv6 address prefix-list PREFIX_LIST
.. clicmd:: match ipv6 address prefix-list PREFIX_LIST
Matches the specified `PREFIX_LIST`
-.. index:: match ipv6 address prefix-len 0-128
.. clicmd:: match ipv6 address prefix-len 0-128
Matches the specified `prefix-len`. This is a Zebra specific command.
-.. index:: match ip next-hop address IPV4_ADDR
.. clicmd:: match ip next-hop address IPV4_ADDR
This is a BGP specific match command. Matches the specified `ipv4_addr`.
-.. index:: match ipv6 next-hop IPV6_ADDR
.. clicmd:: match ipv6 next-hop IPV6_ADDR
This is a BGP specific match command. Matches the specified `ipv6_addr`.
-.. index:: match as-path AS_PATH
.. clicmd:: match as-path AS_PATH
Matches the specified `as_path`.
-.. index:: match metric METRIC
.. clicmd:: match metric METRIC
Matches the specified `metric`.
-.. index:: match tag TAG
.. clicmd:: match tag TAG
Matches the specified tag value associated with the route. This tag value
can be in the range of (1-4294967295).
-.. index:: match local-preference METRIC
.. clicmd:: match local-preference METRIC
Matches the specified `local-preference`.
-.. index:: match community COMMUNITY_LIST
.. clicmd:: match community COMMUNITY_LIST
Matches the specified `community_list`
-.. index:: match peer IPV4_ADDR
.. clicmd:: match peer IPV4_ADDR
This is a BGP specific match command. Matches the peer ip address
if the neighbor was specified in this manner.
-.. index:: match peer IPV6_ADDR
.. clicmd:: match peer IPV6_ADDR
This is a BGP specific match command. Matches the peer ipv6
address if the neighbor was specified in this manner.
-.. index:: match peer INTERFACE_NAME
.. clicmd:: match peer INTERFACE_NAME
This is a BGP specific match command. Matches the peer
interface name specified if the neighbor was specified
in this manner.
-.. index:: match source-protocol PROTOCOL_NAME
.. clicmd:: match source-protocol PROTOCOL_NAME
This is a ZEBRA specific match command. Matches the
originating protocol specified.
-.. index:: match source-instance NUMBER
.. clicmd:: match source-instance NUMBER
This is a ZEBRA specific match command. The number is a range from (0-255).
@@ -225,7 +204,6 @@ Route Map Set Command
.. program:: configure
-.. index:: set tag TAG
.. clicmd:: set tag TAG
Set a tag on the matched route. This tag value can be from (1-4294967295).
@@ -233,13 +211,11 @@ Route Map Set Command
configure option. Tag values from (1-255) are sent to the Linux kernel as a
realm value. Then route policy can be applied. See the tc man page.
-.. index:: set ip next-hop IPV4_ADDRESS
.. clicmd:: set ip next-hop IPV4_ADDRESS
Set the BGP nexthop address to the specified IPV4_ADDRESS. For both
incoming and outgoing route-maps.
-.. index:: set ip next-hop peer-address
.. clicmd:: set ip next-hop peer-address
Set the BGP nexthop address to the address of the peer. For an incoming
@@ -247,13 +223,11 @@ Route Map Set Command
route-map this means the ip address of our self is used to establish the
peering with our neighbor.
-.. index:: set ip next-hop unchanged
.. clicmd:: set ip next-hop unchanged
Set the route-map as unchanged. Pass the route-map through without
changing it's value.
-.. index:: set ipv6 next-hop peer-address
.. clicmd:: set ipv6 next-hop peer-address
Set the BGP nexthop address to the address of the peer. For an incoming
@@ -261,121 +235,104 @@ Route Map Set Command
route-map this means the ip address of our self is used to establish the
peering with our neighbor.
-.. index:: set ipv6 next-hop prefer-global
.. clicmd:: set ipv6 next-hop prefer-global
For Incoming and Import Route-maps if we receive a v6 global and v6 LL
address for the route, then prefer to use the global address as the nexthop.
-.. index:: set ipv6 next-hop global IPV6_ADDRESS
.. clicmd:: set ipv6 next-hop global IPV6_ADDRESS
Set the next-hop to the specified IPV6_ADDRESS for both incoming and
outgoing route-maps.
-.. index:: set local-preference LOCAL_PREF
.. clicmd:: set local-preference LOCAL_PREF
Set the BGP local preference to `local_pref`.
-.. index:: set local-preference +LOCAL_PREF
.. clicmd:: set local-preference +LOCAL_PREF
Add the BGP local preference to an existing `local_pref`.
-.. index:: set local-preference -LOCAL_PREF
.. clicmd:: set local-preference -LOCAL_PREF
Subtract the BGP local preference from an existing `local_pref`.
-.. index:: set distance DISTANCE
-.. clicmd:: [no] set distance DISTANCE
+.. clicmd:: set distance DISTANCE
Set the Administrative distance to DISTANCE to use for the route.
This is only locally significant and will not be dispersed to peers.
-.. index:: set weight WEIGHT
.. clicmd:: set weight WEIGHT
Set the route's weight.
-.. index:: set metric <[+|-](1-4294967295)|rtt|+rtt|-rtt>
-.. clicmd:: [no] set metric <[+|-](1-4294967295)|rtt|+rtt|-rtt>
+.. clicmd:: set metric <[+|-](1-4294967295)|rtt|+rtt|-rtt>
Set the BGP attribute MED to a specific value. Use `+`/`-` to add or subtract
the specified value to/from the MED. Use `rtt` to set the MED to the round
trip time or `+rtt`/`-rtt` to add/subtract the round trip time to/from the
MED.
-.. index:: set as-path prepend AS_PATH
.. clicmd:: set as-path prepend AS_PATH
Set the BGP AS path to prepend.
-.. index:: set community COMMUNITY
.. clicmd:: set community COMMUNITY
Set the BGP community attribute.
-.. index:: set ipv6 next-hop local IPV6_ADDRESS
.. clicmd:: set ipv6 next-hop local IPV6_ADDRESS
Set the BGP-4+ link local IPv6 nexthop address.
-.. index:: set origin ORIGIN <egp|igp|incomplete>
.. clicmd:: set origin ORIGIN <egp|igp|incomplete>
Set BGP route origin.
-.. index:: set table (1-4294967295)
.. clicmd:: set table (1-4294967295)
Set the BGP table to a given table identifier
-.. index:: set sr-te color (1-4294967295)
.. clicmd:: set sr-te color (1-4294967295)
Set the color of a SR-TE Policy to be applied to a learned route. The SR-TE
Policy is uniquely determined by the color and the BGP nexthop.
+
.. _route-map-call-command:
Route Map Call Command
======================
-.. index:: call NAME
.. clicmd:: call NAME
Call route-map `name`. If it returns deny, deny the route and
finish processing the route-map.
+
.. _route-map-exit-action-command:
Route Map Exit Action Command
=============================
-.. index:: on-match next
.. clicmd:: on-match next
-.. index:: continue
.. clicmd:: continue
Proceed on to the next entry in the route-map.
-.. index:: on-match goto N
.. clicmd:: on-match goto N
-.. index:: continue N
.. clicmd:: continue N
Proceed processing the route-map at the first entry whose order is >= N
+
.. _route-map-optimization-command:
Route Map Optimization Command
==============================
-.. index:: route-map optimization
.. clicmd:: route-map optimization
Enable route-map processing optimization. The optimization is
@@ -387,10 +344,6 @@ Route Map Optimization Command
of all the prefixes in all the prefix-lists that are included in the
match rule of all the sequences of a route-map.
-.. index:: route-map optimization
-.. clicmd:: no route-map optimization
-
- Disable the route-map processing optimization.
Route Map Examples
==================
diff --git a/doc/user/routeserver.rst b/doc/user/routeserver.rst
index 474a68db25..5100d679f7 100644
--- a/doc/user/routeserver.rst
+++ b/doc/user/routeserver.rst
@@ -163,13 +163,10 @@ Commands for configuring a Route Server
Now we will describe the commands that have been added to frr
in order to support the route server features.
-.. index:: neighbor PEER-GROUP route-server-client
.. clicmd:: neighbor PEER-GROUP route-server-client
-.. index:: neighbor A.B.C.D route-server-client
.. clicmd:: neighbor A.B.C.D route-server-client
-.. index:: neighbor X:X::X:X route-server-client
.. clicmd:: neighbor X:X::X:X route-server-client
This command configures the peer given by `peer`, `A.B.C.D` or `X:X::X:X` as
@@ -186,14 +183,12 @@ in order to support the route server features.
that moment, every announcement received by the route server will be also
considered for the new Loc-RIB.
-.. index:: neigbor A.B.C.D|X.X::X.X|peer-group route-map WORD import|export
.. clicmd:: neigbor A.B.C.D|X.X::X.X|peer-group route-map WORD import|export
This set of commands can be used to specify the route-map that represents
the Import or Export policy of a peer which is configured as a RS-client
(with the previous command).
-.. index:: match peer A.B.C.D|X:X::X:X
.. clicmd:: match peer A.B.C.D|X:X::X:X
This is a new *match* statement for use in route-maps, enabling them to
@@ -210,7 +205,6 @@ in order to support the route server features.
announce is going to be inserted (how the same export policy is applied
before different Loc-RIBs is shown in :ref:`fig-rs-processing`.).
-.. index:: call WORD
.. clicmd:: call WORD
This command (also used inside a route-map) jumps into a different
diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst
index 451df1aa4e..01705f607c 100644
--- a/doc/user/rpki.rst
+++ b/doc/user/rpki.rst
@@ -54,7 +54,6 @@ In a nutshell, the current implementation provides the following features
Enabling RPKI
-------------
-.. index:: rpki
.. clicmd:: rpki
This command enables the RPKI configuration mode. Most commands that start
@@ -67,7 +66,6 @@ Enabling RPKI
to configure at least one reachable cache server. See section
:ref:`configuring-rpki-rtr-cache-servers` for configuring a cache server.
-.. index:: RPKI and daemons
When first installing FRR with RPKI support from the pre-packaged binaries.
Remember to add ``-M rpki`` to the variable ``bgpd_options`` in
@@ -101,11 +99,8 @@ Configuring RPKI/RTR Cache Servers
The following commands are independent of a specific cache server.
-.. index:: rpki polling_period (1-3600)
.. clicmd:: rpki polling_period (1-3600)
-.. index:: rpki polling_period
-.. clicmd:: no rpki polling_period
Set the number of seconds the router waits until the router asks the cache
again for updated data.
@@ -114,11 +109,8 @@ The following commands are independent of a specific cache server.
The following commands configure one or multiple cache servers.
-.. index:: rpki cache (A.B.C.D|WORD) PORT [SSH_USERNAME] [SSH_PRIVKEY_PATH] [SSH_PUBKEY_PATH] [KNOWN_HOSTS_PATH] PREFERENCE
.. clicmd:: rpki cache (A.B.C.D|WORD) PORT [SSH_USERNAME] [SSH_PRIVKEY_PATH] [SSH_PUBKEY_PATH] [KNOWN_HOSTS_PATH] PREFERENCE
-.. index:: rpki cache (A.B.C.D|WORD) [PORT] PREFERENCE
-.. clicmd:: no rpki cache (A.B.C.D|WORD) [PORT] PREFERENCE
Add a cache server to the socket. By default, the connection between router
and cache server is based on plain TCP. Protecting the connection between
@@ -154,11 +146,8 @@ The following commands are independent of a specific cache server.
Validating BGP Updates
----------------------
-.. index:: match rpki notfound|invalid|valid
.. clicmd:: match rpki notfound|invalid|valid
-.. index:: match rpki notfound|invalid|valid
-.. clicmd:: no match rpki notfound|invalid|valid
Create a clause for a route map to match prefixes with the specified RPKI
state.
@@ -187,11 +176,8 @@ Validating BGP Updates
Debugging
---------
-.. index:: debug rpki
.. clicmd:: debug rpki
-.. index:: debug rpki
-.. clicmd:: no debug rpki
Enable or disable debugging output for RPKI.
@@ -200,26 +186,22 @@ Debugging
Displaying RPKI
---------------
-.. index:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)]
.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)]
Display validated prefixes received from the cache servers filtered
by the specified prefix.
-.. index:: show rpki as-number ASN
.. clicmd:: show rpki as-number ASN
Display validated prefixes received from the cache servers filtered
by ASN.
-.. index:: show rpki prefix-table
.. clicmd:: show rpki prefix-table
Display all validated prefix to origin AS mappings/records which have been
received from the cache servers and stored in the router. Based on this data,
the router validates BGP Updates.
-.. index:: show rpki cache-connection
.. clicmd:: show rpki cache-connection
Display all configured cache servers, whether active or not.
diff --git a/doc/user/sharp.rst b/doc/user/sharp.rst
index 90eae4d65a..9e83e44222 100644
--- a/doc/user/sharp.rst
+++ b/doc/user/sharp.rst
@@ -32,7 +32,6 @@ Using SHARP
All sharp commands are under the enable node and preceded by the ``sharp``
keyword. At present, no sharp commands will be preserved in the config.
-.. index:: sharp install
.. clicmd:: sharp install routes A.B.C.D <nexthop <E.F.G.H|X:X::X:X>|nexthop-group NAME> (1-1000000) [instance (0-255)] [repeat (2-1000)] [opaque WORD]
Install up to 1,000,000 (one million) /32 routes starting at ``A.B.C.D``
@@ -49,7 +48,6 @@ keyword. At present, no sharp commands will be preserved in the config.
number of times specified. If the keyword opaque is specified then the
next word is sent down to zebra as part of the route installation.
-.. index:: sharp remove
.. clicmd:: sharp remove routes A.B.C.D (1-1000000)
Remove up to 1,000,000 (one million) /32 routes starting at ``A.B.C.D``. The
@@ -57,7 +55,6 @@ keyword. At present, no sharp commands will be preserved in the config.
log and when all routes have been successfully deleted the debug log will be
updated with this information as well.
-.. index:: sharp data route
.. clicmd:: sharp data route
Allow end user doing route install and deletion to get timing information
@@ -65,14 +62,12 @@ keyword. At present, no sharp commands will be preserved in the config.
is informational only and you should look at sharp_vty.c for explanation
of the output as that it may change.
-.. index:: sharp label
.. clicmd:: sharp label <ipv4|ipv6> vrf NAME label (0-1000000)
Install a label into the kernel that causes the specified vrf NAME table to
be used for pop and forward operations when the specified label is seen.
-.. index:: sharp watch
-.. clicmd:: [no] sharp watch <nexthop <A.B.C.D|X:X::X:X>|import <A.B.C.D/M:X:X::X:X/M> [connected]
+.. clicmd:: sharp watch <nexthop <A.B.C.D|X:X::X:X>|import <A.B.C.D/M:X:X::X:X/M> [connected]
Instruct zebra to monitor and notify sharp when the specified nexthop is
changed. The notification from zebra is written into the debug log.
@@ -83,13 +78,11 @@ keyword. At present, no sharp commands will be preserved in the config.
for the import keyword connected means exact match. The no form of
the command obviously turns this watching off.
-.. index:: sharp data nexthop
.. clicmd:: sharp data nexthop
Allow end user to dump associated data with the nexthop tracking that
may have been turned on.
-.. index:: sharp lsp
.. clicmd:: sharp lsp [update] (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]]
Install an LSP using the specified in-label, with nexthops as
@@ -98,7 +91,6 @@ keyword. At present, no sharp commands will be preserved in the config.
If ``prefix`` is specified, an existing route with type ``TYPE``
(and optional ``instance`` id) will be updated to use the LSP.
-.. index:: sharp remove lsp
.. clicmd:: sharp remove lsp (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]]
Remove a SHARPD LSP that uses the specified in-label, where the
@@ -106,13 +98,11 @@ keyword. At present, no sharp commands will be preserved in the config.
specified, remove label bindings from the route of type ``TYPE``
also.
-.. index:: sharp send opaque
.. clicmd:: sharp send opaque type (1-255) (1-1000)
Send opaque ZAPI messages with subtype ``type``. Sharpd will send
a stream of messages if the count is greater than one.
-.. index:: sharp send opaque unicast
.. clicmd:: sharp send opaque unicast type (1-255) $proto_str [{instance (0-1000) | session (1-1000)}] (1-1000)
Send unicast opaque ZAPI messages with subtype ``type``. The
@@ -120,7 +110,6 @@ keyword. At present, no sharp commands will be preserved in the config.
client. Sharpd will send a stream of messages if the count is
greater than one.
-.. index:: sharp send opaque reg unreg
.. clicmd:: sharp send opaque <reg | unreg> $proto_str [{instance (0-1000) | session (1-1000)}] type (1-1000)
Send opaque ZAPI registration and unregistration messages for a
@@ -128,19 +117,16 @@ keyword. At present, no sharp commands will be preserved in the config.
name, and can include optional zapi ``instance`` and ``session``
values.
-.. index:: sharp create session
.. clicmd:: sharp create session (1-1024)
Create an additional zapi client session for testing, using the
specified session id.
-.. index:: sharp remove session
.. clicmd:: sharp remove session (1-1024)
Remove a test zapi client session that was created with the
specified session id.
-.. index:: sharp neigh discover
.. clicmd:: sharp neigh discover [vrf NAME] <A.B.C.D|X:X::X:X> IFNAME
Send an ARP/NDP request to trigger the addition of a neighbor in the ARP
diff --git a/doc/user/snmp.rst b/doc/user/snmp.rst
index ebbe178e0b..b9058cc0d3 100644
--- a/doc/user/snmp.rst
+++ b/doc/user/snmp.rst
@@ -130,10 +130,7 @@ need to configure FRR to use another transport, you can configure it through
Here is the syntax for using AgentX:
-.. index:: agentx
.. clicmd:: agentx
-.. index:: agentx
-.. clicmd:: no agentx
.. include:: snmptrap.rst
diff --git a/doc/user/static.rst b/doc/user/static.rst
index 6302d1b148..200d187370 100644
--- a/doc/user/static.rst
+++ b/doc/user/static.rst
@@ -35,10 +35,8 @@ Static Route Commands
Static routing is a very fundamental feature of routing technology. It defines
a static prefix and gateway.
-.. index:: ip route NETWORK GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME
.. clicmd:: ip route NETWORK GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME
-.. index:: ipv6 route NETWORK from SRCPREFIX GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME
.. clicmd:: ipv6 route NETWORK from SRCPREFIX GATEWAY table TABLENO nexthop-vrf VRFNAME DISTANCE vrf VRFNAME
NETWORK is destination prefix with a valid v4 or v6 network based upon
diff --git a/doc/user/vnc.rst b/doc/user/vnc.rst
index 4f03e543ac..4ff27c6a63 100644
--- a/doc/user/vnc.rst
+++ b/doc/user/vnc.rst
@@ -110,7 +110,6 @@ These are the statements that can appear between ``vnc defaults`` and
- :clicmd:`export bgp|zebra route-map MAP-NAME`
- :clicmd:`export bgp|zebra no route-map`
-.. index:: exit-vnc
.. clicmd:: exit-vnc
Exit VNC configuration mode.
@@ -136,7 +135,6 @@ Defaults section.
**At least one `nve-group` is mandatory for useful VNC operation.**
-.. index:: vnc nve-group NAME
.. clicmd:: vnc nve-group NAME
Enter VNC configuration mode for defining the NVE group `name`.
@@ -149,14 +147,8 @@ Defaults section.
exit-vnc
-.. index:: vnc nve-group NAME
-.. clicmd:: no vnc nve-group NAME
+The following statements are valid in an NVE group definition:
- Delete the NVE group named `name`.
-
- The following statements are valid in an NVE group definition:
-
-.. index:: l2rd NVE-ID-VALUE
.. clicmd:: l2rd NVE-ID-VALUE
Set the value used to distinguish NVEs connected to the same physical
@@ -166,7 +158,6 @@ Defaults section.
1-255, or it may be specified as `auto:vn`, which means to use the
least-significant octet of the originating NVE's VN address.
-.. index:: prefix vn|un A.B.C.D/M|X:X::X:X/M
.. clicmd:: prefix vn|un A.B.C.D/M|X:X::X:X/M
Specify the matching prefix for this NVE group by either virtual-network
@@ -178,7 +169,6 @@ Defaults section.
These prefixes are used only for determining assignments of NVEs to NVE
Groups.
-.. index:: rd ROUTE-DISTINGUISHER
.. clicmd:: rd ROUTE-DISTINGUISHER
Specify the route distinguisher for routes advertised via BGP
@@ -202,7 +192,6 @@ Defaults section.
`route-distinguisher` is configured, then the advertised RD is set to
``two-byte-autonomous-system-number=0:four-byte-integer=0``.
-.. index:: response-lifetime LIFETIME|infinite
.. clicmd:: response-lifetime LIFETIME|infinite
Specify the response lifetime, in seconds, to be included in RFP response
@@ -218,13 +207,10 @@ Defaults section.
`response-lifetime` is configured, the value 3600 will be used. The maximum
response lifetime is 2147483647.
-.. index:: rt export RT-LIST
.. clicmd:: rt export RT-LIST
-.. index:: rt import RT-LIST
.. clicmd:: rt import RT-LIST
-.. index:: rt both RT-LIST
.. clicmd:: rt both RT-LIST
Specify route target import and export lists. `rt-list` is a
@@ -258,7 +244,6 @@ Defaults section.
simultaneously, and is equivalent to `rt export `rt-list`` followed by
`rt import `rt-list``.
-.. index:: export bgp|zebra route-map MAP-NAME
.. clicmd:: export bgp|zebra route-map MAP-NAME
Specify that the named route-map should be applied to routes being exported
@@ -266,7 +251,6 @@ Defaults section.
:ref:`configuring-export-of-routes-to-other-routing-protocols`. This item
is optional.
-.. index:: export bgp|zebra no route-map
.. clicmd:: export bgp|zebra no route-map
Specify that no route-map should be applied to routes being exported to bgp
@@ -274,7 +258,6 @@ Defaults section.
:ref:`configuring-export-of-routes-to-other-routing-protocols`. This item
is optional.
-.. index:: export bgp|zebra ipv4|ipv6 prefix-list LIST-NAME
.. clicmd:: export bgp|zebra ipv4|ipv6 prefix-list LIST-NAME
Specify that the named prefix-list filter should be applied to routes being
@@ -283,7 +266,6 @@ Defaults section.
:ref:`configuring-export-of-routes-to-other-routing-protocols`. This item
is optional.
-.. index:: export bgp|zebra no ipv4|ipv6 prefix-list
.. clicmd:: export bgp|zebra no ipv4|ipv6 prefix-list
Specify that no prefix-list filter should be applied to routes being
@@ -309,7 +291,6 @@ Note that a corresponding NVE group configuration must be present, and that
other NVE associated configuration information, notably RD, is not impacted by
L2 Group Configuration.
-.. index:: vnc l2-group NAME
.. clicmd:: vnc l2-group NAME
Enter VNC configuration mode for defining the L2 group `name`.
@@ -322,35 +303,26 @@ L2 Group Configuration.
exit-vnc
-.. index:: vnc l2-group NAME
-.. clicmd:: no vnc l2-group NAME
Delete the L2 group named `name`.
The following statements are valid in a L2 group definition:
-.. index:: logical-network-id VALUE
.. clicmd:: logical-network-id VALUE
Define the Logical Network Identifier with a value in the range of
0-4294967295 that identifies the logical Ethernet segment.
-.. index:: labels LABEL-LIST
.. clicmd:: labels LABEL-LIST
-.. index:: labels LABEL-LIST
-.. clicmd:: no labels LABEL-LIST
Add or remove labels associated with the group. `label-list` is a
space separated list of label values in the range of 0-1048575.
-.. index:: rt import RT-TARGET
.. clicmd:: rt import RT-TARGET
-.. index:: rt export RT-TARGET
.. clicmd:: rt export RT-TARGET
-.. index:: rt both RT-TARGET
.. clicmd:: rt both RT-TARGET
Specify the route target import and export value associated with the group.
@@ -484,14 +456,10 @@ There is currently no policy (prefix-list or route-map) support for
Redistribution Command Syntax
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-.. index:: vnc redistribute ipv4|ipv6 bgp|bgp-direct|ipv6 bgp-direct-to-nve-groups|connected|kernel|ospf|rip|static
.. clicmd:: vnc redistribute ipv4|ipv6 bgp|bgp-direct|ipv6 bgp-direct-to-nve-groups|connected|kernel|ospf|rip|static
-.. index:: vnc redistribute ipv4|ipv6 bgp-direct-to-nve-groups view VIEWNAME
.. clicmd:: vnc redistribute ipv4|ipv6 bgp-direct-to-nve-groups view VIEWNAME
-.. index:: vnc redistribute ipv4|ipv6 bgp|bgp-direct|bgp-direct-to-nve-groups|connected|kernel|ospf|rip|static
-.. clicmd:: no vnc redistribute ipv4|ipv6 bgp|bgp-direct|bgp-direct-to-nve-groups|connected|kernel|ospf|rip|static
Import (or do not import) prefixes from another routing protocols. Specify
both the address family to import (`ipv4` or `ipv6`) and the protocol
@@ -502,17 +470,13 @@ Redistribution Command Syntax
Prefixes from all other protocols (including `bgp`) are imported via the
`zebra` kernel routing process.
-.. index:: vnc redistribute mode plain|nve-group|resolve-nve
.. clicmd:: vnc redistribute mode plain|nve-group|resolve-nve
Redistribute routes from other protocols into VNC using the specified mode.
Not all combinations of modes and protocols are supported.
-.. index:: vnc redistribute nve-group GROUP-NAME
.. clicmd:: vnc redistribute nve-group GROUP-NAME
-.. index:: vnc redistribute nve-group GROUP-NAME
-.. clicmd:: no vnc redistribute nve-group GROUP-NAME
When using `nve-group` mode, assign (or do not assign) the NVE group
`group-name` to routes redistributed from another routing protocol.
@@ -522,7 +486,6 @@ Redistribution Command Syntax
prefix must be specified as a full-length (/32 for IPv4, /128 for IPv6)
prefix.
-.. index:: vnc redistribute lifetime LIFETIME|infinite
.. clicmd:: vnc redistribute lifetime LIFETIME|infinite
Assign a registration lifetime, either `lifetime` seconds or `infinite`, to
@@ -530,7 +493,6 @@ Redistribution Command Syntax
received via RFP registration messages from an NVE. `lifetime` can be any
integer between 1 and 4294967295, inclusive.
-.. index:: vnc redistribute resolve-nve roo-ec-local-admin 0-65536
.. clicmd:: vnc redistribute resolve-nve roo-ec-local-admin 0-65536
Assign a value to the local-administrator subfield used in the
@@ -545,25 +507,21 @@ specified outside the context of an nve-group, then they apply only for
redistribution modes `plain` and `resolve-nve`, and then only for routes
being redistributed from `bgp-direct`.
-.. index:: vnc redistribute bgp-direct (ipv4|ipv6) prefix-list LIST-NAME
.. clicmd:: vnc redistribute bgp-direct (ipv4|ipv6) prefix-list LIST-NAME
When redistributing `bgp-direct` routes,
specifies that the named prefix-list should be applied.
-.. index:: vnc redistribute bgp-direct no (ipv4|ipv6) prefix-list
.. clicmd:: vnc redistribute bgp-direct no (ipv4|ipv6) prefix-list
When redistributing `bgp-direct` routes,
specifies that no prefix-list should be applied.
-.. index:: vnc redistribute bgp-direct route-map MAP-NAME
.. clicmd:: vnc redistribute bgp-direct route-map MAP-NAME
When redistributing `bgp-direct` routes,
specifies that the named route-map should be applied.
-.. index:: vnc redistribute bgp-direct no route-map
.. clicmd:: vnc redistribute bgp-direct no route-map
When redistributing `bgp-direct` routes,
@@ -582,7 +540,6 @@ downstream protocol must also be configured to import the routes. For example,
when VNC routes are exported to unicast BGP, the BGP configuration must include
a corresponding `redistribute vnc-direct` statement.
-.. index:: export bgp|zebra mode none|group-nve|registering-nve|ce
.. clicmd:: export bgp|zebra mode none|group-nve|registering-nve|ce
Specify how routes should be exported to bgp or zebra. If the mode is
@@ -600,10 +557,8 @@ a corresponding `redistribute vnc-direct` statement.
The default for both bgp and zebra is mode `none`.
-.. index:: vnc export bgp|zebra group-nve group GROUP-NAME
.. clicmd:: vnc export bgp|zebra group-nve group GROUP-NAME
-.. index:: vnc export bgp|zebra group-nve no group GROUP-NAME
.. clicmd:: vnc export bgp|zebra group-nve no group GROUP-NAME
When export mode is `group-nve`, export (or do not export) prefixes from the
@@ -702,14 +657,12 @@ manually and dynamically added information.
`local-next-hop` parameter is used to delete specific local nexthop
information.
-.. index:: clear vnc mac (\\*|xx:xx:xx:xx:xx:xx) virtual-network-identifier (\\*|(1-4294967295)) (\\*|[(vn|un) (A.B.C.D|X:X::X:X|\\*) [(un|vn) (A.B.C.D|X:X::X:X|\*)] [prefix (\\*|A.B.C.D/M|X:X::X:X/M)])
.. clicmd:: clear vnc mac (\*|xx:xx:xx:xx:xx:xx) virtual-network-identifier (\*|(1-4294967295)) (\*|[(vn|un) (A.B.C.D|X:X::X:X|\*) [(un|vn) (A.B.C.D|X:X::X:X|\*)] [prefix (\*|A.B.C.D/M|X:X::X:X/M)])
Delete mac forwarding information. Any or all of these parameters may be
wildcarded to (potentially) match more than one registration. The default
value for the `prefix` parameter is the wildcard value `*`.
-.. index:: clear vnc nve (\*|((vn|un) (A.B.C.D|X:X::X:X) [(un|vn) (A.B.C.D|X:X::X:X)]))
.. clicmd:: clear vnc nve (\*|((vn|un) (A.B.C.D|X:X::X:X) [(un|vn) (A.B.C.D|X:X::X:X)]))
Delete prefixes associated with the NVE specified by the given VN and UN
@@ -729,24 +682,20 @@ running-configuration` command when in `enable` mode.
The following commands are used to clear and display Virtual Network Control
related information:
-.. index:: clear vnc counters
.. clicmd:: clear vnc counters
Reset the counter values stored by the NVA. Counter
values can be seen using the `show vnc` commands listed above. This
command is only available in `enable` mode.
-.. index:: show vnc summary
.. clicmd:: show vnc summary
Print counter values and other general information
about the NVA. Counter values can be reset
using the `clear vnc counters` command listed below.
-.. index:: show vnc nves
.. clicmd:: show vnc nves
-.. index:: show vnc nves vn|un ADDRESS
.. clicmd:: show vnc nves vn|un ADDRESS
Display the NVA's current clients. Specifying `address` limits the output to
@@ -754,10 +703,8 @@ related information:
communicated with the NVE, per-NVE summary counters and each NVE's addresses
will be displayed.
-.. index:: show vnc queries
.. clicmd:: show vnc queries
-.. index:: show vnc queries PREFIX
.. clicmd:: show vnc queries PREFIX
Display active Query information. Queries remain valid for the default
@@ -768,10 +715,8 @@ related information:
Query information is provided for each querying NVE, and includes the Query
Target and the time remaining before the information is removed.
-.. index:: show vnc registrations [all|local|remote|holddown|imported]
.. clicmd:: show vnc registrations [all|local|remote|holddown|imported]
-.. index:: show vnc registrations [all|local|remote|holddown|imported] PREFIX
.. clicmd:: show vnc registrations [all|local|remote|holddown|imported] PREFIX
Display local, remote, holddown, and/or imported registration information.
@@ -791,10 +736,8 @@ related information:
registrations, the amount of time remaining before the information is
removed.
-.. index:: show vnc responses [active|removed]
.. clicmd:: show vnc responses [active|removed]
-.. index:: show vnc responses [active|removed] PREFIX
.. clicmd:: show vnc responses [active|removed] PREFIX
Display all, active and/or removed response information which are
@@ -811,7 +754,6 @@ related information:
the administrative cost, the provided response lifetime and the time
remaining before the information is to be removed or will become inactive.
-.. index:: show memory vnc
.. clicmd:: show memory vnc
Print the number of memory items allocated by the NVA.
diff --git a/doc/user/vrrp.rst b/doc/user/vrrp.rst
index a39bd53844..44a56f2fca 100644
--- a/doc/user/vrrp.rst
+++ b/doc/user/vrrp.rst
@@ -358,30 +358,26 @@ using VRRPv2.
All interface configuration commands are documented below.
-.. index:: vrrp (1-255) [version (2-3)]
-.. clicmd:: [no] vrrp (1-255) [version (2-3)]
+.. clicmd:: vrrp (1-255) [version (2-3)]
Create a VRRP router with the specified VRID on the interface. Optionally
specify the protocol version. If the protocol version is not specified, the
default is VRRPv3.
-.. index:: vrrp (1-255) advertisement-interval (10-40950)
-.. clicmd:: [no] vrrp (1-255) advertisement-interval (10-40950)
+.. clicmd:: vrrp (1-255) advertisement-interval (10-40950)
Set the advertisement interval. This is the interval at which VRRP
advertisements will be sent. Values are given in milliseconds, but must be
multiples of 10, as VRRP itself uses centiseconds.
-.. index:: vrrp (1-255) ip A.B.C.D
-.. clicmd:: [no] vrrp (1-255) ip A.B.C.D
+.. clicmd:: vrrp (1-255) ip A.B.C.D
Add an IPv4 address to the router. This address must already be configured
on the appropriate macvlan device. Adding an IP address to the router will
implicitly activate the router; see :clicmd:`[no] vrrp (1-255) shutdown` to
override this behavior.
-.. index:: vrrp (1-255) ipv6 X:X::X:X
-.. clicmd:: [no] vrrp (1-255) ipv6 X:X::X:X
+.. clicmd:: vrrp (1-255) ipv6 X:X::X:X
Add an IPv6 address to the router. This address must already be configured
on the appropriate macvlan device. Adding an IP address to the router will
@@ -391,23 +387,20 @@ All interface configuration commands are documented below.
This command will fail if the protocol version is set to VRRPv2, as VRRPv2
does not support IPv6.
-.. index:: vrrp (1-255) preempt
-.. clicmd:: [no] vrrp (1-255) preempt
+.. clicmd:: vrrp (1-255) preempt
Toggle preempt mode. When enabled, preemption allows Backup routers with
higher priority to take over Master status from the existing Master. Enabled
by default.
-.. index:: vrrp (1-255) priority (1-254)
-.. clicmd:: [no] vrrp (1-255) priority (1-254)
+.. clicmd:: vrrp (1-255) priority (1-254)
Set the router priority. The router with the highest priority is elected as
the Master. If all routers in the VRRP virtual router are configured with
the same priority, the router with the highest primary IP address is elected
as the Master. Priority value 255 is reserved for the acting Master router.
-.. index:: vrrp (1-255) shutdown
-.. clicmd:: [no] vrrp (1-255) shutdown
+.. clicmd:: vrrp (1-255) shutdown
Place the router into administrative shutdown. VRRP will not activate for
this router until this command is removed with the ``no`` form.
@@ -419,7 +412,6 @@ Global Configuration
Show commands, global defaults and debugging configuration commands.
-.. index:: show vrrp [interface INTERFACE] [(1-255)] [json]
.. clicmd:: show vrrp [interface INTERFACE] [(1-255)] [json]
Shows VRRP status for some or all configured VRRP routers. Specifying an
@@ -427,8 +419,7 @@ Show commands, global defaults and debugging configuration commands.
VRID will only show routers with that VRID. Specifying ``json`` will dump
each router state in a JSON array.
-.. index:: debug vrrp [{protocol|autoconfigure|packets|sockets|ndisc|arp|zebra}]
-.. clicmd:: [no] debug vrrp [{protocol|autoconfigure|packets|sockets|ndisc|arp|zebra}]
+.. clicmd:: debug vrrp [{protocol|autoconfigure|packets|sockets|ndisc|arp|zebra}]
Toggle debugging logs for VRRP components.
If no component is specified, debugging for all components are turned on/off.
@@ -457,8 +448,7 @@ Show commands, global defaults and debugging configuration commands.
zebra
Logs communications with Zebra.
-.. index:: vrrp default <advertisement-interval (1-4096)|preempt|priority (1-254)|shutdown>
-.. clicmd:: [no] vrrp default <advertisement-interval (1-4096)|preempt|priority (1-254)|shutdown>
+.. clicmd:: vrrp default <advertisement-interval (1-4096)|preempt|priority (1-254)|shutdown>
Configure defaults for new VRRP routers. These values will not affect
already configured VRRP routers, but will be applied to newly configured
@@ -480,8 +470,7 @@ After configuring the interfaces as described in
:ref:`vrrp-system-configuration`, and configuring any defaults you may want,
execute the following command:
-.. index:: vrrp autoconfigure [version (2-3)]
-.. clicmd:: [no] vrrp autoconfigure [version (2-3)]
+.. clicmd:: vrrp autoconfigure [version (2-3)]
Generates VRRP configuration based on the interface configuration on the
base system. If the protocol version is not specified, the default is VRRPv3.
diff --git a/doc/user/vtysh.rst b/doc/user/vtysh.rst
index b1339f26e5..ec674e377c 100644
--- a/doc/user/vtysh.rst
+++ b/doc/user/vtysh.rst
@@ -22,7 +22,6 @@ administrator with an external editor.
have effect for vtysh) need to be manually updated in :file:`vtysh.conf`.
-.. index:: copy FILENAME running-config
.. clicmd:: copy FILENAME running-config
Process and load a configuration file manually; each line in the
@@ -52,8 +51,7 @@ and the :clicmd:`terminal paginate` command:
This variable should be set by the user according to their preferences,
in their :file:`~/.profile` file.
-.. index:: terminal paginate
-.. clicmd:: [no] terminal paginate
+.. clicmd:: terminal paginate
Enables/disables vtysh output pagination. This command is intended to
be placed in :file:`vtysh.conf` to set a system-wide default. If this
@@ -100,7 +98,6 @@ could be made SGID (set group ID) to the |INSTALL_VTY_GROUP| group.
No security guarantees are made for this configuration.
-.. index:: username USERNAME nopassword
.. clicmd:: username USERNAME nopassword
If PAM support is enabled at build-time, this command allows disabling the
@@ -162,11 +159,8 @@ it can lead to /all/ of your daemons being unable to start up. Per daemon files
are more robust as impact of errors in configuration are limited to the daemon
in whose file the error is made.
-.. index:: service integrated-vtysh-config
.. clicmd:: service integrated-vtysh-config
-.. index:: service integrated-vtysh-config
-.. clicmd:: no service integrated-vtysh-config
Control whether integrated :file:`frr.conf` file is written when
'write file' is issued.
@@ -195,7 +189,6 @@ in whose file the error is made.
preset one of the two operating modes and ensure consistent operation across
installations.
-.. index:: write integrated
.. clicmd:: write integrated
Unconditionally (regardless of ``service integrated-vtysh-config`` setting)
diff --git a/doc/user/watchfrr.rst b/doc/user/watchfrr.rst
index b29e602fe5..3a19e3c4fa 100644
--- a/doc/user/watchfrr.rst
+++ b/doc/user/watchfrr.rst
@@ -16,14 +16,12 @@ require end users management.
WATCHFRR commands
=================
-.. index:: show watchfrr
.. clicmd:: show watchfrr
Give status information about the state of the different daemons being
watched by WATCHFRR
-.. index:: watchfrr ignore DAEMON
-.. clicmd:: [no] watchfrr ignore DAEMON
+.. clicmd:: watchfrr ignore DAEMON
Tell WATCHFRR to ignore a particular DAEMON if it goes unresponsive.
This is particularly useful when you are a developer and need to debug
diff --git a/doc/user/wecmp_linkbw.rst b/doc/user/wecmp_linkbw.rst
index 6e516bcf9f..4df6559e5c 100644
--- a/doc/user/wecmp_linkbw.rst
+++ b/doc/user/wecmp_linkbw.rst
@@ -173,7 +173,6 @@ ECMP as recommended in [Draft-IETF-idr-link-bandwidth]_.
The operator can change these behaviors with the following configuration:
-.. index:: bgp bestpath bandwidth <ignore | skip-missing | default-weight-for-missing>
.. clicmd:: bgp bestpath bandwidth <ignore | skip-missing | default-weight-for-missing>
The different options imply behavior as follows:
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index a9979558c3..e5cd1de201 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -115,44 +115,30 @@ Interface Commands
Standard Commands
-----------------
-.. index:: interface IFNAME
.. clicmd:: interface IFNAME
-.. index:: interface IFNAME vrf VRF
.. clicmd:: interface IFNAME vrf VRF
-.. index:: shutdown
.. clicmd:: shutdown
-.. index:: shutdown
-.. clicmd:: no shutdown
Up or down the current interface.
-.. index:: ip address ADDRESS/PREFIX
.. clicmd:: ip address ADDRESS/PREFIX
-.. index:: ipv6 address ADDRESS/PREFIX
.. clicmd:: ipv6 address ADDRESS/PREFIX
-.. index:: ip address ADDRESS/PREFIX
-.. clicmd:: no ip address ADDRESS/PREFIX
-.. index:: ipv6 address ADDRESS/PREFIX
-.. clicmd:: no ipv6 address ADDRESS/PREFIX
Set the IPv4 or IPv6 address/prefix for the interface.
-.. index:: ip address LOCAL-ADDR peer PEER-ADDR/PREFIX
.. clicmd:: ip address LOCAL-ADDR peer PEER-ADDR/PREFIX
-.. index:: ip address LOCAL-ADDR peer PEER-ADDR/PREFIX
-.. clicmd:: no ip address LOCAL-ADDR peer PEER-ADDR/PREFIX
Configure an IPv4 Point-to-Point address on the interface. (The concept of
PtP addressing does not exist for IPv6.)
@@ -162,38 +148,28 @@ Standard Commands
behind the other end of the link (or even on the link in Point-to-Multipoint
setups), though generally /32s are used.
-.. index:: description DESCRIPTION ...
.. clicmd:: description DESCRIPTION ...
Set description for the interface.
-.. index:: multicast
.. clicmd:: multicast
-.. index:: multicast
-.. clicmd:: no multicast
Enable or disables multicast flag for the interface.
-.. index:: bandwidth (1-10000000)
.. clicmd:: bandwidth (1-10000000)
-.. index:: bandwidth (1-10000000)
-.. clicmd:: no bandwidth (1-10000000)
Set bandwidth value of the interface in kilobits/sec. This is for
calculating OSPF cost. This command does not affect the actual device
configuration.
-.. index:: link-detect
.. clicmd:: link-detect
-.. index:: link-detect
-.. clicmd:: no link-detect
Enable/disable link-detect on platforms which support this. Currently only
Linux, and only where network interface drivers support reporting
@@ -212,11 +188,8 @@ Link Parameters Commands
protocol extensions that can be used with MPLS-TE. FRR does not
support a complete RSVP-TE solution currently.
-.. index:: link-params
.. clicmd:: link-params
-.. index:: link-param
-.. clicmd:: no link-param
Enter into the link parameters sub node. At least 'enable' must be
set to activate the link parameters, and consequently routing
@@ -228,24 +201,18 @@ Link Parameters Commands
Under link parameter statement, the following commands set the different TE values:
-.. index:: link-params [enable]
.. clicmd:: link-params [enable]
Enable link parameters for this interface.
-.. index:: link-params [metric (0-4294967295)]
.. clicmd:: link-params [metric (0-4294967295)]
-.. index:: link-params max-bw BANDWIDTH
.. clicmd:: link-params max-bw BANDWIDTH
-.. index:: link-params max-rsv-bw BANDWIDTH
.. clicmd:: link-params max-rsv-bw BANDWIDTH
-.. index:: link-params unrsv-bw (0-7) BANDWIDTH
.. clicmd:: link-params unrsv-bw (0-7) BANDWIDTH
-.. index:: link-params admin-grp BANDWIDTH
.. clicmd:: link-params admin-grp BANDWIDTH
These commands specifies the Traffic Engineering parameters of the interface
@@ -258,22 +225,16 @@ Link Parameters Commands
Note that BANDIWDTH is specified in IEEE floating point format and express
in Bytes/second.
-.. index:: link-param delay (0-16777215) [min (0-16777215) | max (0-16777215)]
.. clicmd:: link-param delay (0-16777215) [min (0-16777215) | max (0-16777215)]
-.. index:: link-param delay-variation (0-16777215)
.. clicmd:: link-param delay-variation (0-16777215)
-.. index:: link-param packet-loss PERCENTAGE
.. clicmd:: link-param packet-loss PERCENTAGE
-.. index:: link-param res-bw BANDWIDTH
.. clicmd:: link-param res-bw BANDWIDTH
-.. index:: link-param ava-bw BANDWIDTH
.. clicmd:: link-param ava-bw BANDWIDTH
-.. index:: link-param use-bw BANDWIDTH
.. clicmd:: link-param use-bw BANDWIDTH
These command specifies additional Traffic Engineering parameters of the
@@ -287,17 +248,14 @@ Link Parameters Commands
(µs). Loss is specified in PERCENTAGE ranging from 0 to 50.331642% by step
of 0.000003.
-.. index:: link-param neighbor <A.B.C.D> as (0-65535)
.. clicmd:: link-param neighbor <A.B.C.D> as (0-65535)
-.. index:: link-param no neighbor
.. clicmd:: link-param no neighbor
Specifies the remote ASBR IP address and Autonomous System (AS) number
for InterASv2 link in OSPF (RFC5392). Note that this option is not yet
supported for ISIS (RFC5316).
-.. index:: ip nht resolve-via-default
.. clicmd:: ip nht resolve-via-default
Allows nexthop tracking to resolve via the default route. This is useful
@@ -427,7 +385,6 @@ see https://www.kernel.org/doc/Documentation/networking/vrf.txt.
Because of that difference, there are some subtle differences when running some
commands in relationship to VRF. Here is an extract of some of those commands:
-.. index:: vrf VRF
.. clicmd:: vrf VRF
This command is available on configuration mode. By default, above command
@@ -436,7 +393,6 @@ commands in relationship to VRF. Here is an extract of some of those commands:
The network administrator can however decide to provision this command in
configuration file to provide more clarity about the intended configuration.
-.. index:: netns NAMESPACE
.. clicmd:: netns NAMESPACE
This command is based on VRF configuration mode. This command is available
@@ -447,7 +403,6 @@ commands in relationship to VRF. Here is an extract of some of those commands:
decide to provision this command in configuration file to provide more clarity
about the intended configuration.
-.. index:: show ip route vrf VRF
.. clicmd:: show ip route vrf VRF
The show command permits dumping the routing table associated to the VRF. If
@@ -457,20 +412,17 @@ commands in relationship to VRF. Here is an extract of some of those commands:
launched with :option:`-n` option, this will be the default routing table of
the *Linux network namespace* ``VRF``.
-.. index:: show ip route vrf VRF table TABLENO
.. clicmd:: show ip route vrf VRF table TABLENO
The show command is only available with :option:`-n` option. This command
will dump the routing table ``TABLENO`` of the *Linux network namespace*
``VRF``.
-.. index:: show ip route vrf VRF tables
.. clicmd:: show ip route vrf VRF tables
This command will dump the routing tables within the vrf scope. If `vrf all`
is executed, all routing tables will be dumped.
-.. index:: show <ip|ipv6> route summary [vrf VRF] [table TABLENO] [prefix]
.. clicmd:: show <ip|ipv6> route summary [vrf VRF] [table TABLENO] [prefix]
This command will dump a summary output of the specified VRF and TABLENO
@@ -537,8 +489,7 @@ The push action is generally used for LER devices, which want to encapsulate
all traffic for a wished destination into an MPLS label. This action is stored
in routing entry, and can be configured like a route:
-.. index:: ip route NETWORK MASK GATEWAY|INTERFACE label LABEL
-.. clicmd:: [no] ip route NETWORK MASK GATEWAY|INTERFACE label LABEL
+.. clicmd:: ip route NETWORK MASK GATEWAY|INTERFACE label LABEL
NETWORK and MASK stand for the IP prefix entry to be added as static
route entry.
@@ -568,8 +519,7 @@ The swap action is generally used for LSR devices, which swap a packet with a
label, with an other label. The Pop action is used on LER devices, at the
termination of the MPLS traffic; this is used to remove MPLS header.
-.. index:: mpls lsp INCOMING_LABEL GATEWAY OUTGOING_LABEL|explicit-null|implicit-null
-.. clicmd:: [no] mpls lsp INCOMING_LABEL GATEWAY OUTGOING_LABEL|explicit-null|implicit-null
+.. clicmd:: mpls lsp INCOMING_LABEL GATEWAY OUTGOING_LABEL|explicit-null|implicit-null
INCOMING_LABEL and OUTGOING_LABEL are MPLS labels with values ranging from 16
to 1048575.
@@ -582,7 +532,6 @@ termination of the MPLS traffic; this is used to remove MPLS header.
You can check that the MPLS actions are stored in the zebra MPLS table, by looking at the
presence of the entry.
-.. index:: show mpls table
.. clicmd:: show mpls table
::
@@ -616,11 +565,8 @@ WARNING: RPF lookup results are non-responsive in this version of FRR,
i.e. multicast routing does not actively react to changes in underlying
unicast topology!
-.. index:: ip multicast rpf-lookup-mode MODE
.. clicmd:: ip multicast rpf-lookup-mode MODE
-.. index:: ip multicast rpf-lookup-mode [MODE]
-.. clicmd:: no ip multicast rpf-lookup-mode [MODE]
MODE sets the method used to perform RPF lookups. Supported modes:
@@ -650,10 +596,10 @@ unicast topology!
what the default behavior is.
.. warning::
+
Unreachable routes do not receive special treatment and do not cause
fallback to a second lookup.
-.. index:: show ip rpf ADDR
.. clicmd:: show ip rpf ADDR
Performs a Multicast RPF lookup, as configured with ``ip multicast
@@ -672,18 +618,14 @@ unicast topology!
Indicates that a multicast source lookup for 192.0.2.1 would use an
Unicast RIB entry for 192.0.2.0/24 with a gateway of 198.51.100.1.
-.. index:: show ip rpf
.. clicmd:: show ip rpf
Prints the entire Multicast RIB. Note that this is independent of the
configured RPF lookup mode, the Multicast RIB may be printed yet not
used at all.
-.. index:: ip mroute PREFIX NEXTHOP [DISTANCE]
.. clicmd:: ip mroute PREFIX NEXTHOP [DISTANCE]
-.. index:: ip mroute PREFIX NEXTHOP [DISTANCE]
-.. clicmd:: no ip mroute PREFIX NEXTHOP [DISTANCE]
Adds a static route entry to the Multicast RIB. This performs exactly as the
``ip route`` command, except that it inserts the route in the Multicast RIB
@@ -699,7 +641,6 @@ received from other FRR components. The permit/deny facilities provided by
these commands can be used to filter which routes zebra will install in the
kernel.
-.. index:: ip protocol PROTOCOL route-map ROUTEMAP
.. clicmd:: ip protocol PROTOCOL route-map ROUTEMAP
Apply a route-map filter to routes for the specified protocol. PROTOCOL can
@@ -728,7 +669,6 @@ kernel.
on a per vrf basis, by entering this command under vrf mode for the vrf you
want to apply the route-map against.
-.. index:: set src ADDRESS
.. clicmd:: set src ADDRESS
Within a route-map, set the preferred source address for matching routes
@@ -767,8 +707,7 @@ IPv6 example for OSPFv3.
not created at startup. On Debian, FRR might start before ifupdown
completes. Consider a reboot test.
-.. index:: zebra route-map delay-timer (0-600)
-.. clicmd:: [no] zebra route-map delay-timer (0-600)
+.. clicmd:: zebra route-map delay-timer (0-600)
Set the delay before any route-maps are processed in zebra. The
default time for this is 5 seconds.
@@ -842,21 +781,11 @@ FPM Commands
``fpm`` implementation
----------------------
-.. index:: fpm connection ip A.B.C.D port (1-65535)
.. clicmd:: fpm connection ip A.B.C.D port (1-65535)
- Configure ``zebra`` to connect to a different FPM server than
- ``127.0.0.1`` port ``2620``.
-
-
-.. index:: fpm connection ip A.B.C.D port (1-65535)
-.. clicmd:: no fpm connection ip A.B.C.D port (1-65535)
+ Configure ``zebra`` to connect to a different FPM server than the default of
+ ``127.0.0.1:2060``
- Configure ``zebra`` to connect to the default FPM server at ``127.0.0.1``
- port ``2620``.
-
-
-.. index:: show zebra fpm stats
.. clicmd:: show zebra fpm stats
Shows the FPM statistics.
@@ -892,7 +821,6 @@ FPM Commands
t_conn_up_finishes 1 0
-.. index:: clear zebra fpm stats
.. clicmd:: clear zebra fpm stats
Reset statistics related to the zebra code that interacts with the
@@ -902,35 +830,22 @@ FPM Commands
``dplane_fpm_nl`` implementation
--------------------------------
-.. index:: fpm address <A.B.C.D|X:X::X:X> [port (1-65535)]
.. clicmd:: fpm address <A.B.C.D|X:X::X:X> [port (1-65535)]
Configures the FPM server address. Once configured ``zebra`` will attempt
to connect to it immediately.
+ The ``no`` form disables FPM entirely. ``zebra`` will close any current
+ connections and will not attempt to connect to it anymore.
-.. index:: fpm address [<A.B.C.D|X:X::X:X> [port (1-65535)]]
-.. clicmd:: no fpm address [<A.B.C.D|X:X::X:X> [port (1-65535)]]
-
- Disables FPM entirely. ``zebra`` will close any current connections and
- will not attempt to connect to it anymore.
-
-
-.. index:: fpm use-next-hop-groups
.. clicmd:: fpm use-next-hop-groups
Use the new netlink messages ``RTM_NEWNEXTHOP`` / ``RTM_DELNEXTHOP`` to
group repeated route next hop information.
+ The ``no`` form uses the old known FPM behavior of including next hop
+ information in the route (e.g. ``RTM_NEWROUTE``) messages.
-.. index:: fpm use-next-hop-groups
-.. clicmd:: no fpm use-next-hop-groups
-
- Use the old known FPM behavior of including next hop information in the
- route (e.g. ``RTM_NEWROUTE``) messages.
-
-
-.. index:: show fpm counters [json]
.. clicmd:: show fpm counters [json]
Show the FPM statistics (plain text or JSON formatted).
@@ -955,7 +870,6 @@ FPM Commands
User FPM disable requests: 0
-.. index:: clear fpm counters
.. clicmd:: clear fpm counters
Reset statistics related to the zebra code that interacts with the
@@ -974,14 +888,12 @@ interface IP addresses. The dataplane runs in its own pthread, in
order to off-load work from the main zebra pthread.
-.. index:: show zebra dplane [detailed]
.. clicmd:: show zebra dplane [detailed]
Display statistics about the updates and events passing through the
dataplane subsystem.
-.. index:: show zebra dplane providers
.. clicmd:: show zebra dplane providers
Display information about the running dataplane plugins that are
@@ -989,7 +901,6 @@ order to off-load work from the main zebra pthread.
present.
-.. index:: zebra dplane limit [NUMBER]
.. clicmd:: zebra dplane limit [NUMBER]
Configure the limit on the number of pending updates that are
@@ -999,7 +910,6 @@ order to off-load work from the main zebra pthread.
zebra Terminal Mode Commands
============================
-.. index:: show ip route
.. clicmd:: show ip route
Display current routes which zebra holds in its database.
@@ -1016,19 +926,15 @@ zebra Terminal Mode Commands
C* 203.181.89.240/28 eth0
-.. index:: show ipv6 route
.. clicmd:: show ipv6 route
-.. index:: show [ip|ipv6] route [PREFIX] [nexthop-group]
.. clicmd:: show [ip|ipv6] route [PREFIX] [nexthop-group]
Display detailed information about a route. If [nexthop-group] is
included, it will display the nexthop group ID the route is using as well.
-.. index:: show interface [NAME] [{vrf VRF|brief}] [nexthop-group]
.. clicmd:: show interface [NAME] [{vrf VRF|brief}] [nexthop-group]
-.. index:: show interface [NAME] [{vrf all|brief}] [nexthop-group]
.. clicmd:: show interface [NAME] [{vrf all|brief}] [nexthop-group]
Display interface information. If no extra information is added, it will
@@ -1036,34 +942,27 @@ zebra Terminal Mode Commands
detailed information about that single interface. If [nexthop-group] is
specified, it will display nexthop groups pointing out that interface.
-.. index:: show ip prefix-list [NAME]
.. clicmd:: show ip prefix-list [NAME]
-.. index:: show route-map [NAME]
.. clicmd:: show route-map [NAME]
-.. index:: show ip protocol
.. clicmd:: show ip protocol
-.. index:: show ip forward
.. clicmd:: show ip forward
Display whether the host's IP forwarding function is enabled or not.
Almost any UNIX kernel can be configured with IP forwarding disabled.
If so, the box can't work as a router.
-.. index:: show ipv6 forward
.. clicmd:: show ipv6 forward
Display whether the host's IP v6 forwarding is enabled or not.
-.. index:: show zebra
.. clicmd:: show zebra
Display various statistics related to the installation and deletion
of routes, neighbor updates, and LSP's into the kernel.
-.. index:: show zebra client [summary]
.. clicmd:: show zebra client [summary]
Display statistics about clients that are connected to zebra. This is
@@ -1071,7 +970,6 @@ zebra Terminal Mode Commands
zebra and it's clients. If the summary form of the command is choosen
a table is displayed with shortened information.
-.. index:: show zebra router table summary
.. clicmd:: show zebra router table summary
Display summarized data about tables created, their afi/safi/tableid
@@ -1079,7 +977,6 @@ zebra Terminal Mode Commands
total number of route nodes in the table. Which will be higher than
the actual number of routes that are held.
-.. index:: show nexthop-group rib [ID] [vrf NAME] [singleton [ip|ip6]] [type]
.. clicmd:: show nexthop-group rib [ID] [vrf NAME] [singleton [ip|ip6]] [type]
Display nexthop groups created by zebra. The [vrf NAME] option
@@ -1097,34 +994,29 @@ Many routing protocols require a router-id to be configured. To have a
consistent router-id across all daemons, the following commands are available
to configure and display the router-id:
-.. index:: router-id A.B.C.D
-.. clicmd:: [no] [ip] router-id A.B.C.D
+.. clicmd:: [ip] router-id A.B.C.D
Allow entering of the router-id. This command also works under the
vrf subnode, to allow router-id's per vrf.
-.. index:: router-id A.B.C.D vrf NAME
-.. clicmd:: [no] [ip] router-id A.B.C.D vrf NAME
+.. clicmd:: [ip] router-id A.B.C.D vrf NAME
Configure the router-id of this router from the configure NODE.
A show run of this command will display the router-id command
under the vrf sub node. This command is deprecated and will
be removed at some point in time in the future.
-.. index:: show [ip] router-id [vrf NAME]
.. clicmd:: show [ip] router-id [vrf NAME]
Display the user configured router-id.
For protocols requiring an IPv6 router-id, the following commands are available:
-.. index:: ipv6 router-id X:X::X:X
-.. clicmd:: [no] ipv6 router-id X:X::X:X
+.. clicmd:: ipv6 router-id X:X::X:X
Configure the IPv6 router-id of this router. Like its IPv4 counterpart,
this command works under the vrf subnode, to allow router-id's per vrf.
-.. index:: show ipv6 router-id [vrf NAME]
.. clicmd:: show ipv6 router-id [vrf NAME]
Display the user configured IPv6 router-id.
diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c
index 252cd647a2..7eee254627 100644
--- a/eigrpd/eigrp_packet.c
+++ b/eigrpd/eigrp_packet.c
@@ -572,17 +572,11 @@ int eigrp_read(struct thread *thread)
/* If incoming interface is passive one, ignore it. */
if (eigrp_if_is_passive(ei)) {
- char buf[3][INET_ADDRSTRLEN];
-
if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
zlog_debug(
- "ignoring packet from router %s sent to %s, received on a passive interface, %s",
- inet_ntop(AF_INET, &eigrph->vrid, buf[0],
- sizeof(buf[0])),
- inet_ntop(AF_INET, &iph->ip_dst, buf[1],
- sizeof(buf[1])),
- inet_ntop(AF_INET, &ei->address.u.prefix4,
- buf[2], sizeof(buf[2])));
+ "ignoring packet from router %u sent to %pI4, received on a passive interface, %pI4",
+ ntohs(eigrph->vrid), &iph->ip_dst,
+ &ei->address.u.prefix4);
if (iph->ip_dst.s_addr == htonl(EIGRP_MULTICAST_ADDRESS)) {
eigrp_if_set_multicast(ei);
diff --git a/eigrpd/eigrp_zebra.c b/eigrpd/eigrp_zebra.c
index e79123e6b4..7c765248c6 100644
--- a/eigrpd/eigrp_zebra.c
+++ b/eigrpd/eigrp_zebra.c
@@ -231,9 +231,7 @@ void eigrp_zebra_route_add(struct eigrp *eigrp, struct prefix *p,
api.nexthop_num = count;
if (IS_DEBUG_EIGRP(zebra, ZEBRA_REDISTRIBUTE)) {
- char buf[PREFIX_STRLEN];
- zlog_debug("Zebra: Route add %pFX nexthop %s", p,
- inet_ntop(AF_INET, 0, buf, PREFIX_STRLEN));
+ zlog_debug("Zebra: Route add %pFX", p);
}
zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index 71d4758163..3c3a68764e 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -49,13 +49,21 @@
#include "isisd/fabricd.h"
#include "isisd/isis_nb.h"
-static struct isis_adjacency *adj_alloc(const uint8_t *id)
+static struct isis_adjacency *adj_alloc(struct isis_circuit *circuit,
+ const uint8_t *id)
{
struct isis_adjacency *adj;
adj = XCALLOC(MTYPE_ISIS_ADJACENCY, sizeof(struct isis_adjacency));
memcpy(adj->sysid, id, ISIS_SYS_ID_LEN);
+ adj->snmp_idx = ++circuit->snmp_adj_idx_gen;
+
+ if (circuit->snmp_adj_list == NULL)
+ circuit->snmp_adj_list = list_new();
+
+ adj->snmp_list_node = listnode_add(circuit->snmp_adj_list, adj);
+
return adj;
}
@@ -65,7 +73,7 @@ struct isis_adjacency *isis_new_adj(const uint8_t *id, const uint8_t *snpa,
struct isis_adjacency *adj;
int i;
- adj = adj_alloc(id); /* P2P kludge */
+ adj = adj_alloc(circuit, id); /* P2P kludge */
if (snpa) {
memcpy(adj->snpa, snpa, ETH_ALEN);
@@ -146,6 +154,8 @@ void isis_delete_adj(void *arg)
if (!adj)
return;
+ /* Remove self from snmp list without walking the list*/
+ list_delete_node(adj->circuit->snmp_adj_list, adj->snmp_list_node);
thread_cancel(&adj->t_expire);
if (adj->adj_state != ISIS_ADJ_DOWN)
@@ -292,7 +302,6 @@ void isis_adj_state_change(struct isis_adjacency **padj,
if (circuit->area->log_adj_changes)
isis_log_adj_change(adj, old_state, new_state, reason);
- circuit->adj_state_changes++;
#ifndef FABRICD
/* send northbound notification */
isis_notif_adj_state_change(adj, new_state, reason);
@@ -303,12 +312,14 @@ void isis_adj_state_change(struct isis_adjacency **padj,
if ((adj->level & level) == 0)
continue;
if (new_state == ISIS_ADJ_UP) {
+ circuit->adj_state_changes++;
circuit->upadjcount[level - 1]++;
/* update counter & timers for debugging
* purposes */
adj->last_flap = time(NULL);
adj->flaps++;
} else if (old_state == ISIS_ADJ_UP) {
+ circuit->adj_state_changes++;
listnode_delete(circuit->u.bc.adjdb[level - 1],
adj);
diff --git a/isisd/isis_adjacency.h b/isisd/isis_adjacency.h
index 2780d826f5..3afb7209f3 100644
--- a/isisd/isis_adjacency.h
+++ b/isisd/isis_adjacency.h
@@ -105,6 +105,8 @@ struct isis_adjacency {
unsigned int mt_count; /* Number of entries in mt_set */
struct bfd_session *bfd_session;
struct list *adj_sids; /* Segment Routing Adj-SIDs. */
+ uint32_t snmp_idx;
+ struct listnode *snmp_list_node;
};
struct isis_threeway_adj;
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 4aac3f8880..62822cbf89 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -71,6 +71,48 @@ DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp))
int isis_if_new_hook(struct interface *);
int isis_if_delete_hook(struct interface *);
+static int isis_circuit_smmp_id_gen(struct isis_circuit *circuit)
+{
+ struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct isis *isis = NULL;
+ uint32_t id;
+ uint32_t i;
+
+ isis = isis_lookup_by_vrfid(vrf->vrf_id);
+ if (isis == NULL)
+ return 0;
+
+ id = isis->snmp_circuit_id_last;
+ id++;
+
+ /* find next unused entry */
+ for (i = 0; i < SNMP_CIRCUITS_MAX; i++) {
+ if (id >= SNMP_CIRCUITS_MAX) {
+ id = 0;
+ continue;
+ }
+
+ if (id == 0)
+ continue;
+
+ if (isis->snmp_circuits[id] == NULL)
+ break;
+
+ id++;
+ }
+
+ if (i == SNMP_CIRCUITS_MAX) {
+ zlog_warn("Could not allocate a smmp-circuit-id");
+ return 0;
+ }
+
+ isis->snmp_circuits[id] = circuit;
+ isis->snmp_circuit_id_last = id;
+ circuit->snmp_id = id;
+
+ return 1;
+}
+
struct isis_circuit *isis_circuit_new(struct isis *isis)
{
struct isis_circuit *circuit;
@@ -80,6 +122,12 @@ struct isis_circuit *isis_circuit_new(struct isis *isis)
circuit->isis = isis;
/*
+ * Note: if snmp-id generation failed circuit will fail
+ * up operation
+ */
+ isis_circuit_smmp_id_gen(circuit);
+
+ /*
* Default values
*/
#ifndef FABRICD
@@ -150,11 +198,18 @@ struct isis_circuit *isis_circuit_new(struct isis *isis)
void isis_circuit_del(struct isis_circuit *circuit)
{
+ struct isis *isis = NULL;
+
if (!circuit)
return;
QOBJ_UNREG(circuit);
+ if (circuit->interface) {
+ isis = isis_lookup_by_vrfid(circuit->interface->vrf_id);
+ isis->snmp_circuits[circuit->snmp_id] = NULL;
+ }
+
isis_circuit_if_unbind(circuit, circuit->interface);
circuit_mt_finish(circuit);
@@ -609,6 +664,7 @@ int isis_circuit_up(struct isis_circuit *circuit)
return ISIS_OK;
if (circuit->is_passive) {
+ circuit->last_uptime = time(NULL);
/* make sure the union fields are initialized, else we
* could end with garbage values from a previous circuit
* type, which would then cause a segfault when building
@@ -623,6 +679,13 @@ int isis_circuit_up(struct isis_circuit *circuit)
return ISIS_OK;
}
+ if (circuit->snmp_id == 0) {
+ /* We cannot bring circuit up if does not have snmp-id */
+ flog_err(EC_ISIS_CONFIG,
+ "No snnmp-id: there are too many circuits:");
+ return ISIS_ERROR;
+ }
+
if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) {
flog_err(
EC_ISIS_CONFIG,
@@ -722,6 +785,8 @@ int isis_circuit_up(struct isis_circuit *circuit)
circuit->tx_queue = isis_tx_queue_new(circuit, send_lsp);
+ circuit->last_uptime = time(NULL);
+
#ifndef FABRICD
/* send northbound notification */
isis_notif_if_state_change(circuit, false);
@@ -828,6 +893,15 @@ void isis_circuit_down(struct isis_circuit *circuit)
thread_cancel(&circuit->u.p2p.t_send_p2p_hello);
}
+ /*
+ * All adjacencies have to be gone, delete snmp list
+ * and reset snmpd idx generator
+ */
+ if (circuit->snmp_adj_list != NULL)
+ list_delete(&circuit->snmp_adj_list);
+
+ circuit->snmp_adj_idx_gen = 0;
+
/* Cancel all active threads */
thread_cancel(&circuit->t_send_csnp[0]);
thread_cancel(&circuit->t_send_csnp[1]);
diff --git a/isisd/isis_circuit.h b/isisd/isis_circuit.h
index 3387232da2..15d58bd736 100644
--- a/isisd/isis_circuit.h
+++ b/isisd/isis_circuit.h
@@ -79,6 +79,7 @@ struct isis_circuit_arg {
struct isis_circuit {
int state;
uint8_t circuit_id; /* l1/l2 bcast CircuitID */
+ time_t last_uptime;
struct isis *isis;
struct isis_area *area; /* back pointer to the area */
struct interface *interface; /* interface info from z */
@@ -115,6 +116,8 @@ struct isis_circuit {
int pad_hellos; /* add padding to Hello PDUs ? */
char ext_domain; /* externalDomain (boolean) */
int lsp_regenerate_pending[ISIS_LEVELS];
+ uint64_t lsp_error_counter;
+
/*
* Configurables
*/
@@ -165,6 +168,12 @@ struct isis_circuit {
uint32_t auth_type_failures; /*authentication-type-fails */
uint32_t auth_failures; /* authentication-fails */
+ uint32_t snmp_id; /* Circuit id in snmp */
+
+ uint32_t snmp_adj_idx_gen; /* Create unique id for adjacency on creation
+ */
+ struct list *snmp_adj_list; /* List in id order */
+
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(isis_circuit)
diff --git a/isisd/isis_cli.c b/isisd/isis_cli.c
index b48da9312f..fb9721e8b3 100644
--- a/isisd/isis_cli.c
+++ b/isisd/isis_cli.c
@@ -1596,93 +1596,120 @@ void cli_show_isis_sr_enabled(struct vty *vty, struct lyd_node *dnode,
}
/*
- * XPath: /frr-isisd:isis/instance/segment-routing/srgb
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-block
*/
-DEFPY_YANG (isis_sr_global_block_label_range,
- isis_sr_global_block_label_range_cmd,
- "segment-routing global-block (16-1048575)$lower_bound (16-1048575)$upper_bound",
- SR_STR
- "Segment Routing Global Block label range\n"
- "The lower bound of the block\n"
- "The upper bound of the block (block size may not exceed 65535)\n")
+
+DEFPY_YANG(
+ isis_sr_global_block_label_range, isis_sr_global_block_label_range_cmd,
+ "segment-routing global-block (16-1048575)$gb_lower_bound (16-1048575)$gb_upper_bound [local-block (16-1048575)$lb_lower_bound (16-1048575)$lb_upper_bound]",
+ SR_STR
+ "Segment Routing Global Block label range\n"
+ "The lower bound of the global block\n"
+ "The upper bound of the global block (block size may not exceed 65535)\n"
+ "Segment Routing Local Block label range\n"
+ "The lower bound of the local block\n"
+ "The upper bound of the local block (block size may not exceed 65535)\n")
{
- nb_cli_enqueue_change(vty, "./segment-routing/srgb/lower-bound",
- NB_OP_MODIFY, lower_bound_str);
- nb_cli_enqueue_change(vty, "./segment-routing/srgb/upper-bound",
- NB_OP_MODIFY, upper_bound_str);
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srgb/lower-bound",
+ NB_OP_MODIFY, gb_lower_bound_str);
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srgb/upper-bound",
+ NB_OP_MODIFY, gb_upper_bound_str);
+
+ nb_cli_enqueue_change(
+ vty, "./segment-routing/label-blocks/srlb/lower-bound",
+ NB_OP_MODIFY, lb_lower_bound ? lb_lower_bound_str : NULL);
+ nb_cli_enqueue_change(
+ vty, "./segment-routing/label-blocks/srlb/upper-bound",
+ NB_OP_MODIFY, lb_upper_bound ? lb_upper_bound_str : NULL);
return nb_cli_apply_changes(vty, NULL);
}
-DEFPY_YANG (no_isis_sr_global_block_label_range,
- no_isis_sr_global_block_label_range_cmd,
- "no segment-routing global-block [(16-1048575) (16-1048575)]",
- NO_STR
- SR_STR
- "Segment Routing Global Block label range\n"
- "The lower bound of the block\n"
- "The upper bound of the block (block size may not exceed 65535)\n")
+DEFPY_YANG(no_isis_sr_global_block_label_range,
+ no_isis_sr_global_block_label_range_cmd,
+ "no segment-routing global-block [(16-1048575) (16-1048575) local-block (16-1048575) (16-1048575)]",
+ NO_STR SR_STR
+ "Segment Routing Global Block label range\n"
+ "The lower bound of the global block\n"
+ "The upper bound of the global block (block size may not exceed 65535)\n"
+ "Segment Routing Local Block label range\n"
+ "The lower bound of the local block\n"
+ "The upper bound of the local block (block size may not exceed 65535)\n")
{
- nb_cli_enqueue_change(vty, "./segment-routing/srgb/lower-bound",
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srgb/lower-bound",
+ NB_OP_MODIFY, NULL);
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srgb/upper-bound",
+ NB_OP_MODIFY, NULL);
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srlb/lower-bound",
NB_OP_MODIFY, NULL);
- nb_cli_enqueue_change(vty, "./segment-routing/srgb/upper-bound",
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srlb/upper-bound",
NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_srgb(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
+void cli_show_isis_label_blocks(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults)
{
- vty_out(vty, " segment-routing global-block %s %s\n",
- yang_dnode_get_string(dnode, "./lower-bound"),
- yang_dnode_get_string(dnode, "./upper-bound"));
+ vty_out(vty, " segment-routing global-block %s %s",
+ yang_dnode_get_string(dnode, "./srgb/lower-bound"),
+ yang_dnode_get_string(dnode, "./srgb/upper-bound"));
+ if (!yang_dnode_is_default(dnode, "./srlb/lower-bound")
+ || !yang_dnode_is_default(dnode, "./srlb/upper-bound"))
+ vty_out(vty, " local-block %s %s",
+ yang_dnode_get_string(dnode, "./srlb/lower-bound"),
+ yang_dnode_get_string(dnode, "./srlb/upper-bound"));
+ vty_out(vty, "\n");
}
/*
* XPath: /frr-isisd:isis/instance/segment-routing/srlb
*/
-DEFPY_YANG (isis_sr_local_block_label_range,
- isis_sr_local_block_label_range_cmd,
- "segment-routing local-block (16-1048575)$lower_bound (16-1048575)$upper_bound",
- SR_STR
- "Segment Routing Local Block label range\n"
- "The lower bound of the block\n"
- "The upper bound of the block (block size may not exceed 65535)\n")
-{
- nb_cli_enqueue_change(vty, "./segment-routing/srlb/lower-bound",
+DEFPY_HIDDEN(
+ isis_sr_local_block_label_range, isis_sr_local_block_label_range_cmd,
+ "segment-routing local-block (16-1048575)$lower_bound (16-1048575)$upper_bound",
+ SR_STR
+ "Segment Routing Local Block label range\n"
+ "The lower bound of the block\n"
+ "The upper bound of the block (block size may not exceed 65535)\n")
+{
+#if CONFDATE > 20220217
+CPP_NOTICE("Use of the local-block command is deprecated")
+#endif
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srlb/lower-bound",
NB_OP_MODIFY, lower_bound_str);
- nb_cli_enqueue_change(vty, "./segment-routing/srlb/upper-bound",
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srlb/upper-bound",
NB_OP_MODIFY, upper_bound_str);
return nb_cli_apply_changes(vty, NULL);
}
-DEFPY_YANG (no_isis_sr_local_block_label_range,
- no_isis_sr_local_block_label_range_cmd,
- "no segment-routing local-block [(16-1048575) (16-1048575)]",
- NO_STR
- SR_STR
- "Segment Routing Local Block label range\n"
- "The lower bound of the block\n"
- "The upper bound of the block (block size may not exceed 65535)\n")
+DEFPY_HIDDEN(no_isis_sr_local_block_label_range,
+ no_isis_sr_local_block_label_range_cmd,
+ "no segment-routing local-block [(16-1048575) (16-1048575)]",
+ NO_STR SR_STR
+ "Segment Routing Local Block label range\n"
+ "The lower bound of the block\n"
+ "The upper bound of the block (block size may not exceed 65535)\n")
{
- nb_cli_enqueue_change(vty, "./segment-routing/srlb/lower-bound",
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srlb/lower-bound",
NB_OP_MODIFY, NULL);
- nb_cli_enqueue_change(vty, "./segment-routing/srlb/upper-bound",
+ nb_cli_enqueue_change(vty,
+ "./segment-routing/label-blocks/srlb/upper-bound",
NB_OP_MODIFY, NULL);
return nb_cli_apply_changes(vty, NULL);
}
-void cli_show_isis_srlb(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults)
-{
- vty_out(vty, " segment-routing local-block %s %s\n",
- yang_dnode_get_string(dnode, "./lower-bound"),
- yang_dnode_get_string(dnode, "./upper-bound"));
-}
-
/*
* XPath: /frr-isisd:isis/instance/segment-routing/msd/node-msd
*/
diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c
index f6175fe9a4..e09e23aaeb 100644
--- a/isisd/isis_dr.c
+++ b/isisd/isis_dr.c
@@ -97,6 +97,7 @@ static int isis_check_dr_change(struct isis_adjacency *adj, int level)
/* was there a DIS state transition ? */
{
adj->dischanges[level - 1]++;
+ adj->circuit->desig_changes[level - 1]++;
/* ok rotate the history list through */
for (i = DIS_RECORDS - 1; i > 0; i--) {
adj->dis_record[(i * ISIS_LEVELS) + level - 1].dis =
diff --git a/isisd/isis_dynhn.c b/isisd/isis_dynhn.c
index 244f388c26..d2c5d93e25 100644
--- a/isisd/isis_dynhn.c
+++ b/isisd/isis_dynhn.c
@@ -166,3 +166,38 @@ void dynhn_print_all(struct vty *vty, struct isis *isis)
cmd_hostname_get());
return;
}
+
+struct isis_dynhn *dynhn_snmp_next(const uint8_t *id, int level)
+{
+ struct listnode *node = NULL;
+ struct isis_dynhn *dyn = NULL;
+ struct isis_dynhn *found_dyn = NULL;
+ int res;
+
+ for (ALL_LIST_ELEMENTS_RO(dyn_cache, node, dyn)) {
+ res = memcmp(dyn->id, id, ISIS_SYS_ID_LEN);
+
+ if (res < 0)
+ continue;
+
+ if (res == 0 && dyn->level <= level)
+ continue;
+
+ if (res == 0) {
+ /*
+ * This is the best match, we can stop
+ * searching
+ */
+
+ found_dyn = dyn;
+ break;
+ }
+
+ if (found_dyn == NULL
+ || memcmp(dyn->id, found_dyn->id, ISIS_SYS_ID_LEN) < 0) {
+ found_dyn = dyn;
+ }
+ }
+
+ return found_dyn;
+}
diff --git a/isisd/isis_dynhn.h b/isisd/isis_dynhn.h
index 973fde8307..8d25582e49 100644
--- a/isisd/isis_dynhn.h
+++ b/isisd/isis_dynhn.h
@@ -38,4 +38,7 @@ struct isis_dynhn *dynhn_find_by_id(const uint8_t *id);
struct isis_dynhn *dynhn_find_by_name(const char *hostname);
void dynhn_print_all(struct vty *vty, struct isis *isis);
+/* Snmp support */
+struct isis_dynhn *dynhn_snmp_next(const uint8_t *id, int level);
+
#endif /* _ZEBRA_ISIS_DYNHN_H */
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c
index 5b3a3827a2..3ebac8aaa9 100644
--- a/isisd/isis_lfa.c
+++ b/isisd/isis_lfa.c
@@ -541,10 +541,16 @@ static int tilfa_repair_list_apply(struct isis_spftree *spftree,
struct isis_spf_adj *sadj = vadj->sadj;
struct mpls_label_stack *label_stack;
+ /*
+ * Don't try to apply the repair list if one was already applied
+ * before (can't have ECMP past the P-node).
+ */
+ if (vadj->label_stack)
+ continue;
+
if (!isis_vertex_adj_exists(spftree, vertex_pnode, sadj))
continue;
- assert(!vadj->label_stack);
label_stack = tilfa_compute_label_stack(spftree->lspdb, sadj,
repair_list);
if (!label_stack) {
@@ -663,6 +669,21 @@ static int tilfa_build_repair_list(struct isis_spftree *spftree_pc,
if ((!is_qnode
|| spftree_pc->lfa.protected_resource.type == LFA_NODE_PROTECTION)
&& vertex_child) {
+ /*
+ * If vertex is the penultimate hop router, then pushing an
+ * Adj-SID towards the final hop means that the No-PHP flag of
+ * the original Prefix-SID must be honored. We do that by
+ * removing the previously added Prefix-SID from the repair list
+ * when those conditions are met.
+ */
+ if (vertex->depth == (vertex_dest->depth - 2)
+ && VTYPE_IP(vertex_dest->type)
+ && vertex_dest->N.ip.sr.present
+ && !CHECK_FLAG(vertex_dest->N.ip.sr.sid.flags,
+ ISIS_PREFIX_SID_NO_PHP)) {
+ list_delete_all_node(repair_list);
+ }
+
label_qnode = tilfa_find_qnode_adj_sid(spftree_pc, vertex->N.id,
vertex_child->N.id);
if (label_qnode == MPLS_INVALID_LABEL) {
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 6d2303817b..06a5a69e3f 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -324,8 +324,8 @@ void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno)
/* check for overflow */
if (newseq < lsp->hdr.seqno) {
/* send northbound notification */
- isis_notif_lsp_exceed_max(lsp->area,
- rawlspid_print(lsp->hdr.lsp_id));
+ lsp->area->lsp_exceeded_max_counter++;
+ isis_notif_lsp_exceed_max(lsp->area, lsp->hdr.lsp_id);
}
#endif /* ifndef FABRICD */
@@ -691,8 +691,8 @@ static void lsp_set_time(struct isis_lsp *lsp)
stream_putw_at(lsp->pdu, 10, lsp->hdr.rem_lifetime);
}
-void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
- struct isis *isis)
+void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
+ char frag, struct isis *isis)
{
struct isis_dynhn *dyn = NULL;
char id[SYSID_STRLEN];
@@ -710,10 +710,10 @@ void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
memcpy(id, sysid_print(lsp_id), 15);
if (frag)
- sprintf(dest, "%s.%02x-%02x", id, LSP_PSEUDO_ID(lsp_id),
- LSP_FRAGMENT(lsp_id));
+ snprintf(dest, dest_len, "%s.%02x-%02x", id,
+ LSP_PSEUDO_ID(lsp_id), LSP_FRAGMENT(lsp_id));
else
- sprintf(dest, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
+ snprintf(dest, dest_len, "%s.%02x", id, LSP_PSEUDO_ID(lsp_id));
}
/* Convert the lsp attribute bits to attribute string */
@@ -747,7 +747,7 @@ void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
char age_out[8];
char b[200];
- lspid_print(lsp->hdr.lsp_id, LSPid, dynhost, 1, isis);
+ lspid_print(lsp->hdr.lsp_id, LSPid, sizeof(LSPid), dynhost, 1, isis);
vty_out(vty, "%-21s%c ", LSPid, lsp->own_lsp ? '*' : ' ');
vty_out(vty, "%5hu ", lsp->hdr.pdu_len);
vty_out(vty, "0x%08x ", lsp->hdr.seqno);
@@ -1357,8 +1357,8 @@ int lsp_generate(struct isis_area *area, int level)
#ifndef FABRICD
/* send northbound notification */
- isis_notif_lsp_gen(area, rawlspid_print(newlsp->hdr.lsp_id),
- newlsp->hdr.seqno, newlsp->last_generated);
+ isis_notif_lsp_gen(area, newlsp->hdr.lsp_id, newlsp->hdr.seqno,
+ newlsp->last_generated);
#endif /* ifndef FABRICD */
return ISIS_OK;
diff --git a/isisd/isis_lsp.h b/isisd/isis_lsp.h
index 0783036e49..896d957607 100644
--- a/isisd/isis_lsp.h
+++ b/isisd/isis_lsp.h
@@ -116,8 +116,8 @@ void lsp_update(struct isis_lsp *lsp, struct isis_lsp_hdr *hdr,
struct isis_tlvs *tlvs, struct stream *stream,
struct isis_area *area, int level, bool confusion);
void lsp_inc_seqno(struct isis_lsp *lsp, uint32_t seqno);
-void lspid_print(uint8_t *lsp_id, char *dest, char dynhost, char frag,
- struct isis *isis);
+void lspid_print(uint8_t *lsp_id, char *dest, size_t dest_len, char dynhost,
+ char frag, struct isis *isis);
void lsp_print(struct isis_lsp *lsp, struct vty *vty, char dynhost,
struct isis *isis);
void lsp_print_detail(struct isis_lsp *lsp, struct vty *vty, char dynhost,
diff --git a/isisd/isis_misc.c b/isisd/isis_misc.c
index 6e9cbaf98e..d3d081d376 100644
--- a/isisd/isis_misc.c
+++ b/isisd/isis_misc.c
@@ -59,27 +59,30 @@ char nlpidstring[30];
const char *isonet_print(const uint8_t *from, int len)
{
int i = 0;
- char *pos = isonet;
+ char tbuf[4];
+ isonet[0] = '\0';
if (!from)
return "unknown";
while (i < len) {
if (i & 1) {
- sprintf(pos, "%02x", *(from + i));
- pos += 2;
+ snprintf(tbuf, sizeof(tbuf), "%02x", *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
} else {
if (i == (len - 1)) { /* No dot at the end of address */
- sprintf(pos, "%02x", *(from + i));
- pos += 2;
+ snprintf(tbuf, sizeof(tbuf), "%02x",
+ *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
} else {
- sprintf(pos, "%02x.", *(from + i));
- pos += 3;
+ snprintf(tbuf, sizeof(tbuf), "%02x.",
+ *(from + i));
+ strlcat(isonet, tbuf, sizeof(isonet));
}
}
i++;
}
- *(pos) = '\0';
+
return isonet;
}
@@ -202,17 +205,18 @@ const char *nlpid2str(uint8_t nlpid)
char *nlpid2string(struct nlpids *nlpids)
{
- char *pos = nlpidstring;
int i;
+ char tbuf[256];
+ nlpidstring[0] = '\0';
for (i = 0; i < nlpids->count; i++) {
- pos += sprintf(pos, "%s", nlpid2str(nlpids->nlpids[i]));
+ snprintf(tbuf, sizeof(tbuf), "%s",
+ nlpid2str(nlpids->nlpids[i]));
+ strlcat(nlpidstring, tbuf, sizeof(nlpidstring));
if (nlpids->count - i > 1)
- pos += sprintf(pos, ", ");
+ strlcat(nlpidstring, ", ", sizeof(nlpidstring));
}
- *(pos) = '\0';
-
return nlpidstring;
}
@@ -359,34 +363,47 @@ const char *isis_format_id(const uint8_t *id, size_t len)
const char *time2string(uint32_t time)
{
- char *pos = datestring;
uint32_t rest;
+ char tbuf[32];
+ datestring[0] = '\0';
if (time == 0)
return "-";
- if (time / SECS_PER_YEAR)
- pos += sprintf(pos, "%uY", time / SECS_PER_YEAR);
+ if (time / SECS_PER_YEAR) {
+ snprintf(tbuf, sizeof(tbuf), "%uY", time / SECS_PER_YEAR);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = time % SECS_PER_YEAR;
- if (rest / SECS_PER_MONTH)
- pos += sprintf(pos, "%uM", rest / SECS_PER_MONTH);
+ if (rest / SECS_PER_MONTH) {
+ snprintf(tbuf, sizeof(tbuf), "%uM", rest / SECS_PER_MONTH);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_MONTH;
- if (rest / SECS_PER_WEEK)
- pos += sprintf(pos, "%uw", rest / SECS_PER_WEEK);
+ if (rest / SECS_PER_WEEK) {
+ snprintf(tbuf, sizeof(tbuf), "%uw", rest / SECS_PER_WEEK);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_WEEK;
- if (rest / SECS_PER_DAY)
- pos += sprintf(pos, "%ud", rest / SECS_PER_DAY);
+ if (rest / SECS_PER_DAY) {
+ snprintf(tbuf, sizeof(tbuf), "%ud", rest / SECS_PER_DAY);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_DAY;
- if (rest / SECS_PER_HOUR)
- pos += sprintf(pos, "%uh", rest / SECS_PER_HOUR);
+ if (rest / SECS_PER_HOUR) {
+ snprintf(tbuf, sizeof(tbuf), "%uh", rest / SECS_PER_HOUR);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_HOUR;
- if (rest / SECS_PER_MINUTE)
- pos += sprintf(pos, "%um", rest / SECS_PER_MINUTE);
+ if (rest / SECS_PER_MINUTE) {
+ snprintf(tbuf, sizeof(tbuf), "%um", rest / SECS_PER_MINUTE);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
rest = rest % SECS_PER_MINUTE;
- if (rest)
- pos += sprintf(pos, "%us", rest);
-
- *(pos) = 0;
+ if (rest) {
+ snprintf(tbuf, sizeof(tbuf), "%us", rest);
+ strlcat(datestring, tbuf, sizeof(datestring));
+ }
return datestring;
}
diff --git a/isisd/isis_nb.c b/isisd/isis_nb.c
index 6d46e6b67e..227724934b 100644
--- a/isisd/isis_nb.c
+++ b/isisd/isis_nb.c
@@ -573,41 +573,44 @@ const struct frr_yang_module_info frr_isisd_info = {
},
},
{
- .xpath = "/frr-isisd:isis/instance/segment-routing/srgb",
+ .xpath = "/frr-isisd:isis/instance/segment-routing/label-blocks",
+ .cbs = {
+ .pre_validate = isis_instance_segment_routing_label_blocks_pre_validate,
+ .cli_show = cli_show_isis_label_blocks,
+ },
+ },
+ {
+ .xpath = "/frr-isisd:isis/instance/segment-routing/label-blocks/srgb",
.cbs = {
.apply_finish = isis_instance_segment_routing_srgb_apply_finish,
- .pre_validate = isis_instance_segment_routing_srgb_pre_validate,
- .cli_show = cli_show_isis_srgb,
},
},
{
- .xpath = "/frr-isisd:isis/instance/segment-routing/srgb/lower-bound",
+ .xpath = "/frr-isisd:isis/instance/segment-routing/label-blocks/srgb/lower-bound",
.cbs = {
.modify = isis_instance_segment_routing_srgb_lower_bound_modify,
},
},
{
- .xpath = "/frr-isisd:isis/instance/segment-routing/srgb/upper-bound",
+ .xpath = "/frr-isisd:isis/instance/segment-routing/label-blocks/srgb/upper-bound",
.cbs = {
.modify = isis_instance_segment_routing_srgb_upper_bound_modify,
},
},
{
- .xpath = "/frr-isisd:isis/instance/segment-routing/srlb",
+ .xpath = "/frr-isisd:isis/instance/segment-routing/label-blocks/srlb",
.cbs = {
.apply_finish = isis_instance_segment_routing_srlb_apply_finish,
- .pre_validate = isis_instance_segment_routing_srlb_pre_validate,
- .cli_show = cli_show_isis_srlb,
},
},
{
- .xpath = "/frr-isisd:isis/instance/segment-routing/srlb/lower-bound",
+ .xpath = "/frr-isisd:isis/instance/segment-routing/label-blocks/srlb/lower-bound",
.cbs = {
.modify = isis_instance_segment_routing_srlb_lower_bound_modify,
},
},
{
- .xpath = "/frr-isisd:isis/instance/segment-routing/srlb/upper-bound",
+ .xpath = "/frr-isisd:isis/instance/segment-routing/label-blocks/srlb/upper-bound",
.cbs = {
.modify = isis_instance_segment_routing_srlb_upper_bound_modify,
},
diff --git a/isisd/isis_nb.h b/isisd/isis_nb.h
index 8ecd8134e6..a6841b9fd4 100644
--- a/isisd/isis_nb.h
+++ b/isisd/isis_nb.h
@@ -387,9 +387,7 @@ lib_interface_state_isis_event_counters_authentication_fails_get_elem(
/* Optional 'pre_validate' callbacks. */
int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate(
struct nb_cb_pre_validate_args *args);
-int isis_instance_segment_routing_srgb_pre_validate(
- struct nb_cb_pre_validate_args *args);
-int isis_instance_segment_routing_srlb_pre_validate(
+int isis_instance_segment_routing_label_blocks_pre_validate(
struct nb_cb_pre_validate_args *args);
/* Optional 'apply_finish' callbacks. */
@@ -476,10 +474,8 @@ void cli_show_isis_mt_ipv6_dstsrc(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_sr_enabled(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
-void cli_show_isis_srgb(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
-void cli_show_isis_srlb(struct vty *vty, struct lyd_node *dnode,
- bool show_defaults);
+void cli_show_isis_label_blocks(struct vty *vty, struct lyd_node *dnode,
+ bool show_defaults);
void cli_show_isis_node_msd(struct vty *vty, struct lyd_node *dnode,
bool show_defaults);
void cli_show_isis_prefix_sid(struct vty *vty, struct lyd_node *dnode,
@@ -553,40 +549,97 @@ void cli_show_isis_mpls_if_ldp_sync_holddown(struct vty *vty,
/* Notifications. */
void isis_notif_db_overload(const struct isis_area *area, bool overload);
void isis_notif_lsp_too_large(const struct isis_circuit *circuit,
- uint32_t pdu_size, const char *lsp_id);
+ uint32_t pdu_size, const uint8_t *lsp_id);
void isis_notif_if_state_change(const struct isis_circuit *circuit, bool down);
void isis_notif_corrupted_lsp(const struct isis_area *area,
- const char *lsp_id); /* currently unused */
+ const uint8_t *lsp_id); /* currently unused */
void isis_notif_lsp_exceed_max(const struct isis_area *area,
- const char *lsp_id);
+ const uint8_t *lsp_id);
void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
uint8_t max_area_addrs,
- const char *raw_pdu);
+ const char *raw_pdu, size_t raw_pdu_len);
void isis_notif_authentication_type_failure(const struct isis_circuit *circuit,
- const char *raw_pdu);
+ const char *raw_pdu,
+ size_t raw_pdu_len);
void isis_notif_authentication_failure(const struct isis_circuit *circuit,
- const char *raw_pdu);
+ const char *raw_pdu, size_t raw_pdu_len);
void isis_notif_adj_state_change(const struct isis_adjacency *adj,
int new_state, const char *reason);
void isis_notif_reject_adjacency(const struct isis_circuit *circuit,
- const char *reason, const char *raw_pdu);
+ const char *reason, const char *raw_pdu,
+ size_t raw_pdu_len);
void isis_notif_area_mismatch(const struct isis_circuit *circuit,
- const char *raw_pdu);
+ const char *raw_pdu, size_t raw_pdu_len);
void isis_notif_lsp_received(const struct isis_circuit *circuit,
- const char *lsp_id, uint32_t seqno,
+ const uint8_t *lsp_id, uint32_t seqno,
uint32_t timestamp, const char *sys_id);
-void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id,
+void isis_notif_lsp_gen(const struct isis_area *area, const uint8_t *lsp_id,
uint32_t seqno, uint32_t timestamp);
void isis_notif_id_len_mismatch(const struct isis_circuit *circuit,
- uint8_t rcv_id_len, const char *raw_pdu);
+ uint8_t rcv_id_len, const char *raw_pdu,
+ size_t raw_pdu_len);
void isis_notif_version_skew(const struct isis_circuit *circuit,
- uint8_t version, const char *raw_pdu);
+ uint8_t version, const char *raw_pdu,
+ size_t raw_pdu_len);
void isis_notif_lsp_error(const struct isis_circuit *circuit,
- const char *lsp_id, const char *raw_pdu,
- uint32_t offset, uint8_t tlv_type);
+ const uint8_t *lsp_id, const char *raw_pdu,
+ size_t raw_pdu_len, uint32_t offset,
+ uint8_t tlv_type);
void isis_notif_seqno_skipped(const struct isis_circuit *circuit,
- const char *lsp_id);
+ const uint8_t *lsp_id);
void isis_notif_own_lsp_purge(const struct isis_circuit *circuit,
- const char *lsp_id);
+ const uint8_t *lsp_id);
+
+/* We also declare hook for every notification */
+
+DECLARE_HOOK(isis_hook_db_overload, (const struct isis_area *area), (area));
+DECLARE_HOOK(isis_hook_lsp_too_large,
+ (const struct isis_circuit *circuit, uint32_t pdu_size,
+ const uint8_t *lsp_id),
+ (circuit, pdu_size, lsp_id));
+/* Note: no isis_hook_corrupted_lsp - because this notificaiton is not used */
+DECLARE_HOOK(isis_hook_lsp_exceed_max,
+ (const struct isis_area *area, const uint8_t *lsp_id),
+ (area, lsp_id));
+DECLARE_HOOK(isis_hook_max_area_addr_mismatch,
+ (const struct isis_circuit *circuit, uint8_t max_addrs,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit, max_addrs, raw_pdu, raw_pdu_len));
+DECLARE_HOOK(isis_hook_authentication_type_failure,
+ (const struct isis_circuit *circuit, const char *raw_pdu,
+ size_t raw_pdu_len),
+ (circuit, raw_pdu, raw_pdu_len));
+DECLARE_HOOK(isis_hook_authentication_failure,
+ (const struct isis_circuit *circuit, const char *raw_pdu,
+ size_t raw_pdu_len),
+ (circuit, raw_pdu, raw_pdu_len));
+DECLARE_HOOK(isis_hook_adj_state_change, (const struct isis_adjacency *adj),
+ (adj));
+DECLARE_HOOK(isis_hook_reject_adjacency,
+ (const struct isis_circuit *circuit, const char *pdu,
+ size_t pdu_len),
+ (circuit, pdu, pdu_len));
+DECLARE_HOOK(isis_hook_area_mismatch,
+ (const struct isis_circuit *circuit, const char *raw_pdu,
+ size_t raw_pdu_len),
+ (circuit));
+DECLARE_HOOK(isis_hook_id_len_mismatch,
+ (const struct isis_circuit *circuit, uint8_t rcv_id_len,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit, rcv_id_len, raw_pdu, raw_pdu_len));
+DECLARE_HOOK(isis_hook_version_skew,
+ (const struct isis_circuit *circuit, uint8_t version,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit));
+DECLARE_HOOK(isis_hook_lsp_error,
+ (const struct isis_circuit *circuit, const uint8_t *lsp_id,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit));
+DECLARE_HOOK(isis_hook_seqno_skipped,
+ (const struct isis_circuit *circuit, const uint8_t *lsp_id),
+ (circuit, lsp_id));
+DECLARE_HOOK(isis_hook_own_lsp_purge,
+ (const struct isis_circuit *circuit, const uint8_t *lsp_id),
+ (circuit, lsp_id));
#endif /* ISISD_ISIS_NB_H_ */
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 45bbc9737b..f0663c691c 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -1943,9 +1943,9 @@ int isis_instance_segment_routing_enabled_modify(
}
/*
- * XPath: /frr-isisd:isis/instance/segment-routing/srgb
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-blocks
*/
-int isis_instance_segment_routing_srgb_pre_validate(
+int isis_instance_segment_routing_label_blocks_pre_validate(
struct nb_cb_pre_validate_args *args)
{
uint32_t srgb_lbound;
@@ -1953,10 +1953,10 @@ int isis_instance_segment_routing_srgb_pre_validate(
uint32_t srlb_lbound;
uint32_t srlb_ubound;
- srgb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
- srgb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
- srlb_lbound = yang_dnode_get_uint32(args->dnode, "../srlb/lower-bound");
- srlb_ubound = yang_dnode_get_uint32(args->dnode, "../srlb/upper-bound");
+ srgb_lbound = yang_dnode_get_uint32(args->dnode, "./srgb/lower-bound");
+ srgb_ubound = yang_dnode_get_uint32(args->dnode, "./srgb/upper-bound");
+ srlb_lbound = yang_dnode_get_uint32(args->dnode, "./srlb/lower-bound");
+ srlb_ubound = yang_dnode_get_uint32(args->dnode, "./srlb/upper-bound");
/* Check that the block size does not exceed 65535 */
if ((srgb_ubound - srgb_lbound + 1) > 65535) {
@@ -1966,12 +1966,18 @@ int isis_instance_segment_routing_srgb_pre_validate(
srgb_lbound, srgb_ubound);
return NB_ERR_VALIDATION;
}
+ if ((srlb_ubound - srlb_lbound + 1) > 65535) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "New SR Local Block (%u/%u) exceed the limit of 65535",
+ srlb_lbound, srlb_ubound);
+ return NB_ERR_VALIDATION;
+ }
/* Validate SRGB against SRLB */
if (!((srgb_ubound < srlb_lbound) || (srgb_lbound > srlb_ubound))) {
snprintf(
args->errmsg, args->errmsg_len,
- "New SR Global Block (%u/%u) conflict with Local Block (%u/%u)",
+ "SR Global Block (%u/%u) conflicts with Local Block (%u/%u)",
srgb_lbound, srgb_ubound, srlb_lbound, srlb_ubound);
return NB_ERR_VALIDATION;
}
@@ -1979,6 +1985,10 @@ int isis_instance_segment_routing_srgb_pre_validate(
return NB_OK;
}
+/*
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-blocks/srgb
+ */
+
void isis_instance_segment_routing_srgb_apply_finish(
struct nb_cb_apply_finish_args *args)
{
@@ -1993,7 +2003,7 @@ void isis_instance_segment_routing_srgb_apply_finish(
}
/*
- * XPath: /frr-isisd:isis/instance/segment-routing/srgb/lower-bound
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-blocks/srgb/lower-bound
*/
int isis_instance_segment_routing_srgb_lower_bound_modify(
struct nb_cb_modify_args *args)
@@ -2018,7 +2028,7 @@ int isis_instance_segment_routing_srgb_lower_bound_modify(
}
/*
- * XPath: /frr-isisd:isis/instance/segment-routing/srgb/upper-bound
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-blocks/srgb/upper-bound
*/
int isis_instance_segment_routing_srgb_upper_bound_modify(
struct nb_cb_modify_args *args)
@@ -2043,41 +2053,8 @@ int isis_instance_segment_routing_srgb_upper_bound_modify(
}
/*
- * XPath: /frr-isisd:isis/instance/segment-routing/srlb
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-blocks/srlb
*/
-int isis_instance_segment_routing_srlb_pre_validate(
- struct nb_cb_pre_validate_args *args)
-{
- uint32_t srgb_lbound;
- uint32_t srgb_ubound;
- uint32_t srlb_lbound;
- uint32_t srlb_ubound;
-
- srgb_lbound = yang_dnode_get_uint32(args->dnode, "../srgb/lower-bound");
- srgb_ubound = yang_dnode_get_uint32(args->dnode, "../srgb/upper-bound");
- srlb_lbound = yang_dnode_get_uint32(args->dnode, "./lower-bound");
- srlb_ubound = yang_dnode_get_uint32(args->dnode, "./upper-bound");
-
- /* Check that the block size does not exceed 65535 */
- if ((srlb_ubound - srlb_lbound + 1) > 65535) {
- snprintf(args->errmsg, args->errmsg_len,
- "New SR Local Block (%u/%u) exceed the limit of 65535",
- srlb_lbound, srlb_ubound);
- return NB_ERR_VALIDATION;
- }
-
- /* Validate SRLB against SRGB */
- if (!((srlb_ubound < srgb_lbound) || (srlb_lbound > srgb_ubound))) {
- snprintf(
- args->errmsg, args->errmsg_len,
- "New SR Local Block (%u/%u) conflict with Global Block (%u/%u)",
- srlb_lbound, srlb_ubound, srgb_lbound, srgb_ubound);
- return NB_ERR_VALIDATION;
- }
-
- return NB_OK;
-}
-
void isis_instance_segment_routing_srlb_apply_finish(
struct nb_cb_apply_finish_args *args)
{
@@ -2092,7 +2069,7 @@ void isis_instance_segment_routing_srlb_apply_finish(
}
/*
- * XPath: /frr-isisd:isis/instance/segment-routing/srlb/lower-bound
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-blocks/srlb/lower-bound
*/
int isis_instance_segment_routing_srlb_lower_bound_modify(
struct nb_cb_modify_args *args)
@@ -2117,7 +2094,7 @@ int isis_instance_segment_routing_srlb_lower_bound_modify(
}
/*
- * XPath: /frr-isisd:isis/instance/segment-routing/srlb/upper-bound
+ * XPath: /frr-isisd:isis/instance/segment-routing/label-blocks/srlb/upper-bound
*/
int isis_instance_segment_routing_srlb_upper_bound_modify(
struct nb_cb_modify_args *args)
@@ -2231,10 +2208,10 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_pre_validate(
struct isis_prefix_sid psid = {};
yang_dnode_get_prefix(&prefix, args->dnode, "./prefix");
- srgb_lbound = yang_dnode_get_uint32(args->dnode,
- "../../srgb/lower-bound");
- srgb_ubound = yang_dnode_get_uint32(args->dnode,
- "../../srgb/upper-bound");
+ srgb_lbound = yang_dnode_get_uint32(
+ args->dnode, "../../label-blocks/srgb/lower-bound");
+ srgb_ubound = yang_dnode_get_uint32(
+ args->dnode, "../../label-blocks/srgb/upper-bound");
sid = yang_dnode_get_uint32(args->dnode, "./sid-value");
sid_type = yang_dnode_get_enum(args->dnode, "./sid-value-type");
diff --git a/isisd/isis_nb_notifications.c b/isisd/isis_nb_notifications.c
index ea33ec10ec..755378a9b7 100644
--- a/isisd/isis_nb_notifications.c
+++ b/isisd/isis_nb_notifications.c
@@ -28,6 +28,56 @@
#include "isisd/isis_dynhn.h"
#include "isisd/isis_misc.h"
+DEFINE_HOOK(isis_hook_lsp_too_large,
+ (const struct isis_circuit *circuit, uint32_t pdu_size,
+ const uint8_t *lsp_id),
+ (circuit, pdu_size, lsp_id));
+DEFINE_HOOK(isis_hook_corrupted_lsp, (const struct isis_area *area), (area));
+DEFINE_HOOK(isis_hook_lsp_exceed_max,
+ (const struct isis_area *area, const uint8_t *lsp_id),
+ (area, lsp_id));
+DEFINE_HOOK(isis_hook_max_area_addr_mismatch,
+ (const struct isis_circuit *circuit, uint8_t max_addrs,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit, max_addrs, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_authentication_type_failure,
+ (const struct isis_circuit *circuit, const char *raw_pdu,
+ size_t raw_pdu_len),
+ (circuit, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_authentication_failure,
+ (const struct isis_circuit *circuit, const char *raw_pdu,
+ size_t raw_pdu_len),
+ (circuit, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_adj_state_change, (const struct isis_adjacency *adj),
+ (adj));
+DEFINE_HOOK(isis_hook_reject_adjacency,
+ (const struct isis_circuit *circuit, const char *raw_pdu,
+ size_t raw_pdu_len),
+ (circuit, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_area_mismatch,
+ (const struct isis_circuit *circuit, const char *raw_pdu,
+ size_t raw_pdu_len),
+ (circuit, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_id_len_mismatch,
+ (const struct isis_circuit *circuit, uint8_t rcv_id_len,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit, rcv_id_len, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_version_skew,
+ (const struct isis_circuit *circuit, uint8_t version,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit, version, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_lsp_error,
+ (const struct isis_circuit *circuit, const uint8_t *lsp_id,
+ const char *raw_pdu, size_t raw_pdu_len),
+ (circuit, lsp_id, raw_pdu, raw_pdu_len));
+DEFINE_HOOK(isis_hook_seqno_skipped,
+ (const struct isis_circuit *circuit, const uint8_t *lsp_id),
+ (circuit, lsp_id));
+DEFINE_HOOK(isis_hook_own_lsp_purge,
+ (const struct isis_circuit *circuit, const uint8_t *lsp_id),
+ (circuit, lsp_id));
+
+
/*
* Helper functions.
*/
@@ -92,7 +142,7 @@ void isis_notif_db_overload(const struct isis_area *area, bool overload)
* XPath: /frr-isisd:lsp-too-large
*/
void isis_notif_lsp_too_large(const struct isis_circuit *circuit,
- uint32_t pdu_size, const char *lsp_id)
+ uint32_t pdu_size, const uint8_t *lsp_id)
{
const char *xpath = "/frr-isisd:lsp-too-large";
struct list *arguments = yang_data_list_new();
@@ -106,9 +156,11 @@ void isis_notif_lsp_too_large(const struct isis_circuit *circuit,
data = yang_data_new_uint32(xpath_arg, pdu_size);
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
+ hook_call(isis_hook_lsp_too_large, circuit, pdu_size, lsp_id);
+
nb_notification_send(xpath, arguments);
}
@@ -135,7 +187,8 @@ void isis_notif_if_state_change(const struct isis_circuit *circuit, bool down)
/*
* XPath: /frr-isisd:corrupted-lsp-detected
*/
-void isis_notif_corrupted_lsp(const struct isis_area *area, const char *lsp_id)
+void isis_notif_corrupted_lsp(const struct isis_area *area,
+ const uint8_t *lsp_id)
{
const char *xpath = "/frr-isisd:corrupted-lsp-detected";
struct list *arguments = yang_data_list_new();
@@ -144,16 +197,19 @@ void isis_notif_corrupted_lsp(const struct isis_area *area, const char *lsp_id)
notif_prep_instance_hdr(xpath, area, "default", arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
+ hook_call(isis_hook_corrupted_lsp, area);
+
nb_notification_send(xpath, arguments);
}
/*
* XPath: /frr-isisd:attempt-to-exceed-max-sequence
*/
-void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *lsp_id)
+void isis_notif_lsp_exceed_max(const struct isis_area *area,
+ const uint8_t *lsp_id)
{
const char *xpath = "/frr-isisd:attempt-to-exceed-max-sequence";
struct list *arguments = yang_data_list_new();
@@ -162,9 +218,11 @@ void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *lsp_id)
notif_prep_instance_hdr(xpath, area, "default", arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
+ hook_call(isis_hook_lsp_exceed_max, area, lsp_id);
+
nb_notification_send(xpath, arguments);
}
@@ -173,7 +231,7 @@ void isis_notif_lsp_exceed_max(const struct isis_area *area, const char *lsp_id)
*/
void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
uint8_t max_area_addrs,
- const char *raw_pdu)
+ const char *raw_pdu, size_t raw_pdu_len)
{
const char *xpath = "/frr-isisd:max-area-addresses-mismatch";
struct list *arguments = yang_data_list_new();
@@ -190,6 +248,9 @@ void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
+ hook_call(isis_hook_max_area_addr_mismatch, circuit, max_area_addrs,
+ raw_pdu, raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -197,7 +258,8 @@ void isis_notif_max_area_addr_mismatch(const struct isis_circuit *circuit,
* XPath: /frr-isisd:authentication-type-failure
*/
void isis_notif_authentication_type_failure(const struct isis_circuit *circuit,
- const char *raw_pdu)
+ const char *raw_pdu,
+ size_t raw_pdu_len)
{
const char *xpath = "/frr-isisd:authentication-type-failure";
struct list *arguments = yang_data_list_new();
@@ -211,6 +273,9 @@ void isis_notif_authentication_type_failure(const struct isis_circuit *circuit,
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
+ hook_call(isis_hook_authentication_type_failure, circuit, raw_pdu,
+ raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -218,7 +283,7 @@ void isis_notif_authentication_type_failure(const struct isis_circuit *circuit,
* XPath: /frr-isisd:authentication-failure
*/
void isis_notif_authentication_failure(const struct isis_circuit *circuit,
- const char *raw_pdu)
+ const char *raw_pdu, size_t raw_pdu_len)
{
const char *xpath = "/frr-isisd:authentication-failure";
struct list *arguments = yang_data_list_new();
@@ -232,6 +297,9 @@ void isis_notif_authentication_failure(const struct isis_circuit *circuit,
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
+ hook_call(isis_hook_authentication_failure, circuit, raw_pdu,
+ raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -269,6 +337,8 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj,
listnode_add(arguments, data);
}
+ hook_call(isis_hook_adj_state_change, adj);
+
nb_notification_send(xpath, arguments);
}
@@ -276,7 +346,8 @@ void isis_notif_adj_state_change(const struct isis_adjacency *adj,
* XPath: /frr-isisd:rejected-adjacency
*/
void isis_notif_reject_adjacency(const struct isis_circuit *circuit,
- const char *reason, const char *raw_pdu)
+ const char *reason, const char *raw_pdu,
+ size_t raw_pdu_len)
{
const char *xpath = "/frr-isisd:rejected-adjacency";
struct list *arguments = yang_data_list_new();
@@ -293,6 +364,8 @@ void isis_notif_reject_adjacency(const struct isis_circuit *circuit,
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
+ hook_call(isis_hook_reject_adjacency, circuit, raw_pdu, raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -300,7 +373,7 @@ void isis_notif_reject_adjacency(const struct isis_circuit *circuit,
* XPath: /frr-isisd:area-mismatch
*/
void isis_notif_area_mismatch(const struct isis_circuit *circuit,
- const char *raw_pdu)
+ const char *raw_pdu, size_t raw_pdu_len)
{
const char *xpath = "/frr-isisd:area-mismatch";
struct list *arguments = yang_data_list_new();
@@ -314,6 +387,8 @@ void isis_notif_area_mismatch(const struct isis_circuit *circuit,
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
+ hook_call(isis_hook_area_mismatch, circuit, raw_pdu, raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -321,7 +396,7 @@ void isis_notif_area_mismatch(const struct isis_circuit *circuit,
* XPath: /frr-isisd:lsp-received
*/
void isis_notif_lsp_received(const struct isis_circuit *circuit,
- const char *lsp_id, uint32_t seqno,
+ const uint8_t *lsp_id, uint32_t seqno,
uint32_t timestamp, const char *sys_id)
{
const char *xpath = "/frr-isisd:lsp-received";
@@ -333,7 +408,7 @@ void isis_notif_lsp_received(const struct isis_circuit *circuit,
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath);
data = yang_data_new_uint32(xpath_arg, seqno);
@@ -351,7 +426,7 @@ void isis_notif_lsp_received(const struct isis_circuit *circuit,
/*
* XPath: /frr-isisd:lsp-generation
*/
-void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id,
+void isis_notif_lsp_gen(const struct isis_area *area, const uint8_t *lsp_id,
uint32_t seqno, uint32_t timestamp)
{
const char *xpath = "/frr-isisd:lsp-generation";
@@ -361,7 +436,7 @@ void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id,
notif_prep_instance_hdr(xpath, area, "default", arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/sequence", xpath);
data = yang_data_new_uint32(xpath_arg, seqno);
@@ -377,7 +452,8 @@ void isis_notif_lsp_gen(const struct isis_area *area, const char *lsp_id,
* XPath: /frr-isisd:id-len-mismatch
*/
void isis_notif_id_len_mismatch(const struct isis_circuit *circuit,
- uint8_t rcv_id_len, const char *raw_pdu)
+ uint8_t rcv_id_len, const char *raw_pdu,
+ size_t raw_pdu_len)
{
const char *xpath = "/frr-isisd:id-len-mismatch";
struct list *arguments = yang_data_list_new();
@@ -394,6 +470,9 @@ void isis_notif_id_len_mismatch(const struct isis_circuit *circuit,
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
+ hook_call(isis_hook_id_len_mismatch, circuit, rcv_id_len, raw_pdu,
+ raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -401,7 +480,8 @@ void isis_notif_id_len_mismatch(const struct isis_circuit *circuit,
* XPath: /frr-isisd:version-skew
*/
void isis_notif_version_skew(const struct isis_circuit *circuit,
- uint8_t version, const char *raw_pdu)
+ uint8_t version, const char *raw_pdu,
+ size_t raw_pdu_len)
{
const char *xpath = "/frr-isisd:version-skew";
struct list *arguments = yang_data_list_new();
@@ -418,6 +498,9 @@ void isis_notif_version_skew(const struct isis_circuit *circuit,
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
+ hook_call(isis_hook_version_skew, circuit, version, raw_pdu,
+ raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -425,7 +508,8 @@ void isis_notif_version_skew(const struct isis_circuit *circuit,
* XPath: /frr-isisd:lsp-error-detected
*/
void isis_notif_lsp_error(const struct isis_circuit *circuit,
- const char *lsp_id, const char *raw_pdu,
+ const uint8_t *lsp_id, const char *raw_pdu,
+ size_t raw_pdu_len,
__attribute__((unused)) uint32_t offset,
__attribute__((unused)) uint8_t tlv_type)
{
@@ -438,13 +522,15 @@ void isis_notif_lsp_error(const struct isis_circuit *circuit,
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/raw-pdu", xpath);
data = yang_data_new(xpath_arg, raw_pdu);
listnode_add(arguments, data);
/* ignore offset and tlv_type which cannot be set properly */
+ hook_call(isis_hook_lsp_error, circuit, lsp_id, raw_pdu, raw_pdu_len);
+
nb_notification_send(xpath, arguments);
}
@@ -452,7 +538,7 @@ void isis_notif_lsp_error(const struct isis_circuit *circuit,
* XPath: /frr-isisd:sequence-number-skipped
*/
void isis_notif_seqno_skipped(const struct isis_circuit *circuit,
- const char *lsp_id)
+ const uint8_t *lsp_id)
{
const char *xpath = "/frr-isisd:sequence-number-skipped";
struct list *arguments = yang_data_list_new();
@@ -463,9 +549,11 @@ void isis_notif_seqno_skipped(const struct isis_circuit *circuit,
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
+ hook_call(isis_hook_seqno_skipped, circuit, lsp_id);
+
nb_notification_send(xpath, arguments);
}
@@ -473,7 +561,7 @@ void isis_notif_seqno_skipped(const struct isis_circuit *circuit,
* XPath: /frr-isisd:own-lsp-purge
*/
void isis_notif_own_lsp_purge(const struct isis_circuit *circuit,
- const char *lsp_id)
+ const uint8_t *lsp_id)
{
const char *xpath = "/frr-isisd:own-lsp-purge";
struct list *arguments = yang_data_list_new();
@@ -484,8 +572,10 @@ void isis_notif_own_lsp_purge(const struct isis_circuit *circuit,
notif_prep_instance_hdr(xpath, area, "default", arguments);
notif_prepr_iface_hdr(xpath, circuit, arguments);
snprintf(xpath_arg, sizeof(xpath_arg), "%s/lsp-id", xpath);
- data = yang_data_new_string(xpath_arg, lsp_id);
+ data = yang_data_new_string(xpath_arg, rawlspid_print(lsp_id));
listnode_add(arguments, data);
+ hook_call(isis_hook_own_lsp_purge, circuit, lsp_id);
+
nb_notification_send(xpath, arguments);
}
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index a02b48157f..7256fcbbc7 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -549,6 +549,19 @@ static int pdu_len_validate(uint16_t pdu_len, struct isis_circuit *circuit)
return 0;
}
+static void update_rej_adj_count(struct isis_circuit *circuit)
+{
+ circuit->rej_adjacencies++;
+ if (circuit->is_type == IS_LEVEL_1)
+ circuit->area->rej_adjacencies[0]++;
+ else if (circuit->is_type == IS_LEVEL_2)
+ circuit->area->rej_adjacencies[1]++;
+ else {
+ circuit->area->rej_adjacencies[0]++;
+ circuit->area->rej_adjacencies[1]++;
+ }
+}
+
static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
uint8_t *ssnpa)
{
@@ -581,22 +594,22 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (p2p_hello) {
if (circuit->circ_type != CIRCUIT_T_P2P) {
zlog_warn("p2p hello on non p2p circuit");
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "p2p hello on non p2p circuit",
- raw_pdu);
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_WARNING;
}
} else {
if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
zlog_warn("lan hello on non broadcast circuit");
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "lan hello on non broadcast circuit",
- raw_pdu);
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_WARNING;
}
@@ -605,12 +618,12 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
zlog_debug(
"level %d LAN Hello received over circuit with externalDomain = true",
level);
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit,
"LAN Hello received over circuit with externalDomain = true",
- raw_pdu);
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_WARNING;
}
@@ -622,10 +635,11 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
circuit->area->area_tag,
circuit->interface->name);
}
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
- isis_notif_reject_adjacency(
- circuit, "Interface level mismatch", raw_pdu);
+ isis_notif_reject_adjacency(circuit,
+ "Interface level mismatch",
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_WARNING;
}
@@ -652,10 +666,10 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
"ISIS-Adj (%s): Rcvd %s from (%s) with invalid pdu length %hu",
circuit->area->area_tag, pdu_name,
circuit->interface->name, iih.pdu_len);
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
isis_notif_reject_adjacency(circuit, "Invalid PDU length",
- raw_pdu);
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_WARNING;
}
@@ -664,10 +678,11 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
flog_err(EC_ISIS_PACKET,
"Level %d LAN Hello with Circuit Type %d", level,
iih.circ_type);
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
- isis_notif_reject_adjacency(
- circuit, "LAN Hello with wrong IS-level", raw_pdu);
+ isis_notif_reject_adjacency(circuit,
+ "LAN Hello with wrong IS-level",
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_ERROR;
}
@@ -678,10 +693,10 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
if (isis_unpack_tlvs(STREAM_READABLE(circuit->rcv_stream),
circuit->rcv_stream, &iih.tlvs, &error_log)) {
zlog_warn("isis_unpack_tlvs() failed: %s", error_log);
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
isis_notif_reject_adjacency(circuit, "Failed to unpack TLVs",
- raw_pdu);
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
goto out;
}
@@ -690,17 +705,18 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
zlog_warn("No Area addresses TLV in %s", pdu_name);
#ifndef FABRICD
/* send northbound notification */
- isis_notif_area_mismatch(circuit, raw_pdu);
+ isis_notif_area_mismatch(circuit, raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
goto out;
}
if (!iih.tlvs->protocols_supported.count) {
zlog_warn("No supported protocols TLV in %s", pdu_name);
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
- isis_notif_reject_adjacency(
- circuit, "No supported protocols TLV", raw_pdu);
+ isis_notif_reject_adjacency(circuit,
+ "No supported protocols TLV",
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
goto out;
}
@@ -716,12 +732,13 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
stream_get_from(raw_pdu, circuit->rcv_stream, pdu_start,
pdu_end - pdu_start);
if (auth_code == ISIS_AUTH_FAILURE) {
- circuit->auth_failures++;
- isis_notif_authentication_failure(circuit, raw_pdu);
+ update_rej_adj_count(circuit);
+ isis_notif_authentication_failure(circuit, raw_pdu,
+ sizeof(raw_pdu));
} else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
- circuit->auth_type_failures++;
- isis_notif_authentication_type_failure(circuit,
- raw_pdu);
+ update_rej_adj_count(circuit);
+ isis_notif_authentication_type_failure(circuit, raw_pdu,
+ sizeof(raw_pdu));
}
#endif /* ifndef FABRICD */
goto out;
@@ -731,10 +748,11 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
zlog_warn(
"ISIS-Adj (%s): Received IIH with own sysid on %s - discard",
circuit->area->area_tag, circuit->interface->name);
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
- isis_notif_reject_adjacency(
- circuit, "Received IIH with our own sysid", raw_pdu);
+ isis_notif_reject_adjacency(circuit,
+ "Received IIH with our own sysid",
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
goto out;
}
@@ -752,7 +770,7 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
}
#ifndef FABRICD
/* send northbound notification */
- isis_notif_area_mismatch(circuit, raw_pdu);
+ isis_notif_area_mismatch(circuit, raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
goto out;
}
@@ -769,11 +787,11 @@ static int process_hello(uint8_t pdu_type, struct isis_circuit *circuit,
"ISIS-Adj (%s): Neither IPv4 nor IPv6 considered usable. Ignoring IIH",
circuit->area->area_tag);
}
- circuit->rej_adjacencies++;
+ update_rej_adj_count(circuit);
#ifndef FABRICD
isis_notif_reject_adjacency(
circuit, "Neither IPv4 not IPv6 considered usable",
- raw_pdu);
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
goto out;
}
@@ -857,8 +875,8 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
#ifndef FABRICD
/* send northbound notification */
- isis_notif_lsp_received(circuit, rawlspid_print(hdr.lsp_id), hdr.seqno,
- time(NULL), sysid_print(hdr.lsp_id));
+ isis_notif_lsp_received(circuit, hdr.lsp_id, hdr.seqno, time(NULL),
+ sysid_print(hdr.lsp_id));
#endif /* ifndef FABRICD */
if (pdu_len_validate(hdr.pdu_len, circuit)) {
@@ -931,8 +949,18 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
* we change the code above to return those extra fields, we
* will send dummy values which are ignored in the callback
*/
- isis_notif_lsp_error(circuit, rawlspid_print(hdr.lsp_id),
- raw_pdu, 0, 0);
+ circuit->lsp_error_counter++;
+ if (circuit->is_type == IS_LEVEL_1) {
+ circuit->area->lsp_error_counter[0]++;
+ } else if (circuit->is_type == IS_LEVEL_2) {
+ circuit->area->lsp_error_counter[1]++;
+ } else {
+ circuit->area->lsp_error_counter[0]++;
+ circuit->area->lsp_error_counter[1]++;
+ }
+
+ isis_notif_lsp_error(circuit, hdr.lsp_id, raw_pdu,
+ sizeof(raw_pdu), 0, 0);
#endif /* ifndef FABRICD */
goto out;
}
@@ -956,11 +984,28 @@ static int process_lsp(uint8_t pdu_type, struct isis_circuit *circuit,
/* send northbound notification */
if (auth_code == ISIS_AUTH_FAILURE) {
circuit->auth_failures++;
- isis_notif_authentication_failure(circuit, raw_pdu);
+ if (circuit->is_type == IS_LEVEL_1) {
+ circuit->area->auth_failures[0]++;
+ } else if (circuit->is_type == IS_LEVEL_2) {
+ circuit->area->auth_failures[1]++;
+ } else {
+ circuit->area->auth_failures[0]++;
+ circuit->area->auth_failures[1]++;
+ }
+ isis_notif_authentication_failure(circuit, raw_pdu,
+ sizeof(raw_pdu));
} else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
circuit->auth_type_failures++;
- isis_notif_authentication_type_failure(circuit,
- raw_pdu);
+ if (circuit->is_type == IS_LEVEL_1) {
+ circuit->area->auth_type_failures[0]++;
+ } else if (circuit->is_type == IS_LEVEL_2) {
+ circuit->area->auth_type_failures[1]++;
+ } else {
+ circuit->area->auth_type_failures[0]++;
+ circuit->area->auth_type_failures[1]++;
+ }
+ isis_notif_authentication_type_failure(circuit, raw_pdu,
+ sizeof(raw_pdu));
}
#endif /* ifndef FABRICD */
goto out;
@@ -1105,10 +1150,10 @@ dontcheckadj:
if (lsp->hdr.seqno < hdr.seqno) {
/* send northbound
* notification */
+ circuit->area
+ ->lsp_seqno_skipped_counter++;
isis_notif_seqno_skipped(
- circuit,
- rawlspid_print(
- hdr.lsp_id));
+ circuit, hdr.lsp_id);
}
#endif /* ifndef FABRICD */
lsp_inc_seqno(lsp, hdr.seqno);
@@ -1129,8 +1174,7 @@ dontcheckadj:
/* our own LSP with 0 remaining life time */
#ifndef FABRICD
/* send northbound notification */
- isis_notif_own_lsp_purge(
- circuit, rawlspid_print(hdr.lsp_id));
+ isis_notif_own_lsp_purge(circuit, hdr.lsp_id);
#endif /* ifndef FABRICD */
}
}
@@ -1158,8 +1202,8 @@ dontcheckadj:
lsp_inc_seqno(lsp, hdr.seqno);
#ifndef FABRICD
/* send northbound notification */
- isis_notif_seqno_skipped(circuit,
- rawlspid_print(hdr.lsp_id));
+ circuit->area->lsp_seqno_skipped_counter++;
+ isis_notif_seqno_skipped(circuit, hdr.lsp_id);
#endif /* ifndef FABRICD */
if (IS_DEBUG_UPDATE_PACKETS) {
zlog_debug(
@@ -1388,12 +1432,28 @@ static int process_snp(uint8_t pdu_type, struct isis_circuit *circuit,
pdu_end - pdu_start);
if (auth_code == ISIS_AUTH_FAILURE) {
circuit->auth_failures++;
- isis_notif_authentication_failure(circuit,
- raw_pdu);
+ if (circuit->is_type == IS_LEVEL_1) {
+ circuit->area->auth_failures[0]++;
+ } else if (circuit->is_type == IS_LEVEL_2) {
+ circuit->area->auth_failures[1]++;
+ } else {
+ circuit->area->auth_failures[0]++;
+ circuit->area->auth_failures[1]++;
+ }
+ isis_notif_authentication_failure(
+ circuit, raw_pdu, sizeof(raw_pdu));
} else { /* AUTH_TYPE_FAILURE or NO_VALIDATOR */
circuit->auth_type_failures++;
- isis_notif_authentication_type_failure(circuit,
- raw_pdu);
+ if (circuit->is_type == IS_LEVEL_1) {
+ circuit->area->auth_type_failures[0]++;
+ } else if (circuit->is_type == IS_LEVEL_2) {
+ circuit->area->auth_type_failures[1]++;
+ } else {
+ circuit->area->auth_type_failures[0]++;
+ circuit->area->auth_type_failures[1]++;
+ }
+ isis_notif_authentication_type_failure(
+ circuit, raw_pdu, sizeof(raw_pdu));
}
#endif /* ifndef FABRICD */
goto out;
@@ -1620,7 +1680,8 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
zlog_warn("Unsupported ISIS version %hhu", version1);
#ifndef FABRICD
/* send northbound notification */
- isis_notif_version_skew(circuit, version1, raw_pdu);
+ isis_notif_version_skew(circuit, version1, raw_pdu,
+ sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_WARNING;
}
@@ -1631,9 +1692,19 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
"IDFieldLengthMismatch: ID Length field in a received PDU %hhu, while the parameter for this IS is %u",
id_len, ISIS_SYS_ID_LEN);
circuit->id_len_mismatches++;
+ if (circuit->is_type == IS_LEVEL_1) {
+ circuit->area->id_len_mismatches[0]++;
+ } else if (circuit->is_type == IS_LEVEL_2) {
+ circuit->area->id_len_mismatches[1]++;
+ } else {
+ circuit->area->id_len_mismatches[0]++;
+ circuit->area->id_len_mismatches[1]++;
+ }
+
#ifndef FABRICD
/* send northbound notification */
- isis_notif_id_len_mismatch(circuit, id_len, raw_pdu);
+ isis_notif_id_len_mismatch(circuit, id_len, raw_pdu,
+ sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_ERROR;
}
@@ -1662,7 +1733,8 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
zlog_warn("Unsupported ISIS PDU version %hhu", version2);
#ifndef FABRICD
/* send northbound notification */
- isis_notif_version_skew(circuit, version2, raw_pdu);
+ isis_notif_version_skew(circuit, version2, raw_pdu,
+ sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_WARNING;
}
@@ -1686,7 +1758,7 @@ int isis_handle_pdu(struct isis_circuit *circuit, uint8_t *ssnpa)
#ifndef FABRICD
/* send northbound notification */
isis_notif_max_area_addr_mismatch(circuit, max_area_addrs,
- raw_pdu);
+ raw_pdu, sizeof(raw_pdu));
#endif /* ifndef FABRICD */
return ISIS_ERROR;
}
@@ -2409,7 +2481,7 @@ void send_lsp(struct isis_circuit *circuit, struct isis_lsp *lsp,
#ifndef FABRICD
/* send a northbound notification */
isis_notif_lsp_too_large(circuit, stream_get_endp(lsp->pdu),
- rawlspid_print(lsp->hdr.lsp_id));
+ lsp->hdr.lsp_id);
#endif /* ifndef FABRICD */
if (IS_DEBUG_PACKET_DUMP)
zlog_dump_data(STREAM_DATA(lsp->pdu),
diff --git a/isisd/isis_redist.c b/isisd/isis_redist.c
index 240be27cf3..856c47b9b7 100644
--- a/isisd/isis_redist.c
+++ b/isisd/isis_redist.c
@@ -219,7 +219,7 @@ static void isis_redist_ensure_default(struct isis *isis, int family)
/* Handle notification about route being added */
void isis_redist_add(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p, uint8_t distance,
- uint32_t metric)
+ uint32_t metric, const route_tag_t tag)
{
int family = p->family;
struct route_table *ei_table = get_ext_info(isis, family);
@@ -250,6 +250,7 @@ void isis_redist_add(struct isis *isis, int type, struct prefix *p,
info->origin = type;
info->distance = distance;
info->metric = metric;
+ info->tag = tag;
if (is_default_prefix(p)
&& (!src_p || !src_p->prefixlen)) {
@@ -288,7 +289,7 @@ void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
* "always" setting will ignore routes with origin
* DEFAULT_ROUTE. */
isis_redist_add(isis, DEFAULT_ROUTE, p, NULL, 254,
- MAX_WIDE_PATH_METRIC);
+ MAX_WIDE_PATH_METRIC, 0);
return;
}
diff --git a/isisd/isis_redist.h b/isisd/isis_redist.h
index afce922240..fcc4ceadf4 100644
--- a/isisd/isis_redist.h
+++ b/isisd/isis_redist.h
@@ -31,6 +31,7 @@ struct isis_ext_info {
int origin;
uint32_t metric;
uint8_t distance;
+ route_tag_t tag;
};
struct isis_redist {
@@ -50,7 +51,7 @@ struct route_table *get_ext_reach(struct isis_area *area, int family,
int level);
void isis_redist_add(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p, uint8_t distance,
- uint32_t metric);
+ uint32_t metric, route_tag_t tag);
void isis_redist_delete(struct isis *isis, int type, struct prefix *p,
struct prefix_ipv6 *src_p);
int isis_redist_config_write(struct vty *vty, struct isis_area *area,
diff --git a/isisd/isis_routemap.c b/isisd/isis_routemap.c
index db0f2fd8be..626e399e15 100644
--- a/isisd/isis_routemap.c
+++ b/isisd/isis_routemap.c
@@ -112,6 +112,35 @@ static const struct route_map_rule_cmd
/* ------------------------------------------------------------*/
+/* `match tag TAG' */
+/* Match function return 1 if match is success else return zero. */
+static enum route_map_cmd_result_t
+route_match_tag(void *rule, const struct prefix *p, void *object)
+{
+ route_tag_t *tag;
+ struct isis_ext_info *info;
+ route_tag_t info_tag;
+
+ tag = rule;
+ info = object;
+
+ info_tag = info->tag;
+ if (info_tag == *tag)
+ return RMAP_MATCH;
+ else
+ return RMAP_NOMATCH;
+}
+
+/* Route map commands for tag matching. */
+static const struct route_map_rule_cmd route_match_tag_cmd = {
+ "tag",
+ route_match_tag,
+ route_map_rule_tag_compile,
+ route_map_rule_tag_free,
+};
+
+/* ------------------------------------------------------------*/
+
static enum route_map_cmd_result_t
route_match_ipv6_address(void *rule, const struct prefix *prefix, void *object)
{
@@ -234,6 +263,9 @@ void isis_route_map_init(void)
route_map_match_ipv6_address_prefix_list_hook(generic_match_add);
route_map_no_match_ipv6_address_prefix_list_hook(generic_match_delete);
+ route_map_match_tag_hook(generic_match_add);
+ route_map_no_match_tag_hook(generic_match_delete);
+
route_map_set_metric_hook(generic_set_add);
route_map_no_set_metric_hook(generic_set_delete);
@@ -241,5 +273,6 @@ void isis_route_map_init(void)
route_map_install_match(&route_match_ip_address_prefix_list_cmd);
route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ipv6_address_prefix_list_cmd);
+ route_map_install_match(&route_match_tag_cmd);
route_map_install_set(&route_set_metric_cmd);
}
diff --git a/isisd/isis_snmp.c b/isisd/isis_snmp.c
new file mode 100644
index 0000000000..cab9199731
--- /dev/null
+++ b/isisd/isis_snmp.c
@@ -0,0 +1,3457 @@
+/*
+ * ISIS SNMP support
+ * Copyright (C) 2020 Volta Networks, Inc.
+ * Aleksey Romanov
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * This is minimal read-only implementations providing isisReadOnlyCompliance
+ */
+
+#include <zebra.h>
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+#include "vrf.h"
+#include "if.h"
+#include "log.h"
+#include "prefix.h"
+#include "table.h"
+#include "command.h"
+#include "memory.h"
+#include "smux.h"
+#include "libfrr.h"
+#include "version.h"
+
+#include "isisd/isis_constants.h"
+#include "isisd/isis_common.h"
+#include "isisd/isis_flags.h"
+#include "isisd/isis_circuit.h"
+#include "isisd/isis_lsp.h"
+#include "isisd/isis_pdu.h"
+#include "isisd/isis_network.h"
+#include "isisd/isis_misc.h"
+#include "isisd/isis_constants.h"
+#include "isisd/isis_adjacency.h"
+#include "isisd/isis_dynhn.h"
+#include "isisd/isis_te.h"
+#include "isisd/isis_dr.h"
+#include "isisd/isis_nb.h"
+#include "isisd/isisd.h"
+
+/* ISIS-MIB. */
+#define ISIS_MIB 1, 3, 6, 1, 2, 1, 138
+
+#define ISIS_OBJECTS 1
+#define ISIS_SYSTEM 1, 1
+#define ISIS_SYSLEVEL 1, 2
+#define ISIS_CIRC 1, 3
+#define ISIS_CIRC_LEVEL_VALUES 1, 4
+#define ISIS_COUNTERS 1, 5
+#define ISIS_ISADJ 1, 6
+
+/************************ isisSystemGroup ************************/
+
+/* isisSysObject */
+#define ISIS_SYS_OBJECT 1, 1, 1
+#define ISIS_SYS_VERSION 1
+#define ISIS_SYS_LEVELTYPE 2
+#define ISIS_SYS_ID 3
+#define ISIS_SYS_MAXPATHSPLITS 4
+#define ISIS_SYS_MAXLSPGENINT 5
+#define ISIS_SYS_POLLESHELLORATE 6
+#define ISIS_SYS_WAITTIME 7
+#define ISIS_SYS_ADMINSTATE 8
+#define ISIS_SYS_L2TOL1LEAKING 9
+#define ISIS_SYS_MAXAGE 10
+#define ISIS_SYS_RECEIVELSPBUFFERSIZE 11
+#define ISIS_SYS_PROTSUPPORTED 12
+#define ISIS_SYS_NOTIFICATIONENABLE 13
+
+/* isisManAreaAddrEntry */
+#define ISIS_MANAREA_ADDRENTRY 1, 1, 2, 1
+#define ISIS_MANAREA_ADDREXISTSTATE 2
+
+/* isisAreaAddrEntry */
+#define ISIS_AREA_ADDRENTRY 1, 1, 3, 1
+#define ISIS_AREA_ADDR 1
+
+/* isisSummAddrEntry */
+#define ISIS_SUMM_ADDRENTRY 1, 1, 4, 1
+#define ISIS_SUMM_ADDREXISTSTATE 4
+#define ISIS_SUMM_ADDRMETRIC 5
+#define ISIS_SUMM_ADDRFULLMETRIC 6
+
+/* isisRedistributeAddrEntry */
+#define ISIS_REDISTRIBUTE_ADDRENTRY 1, 1, 5, 1
+#define ISIS_REDISTRIBUTE_ADDREXISTSTATE 3
+
+/* isisRouterEntry */
+#define ISIS_ROUTER_ENTRY 1, 1, 6, 1
+#define ISIS_ROUTER_HOSTNAME 3
+#define ISIS_ROUTER_ID 4
+
+/* isisSysLevelTable */
+#define ISIS_SYSLEVEL_ENTRY 1, 2, 1, 1
+#define ISIS_SYSLEVEL_ORIGLSPBUFFSIZE 2
+#define ISIS_SYSLEVEL_MINLSPGENINT 3
+#define ISIS_SYSLEVEL_STATE 4
+#define ISIS_SYSLEVEL_SETOVERLOAD 5
+#define ISIS_SYSLEVEL_SETOVERLOADUNTIL 6
+#define ISIS_SYSLEVEL_METRICSTYLE 7
+#define ISIS_SYSLEVEL_SPFCONSIDERS 8
+#define ISIS_SYSLEVEL_TEENABLED 9
+
+
+/* isisSystemCounterEntry */
+#define ISIS_SYSTEM_COUNTER_ENTRY 1, 5, 1, 1
+#define ISIS_SYSSTAT_CORRLSPS 2
+#define ISIS_SYSSTAT_AUTHTYPEFAILS 3
+#define ISIS_SYSSTAT_AUTHFAILS 4
+#define ISIS_SYSSTAT_LSPDBASEOLOADS 5
+#define ISIS_SYSSTAT_MANADDRDROPFROMAREAS 6
+#define ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS 7
+#define ISIS_SYSSTAT_SEQNUMSKIPS 8
+#define ISIS_SYSSTAT_OWNLSPPURGES 9
+#define ISIS_SYSSTAT_IDFIELDLENMISMATCHES 10
+#define ISIS_SYSSTAT_PARTCHANGES 11
+#define ISIS_SYSSTAT_SPFRUNS 12
+#define ISIS_SYSSTAT_LSPERRORS 13
+
+
+/************************ isisCircuitGroup ************************/
+
+/* Scalar directly under isisCirc */
+#define ISIS_NEXTCIRC_INDEX 1
+
+/* isisCircEntry */
+#define ISIS_CIRC_ENTRY 1, 3, 2, 1
+#define ISIS_CIRC_IFINDEX 2
+#define ISIS_CIRC_ADMINSTATE 3
+#define ISIS_CIRC_EXISTSTATE 4
+#define ISIS_CIRC_TYPE 5
+#define ISIS_CIRC_EXTDOMAIN 6
+#define ISIS_CIRC_LEVELTYPE 7
+#define ISIS_CIRC_PASSIVECIRCUIT 8
+#define ISIS_CIRC_MESHGROUPENABLED 9
+#define ISIS_CIRC_MESHGROUP 10
+#define ISIS_CIRC_SMALLHELLOS 11
+#define ISIS_CIRC_LASTUPTIME 12
+#define ISIS_CIRC_3WAYENABLED 13
+#define ISIS_CIRC_EXTENDEDCIRCID 14
+
+/* isisCircLevelEntry */
+#define ISIS_CIRCLEVEL_ENTRY 1, 4, 1, 1
+#define ISIS_CIRCLEVEL_METRIC 2
+#define ISIS_CIRCLEVEL_WIDEMETRIC 3
+#define ISIS_CIRCLEVEL_ISPRIORITY 4
+#define ISIS_CIRCLEVEL_IDOCTET 5
+#define ISIS_CIRCLEVEL_ID 6
+#define ISIS_CIRCLEVEL_DESIS 7
+#define ISIS_CIRCLEVEL_HELLOMULTIPLIER 8
+#define ISIS_CIRCLEVEL_HELLOTIMER 9
+#define ISIS_CIRCLEVEL_DRHELLOTIMER 10
+#define ISIS_CIRCLEVEL_LSPTHROTTLE 11
+#define ISIS_CIRCLEVEL_MINLSPRETRANSINT 12
+#define ISIS_CIRCLEVEL_CSNPINTERVAL 13
+#define ISIS_CIRCLEVEL_PARTSNPINTERVAL 14
+
+/* isisCircuitCounterEntry */
+#define ISIS_CIRC_COUNTER_ENTRY 1, 5, 2, 1
+#define ISIS_CIRC_ADJCHANGES 2
+#define ISIS_CIRC_NUMADJ 3
+#define ISIS_CIRC_INITFAILS 4
+#define ISIS_CIRC_REJADJS 5
+#define ISIS_CIRC_IDFIELDLENMISMATCHES 6
+#define ISIS_CIRC_MAXAREAADDRMISMATCHES 7
+#define ISIS_CIRC_AUTHTYPEFAILS 8
+#define ISIS_CIRC_AUTHFAILS 9
+#define ISIS_CIRC_LANDESISCHANGES 10
+
+
+/************************ isisISAdjGroup ************************/
+
+/* isisISAdjEntry */
+#define ISIS_ISADJ_ENTRY 1, 6, 1, 1
+#define ISIS_ISADJ_STATE 2
+#define ISIS_ISADJ_3WAYSTATE 3
+#define ISIS_ISADJ_NEIGHSNPAADDRESS 4
+#define ISIS_ISADJ_NEIGHSYSTYPE 5
+#define ISIS_ISADJ_NEIGHSYSID 6
+#define ISIS_ISADJ_NBREXTENDEDCIRCID 7
+#define ISIS_ISADJ_USAGE 8
+#define ISIS_ISADJ_HOLDTIMER 9
+#define ISIS_ISADJ_NEIGHPRIORITY 10
+#define ISIS_ISADJ_LASTUPTIME 11
+
+/* isisISAdjAreadAddrEntry */
+#define ISIS_ISADJAREA_ADDRENTRY 1, 6, 2, 1
+#define ISIS_ISADJAREA_ADDRESS 2
+
+/* isisISAdjIPAddrEntry*/
+#define ISIS_ISADJIPADDR_ENTRY 1, 6, 3, 1
+#define ISIS_ISADJIPADDR_TYPE 2
+#define ISIS_ISADJIPADDR_ADDRESS 3
+
+
+/* isisISAdjProtSuppEntty */
+
+#define ISIS_ISADJPROTSUPP_ENTRY 1, 6, 4, 1
+#define ISIS_ISADJPROTSUPP_PROTOCOL 1
+
+
+/************************ Trap data variables ************************/
+#define ISIS_NOTIFICATION_ENTRY 1, 10, 1
+#define ISIS_NOTIF_SYLELVELINDEX 1
+#define ISIS_NOTIF_CIRCIFINDEX 2
+#define ISIS_PDU_LSPID 3
+#define ISIS_PDU_FRAGMENT 4
+#define ISIS_PDU_FIELDLEN 5
+#define ISIS_PDU_MAXAREAADDR 6
+#define ISIS_PDU_PROTOVER 7
+#define ISIS_PDU_LSPSIZE 8
+#define ISIS_PDU_ORIGBUFFERSIZE 9
+#define ISIS_PDU_BUFFERSIZE 10
+#define ISIS_PDU_PROTSUPP 11
+#define ISIS_ADJ_STATE 12
+#define ISIS_ERROR_OFFSET 13
+#define ISIS_ERROR_TLVTYPE 14
+#define ISIS_NOTIF_AREAADDR 15
+
+/************************ Traps ************************/
+#define ISIS_NOTIFICATIONS ISIS_MIB, 0
+#define ISIS_TRAP_DB_OVERLOAD 1
+#define ISIS_TRAP_MAN_ADDR_DROP 2
+#define ISIS_TRAP_CORRUPTED_LSP 3
+#define ISIS_TRAP_LSP_EXCEED_MAX 4
+#define ISIS_TRAP_ID_LEN_MISMATCH 5
+#define ISIS_TRAP_MAX_AREA_ADDR_MISMATCH 6
+#define ISIS_TRAP_OWN_LSP_PURGE 7
+#define ISIS_TRAP_SEQNO_SKIPPED 8
+#define ISIS_TRAP_AUTHEN_TYPE_FAILURE 9
+#define ISIS_TRAP_AUTHEN_FAILURE 10
+#define ISIS_TRAP_VERSION_SKEW 11
+#define ISIS_TRAP_AREA_MISMATCH 12
+#define ISIS_TRAP_REJ_ADJACENCY 13
+#define ISIS_TRAP_LSP_TOO_LARGE 14
+#define ISIS_TRAP_LSP_BUFFSIZE_MISMATCH 15
+#define ISIS_TRAP_PROTSUPP_MISMATCH 16
+#define ISIS_TRAP_ADJ_STATE_CHANGE 17
+#define ISIS_TRAP_LSP_ERROR 18
+
+/* Change this definition if number of traps changes */
+#define ISIS_TRAP_LAST_TRAP ISIS_TRAP_LSP_ERROR
+
+#define ISIS_SNMP_TRAP_VAR 1, 3, 6, 1, 6, 3, 1, 1, 4, 1, 0
+
+
+/* SNMP value hack. */
+#define COUNTER32 ASN_COUNTER
+#define INTEGER ASN_INTEGER
+#define UNSIGNED32 ASN_GAUGE
+#define TIMESTAMP ASN_TIMETICKS
+#define TIMETICKS ASN_TIMETICKS
+#define STRING ASN_OCTET_STR
+
+/* Declare static local variables for convenience. */
+SNMP_LOCAL_VARIABLES
+
+/* If ARRAY_SIZE is not available use a primitive substitution */
+#ifndef ARRAY_SIZE
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+#endif
+
+/*
+ * Define time function, it serves two purposes
+ * 1. Uses unint32_t for unix time and encapsulates
+ * sing extension issues in conversion from time_t
+ *
+ * 2. I could be replaced in unit test environment
+ */
+#ifndef ISIS_SNMP_HAVE_TIME_FUNC
+static uint32_t isis_snmp_time(void)
+{
+ return (uint32_t)time(NULL);
+}
+
+#endif
+
+/* ISIS-MIB instances. */
+static oid isis_oid[] = {ISIS_MIB};
+
+/* SNMP trap variable */
+static oid isis_snmp_trap_var[] = {ISIS_SNMP_TRAP_VAR};
+
+/* SNMP trap values (others are calculated on the fly */
+static oid isis_snmp_notifications[] = {ISIS_NOTIFICATIONS};
+static oid isis_snmp_trap_val_db_overload[] = {ISIS_NOTIFICATIONS,
+ ISIS_TRAP_DB_OVERLOAD};
+static oid isis_snmp_trap_val_lsp_exceed_max[] = {ISIS_NOTIFICATIONS,
+ ISIS_TRAP_LSP_EXCEED_MAX};
+static oid isis_snmp_trap_val_area_mismatch[] = {ISIS_NOTIFICATIONS,
+ ISIS_TRAP_AREA_MISMATCH};
+static oid isis_snmp_trap_val_lsp_error[] = {ISIS_NOTIFICATIONS,
+ ISIS_TRAP_LSP_ERROR};
+
+/*
+ * Trap vars under 'isisNotifications': note: we use full names of variables
+ * scalar index
+ */
+static oid isis_snmp_trap_data_var_sys_level_index[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_NOTIF_SYLELVELINDEX, 0};
+static oid isis_snmp_trap_data_var_circ_if_index[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_NOTIF_CIRCIFINDEX, 0};
+static oid isis_snmp_trap_data_var_pdu_lsp_id[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_LSPID, 0};
+static oid isis_snmp_trap_data_var_pdu_fragment[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_FRAGMENT, 0};
+static oid isis_snmp_trap_data_var_pdu_field_len[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_FIELDLEN, 0};
+static oid isis_snmp_trap_data_var_pdu_max_area_addr[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_MAXAREAADDR, 0};
+static oid isis_snmp_trap_data_var_pdu_proto_ver[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_PROTOVER, 0};
+static oid isis_snmp_trap_data_var_pdu_lsp_size[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_PDU_LSPSIZE, 0};
+static oid isis_snmp_trap_data_var_adj_state[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_ADJ_STATE, 0};
+static oid isis_snmp_trap_data_var_error_offset[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_ERROR_OFFSET, 0};
+static oid isis_snmp_trap_data_var_error_tlv_type[] = {
+ ISIS_MIB, ISIS_NOTIFICATION_ENTRY, ISIS_ERROR_TLVTYPE, 0};
+
+/*
+ * Other variables used by traps: note we use full names of variables and
+ * reserve space for index
+ */
+static oid isis_snmp_trap_data_var_sys_level_state[] = {
+ ISIS_MIB, ISIS_SYSLEVEL_ENTRY, ISIS_SYSLEVEL_STATE, 0};
+
+/* Throttle time values for traps */
+static time_t isis_snmp_trap_timestamp[ISIS_TRAP_LAST_TRAP]; /* ?? 1 */
+
+/* Max len of raw-pdu in traps */
+#define ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN (64)
+
+/*
+ * Just to save on typing we have a shortcut structure
+ * to specify mib layout as prefix/leaf combination
+ */
+#define ISIS_SNMP_PREF_LEN_MAX 10
+struct isis_var_prefix {
+ FindVarMethod *findVar;
+ uint8_t ivd_pref_len;
+ oid ivd_pref[ISIS_SNMP_PREF_LEN_MAX];
+};
+
+
+/* Find-val functions */
+static uint8_t *isis_snmp_find_sys_object(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_man_area(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_area_addr(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_summ_addr(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_redistribute_addr(struct variable *, oid *,
+ size_t *, int, size_t *,
+ WriteMethod **);
+
+static uint8_t *isis_snmp_find_router(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_sys_level(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_system_counter(struct variable *, oid *,
+ size_t *, int, size_t *,
+ WriteMethod **);
+
+static uint8_t *isis_snmp_find_next_circ_index(struct variable *, oid *,
+ size_t *, int, size_t *,
+ WriteMethod **);
+
+static uint8_t *isis_snmp_find_circ(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_circ_level(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_circ_counter(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_isadj(struct variable *, oid *, size_t *, int,
+ size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_isadj_area(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable *, oid *, size_t *,
+ int, size_t *, WriteMethod **);
+
+static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable *, oid *,
+ size_t *, int, size_t *,
+ WriteMethod **);
+
+/*
+ * Just to save on typing we have a shortcut structure
+ * to specify mib layout, we populate the rest of the data
+ * during initialization
+ */
+#define ISIS_PREF_LEN_MAX (6)
+
+struct isis_func_to_prefix {
+ FindVarMethod *ihtp_func;
+ oid ihtp_pref_oid[ISIS_PREF_LEN_MAX];
+ uint8_t ihtp_pref_len;
+};
+
+static struct isis_func_to_prefix isis_func_to_prefix_arr[] = {
+ {isis_snmp_find_sys_object, {ISIS_SYS_OBJECT}, 3},
+ {isis_snmp_find_man_area, {ISIS_MANAREA_ADDRENTRY}, 4},
+ {isis_snmp_find_area_addr, {ISIS_AREA_ADDRENTRY}, 4},
+ {isis_snmp_find_summ_addr, {ISIS_SUMM_ADDRENTRY}, 4},
+ {isis_snmp_find_redistribute_addr, {ISIS_REDISTRIBUTE_ADDRENTRY}, 4},
+ {isis_snmp_find_router, {ISIS_ROUTER_ENTRY}, 4},
+ {isis_snmp_find_sys_level, {ISIS_SYSLEVEL_ENTRY}, 4},
+ {isis_snmp_find_system_counter, {ISIS_SYSTEM_COUNTER_ENTRY}, 4},
+ {isis_snmp_find_next_circ_index, {ISIS_CIRC}, 2},
+ {isis_snmp_find_circ, {ISIS_CIRC_ENTRY}, 4},
+ {isis_snmp_find_circ_level, {ISIS_CIRCLEVEL_ENTRY}, 4},
+ {isis_snmp_find_circ_counter, {ISIS_CIRC_COUNTER_ENTRY}, 4},
+ {isis_snmp_find_isadj, {ISIS_ISADJ_ENTRY}, 4},
+ {isis_snmp_find_isadj_area, {ISIS_ISADJAREA_ADDRENTRY}, 4},
+ {isis_snmp_find_isadj_ipaddr, {ISIS_ISADJIPADDR_ENTRY}, 4},
+ {isis_snmp_find_isadj_prot_supp, {ISIS_ISADJPROTSUPP_ENTRY}, 4},
+};
+static size_t isis_func_to_prefix_count = ARRAY_SIZE(isis_func_to_prefix_arr);
+
+static struct variable isis_var_arr[] = {
+ {ISIS_SYS_VERSION, INTEGER, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_LEVELTYPE, INTEGER, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_ID, STRING, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_MAXPATHSPLITS, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_MAXLSPGENINT, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_POLLESHELLORATE, UNSIGNED32, RONLY,
+ isis_snmp_find_sys_object},
+ {ISIS_SYS_WAITTIME, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_ADMINSTATE, INTEGER, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_L2TOL1LEAKING, INTEGER, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_MAXAGE, UNSIGNED32, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_RECEIVELSPBUFFERSIZE, UNSIGNED32, RONLY,
+ isis_snmp_find_sys_object},
+ {ISIS_SYS_PROTSUPPORTED, STRING, RONLY, isis_snmp_find_sys_object},
+ {ISIS_SYS_NOTIFICATIONENABLE, INTEGER, RONLY,
+ isis_snmp_find_sys_object},
+ {ISIS_MANAREA_ADDREXISTSTATE, INTEGER, RONLY, isis_snmp_find_man_area},
+ {ISIS_AREA_ADDR, STRING, RONLY, isis_snmp_find_area_addr},
+ {ISIS_SUMM_ADDREXISTSTATE, INTEGER, RONLY, isis_snmp_find_summ_addr},
+ {ISIS_SUMM_ADDRMETRIC, UNSIGNED32, RONLY, isis_snmp_find_summ_addr},
+ {ISIS_SUMM_ADDRFULLMETRIC, UNSIGNED32, RONLY, isis_snmp_find_summ_addr},
+ {ISIS_REDISTRIBUTE_ADDREXISTSTATE, INTEGER, RONLY,
+ isis_snmp_find_redistribute_addr},
+ {ISIS_ROUTER_HOSTNAME, STRING, RONLY, isis_snmp_find_router},
+ {ISIS_ROUTER_ID, UNSIGNED32, RONLY, isis_snmp_find_router},
+ {ISIS_SYSLEVEL_ORIGLSPBUFFSIZE, UNSIGNED32, RONLY,
+ isis_snmp_find_sys_level},
+ {ISIS_SYSLEVEL_MINLSPGENINT, UNSIGNED32, RONLY,
+ isis_snmp_find_sys_level},
+ {ISIS_SYSLEVEL_STATE, INTEGER, RONLY, isis_snmp_find_sys_level},
+ {ISIS_SYSLEVEL_SETOVERLOAD, INTEGER, RONLY, isis_snmp_find_sys_level},
+ {ISIS_SYSLEVEL_SETOVERLOADUNTIL, UNSIGNED32, RONLY,
+ isis_snmp_find_sys_level},
+ {ISIS_SYSLEVEL_METRICSTYLE, INTEGER, RONLY, isis_snmp_find_sys_level},
+ {ISIS_SYSLEVEL_SPFCONSIDERS, INTEGER, RONLY, isis_snmp_find_sys_level},
+ {ISIS_SYSLEVEL_TEENABLED, INTEGER, RONLY, isis_snmp_find_sys_level},
+ {ISIS_SYSSTAT_CORRLSPS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_AUTHTYPEFAILS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_AUTHFAILS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_LSPDBASEOLOADS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_MANADDRDROPFROMAREAS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_SEQNUMSKIPS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_OWNLSPPURGES, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_IDFIELDLENMISMATCHES, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_PARTCHANGES, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_SPFRUNS, COUNTER32, RONLY, isis_snmp_find_system_counter},
+ {ISIS_SYSSTAT_LSPERRORS, COUNTER32, RONLY,
+ isis_snmp_find_system_counter},
+ {ISIS_NEXTCIRC_INDEX, UNSIGNED32, RONLY,
+ isis_snmp_find_next_circ_index},
+ {ISIS_CIRC_IFINDEX, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_ADMINSTATE, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_EXISTSTATE, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_TYPE, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_EXTDOMAIN, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_LEVELTYPE, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_PASSIVECIRCUIT, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_MESHGROUPENABLED, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_MESHGROUP, UNSIGNED32, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_SMALLHELLOS, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_LASTUPTIME, TIMESTAMP, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_3WAYENABLED, INTEGER, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRC_EXTENDEDCIRCID, UNSIGNED32, RONLY, isis_snmp_find_circ},
+ {ISIS_CIRCLEVEL_METRIC, UNSIGNED32, RONLY, isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_WIDEMETRIC, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_ISPRIORITY, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_IDOCTET, UNSIGNED32, RONLY, isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_ID, STRING, RONLY, isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_DESIS, STRING, RONLY, isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_HELLOMULTIPLIER, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_HELLOTIMER, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_DRHELLOTIMER, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_LSPTHROTTLE, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_MINLSPRETRANSINT, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_CSNPINTERVAL, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRCLEVEL_PARTSNPINTERVAL, UNSIGNED32, RONLY,
+ isis_snmp_find_circ_level},
+ {ISIS_CIRC_ADJCHANGES, COUNTER32, RONLY, isis_snmp_find_circ_counter},
+ {ISIS_CIRC_NUMADJ, UNSIGNED32, RONLY, isis_snmp_find_circ_counter},
+ {ISIS_CIRC_INITFAILS, COUNTER32, RONLY, isis_snmp_find_circ_counter},
+ {ISIS_CIRC_REJADJS, COUNTER32, RONLY, isis_snmp_find_circ_counter},
+ {ISIS_CIRC_IDFIELDLENMISMATCHES, COUNTER32, RONLY,
+ isis_snmp_find_circ_counter},
+ {ISIS_CIRC_MAXAREAADDRMISMATCHES, COUNTER32, RONLY,
+ isis_snmp_find_circ_counter},
+ {ISIS_CIRC_AUTHTYPEFAILS, COUNTER32, RONLY,
+ isis_snmp_find_circ_counter},
+ {ISIS_CIRC_AUTHFAILS, COUNTER32, RONLY, isis_snmp_find_circ_counter},
+ {ISIS_CIRC_LANDESISCHANGES, COUNTER32, RONLY,
+ isis_snmp_find_circ_counter},
+ {ISIS_ISADJ_STATE, INTEGER, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_3WAYSTATE, INTEGER, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_NEIGHSNPAADDRESS, STRING, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_NEIGHSYSTYPE, INTEGER, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_NEIGHSYSID, STRING, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_NBREXTENDEDCIRCID, UNSIGNED32, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_USAGE, INTEGER, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_HOLDTIMER, UNSIGNED32, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_NEIGHPRIORITY, UNSIGNED32, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJ_LASTUPTIME, TIMESTAMP, RONLY, isis_snmp_find_isadj},
+ {ISIS_ISADJAREA_ADDRESS, STRING, RONLY, isis_snmp_find_isadj_area},
+ {ISIS_ISADJIPADDR_TYPE, INTEGER, RONLY, isis_snmp_find_isadj_ipaddr},
+ {ISIS_ISADJIPADDR_ADDRESS, STRING, RONLY, isis_snmp_find_isadj_ipaddr},
+ {ISIS_ISADJPROTSUPP_PROTOCOL, INTEGER, RONLY,
+ isis_snmp_find_isadj_prot_supp},
+};
+
+static const size_t isis_var_count = ARRAY_SIZE(isis_var_arr);
+
+/* Minimal set of hard-coded data */
+#define ISIS_VERSION (1)
+
+/* If sys-id is not set use this value */
+static uint8_t isis_null_sysid[ISIS_SYS_ID_LEN];
+
+/* OSI addr-len */
+#define ISIS_SNMP_OSI_ADDR_LEN_MAX (20)
+
+/*
+ * The implementation has a fixed max-path splits value
+ * of 64 (see ISIS_MAX_PATH_SPLITS), the max mib value
+ * is 32.
+ *
+ * FIXME(aromanov): should we return 32 or 64?
+ */
+#define ISIS_SNMP_MAX_PATH_SPLITS (32)
+
+#define ISIS_SNMP_ADMIN_STATE_ON (1)
+
+#define ISIS_SNMP_ROW_STATUS_ACTIVE (1)
+
+#define ISIS_SNMP_LEVEL_STATE_OFF (1)
+#define ISIS_SNMP_LEVEL_STATE_ON (2)
+#define ISIS_SNMP_LEVEL_STATE_WAITING (3)
+#define ISIS_SNMP_LEVEL_STATE_OVERLOADED (4)
+
+#define ISIS_SNMP_TRUTH_VALUE_TRUE (1)
+#define ISIS_SNMP_TRUTH_VALUE_FALSE (2)
+
+#define ISIS_SNMP_METRIC_STYLE_NARROW (1)
+#define ISIS_SNMP_METRIC_STYLE_WIDE (2)
+#define ISIS_SNMP_METRIC_STYLE_BOTH (3)
+
+#define ISIS_SNMP_MESH_GROUP_INACTIVE (1)
+
+#define ISIS_SNMP_ADJ_STATE_DOWN (1)
+#define ISIS_SNMP_ADJ_STATE_INITIALIZING (2)
+#define ISIS_SNMP_ADJ_STATE_UP (3)
+#define ISIS_SNMP_ADJ_STATE_FAILED (4)
+
+#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1 (1)
+#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2 (2)
+#define ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2 (3)
+#define ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN (4)
+
+#define ISIS_SNMP_INET_TYPE_V4 (1)
+#define ISIS_SNMP_INET_TYPE_V6 (2)
+
+#define ISIS_SNMP_P2P_CIRCUIT (3)
+
+/* Protocols supported value */
+static uint8_t isis_snmp_protocols_supported = 0x7; /* All: iso, ipv4, ipv6 */
+
+/*
+ * Convenience function to move to the next circuit,
+ */
+static struct isis_circuit *isis_snmp_circuit_next(struct isis_circuit *circuit)
+{
+ uint32_t start;
+ uint32_t off;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return NULL;
+
+ start = 1;
+
+ if (circuit != NULL)
+ start = circuit->snmp_id + 1;
+
+ for (off = start; off < SNMP_CIRCUITS_MAX; off++) {
+ circuit = isis->snmp_circuits[off];
+
+ if (circuit != NULL)
+ return circuit;
+ }
+
+ return NULL;
+}
+
+/*
+ * Convenience function to get the first matching level
+ */
+static int isis_snmp_circuit_get_level_lo(struct isis_circuit *circuit)
+{
+ if (circuit->is_type == IS_LEVEL_2)
+ return IS_LEVEL_2;
+
+ return IS_LEVEL_1;
+}
+
+/* Check level match */
+static int isis_snmp_get_level_match(int is_type, int level)
+{
+ if (is_type != IS_LEVEL_1 && is_type != IS_LEVEL_2
+ && is_type != IS_LEVEL_1_AND_2)
+ return 0;
+
+ if (level != IS_LEVEL_1 && level != IS_LEVEL_2)
+ return 0;
+
+
+ if (is_type == IS_LEVEL_1) {
+ if (level == IS_LEVEL_1)
+ return 1;
+
+ return 0;
+ }
+
+ if (is_type == IS_LEVEL_2) {
+ if (level == IS_LEVEL_2)
+ return 1;
+
+ return 0;
+ }
+
+ return 1;
+}
+/*
+ * Helper function to convert oid index representing
+ * octet-string index (e.g. isis-sys-id) to byte string
+ * representing the same index.
+ *
+ * Also we do not fail if idx is longer than max_len,
+ * so we can use the same function to check compound
+ * indexes.
+ */
+static int isis_snmp_conv_exact(uint8_t *buf, size_t max_len, size_t *out_len,
+ const oid *idx, size_t idx_len)
+{
+ size_t off;
+ size_t len;
+
+ /* Oid representation: length followed by bytes */
+ if (idx == NULL || idx_len == 0)
+ return 0;
+
+ len = idx[0];
+
+ if (len > max_len)
+ return 0;
+
+ if (idx_len < len + 1)
+ return 0;
+
+ for (off = 0; off < len; off++) {
+ if (idx[off + 1] > 0xff)
+ return 0;
+
+ buf[off] = (uint8_t)(idx[off + 1] & 0xff);
+ }
+
+ *out_len = len;
+
+ return 1;
+}
+
+static int isis_snmp_conv_next(uint8_t *buf, size_t max_len, size_t *out_len,
+ int *try_exact, const oid *idx, size_t idx_len)
+{
+ size_t off;
+ size_t len;
+ size_t cmp_len;
+
+ if (idx == NULL || idx_len == 0) {
+ *out_len = 0;
+ *try_exact = 1;
+ return 1;
+ }
+
+ len = idx[0];
+
+ if (len > max_len)
+ return 0;
+
+ cmp_len = len;
+
+ if ((idx_len - 1) < cmp_len)
+ cmp_len = idx_len - 1;
+
+ for (off = 0; off < cmp_len; off++) {
+ if (idx[off + 1] > 0xff) {
+ memset(buf + off, 0xff, len - off);
+ *out_len = len;
+ *try_exact = 1;
+ return 1;
+ }
+
+ buf[off] = (uint8_t)(idx[off + 1] & 0xff);
+ }
+
+ if (cmp_len < len)
+ memset(buf + cmp_len, 0, len - cmp_len);
+
+ *out_len = len;
+ *try_exact = cmp_len < len ? 1 : 0;
+ return 1;
+}
+
+/*
+ * Helper functions to find area address from snmp index
+ */
+static int isis_snmp_area_addr_lookup_exact(oid *oid_idx, size_t oid_idx_len,
+ struct isis_area **ret_area,
+ struct area_addr **ret_addr)
+{
+ uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX];
+ size_t addr_len;
+ struct isis_area *area = NULL;
+ struct area_addr *addr = NULL;
+ struct listnode *addr_node;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return 0;
+
+ if (list_isempty(isis->area_list)) {
+ /* Area is not configured yet */
+ return 0;
+ }
+
+ area = listgetdata(listhead(isis->area_list));
+
+ int res = isis_snmp_conv_exact(cmp_buf, sizeof(cmp_buf), &addr_len,
+ oid_idx, oid_idx_len);
+
+
+ if (!res || addr_len == 0 || oid_idx_len != (addr_len + 1)) {
+ /* Bad conversion, empty address or extra oids at the end */
+ return 0;
+ }
+
+ for (ALL_LIST_ELEMENTS_RO(area->area_addrs, addr_node, addr)) {
+ if (addr->addr_len != addr_len)
+ continue;
+
+ if (memcmp(addr->area_addr, cmp_buf, addr_len) == 0) {
+ if (ret_area != 0)
+ *ret_area = area;
+
+ if (ret_addr != 0)
+ *ret_addr = addr;
+
+ return 1;
+ }
+ }
+ return 0;
+}
+
+static int isis_snmp_area_addr_lookup_next(oid *oid_idx, size_t oid_idx_len,
+ struct isis_area **ret_area,
+ struct area_addr **ret_addr)
+{
+ uint8_t cmp_buf[ISIS_SNMP_OSI_ADDR_LEN_MAX];
+ size_t addr_len;
+ int try_exact = 0;
+ struct isis_area *found_area = NULL;
+ struct isis_area *area = NULL;
+ struct area_addr *found_addr = NULL;
+ struct area_addr *addr = NULL;
+ struct listnode *addr_node;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return 0;
+
+ if (list_isempty(isis->area_list)) {
+ /* Area is not configured yet */
+ return 0;
+ }
+
+ area = listgetdata(listhead(isis->area_list));
+
+ int res = isis_snmp_conv_next(cmp_buf, sizeof(cmp_buf), &addr_len,
+ &try_exact, oid_idx, oid_idx_len);
+
+ if (!res)
+ return 0;
+
+ for (ALL_LIST_ELEMENTS_RO(area->area_addrs, addr_node, addr)) {
+ if (addr->addr_len < addr_len)
+ continue;
+
+ if (addr->addr_len == addr_len) {
+ if (addr_len == 0)
+ continue;
+
+ res = memcmp(addr->area_addr, cmp_buf, addr_len);
+
+ if (res < 0)
+ continue;
+
+ if (res == 0 && addr->addr_len == addr_len) {
+ if (try_exact) {
+ /*
+ * This is the best match no point
+ * to look further
+ */
+ found_area = area;
+ found_addr = addr;
+ break;
+ }
+ continue;
+ }
+ }
+
+ if (found_addr == NULL || addr->addr_len < found_addr->addr_len
+ || (addr->addr_len == found_addr->addr_len
+ && memcmp(addr->area_addr, found_addr->area_addr,
+ addr->addr_len)
+ < 0)) {
+ found_area = area;
+ found_addr = addr;
+ }
+ }
+
+ if (found_area == NULL)
+ return 0;
+
+ if (ret_area != 0)
+ *ret_area = found_area;
+
+ if (ret_addr != 0)
+ *ret_addr = found_addr;
+
+ return 1;
+}
+
+/*
+ * Helper functions to find circuit from
+ * snmp index
+ */
+static int isis_snmp_circuit_lookup_exact(oid *oid_idx, size_t oid_idx_len,
+ struct isis_circuit **ret_circuit)
+{
+ struct isis_circuit *circuit;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return 0;
+
+ if (oid_idx == NULL || oid_idx_len < 1
+ || oid_idx[0] > SNMP_CIRCUITS_MAX)
+ return 0;
+
+ circuit = isis->snmp_circuits[oid_idx[0]];
+ if (circuit == NULL)
+ return 0;
+
+ if (ret_circuit != NULL)
+ *ret_circuit = circuit;
+
+ return 1;
+}
+
+static int isis_snmp_circuit_lookup_next(oid *oid_idx, size_t oid_idx_len,
+ struct isis_circuit **ret_circuit)
+{
+ oid off;
+ oid start;
+ struct isis_circuit *circuit;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return 0;
+
+ start = 0;
+
+ if (oid_idx != NULL || oid_idx_len != 0) {
+ if (oid_idx[0] > SNMP_CIRCUITS_MAX)
+ return 0;
+
+ start = oid_idx[0];
+ }
+
+ for (off = start; off < SNMP_CIRCUITS_MAX; ++off) {
+ circuit = isis->snmp_circuits[off];
+
+ if (circuit != NULL && off > start) {
+ if (ret_circuit != NULL)
+ *ret_circuit = circuit;
+
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Helper functions to find circuit level
+ * combination from snmp index
+ */
+static int isis_snmp_circuit_level_lookup_exact(
+ oid *oid_idx, size_t oid_idx_len, int check_match,
+ struct isis_circuit **ret_circuit, int *ret_level)
+{
+ int level;
+ int res;
+ struct isis_circuit *circuit;
+
+ /* Minor optimization: check level first */
+ if (oid_idx == NULL || oid_idx_len < 2)
+ return 0;
+
+ if (oid_idx[1] < IS_LEVEL_1 || oid_idx[1] > IS_LEVEL_2)
+ return 0;
+
+ level = (int)oid_idx[1];
+
+ res = isis_snmp_circuit_lookup_exact(oid_idx, oid_idx_len, &circuit);
+
+ if (!res)
+ return 0;
+
+ if (check_match && !isis_snmp_get_level_match(circuit->is_type, level))
+ return 0;
+
+ if (ret_circuit != NULL)
+ *ret_circuit = circuit;
+
+ if (ret_level != NULL)
+ *ret_level = level;
+
+ return 1;
+}
+
+static int isis_snmp_circuit_level_lookup_next(
+ oid *oid_idx, size_t oid_idx_len, int check_match,
+ struct isis_circuit **ret_circuit, int *ret_level)
+{
+ oid off;
+ oid start;
+ struct isis_circuit *circuit;
+ int level;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return 0;
+
+ start = 0;
+
+ if (oid_idx != NULL || oid_idx_len != 0) {
+ if (oid_idx[0] > SNMP_CIRCUITS_MAX)
+ return 0;
+
+ start = oid_idx[0];
+ }
+
+ for (off = start; off < SNMP_CIRCUITS_MAX; off++) {
+ circuit = isis->snmp_circuits[off];
+
+ if (circuit == NULL)
+ continue;
+
+ if (off > start || oid_idx_len < 2) {
+ /* Found and can use level 1 */
+ level = IS_LEVEL_1;
+ break;
+ }
+
+ /* We have to check level specified by index */
+ if (oid_idx[1] < IS_LEVEL_1) {
+ level = IS_LEVEL_1;
+ break;
+ }
+
+ if (oid_idx[1] < IS_LEVEL_2) {
+ level = IS_LEVEL_2;
+ break;
+ }
+
+ /* Try next */
+ circuit = NULL;
+ }
+
+ if (circuit == NULL)
+ return 0;
+
+ if (check_match
+ && !isis_snmp_get_level_match(circuit->is_type, level)) {
+ if (level == IS_LEVEL_1) {
+ /*
+ * We can simply advance level because
+ * at least one level should match
+ */
+ level = IS_LEVEL_2;
+ } else {
+ /* We have to move to the next circuit */
+ circuit = isis_snmp_circuit_next(circuit);
+ if (circuit == NULL)
+ return 0;
+
+ level = isis_snmp_circuit_get_level_lo(circuit);
+ }
+ }
+
+ if (ret_circuit != NULL)
+ *ret_circuit = circuit;
+
+ if (ret_level != NULL)
+ *ret_level = level;
+
+ return 1;
+}
+
+/*
+ * Helper functions to find adjacency
+ * from snmp index.
+ *
+ * We have 4 tables related to adjacency
+ * looking up adjacency is quite expensive
+ * in case of bcast interfaces.
+ *
+ * It is pain to have 4 very similar functions
+ * hence we pass in and out additional data
+ * we are looking for.
+ *
+ * Note: we use data-len value to distinguish
+ * between ipv4 and ipv6 addresses
+ */
+#define ISIS_SNMP_ADJ_DATA_NONE (1)
+#define ISIS_SNMP_ADJ_DATA_AREA_ADDR (2)
+#define ISIS_SNMP_ADJ_DATA_IP_ADDR (3)
+#define ISIS_SNMP_ADJ_DATA_PROTO (4)
+
+/*
+ * Helper function to process data associated
+ * with adjacency
+ */
+static int isis_snmp_adj_helper(struct isis_adjacency *adj, int data_id,
+ oid data_off, uint8_t **ret_data,
+ size_t *ret_data_len)
+{
+ uint8_t *data = NULL;
+ size_t data_len = 0;
+
+ switch (data_id) {
+ case ISIS_SNMP_ADJ_DATA_NONE:
+ break;
+
+ case ISIS_SNMP_ADJ_DATA_AREA_ADDR:
+ if (data_off >= adj->area_address_count)
+ return 0;
+
+ data = adj->area_addresses[data_off].area_addr;
+ data_len = adj->area_addresses[data_off].addr_len;
+ break;
+
+ case ISIS_SNMP_ADJ_DATA_IP_ADDR:
+ if (data_off
+ >= (adj->ipv4_address_count + adj->ipv6_address_count))
+ return 0;
+
+ if (data_off >= adj->ipv4_address_count) {
+ data = (uint8_t *)&adj->ipv6_addresses
+ [data_off - adj->ipv4_address_count];
+ data_len = sizeof(adj->ipv6_addresses[0]);
+ } else {
+ data = (uint8_t *)&adj->ipv4_addresses[data_off];
+ data_len = sizeof(adj->ipv4_addresses[0]);
+ }
+
+ break;
+
+
+ case ISIS_SNMP_ADJ_DATA_PROTO:
+ if (data_off >= adj->nlpids.count)
+ return 0;
+
+ data = &adj->nlpids.nlpids[data_off];
+ data_len = sizeof(adj->nlpids.nlpids[0]);
+ break;
+
+ default:
+ assert(0);
+ return 0;
+ }
+
+ if (ret_data != NULL)
+ *ret_data = data;
+
+ if (ret_data_len != NULL)
+ *ret_data_len = data_len;
+
+ return 1;
+}
+
+static int isis_snmp_adj_lookup_exact(oid *oid_idx, size_t oid_idx_len,
+ int data_id,
+ struct isis_adjacency **ret_adj,
+ oid *ret_data_idx, uint8_t **ret_data,
+ size_t *ret_data_len)
+{
+ int res;
+ struct listnode *node;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj;
+ struct isis_adjacency *tmp_adj;
+ oid adj_idx;
+ oid data_off;
+ uint8_t *data;
+ size_t data_len;
+
+ res = isis_snmp_circuit_lookup_exact(oid_idx, oid_idx_len, &circuit);
+
+ if (!res)
+ return 0;
+
+ if (oid_idx == NULL || oid_idx_len < 2
+ || (data_id != ISIS_SNMP_ADJ_DATA_NONE && oid_idx_len < 3))
+ return 0;
+
+ adj_idx = oid_idx[1];
+
+ if (data_id != ISIS_SNMP_ADJ_DATA_NONE) {
+ if (oid_idx[2] == 0)
+ return 0;
+
+ data_off = oid_idx[2] - 1;
+ } else {
+ /*
+ * Data-off is not used if data-id is none
+ * but we set it just for consistency
+ */
+ data_off = 0;
+ }
+
+ adj = NULL;
+ data = NULL;
+ data_len = 0;
+
+ for (ALL_LIST_ELEMENTS_RO(circuit->snmp_adj_list, node, tmp_adj)) {
+ if (tmp_adj->snmp_idx > adj_idx) {
+ /*
+ * Adjacencies are ordered in the list
+ * no point to look further
+ */
+ break;
+ }
+
+ if (tmp_adj->snmp_idx == adj_idx) {
+ res = isis_snmp_adj_helper(tmp_adj, data_id, data_off,
+ &data, &data_len);
+ if (res)
+ adj = tmp_adj;
+
+ break;
+ }
+ }
+
+ if (adj == NULL)
+ return 0;
+
+ if (ret_adj != NULL)
+ *ret_adj = adj;
+
+ if (ret_data_idx != NULL)
+ *ret_data_idx = data_off + 1;
+
+ if (ret_data)
+ *ret_data = data;
+
+ if (ret_data_len)
+ *ret_data_len = data_len;
+
+ return 1;
+}
+
+static int isis_snmp_adj_lookup_next(oid *oid_idx, size_t oid_idx_len,
+ int data_id,
+ struct isis_adjacency **ret_adj,
+ oid *ret_data_idx, uint8_t **ret_data,
+ size_t *ret_data_len)
+{
+ struct listnode *node;
+ struct isis_circuit *circuit;
+ struct isis_adjacency *adj;
+ struct isis_adjacency *tmp_adj;
+ oid circ_idx;
+ oid adj_idx;
+ oid data_idx;
+ uint8_t *data;
+ size_t data_len;
+
+ adj = NULL;
+ data = NULL;
+ data_len = 0;
+
+ /*
+ * Note: we rely on the fact that data indexes are consequtive
+ * starting from 1
+ */
+
+ if (oid_idx == 0 || oid_idx_len == 0) {
+ circ_idx = 0;
+ adj_idx = 0;
+ data_idx = 0;
+ } else if (oid_idx_len == 1) {
+ circ_idx = oid_idx[0];
+ adj_idx = 0;
+ data_idx = 0;
+ } else if (oid_idx_len == 2) {
+ circ_idx = oid_idx[0];
+ adj_idx = oid_idx[1];
+ data_idx = 0;
+ } else {
+ circ_idx = oid_idx[0];
+ adj_idx = oid_idx[1];
+
+ if (data_id == ISIS_SNMP_ADJ_DATA_NONE)
+ data_idx = 0;
+ else
+ data_idx = oid_idx[2];
+ }
+
+ if (!isis_snmp_circuit_lookup_exact(&circ_idx, 1, &circuit)
+ && !isis_snmp_circuit_lookup_next(&circ_idx, 1, &circuit))
+ /* No circuit */
+ return 0;
+
+ if (circuit->snmp_id != circ_idx) {
+ /* Match is not exact */
+ circ_idx = 0;
+ adj_idx = 0;
+ data_idx = 0;
+ }
+
+ /*
+ * Note: the simple loop below will work in all cases
+ */
+ while (circuit != NULL) {
+ for (ALL_LIST_ELEMENTS_RO(circuit->snmp_adj_list, node,
+ tmp_adj)) {
+ if (tmp_adj->snmp_idx < adj_idx)
+ continue;
+
+ if (tmp_adj->snmp_idx == adj_idx
+ && data_id == ISIS_SNMP_ADJ_DATA_NONE)
+ continue;
+
+ if (adj_idx != 0 && tmp_adj->snmp_idx > adj_idx)
+ data_idx = 0;
+
+ if (isis_snmp_adj_helper(tmp_adj, data_id, data_idx,
+ &data, &data_len)) {
+ adj = tmp_adj;
+ break;
+ }
+ }
+
+ if (adj != NULL)
+ break;
+
+ circuit = isis_snmp_circuit_next(circuit);
+ circ_idx = 0;
+ adj_idx = 0;
+ data_idx = 0;
+ }
+
+ if (adj == NULL)
+ return 0;
+
+ if (ret_adj != NULL)
+ *ret_adj = adj;
+
+ if (ret_data_idx != 0) {
+ if (data_id == ISIS_SNMP_ADJ_DATA_NONE)
+ /*
+ * Value does not matter but let us set
+ * it to zero for consistency
+ */
+ *ret_data_idx = 0;
+ else
+ *ret_data_idx = data_idx + 1;
+ }
+
+ if (ret_data != 0)
+ *ret_data = data;
+
+ if (ret_data_len != 0)
+ *ret_data_len = data_len;
+
+ return 1;
+}
+
+static uint8_t *isis_snmp_find_sys_object(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ struct isis_area *area = NULL;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return NULL;
+
+ if (!list_isempty(isis->area_list))
+ area = listgetdata(listhead(isis->area_list));
+
+ /* Check whether the instance identifier is valid */
+ if (smux_header_generic(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ switch (v->magic) {
+ case ISIS_SYS_VERSION:
+ return SNMP_INTEGER(ISIS_VERSION);
+
+ case ISIS_SYS_LEVELTYPE:
+ /*
+ * If we do not have areas use 1&2 otherwise use settings
+ * from the first area in the list
+ */
+ if (area == NULL)
+ return SNMP_INTEGER(IS_LEVEL_1_AND_2);
+
+ return SNMP_INTEGER(area->is_type);
+
+ case ISIS_SYS_ID:
+ if (!isis->sysid_set) {
+ *var_len = ISIS_SYS_ID_LEN;
+ return isis_null_sysid;
+ }
+
+ *var_len = ISIS_SYS_ID_LEN;
+ return isis->sysid;
+
+ case ISIS_SYS_MAXPATHSPLITS:
+ return SNMP_INTEGER(ISIS_SNMP_MAX_PATH_SPLITS);
+
+ case ISIS_SYS_MAXLSPGENINT:
+ return SNMP_INTEGER(DEFAULT_MAX_LSP_GEN_INTERVAL);
+
+ case ISIS_SYS_POLLESHELLORATE:
+ return SNMP_INTEGER(DEFAULT_HELLO_INTERVAL);
+
+ case ISIS_SYS_WAITTIME:
+ /* Note: it seems that we have same fixed delay time */
+ return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL);
+
+ case ISIS_SYS_ADMINSTATE:
+ /* If daemon is running it admin state is on */
+ return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON);
+
+
+ case ISIS_SYS_L2TOL1LEAKING:
+ /* We do not allow l2-to-l1 leaking */
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ case ISIS_SYS_MAXAGE:
+ return SNMP_INTEGER(MAX_AGE);
+
+ case ISIS_SYS_RECEIVELSPBUFFERSIZE:
+ if (area == NULL)
+ return SNMP_INTEGER(DEFAULT_LSP_MTU);
+
+ return SNMP_INTEGER(area->lsp_mtu);
+
+ case ISIS_SYS_PROTSUPPORTED:
+ *var_len = 1;
+ return &isis_snmp_protocols_supported;
+
+ case ISIS_SYS_NOTIFICATIONENABLE:
+ if (isis->snmp_notifications)
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
+
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+
+static uint8_t *isis_snmp_find_man_area(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ int res;
+ struct area_addr *area_addr = NULL;
+ oid *oid_idx;
+ size_t oid_idx_len;
+ size_t off = 0;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+
+ if (exact) {
+ res = isis_snmp_area_addr_lookup_exact(oid_idx, oid_idx_len,
+ NULL, &area_addr);
+
+ if (!res)
+ return NULL;
+
+ } else {
+ res = isis_snmp_area_addr_lookup_next(oid_idx, oid_idx_len,
+ NULL, &area_addr);
+
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = area_addr->addr_len;
+
+ for (off = 0; off < area_addr->addr_len; off++)
+ name[v->namelen + 1 + off] = area_addr->area_addr[off];
+
+ *length = v->namelen + 1 + area_addr->addr_len;
+ }
+
+ switch (v->magic) {
+ case ISIS_MANAREA_ADDREXISTSTATE:
+ return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_area_addr(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /*
+ * Area addresses in sense of addresses reported by L1 lsps
+ * are not supported yet.
+ */
+ (void)v;
+ (void)name;
+ (void)length;
+ (void)exact;
+ (void)var_len;
+
+
+ *write_method = NULL;
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_summ_addr(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /*
+ * So far there is no way to set summary table values through cli
+ * and snmp operations are read-only, hence there are no entries
+ */
+ (void)v;
+ (void)name;
+ (void)length;
+ (void)exact;
+ (void)var_len;
+ *write_method = NULL;
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_redistribute_addr(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /*
+ * It is not clear at the point whether redist code in isis is actually
+ * used for now we will consider that entries are not present
+ */
+ (void)v;
+ (void)name;
+ (void)length;
+ (void)exact;
+ (void)var_len;
+ *write_method = NULL;
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_router(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ uint8_t cmp_buf[ISIS_SYS_ID_LEN];
+ size_t cmp_len;
+ int try_exact;
+ int cmp_level;
+ int res;
+ struct isis_dynhn *dyn = NULL;
+ oid *oid_idx;
+ size_t oid_idx_len;
+ size_t off = 0;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+
+ if (exact) {
+ res = isis_snmp_conv_exact(cmp_buf, sizeof(cmp_buf), &cmp_len,
+ oid_idx, oid_idx_len);
+
+ if (!res || cmp_len != ISIS_SYS_ID_LEN
+ || oid_idx_len != (cmp_len + 2))
+ /*
+ * Bad conversion, or bad length,
+ * or extra oids at the end
+ */
+ return NULL;
+
+ if (oid_idx[ISIS_SYS_ID_LEN + 1] < IS_LEVEL_1
+ || oid_idx[ISIS_SYS_ID_LEN + 1] > IS_LEVEL_2)
+ /* Level part of the index is out of range */
+ return NULL;
+
+ cmp_level = (int)oid_idx[ISIS_SYS_ID_LEN + 1];
+
+ dyn = dynhn_find_by_id(cmp_buf);
+
+ if (dyn == NULL || dyn->level != cmp_level)
+ return NULL;
+
+ switch (v->magic) {
+ case ISIS_ROUTER_HOSTNAME:
+ *var_len = strlen(dyn->hostname);
+ return (uint8_t *)dyn->hostname;
+
+ case ISIS_ROUTER_ID:
+ /* It seems that we do no know router-id in lsps */
+ return SNMP_INTEGER(0);
+
+ default:
+ break;
+ }
+
+ return NULL;
+ }
+
+ res = isis_snmp_conv_next(cmp_buf, sizeof(cmp_buf), &cmp_len,
+ &try_exact, oid_idx, oid_idx_len);
+
+
+ if (!res)
+ /* Bad conversion */
+ return NULL;
+
+ if (cmp_len != ISIS_SYS_ID_LEN) {
+ /* We do not have valid index oids */
+ memset(cmp_buf, 0, sizeof(cmp_buf));
+ cmp_level = 0;
+ } else if (try_exact)
+ /*
+ * We have no valid level index.
+ * Let start from non-existing level 0 and
+ * hence not need to do exact match
+ */
+ cmp_level = 0;
+ else if (oid_idx_len < (ISIS_SYS_ID_LEN + 2))
+ cmp_level = 0;
+ else if (oid_idx[ISIS_SYS_ID_LEN + 1] <= IS_LEVEL_2)
+ cmp_level = (int)oid_idx[ISIS_SYS_ID_LEN + 1];
+ else
+ /*
+ * Any value greater than 2 will have the same result
+ * but we can have integer overflows, hence 3 is a reasonable
+ * choice
+ */
+ cmp_level = (int)(IS_LEVEL_2 + 1);
+
+ dyn = dynhn_snmp_next(cmp_buf, cmp_level);
+
+ if (dyn == NULL)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = ISIS_SYS_ID_LEN;
+
+ for (off = 0; off < ISIS_SYS_ID_LEN; off++)
+ name[v->namelen + 1 + off] = dyn->id[off];
+
+ name[v->namelen + 1 + ISIS_SYS_ID_LEN] = (oid)dyn->level;
+
+ /* Set length */
+ *length = v->namelen + 1 + ISIS_SYS_ID_LEN + 1;
+
+ switch (v->magic) {
+ case ISIS_ROUTER_HOSTNAME:
+ *var_len = strlen(dyn->hostname);
+ return (uint8_t *)dyn->hostname;
+
+ case ISIS_ROUTER_ID:
+ /* It seems that we do no know router-id in lsps */
+ return SNMP_INTEGER(0);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_sys_level(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int level;
+ int level_match;
+ struct isis_area *area = NULL;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return NULL;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+
+ if (exact) {
+ if (oid_idx == NULL || oid_idx_len != 1)
+ return NULL;
+
+ if (oid_idx[0] == IS_LEVEL_1)
+ level = IS_LEVEL_1;
+ else if (oid_idx[0] == IS_LEVEL_2)
+ level = IS_LEVEL_2;
+ else
+ return NULL;
+
+ } else {
+ if (oid_idx == NULL)
+ level = IS_LEVEL_1;
+ else if (oid_idx_len == 0)
+ level = IS_LEVEL_1;
+ else if (oid_idx[0] < IS_LEVEL_1)
+ level = IS_LEVEL_1;
+ else if (oid_idx[0] < IS_LEVEL_2)
+ level = IS_LEVEL_2;
+ else
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = level;
+
+ /* Set length */
+ *length = v->namelen + 1;
+ }
+
+ area = NULL;
+
+ if (!list_isempty(isis->area_list))
+ area = listgetdata(listhead(isis->area_list));
+
+ level_match = 0;
+
+ if (area != NULL)
+ level_match = isis_snmp_get_level_match(area->is_type, level);
+
+ switch (v->magic) {
+ case ISIS_SYSLEVEL_ORIGLSPBUFFSIZE:
+ if (level_match)
+ return SNMP_INTEGER(area->lsp_mtu);
+
+ return SNMP_INTEGER(DEFAULT_LSP_MTU);
+
+ case ISIS_SYSLEVEL_MINLSPGENINT:
+ if (level_match)
+ return SNMP_INTEGER(area->lsp_gen_interval[level - 1]);
+ else
+ return SNMP_INTEGER(DEFAULT_MIN_LSP_GEN_INTERVAL);
+
+ case ISIS_SYSLEVEL_STATE:
+ if (level_match) {
+ if (area->overload_bit)
+ return SNMP_INTEGER(
+ ISIS_SNMP_LEVEL_STATE_OVERLOADED);
+
+ return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_ON);
+ }
+ return SNMP_INTEGER(ISIS_SNMP_LEVEL_STATE_OFF);
+
+ case ISIS_SYSLEVEL_SETOVERLOAD:
+ if (level_match && area->overload_bit)
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
+
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ case ISIS_SYSLEVEL_SETOVERLOADUNTIL:
+ /* We do not have automatic cleanup of overload bit */
+ return SNMP_INTEGER(0);
+
+ case ISIS_SYSLEVEL_METRICSTYLE:
+ if (level_match) {
+ if (area->newmetric && area->oldmetric)
+ return SNMP_INTEGER(
+ ISIS_SNMP_METRIC_STYLE_BOTH);
+
+ if (area->newmetric)
+ return SNMP_INTEGER(
+ ISIS_SNMP_METRIC_STYLE_WIDE);
+
+ return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW);
+ }
+ return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_NARROW);
+
+ case ISIS_SYSLEVEL_SPFCONSIDERS:
+ return SNMP_INTEGER(ISIS_SNMP_METRIC_STYLE_BOTH);
+
+ case ISIS_SYSLEVEL_TEENABLED:
+ if (level_match && IS_MPLS_TE(area->mta))
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
+
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_system_counter(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int level;
+ int level_match;
+ struct isis_area *area = NULL;
+ uint32_t val;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return NULL;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+
+ if (exact) {
+ if (oid_idx == NULL || oid_idx_len != 1)
+ return 0;
+
+ if (oid_idx[0] == IS_LEVEL_1)
+ level = IS_LEVEL_1;
+ else if (oid_idx[0] == IS_LEVEL_2)
+ level = IS_LEVEL_2;
+ else
+ return NULL;
+
+ } else {
+ if (oid_idx == NULL)
+ level = IS_LEVEL_1;
+ else if (oid_idx_len == 0)
+ level = IS_LEVEL_1;
+ else if (oid_idx[0] < IS_LEVEL_1)
+ level = IS_LEVEL_1;
+ else if (oid_idx[0] < IS_LEVEL_2)
+ level = IS_LEVEL_2;
+ else
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = level;
+
+ /* Set length */
+ *length = v->namelen + 1;
+ }
+
+ area = NULL;
+
+ if (!list_isempty(isis->area_list))
+ area = listgetdata(listhead(isis->area_list));
+
+ level_match = 0;
+
+ if (area != NULL)
+ level_match = isis_snmp_get_level_match(area->is_type, level);
+
+ if (!level_match)
+ /* If level does not match all counters are zeros */
+ return SNMP_INTEGER(0);
+
+ val = 0;
+
+ switch (v->magic) {
+ case ISIS_SYSSTAT_CORRLSPS:
+ val = 0;
+ break;
+
+ case ISIS_SYSSTAT_AUTHTYPEFAILS:
+ val = (uint32_t)area->auth_type_failures[level - 1];
+ break;
+
+ case ISIS_SYSSTAT_AUTHFAILS:
+ val = (uint32_t)area->auth_failures[level - 1];
+ break;
+
+ case ISIS_SYSSTAT_LSPDBASEOLOADS:
+ val = area->overload_counter;
+ break;
+
+ case ISIS_SYSSTAT_MANADDRDROPFROMAREAS:
+ /* We do not support manual addresses */
+ val = 0;
+ break;
+
+ case ISIS_SYSSTAT_ATTMPTTOEXMAXSEQNUMS:
+ val = area->lsp_exceeded_max_counter;
+ break;
+
+ case ISIS_SYSSTAT_SEQNUMSKIPS:
+ val = area->lsp_seqno_skipped_counter;
+ break;
+
+ case ISIS_SYSSTAT_OWNLSPPURGES:
+ if (!area->purge_originator)
+ val = 0;
+ else
+ val = area->lsp_purge_count[level - 1];
+ break;
+
+ case ISIS_SYSSTAT_IDFIELDLENMISMATCHES:
+ val = (uint32_t)area->id_len_mismatches[level - 1];
+ break;
+
+ case ISIS_SYSSTAT_PARTCHANGES:
+ /* Not supported */
+ val = 0;
+ break;
+
+ case ISIS_SYSSTAT_SPFRUNS:
+ val = (uint32_t)area->spf_run_count[level - 1];
+ break;
+
+ case ISIS_SYSSTAT_LSPERRORS:
+ val = (uint32_t)area->lsp_error_counter[level - 1];
+ break;
+
+ default:
+ return NULL;
+ }
+
+ return SNMP_INTEGER(val);
+}
+
+static uint8_t *isis_snmp_find_next_circ_index(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /* Check whether the instance identifier is valid */
+ if (smux_header_generic(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ switch (v->magic) {
+ case ISIS_NEXTCIRC_INDEX:
+ /*
+ * We do not support circuit creation through snmp
+ */
+ return SNMP_INTEGER(0);
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static uint8_t *isis_snmp_find_circ(struct variable *v, oid *name,
+ size_t *length, int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ /* Index is circuit-id: 1-255 */
+ oid *oid_idx;
+ size_t oid_idx_len;
+ struct isis_circuit *circuit;
+ uint64_t up_ticks;
+ uint64_t delta_ticks;
+ uint32_t now_time;
+ int res;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+ if (exact) {
+ res = isis_snmp_circuit_lookup_exact(oid_idx, oid_idx_len,
+ &circuit);
+
+ if (!res || oid_idx_len != 1)
+ return NULL;
+
+ } else {
+ res = isis_snmp_circuit_lookup_next(oid_idx, oid_idx_len,
+ &circuit);
+
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = circuit->snmp_id;
+
+ /* Set length */
+ *length = v->namelen + 1;
+ }
+
+ switch (v->magic) {
+ case ISIS_CIRC_IFINDEX:
+ if (circuit->interface == 0)
+ return SNMP_INTEGER(0);
+
+ return SNMP_INTEGER(circuit->interface->ifindex);
+
+ case ISIS_CIRC_ADMINSTATE:
+ return SNMP_INTEGER(ISIS_SNMP_ADMIN_STATE_ON);
+
+ case ISIS_CIRC_EXISTSTATE:
+ return SNMP_INTEGER(ISIS_SNMP_ROW_STATUS_ACTIVE);
+
+ case ISIS_CIRC_TYPE:
+ /*
+ * Note: values do not match 100%:
+ *
+ * 1. From isis_circuit.h:
+ * CIRCUIT_T_UNKNOWN 0
+ * CIRCUIT_T_BROADCAST 1
+ * CIRCUIT_T_P2P 2
+ * CIRCUIT_T_LOOPBACK 3
+ *
+ * 2. From rfc:
+ * broadcast(1),
+ * ptToPt(2),
+ * staticIn(3),
+ * staticOut(4),
+ */
+
+ return SNMP_INTEGER(circuit->circ_type);
+
+ case ISIS_CIRC_EXTDOMAIN:
+ if (circuit->ext_domain)
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
+
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ case ISIS_CIRC_LEVELTYPE:
+ return SNMP_INTEGER(circuit->is_type);
+
+ case ISIS_CIRC_PASSIVECIRCUIT:
+ if (circuit->is_passive)
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
+
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ case ISIS_CIRC_MESHGROUPENABLED:
+ /* Not supported */
+ return SNMP_INTEGER(ISIS_SNMP_MESH_GROUP_INACTIVE);
+
+ case ISIS_CIRC_MESHGROUP:
+ /* Not supported */
+ return SNMP_INTEGER(0);
+
+ case ISIS_CIRC_SMALLHELLOS:
+ /*
+ * return false if lan hellos must be padded
+ */
+ if (circuit->pad_hellos)
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_TRUE);
+
+ case ISIS_CIRC_LASTUPTIME:
+ if (circuit->last_uptime == 0)
+ return SNMP_INTEGER(0);
+
+ up_ticks = netsnmp_get_agent_uptime();
+ now_time = isis_snmp_time();
+
+ if (circuit->last_uptime >= now_time)
+ return SNMP_INTEGER(up_ticks);
+
+ delta_ticks = (now_time - circuit->last_uptime) * 10;
+
+ if (up_ticks < delta_ticks)
+ return SNMP_INTEGER(up_ticks);
+
+ return SNMP_INTEGER((uint32_t)(up_ticks - delta_ticks));
+
+ case ISIS_CIRC_3WAYENABLED:
+ /* Not supported */
+ return SNMP_INTEGER(ISIS_SNMP_TRUTH_VALUE_FALSE);
+
+ case ISIS_CIRC_EXTENDEDCIRCID:
+ /* Used for 3-way hand shake only */
+ return SNMP_INTEGER(0);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_circ_level(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ static uint8_t circuit_id_val[ISIS_SYS_ID_LEN + 1];
+ /* Index is circuit-id: 1-255 + level: 1-2 */
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int res;
+ struct isis_circuit *circuit;
+ int level;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL)
+ return NULL;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+ if (exact) {
+ res = isis_snmp_circuit_level_lookup_exact(oid_idx, oid_idx_len,
+ 1, &circuit, &level);
+
+ if (!res || oid_idx_len != 2)
+ return NULL;
+
+ } else {
+ res = isis_snmp_circuit_level_lookup_next(oid_idx, oid_idx_len,
+ 1, &circuit, &level);
+
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = circuit->snmp_id;
+ name[v->namelen + 1] = level;
+
+ /* Set length */
+ *length = v->namelen + 2;
+ }
+
+ switch (v->magic) {
+ case ISIS_CIRCLEVEL_METRIC:
+ return SNMP_INTEGER(circuit->metric[level - 1]);
+
+ case ISIS_CIRCLEVEL_WIDEMETRIC:
+ if (circuit->area == NULL || !circuit->area->newmetric) {
+ /* What should we do if wide metric is not supported? */
+ return SNMP_INTEGER(0);
+ }
+ return SNMP_INTEGER(circuit->te_metric[level - 1]);
+
+ case ISIS_CIRCLEVEL_ISPRIORITY:
+ return SNMP_INTEGER(circuit->priority[level - 1]);
+
+ case ISIS_CIRCLEVEL_IDOCTET:
+ return SNMP_INTEGER(circuit->circuit_id);
+
+ case ISIS_CIRCLEVEL_ID:
+ if (circuit->circ_type != CIRCUIT_T_P2P) {
+ /*
+ * Unless it is point-to-point circuit, the value is and
+ * empty octet string
+ */
+ *var_len = 0;
+ return circuit_id_val;
+ }
+
+ /* !!!!!! Circuit-id is zero for p2p links */
+ if (circuit->u.p2p.neighbor == NULL
+ || circuit->u.p2p.neighbor->adj_state != ISIS_ADJ_UP) {
+ /* No adjacency or adjacency not fully up yet */
+ memcpy(circuit_id_val, isis->sysid, ISIS_SYS_ID_LEN);
+ circuit_id_val[ISIS_SYS_ID_LEN] = circuit->circuit_id;
+ *var_len = ISIS_SYS_ID_LEN + 1;
+ return circuit_id_val;
+ }
+
+ /* Adjacency fully-up */
+ memcpy(circuit_id_val, circuit->u.p2p.neighbor->sysid,
+ ISIS_SYS_ID_LEN);
+ circuit_id_val[ISIS_SYS_ID_LEN] = 0;
+ *var_len = ISIS_SYS_ID_LEN + 1;
+ return circuit_id_val;
+
+ case ISIS_CIRCLEVEL_DESIS:
+ if (circuit->circ_type != CIRCUIT_T_BROADCAST
+ || !circuit->u.bc.is_dr[level - 1]) {
+ /*
+ * Unless it is lan circuit participating in dis process
+ * the value is an empty octet string
+ */
+ *var_len = 0;
+ return circuit_id_val;
+ }
+
+ *var_len = ISIS_SYS_ID_LEN + 1;
+
+ if (level == IS_LEVEL_1)
+ return circuit->u.bc.l1_desig_is;
+
+ return circuit->u.bc.l2_desig_is;
+
+ case ISIS_CIRCLEVEL_HELLOMULTIPLIER:
+ return SNMP_INTEGER(circuit->hello_multiplier[level - 1]);
+
+ case ISIS_CIRCLEVEL_HELLOTIMER:
+ return SNMP_INTEGER(circuit->hello_interval[level - 1] * 1000);
+
+ case ISIS_CIRCLEVEL_DRHELLOTIMER:
+ return SNMP_INTEGER(circuit->hello_interval[level - 1] * 1000);
+
+ case ISIS_CIRCLEVEL_LSPTHROTTLE:
+ if (circuit->area)
+ return SNMP_INTEGER(
+ circuit->area->min_spf_interval[level - 1]
+ * 1000);
+ else
+ return SNMP_INTEGER(0);
+
+ case ISIS_CIRCLEVEL_MINLSPRETRANSINT:
+ if (circuit->area)
+ return SNMP_INTEGER(
+ circuit->area->min_spf_interval[level - 1]);
+ else
+ return SNMP_INTEGER(0);
+
+ case ISIS_CIRCLEVEL_CSNPINTERVAL:
+ return SNMP_INTEGER(circuit->csnp_interval[level - 1]);
+
+ case ISIS_CIRCLEVEL_PARTSNPINTERVAL:
+ return SNMP_INTEGER(circuit->psnp_interval[level - 1]);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_circ_counter(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /* Index circuit-id 1-255 + level */
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int res;
+ struct isis_circuit *circuit;
+ int level;
+ uint32_t val = 0;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+ if (exact) {
+ res = isis_snmp_circuit_level_lookup_exact(oid_idx, oid_idx_len,
+ 1, &circuit, &level);
+
+ if (!res || oid_idx_len != 2)
+ return NULL;
+
+ } else {
+ res = isis_snmp_circuit_level_lookup_next(oid_idx, oid_idx_len,
+ 1, &circuit, &level);
+
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = circuit->snmp_id;
+ if (circuit->circ_type == CIRCUIT_T_P2P)
+ name[v->namelen + 1] = ISIS_SNMP_P2P_CIRCUIT;
+ else
+ name[v->namelen + 1] = level;
+
+ /* Set length */
+ *length = v->namelen + 2;
+ }
+
+ switch (v->magic) {
+ case ISIS_CIRC_ADJCHANGES:
+ val = circuit->adj_state_changes;
+ break;
+
+ case ISIS_CIRC_NUMADJ:
+ if (circuit->circ_type == CIRCUIT_T_P2P) {
+ val = circuit->u.p2p.neighbor == NULL ? 0 : 1;
+ break;
+ }
+
+ if (circuit->circ_type != CIRCUIT_T_BROADCAST) {
+ val = 0;
+ break;
+ }
+
+ if (level == IS_LEVEL_1) {
+ if (circuit->u.bc.adjdb[0] == NULL)
+ val = 0;
+ else
+ val = listcount(circuit->u.bc.adjdb[0]);
+ break;
+ }
+
+ if (circuit->u.bc.adjdb[1] == NULL)
+ val = 0;
+ else
+ val = listcount(circuit->u.bc.adjdb[1]);
+
+ break;
+
+ case ISIS_CIRC_INITFAILS:
+ val = circuit->init_failures; /* counter never incremented */
+ break;
+
+ case ISIS_CIRC_REJADJS:
+ val = circuit->rej_adjacencies;
+ break;
+
+ case ISIS_CIRC_IDFIELDLENMISMATCHES:
+ val = circuit->id_len_mismatches;
+ break;
+
+ case ISIS_CIRC_MAXAREAADDRMISMATCHES:
+ val = circuit->max_area_addr_mismatches;
+ break;
+
+ case ISIS_CIRC_AUTHTYPEFAILS:
+ val = circuit->auth_type_failures;
+ break;
+
+ case ISIS_CIRC_AUTHFAILS:
+ val = circuit->auth_failures;
+ break;
+
+ case ISIS_CIRC_LANDESISCHANGES:
+ if (circuit->circ_type == CIRCUIT_T_P2P)
+ val = 0;
+ else
+ val = circuit->desig_changes[level - 1];
+ break;
+
+ default:
+ return NULL;
+ }
+
+ return SNMP_INTEGER(val);
+}
+
+static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
+ size_t *length, int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ /* Index is circuit-id: 1-255 + adj-id: 1-... */
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int res;
+ uint32_t val;
+ struct isis_adjacency *adj;
+ uint64_t up_ticks;
+ uint64_t delta_ticks;
+ uint32_t now_time;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+ if (exact) {
+ res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
+ ISIS_SNMP_ADJ_DATA_NONE, &adj,
+ NULL, NULL, NULL);
+
+ if (!res || oid_idx_len != 2)
+ return NULL;
+
+ } else {
+ res = isis_snmp_adj_lookup_next(oid_idx, oid_idx_len,
+ ISIS_SNMP_ADJ_DATA_NONE, &adj,
+ NULL, NULL, NULL);
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = adj->circuit->snmp_id;
+ name[v->namelen + 1] = adj->snmp_idx;
+
+ /* Set length */
+ *length = v->namelen + 2;
+ }
+
+ switch (v->magic) {
+ case ISIS_ISADJ_STATE:
+ val = ISIS_SNMP_ADJ_STATE_DOWN;
+
+ switch (adj->adj_state) {
+ case ISIS_ADJ_UNKNOWN:
+ case ISIS_ADJ_DOWN:
+ val = ISIS_SNMP_ADJ_STATE_DOWN;
+ break;
+
+ case ISIS_ADJ_INITIALIZING:
+ val = ISIS_SNMP_ADJ_STATE_INITIALIZING;
+ break;
+
+ case ISIS_ADJ_UP:
+ val = ISIS_SNMP_ADJ_STATE_UP;
+ break;
+ }
+
+ return SNMP_INTEGER(val);
+
+ case ISIS_ISADJ_3WAYSTATE:
+ return SNMP_INTEGER(adj->threeway_state);
+
+ case ISIS_ISADJ_NEIGHSNPAADDRESS: {
+ const char *snpa = (char *)snpa_print(adj->snpa);
+ *var_len = strlen(snpa);
+ return (uint8_t *)snpa;
+ }
+
+ case ISIS_ISADJ_NEIGHSYSTYPE:
+ val = ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN;
+
+ switch (adj->sys_type) {
+ case ISIS_SYSTYPE_UNKNOWN:
+ case ISIS_SYSTYPE_ES:
+ val = ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN;
+ break;
+
+ case ISIS_SYSTYPE_IS:
+ val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1_L2;
+ break;
+
+ case ISIS_SYSTYPE_L1_IS:
+ val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L1;
+ break;
+
+ case ISIS_SYSTYPE_L2_IS:
+ val = ISIS_SNMP_ADJ_NEIGHTYPE_IS_L2;
+ break;
+ }
+
+ return SNMP_INTEGER(val);
+
+ case ISIS_ISADJ_NEIGHSYSID:
+ *var_len = sizeof(adj->sysid);
+ return adj->sysid;
+
+ case ISIS_ISADJ_NBREXTENDEDCIRCID:
+ return SNMP_INTEGER(adj->ext_circuit_id != 0 ? 1 : 0);
+
+ case ISIS_ISADJ_USAGE:
+ /* It seems that no value conversion is required */
+ return SNMP_INTEGER(adj->adj_usage);
+
+ case ISIS_ISADJ_HOLDTIMER:
+ /*
+ * It seems that we want remaining timer
+ */
+ if (adj->last_upd != 0) {
+ val = isis_snmp_time();
+ if (val < (adj->last_upd + adj->hold_time))
+ return SNMP_INTEGER(adj->last_upd
+ + adj->hold_time - val);
+ }
+ /* Not running or just expired */
+ return SNMP_INTEGER(0);
+
+ case ISIS_ISADJ_NEIGHPRIORITY:
+ return SNMP_INTEGER(adj->prio[adj->level - 1]);
+
+ case ISIS_ISADJ_LASTUPTIME:
+ if (adj->flaps == 0)
+ return SNMP_INTEGER(0);
+
+ up_ticks = netsnmp_get_agent_uptime();
+
+ now_time = isis_snmp_time();
+
+ if (adj->last_flap >= now_time)
+ return SNMP_INTEGER(up_ticks);
+
+ delta_ticks = (now_time - adj->last_flap) * 10;
+
+ if (up_ticks < delta_ticks)
+ return SNMP_INTEGER(up_ticks);
+
+ return SNMP_INTEGER((uint32_t)(up_ticks - delta_ticks));
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_isadj_area(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /* Index circuit-id: 1-255 + adj-id: 1-... */
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int res;
+ struct isis_adjacency *adj;
+ oid data_idx;
+ uint8_t *data;
+ size_t data_len;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+ if (exact) {
+ res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
+ ISIS_SNMP_ADJ_DATA_AREA_ADDR,
+ &adj, NULL, &data, &data_len);
+
+ if (!res || oid_idx_len != 3)
+ return NULL;
+
+ } else {
+ res = isis_snmp_adj_lookup_next(
+ oid_idx, oid_idx_len, ISIS_SNMP_ADJ_DATA_AREA_ADDR,
+ &adj, &data_idx, &data, &data_len);
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = adj->circuit->snmp_id;
+ name[v->namelen + 1] = adj->snmp_idx;
+ name[v->namelen + 2] = data_idx;
+
+ /* Set length */
+ *length = v->namelen + 3;
+ }
+
+ switch (v->magic) {
+ case ISIS_ISADJAREA_ADDRESS:
+ *var_len = data_len;
+ return data;
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_isadj_ipaddr(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /* Index circuit-id 1-255 + adj-id 1-... */
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int res;
+ struct isis_adjacency *adj;
+ oid data_idx;
+ uint8_t *data;
+ size_t data_len;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+ if (exact) {
+ res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
+ ISIS_SNMP_ADJ_DATA_IP_ADDR,
+ &adj, NULL, &data, &data_len);
+
+ if (!res || oid_idx_len != 3)
+ return NULL;
+ } else {
+ res = isis_snmp_adj_lookup_next(
+ oid_idx, oid_idx_len, ISIS_SNMP_ADJ_DATA_IP_ADDR, &adj,
+ &data_idx, &data, &data_len);
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = adj->circuit->snmp_id;
+ name[v->namelen + 1] = adj->snmp_idx;
+ name[v->namelen + 2] = data_idx;
+
+ /* Set length */
+ *length = v->namelen + 3;
+ }
+
+ switch (v->magic) {
+ case ISIS_ISADJIPADDR_TYPE:
+ if (data_len == 4)
+ return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V4);
+
+ return SNMP_INTEGER(ISIS_SNMP_INET_TYPE_V6);
+
+ case ISIS_ISADJIPADDR_ADDRESS:
+ *var_len = data_len;
+ return data;
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+static uint8_t *isis_snmp_find_isadj_prot_supp(struct variable *v, oid *name,
+ size_t *length, int exact,
+ size_t *var_len,
+ WriteMethod **write_method)
+{
+ /* Index circuit-id 1-255 + adj-id 1-... */
+ oid *oid_idx;
+ size_t oid_idx_len;
+ int res;
+ struct isis_adjacency *adj;
+ oid data_idx;
+ uint8_t *data;
+ size_t data_len;
+
+ *write_method = NULL;
+
+ if (*length <= v->namelen) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else if (memcmp(name, v->name, v->namelen * sizeof(oid)) != 0) {
+ oid_idx = NULL;
+ oid_idx_len = 0;
+ } else {
+ oid_idx = name + v->namelen;
+ oid_idx_len = *length - v->namelen;
+ }
+ if (exact) {
+ res = isis_snmp_adj_lookup_exact(oid_idx, oid_idx_len,
+ ISIS_SNMP_ADJ_DATA_PROTO, &adj,
+ NULL, &data, &data_len);
+
+ if (!res || oid_idx_len != 3)
+ return NULL;
+
+ } else {
+ res = isis_snmp_adj_lookup_next(oid_idx, oid_idx_len,
+ ISIS_SNMP_ADJ_DATA_PROTO, &adj,
+ &data_idx, &data, &data_len);
+ if (!res)
+ return NULL;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ name[v->namelen] = adj->circuit->snmp_id;
+ name[v->namelen + 1] = adj->snmp_idx;
+ name[v->namelen + 2] = data_idx;
+
+ /* Set length */
+ *length = v->namelen + 3;
+ }
+
+ switch (v->magic) {
+ case ISIS_ISADJPROTSUPP_PROTOCOL:
+ return SNMP_INTEGER(*data);
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
+
+/* Register ISIS-MIB. */
+static int isis_snmp_init(struct thread_master *tm)
+{
+ struct isis_func_to_prefix *h2f = isis_func_to_prefix_arr;
+ struct variable *v;
+
+ for (size_t off = 0; off < isis_var_count; off++) {
+ v = &isis_var_arr[off];
+
+ if (v->findVar != h2f->ihtp_func) {
+ /* Next table */
+ h2f++;
+ assert(h2f < (isis_func_to_prefix_arr
+ + isis_func_to_prefix_count));
+ assert(v->findVar == h2f->ihtp_func);
+ }
+
+ v->namelen = h2f->ihtp_pref_len + 1;
+ memcpy(v->name, h2f->ihtp_pref_oid,
+ h2f->ihtp_pref_len * sizeof(oid));
+ v->name[h2f->ihtp_pref_len] = v->magic;
+ }
+
+
+ smux_init(tm);
+ REGISTER_MIB("mibII/isis", isis_var_arr, variable, isis_oid);
+ return 0;
+}
+
+/*
+ * ISIS notification functions: we have one function per notification
+ */
+static int isis_snmp_trap_throttle(oid trap_id)
+{
+ time_t time_now;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL || !isis->snmp_notifications || !smux_enabled())
+ return 0;
+
+ time_now = isis_snmp_time();
+
+ if ((isis_snmp_trap_timestamp[trap_id] + 5) > time_now)
+ /* Throttle trap rate at 1 in 5 secs */
+ return 0;
+
+ isis_snmp_trap_timestamp[trap_id] = time_now;
+ return 1;
+}
+
+static int isis_snmp_db_overload_update(const struct isis_area *area)
+{
+ netsnmp_variable_list *notification_vars;
+ long val;
+ uint32_t off;
+
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_DB_OVERLOAD))
+ return 0;
+
+ notification_vars = NULL;
+
+ /* Put in trap value */
+ snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
+ ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ (uint8_t *)&isis_snmp_trap_val_db_overload,
+ sizeof(isis_snmp_trap_val_db_overload));
+
+ /* Prepare data */
+ val = area->is_type;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_sys_level_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ (uint8_t *)&val, sizeof(val));
+
+ /* Patch sys_level_state with proper index */
+ off = ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state) - 1;
+ isis_snmp_trap_data_var_sys_level_state[off] = val;
+
+ /* Prepare data */
+ if (area->overload_bit)
+ val = ISIS_SNMP_LEVEL_STATE_OVERLOADED;
+ else
+ val = ISIS_SNMP_LEVEL_STATE_ON;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_sys_level_state,
+ ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_state), INTEGER,
+ (uint8_t *)&val, sizeof(val));
+
+ send_v2trap(notification_vars);
+ snmp_free_varbind(notification_vars);
+ smux_events_update();
+ return 0;
+}
+
+static int isis_snmp_lsp_exceed_max_update(const struct isis_area *area,
+ const uint8_t *lsp_id)
+{
+ netsnmp_variable_list *notification_vars;
+ long val;
+
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_EXCEED_MAX))
+ return 0;
+
+ notification_vars = NULL;
+
+ /* Put in trap value */
+ snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
+ ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ (uint8_t *)&isis_snmp_trap_val_lsp_exceed_max,
+ sizeof(isis_snmp_trap_val_lsp_exceed_max));
+
+ /* Prepare data */
+ val = area->is_type;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_sys_level_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ (uint8_t *)&val, sizeof(val));
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_pdu_lsp_id,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ ISIS_SYS_ID_LEN + 2);
+
+ send_v2trap(notification_vars);
+ snmp_free_varbind(notification_vars);
+ smux_events_update();
+ return 0;
+}
+
+
+/*
+ * A common function to handle popular combination of trap objects
+ * isisNotificationSysLevelIndex,
+ * optional-object-a
+ * isisNotificationCircIfIndex,
+ * optional-object-b
+ */
+static void isis_snmp_update_worker_a(const struct isis_circuit *circuit,
+ oid trap_id, const oid *oid_a,
+ size_t oid_a_len, uint8_t type_a,
+ const void *data_a, size_t data_a_len,
+ const oid *oid_b, size_t oid_b_len,
+ uint8_t type_b, const void *data_b,
+ size_t data_b_len)
+{
+ netsnmp_variable_list *notification_vars = NULL;
+ oid var_name[MAX_OID_LEN];
+ size_t var_count;
+ long val;
+
+ /* Sanity */
+ if (trap_id != ISIS_TRAP_ID_LEN_MISMATCH
+ && trap_id != ISIS_TRAP_MAX_AREA_ADDR_MISMATCH
+ && trap_id != ISIS_TRAP_OWN_LSP_PURGE
+ && trap_id != ISIS_TRAP_SEQNO_SKIPPED
+ && trap_id != ISIS_TRAP_AUTHEN_TYPE_FAILURE
+ && trap_id != ISIS_TRAP_AUTHEN_FAILURE
+ && trap_id != ISIS_TRAP_REJ_ADJACENCY)
+ return;
+
+ /* Put in trap value */
+ memcpy(var_name, isis_snmp_notifications,
+ sizeof(isis_snmp_notifications));
+ var_count = ARRAY_SIZE(isis_snmp_notifications);
+ var_name[var_count++] = trap_id;
+
+ /* Put in trap value */
+ snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
+ ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ (uint8_t *)var_name, var_count * sizeof(oid));
+
+ val = circuit->is_type;
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_sys_level_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ (uint8_t *)&val, sizeof(val));
+
+ if (oid_a_len != 0) {
+ if (oid_a == NULL || data_a == NULL || data_a_len == 0)
+ return;
+
+ snmp_varlist_add_variable(&notification_vars, oid_a, oid_a_len,
+ type_a, (uint8_t *)data_a,
+ data_a_len);
+ }
+
+ if (circuit->interface == NULL)
+ val = 0;
+ else
+ val = circuit->interface->ifindex;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_circ_if_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ (uint8_t *)&val, sizeof(val));
+
+
+ if (oid_b_len != 0) {
+ if (oid_b == NULL || data_b == NULL || data_b_len == 0)
+ return;
+
+ snmp_varlist_add_variable(&notification_vars, oid_b, oid_b_len,
+ type_b, (uint8_t *)data_b,
+ data_b_len);
+ }
+
+ send_v2trap(notification_vars);
+ snmp_free_varbind(notification_vars);
+ smux_events_update();
+}
+
+/*
+ * A common function to handle popular combination of trap objects
+ * isisNotificationSysLevelIndex,
+ * isisNotificationCircIfIndex,
+ * optional-var-a
+ * optional-var-b
+ *
+ * Note: the only difference with worker_a is order of circ-if-index vs
+ * optional-var-a
+ */
+static void isis_snmp_update_worker_b(const struct isis_circuit *circuit,
+ oid trap_id, const oid *oid_a,
+ size_t oid_a_len, uint8_t type_a,
+ const void *data_a, size_t data_a_len,
+ const oid *oid_b, size_t oid_b_len,
+ uint8_t type_b, const void *data_b,
+ size_t data_b_len)
+{
+ netsnmp_variable_list *notification_vars = NULL;
+ oid var_name[MAX_OID_LEN];
+ size_t var_count;
+ long val;
+
+ /* Sanity */
+ if (trap_id != ISIS_TRAP_VERSION_SKEW
+ && trap_id != ISIS_TRAP_LSP_TOO_LARGE
+ && trap_id != ISIS_TRAP_ADJ_STATE_CHANGE)
+ return;
+
+ /* Put in trap value */
+ memcpy(var_name, isis_snmp_notifications,
+ sizeof(isis_snmp_notifications));
+ var_count = ARRAY_SIZE(isis_snmp_notifications);
+ var_name[var_count++] = trap_id;
+
+ /* Put in trap value */
+ snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
+ ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ (uint8_t *)var_name, var_count * sizeof(oid));
+
+ val = circuit->is_type;
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_sys_level_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ (uint8_t *)&val, sizeof(val));
+
+ if (circuit->interface == NULL)
+ val = 0;
+ else
+ val = circuit->interface->ifindex;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_circ_if_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ (uint8_t *)&val, sizeof(val));
+
+
+ if (oid_a_len != 0) {
+ if (oid_a == NULL || data_a == NULL || data_a_len == 0)
+ return;
+
+ snmp_varlist_add_variable(&notification_vars, oid_a, oid_a_len,
+ type_a, (uint8_t *)data_a,
+ data_a_len);
+ }
+
+ if (oid_b_len != 0) {
+ if (oid_b == NULL || data_b == NULL || data_b_len == 0)
+ return;
+
+ snmp_varlist_add_variable(&notification_vars, oid_b, oid_b_len,
+ type_b, (uint8_t *)data_b,
+ data_b_len);
+ }
+
+ send_v2trap(notification_vars);
+ snmp_free_varbind(notification_vars);
+ smux_events_update();
+}
+
+
+static int isis_snmp_id_len_mismatch_update(const struct isis_circuit *circuit,
+ uint8_t rcv_id, const char *raw_pdu,
+ size_t raw_pdu_len)
+{
+ long val;
+
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_ID_LEN_MISMATCH))
+ return 0;
+
+ val = rcv_id;
+
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ isis_snmp_update_worker_a(
+ circuit, ISIS_TRAP_ID_LEN_MISMATCH,
+ isis_snmp_trap_data_var_pdu_field_len,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_field_len), UNSIGNED32,
+ &val, sizeof(val), isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+ return 0;
+}
+
+static int
+isis_snmp_max_area_addr_mismatch_update(const struct isis_circuit *circuit,
+ uint8_t max_addrs, const char *raw_pdu,
+ size_t raw_pdu_len)
+{
+ long val;
+
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_MAX_AREA_ADDR_MISMATCH))
+ return 0;
+
+ val = max_addrs;
+
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ isis_snmp_update_worker_a(
+ circuit, ISIS_TRAP_MAX_AREA_ADDR_MISMATCH,
+ isis_snmp_trap_data_var_pdu_max_area_addr,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_max_area_addr),
+ UNSIGNED32, &val, sizeof(val),
+ isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+ return 0;
+}
+
+static int isis_snmp_own_lsp_purge_update(const struct isis_circuit *circuit,
+ const uint8_t *lsp_id)
+{
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_OWN_LSP_PURGE))
+ return 0;
+
+ isis_snmp_update_worker_a(
+ circuit, ISIS_TRAP_OWN_LSP_PURGE, NULL, 0, STRING, NULL, 0,
+ isis_snmp_trap_data_var_pdu_lsp_id,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ ISIS_SYS_ID_LEN + 2);
+ return 0;
+}
+
+static int isis_snmp_seqno_skipped_update(const struct isis_circuit *circuit,
+ const uint8_t *lsp_id)
+{
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_SEQNO_SKIPPED))
+ return 0;
+
+ isis_snmp_update_worker_a(
+ circuit, ISIS_TRAP_SEQNO_SKIPPED, NULL, 0, STRING, NULL, 0,
+ isis_snmp_trap_data_var_pdu_lsp_id,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ ISIS_SYS_ID_LEN + 2);
+ return 0;
+}
+
+static int
+isis_snmp_authentication_type_failure_update(const struct isis_circuit *circuit,
+ const char *raw_pdu,
+ size_t raw_pdu_len)
+{
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_TYPE_FAILURE))
+ return 0;
+
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ isis_snmp_update_worker_a(
+ circuit, ISIS_TRAP_AUTHEN_TYPE_FAILURE, NULL, 0, STRING, NULL,
+ 0, isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+ return 0;
+}
+
+static int
+isis_snmp_authentication_failure_update(const struct isis_circuit *circuit,
+ char const *raw_pdu, size_t raw_pdu_len)
+{
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_AUTHEN_FAILURE))
+ return 0;
+
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ isis_snmp_update_worker_a(
+ circuit, ISIS_TRAP_AUTHEN_FAILURE, NULL, 0, STRING, NULL, 0,
+ isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+ return 0;
+}
+
+static int isis_snmp_version_skew_update(const struct isis_circuit *circuit,
+ uint8_t version, const char *raw_pdu,
+ size_t raw_pdu_len)
+{
+ long val;
+
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_VERSION_SKEW))
+ return 0;
+
+ val = version;
+
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ isis_snmp_update_worker_b(
+ circuit, ISIS_TRAP_VERSION_SKEW,
+ isis_snmp_trap_data_var_pdu_proto_ver,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_proto_ver), UNSIGNED32,
+ &val, sizeof(val), isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+ return 0;
+}
+
+static int isis_snmp_area_mismatch_update(const struct isis_circuit *circuit,
+ const char *raw_pdu,
+ size_t raw_pdu_len)
+{
+ /*
+ * This is a special case because
+ * it does not include isisNotificationSysLevelIndex
+ */
+ netsnmp_variable_list *notification_vars;
+ long val;
+
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_AREA_MISMATCH))
+ return 0;
+
+ notification_vars = NULL;
+
+ /* Put in trap value */
+ snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
+ ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ (uint8_t *)&isis_snmp_trap_val_area_mismatch,
+ sizeof(isis_snmp_trap_val_area_mismatch));
+
+
+ if (circuit->interface == NULL)
+ val = 0;
+ else
+ val = circuit->interface->ifindex;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_circ_if_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ (uint8_t *)&val, sizeof(val));
+
+
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+
+ send_v2trap(notification_vars);
+ snmp_free_varbind(notification_vars);
+ smux_events_update();
+
+ return 0;
+}
+
+static int isis_snmp_reject_adjacency_update(const struct isis_circuit *circuit,
+ const char *raw_pdu,
+ size_t raw_pdu_len)
+{
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_REJ_ADJACENCY))
+ return 0;
+
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ isis_snmp_update_worker_a(
+ circuit, ISIS_TRAP_REJ_ADJACENCY, NULL, 0, STRING, NULL, 0,
+ isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+ return 0;
+}
+
+static int isis_snmp_lsp_too_large_update(const struct isis_circuit *circuit,
+ uint32_t pdu_size,
+ const uint8_t *lsp_id)
+{
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_TOO_LARGE))
+ return 0;
+
+ isis_snmp_update_worker_b(
+ circuit, ISIS_TRAP_LSP_TOO_LARGE,
+ isis_snmp_trap_data_var_pdu_lsp_size,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_size), UNSIGNED32,
+ &pdu_size, sizeof(pdu_size), isis_snmp_trap_data_var_pdu_lsp_id,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ ISIS_SYS_ID_LEN + 2);
+ return 0;
+}
+
+
+static int isis_snmp_adj_state_change_update(const struct isis_adjacency *adj)
+{
+ uint8_t lsp_id[ISIS_SYS_ID_LEN + 2];
+ long val;
+ struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+
+ if (isis == NULL || !isis->snmp_notifications || !smux_enabled())
+ return 0;
+
+ /* Prepare data */
+ memcpy(lsp_id, adj->sysid, ISIS_SYS_ID_LEN);
+ lsp_id[ISIS_SYS_ID_LEN] = 0;
+ lsp_id[ISIS_SYS_ID_LEN + 1] = 0;
+
+ val = ISIS_SNMP_ADJ_STATE_DOWN;
+
+ switch (adj->adj_state) {
+ case ISIS_ADJ_UNKNOWN:
+ val = ISIS_SNMP_ADJ_STATE_DOWN;
+ break;
+
+ case ISIS_ADJ_INITIALIZING:
+ val = ISIS_SNMP_ADJ_STATE_INITIALIZING;
+ break;
+
+ case ISIS_ADJ_UP:
+ val = ISIS_SNMP_ADJ_STATE_UP;
+ break;
+
+ case ISIS_ADJ_DOWN:
+ val = ISIS_SNMP_ADJ_STATE_FAILED;
+ break;
+ }
+
+ isis_snmp_update_worker_b(
+ adj->circuit, ISIS_TRAP_ADJ_STATE_CHANGE,
+ isis_snmp_trap_data_var_pdu_lsp_id,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ ISIS_SYS_ID_LEN + 2, isis_snmp_trap_data_var_adj_state,
+ ARRAY_SIZE(isis_snmp_trap_data_var_adj_state), INTEGER, &val,
+ sizeof(val));
+ return 0;
+}
+
+static int isis_snmp_lsp_error_update(const struct isis_circuit *circuit,
+ const uint8_t *lsp_id,
+ char const *raw_pdu, size_t raw_pdu_len)
+{
+ /*
+ * This is a special case because
+ * it have more variables
+ */
+ netsnmp_variable_list *notification_vars;
+ long val;
+
+ if (!isis_snmp_trap_throttle(ISIS_TRAP_LSP_ERROR))
+ return 0;
+
+ notification_vars = NULL;
+
+ /* Put in trap value */
+ snmp_varlist_add_variable(&notification_vars, isis_snmp_trap_var,
+ ARRAY_SIZE(isis_snmp_trap_var), ASN_OBJECT_ID,
+ (uint8_t *)&isis_snmp_trap_val_lsp_error,
+ sizeof(isis_snmp_trap_val_lsp_error));
+
+ /* Prepare data */
+ val = circuit->is_type;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_sys_level_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_sys_level_index), INTEGER,
+ (uint8_t *)&val, sizeof(val));
+
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_pdu_lsp_id,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_lsp_id), STRING, lsp_id,
+ ISIS_SYS_ID_LEN + 2);
+
+ /* Prepare data */
+ if (circuit->interface == NULL)
+ val = 0;
+ else
+ val = circuit->interface->ifindex;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_circ_if_index,
+ ARRAY_SIZE(isis_snmp_trap_data_var_circ_if_index), UNSIGNED32,
+ (uint8_t *)&val, sizeof(val));
+
+ /* Prepare data */
+ if (raw_pdu_len > ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN)
+ raw_pdu_len = ISIS_SNMP_TRAP_PDU_FRAGMENT_MAX_LEN;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_pdu_fragment,
+ ARRAY_SIZE(isis_snmp_trap_data_var_pdu_fragment), STRING,
+ raw_pdu, raw_pdu_len);
+
+ /* Prepare data */
+ val = 0;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_error_offset,
+ ARRAY_SIZE(isis_snmp_trap_data_var_error_offset), UNSIGNED32,
+ (uint8_t *)&val, sizeof(val));
+
+ /* Prepare data */
+ val = 0;
+
+ snmp_varlist_add_variable(
+ &notification_vars, isis_snmp_trap_data_var_error_tlv_type,
+ ARRAY_SIZE(isis_snmp_trap_data_var_error_tlv_type), UNSIGNED32,
+ (uint8_t *)&val, sizeof(val));
+
+ send_v2trap(notification_vars);
+ snmp_free_varbind(notification_vars);
+ smux_events_update();
+ return 0;
+}
+
+
+static int isis_snmp_module_init(void)
+{
+ hook_register(isis_hook_db_overload, isis_snmp_db_overload_update);
+ hook_register(isis_hook_lsp_exceed_max,
+ isis_snmp_lsp_exceed_max_update);
+ hook_register(isis_hook_id_len_mismatch,
+ isis_snmp_id_len_mismatch_update);
+ hook_register(isis_hook_max_area_addr_mismatch,
+ isis_snmp_max_area_addr_mismatch_update);
+ hook_register(isis_hook_own_lsp_purge, isis_snmp_own_lsp_purge_update);
+ hook_register(isis_hook_seqno_skipped, isis_snmp_seqno_skipped_update);
+ hook_register(isis_hook_authentication_type_failure,
+ isis_snmp_authentication_type_failure_update);
+ hook_register(isis_hook_authentication_failure,
+ isis_snmp_authentication_failure_update);
+ hook_register(isis_hook_version_skew, isis_snmp_version_skew_update);
+ hook_register(isis_hook_area_mismatch, isis_snmp_area_mismatch_update);
+ hook_register(isis_hook_reject_adjacency,
+ isis_snmp_reject_adjacency_update);
+ hook_register(isis_hook_lsp_too_large, isis_snmp_lsp_too_large_update);
+ hook_register(isis_hook_adj_state_change,
+ isis_snmp_adj_state_change_update);
+ hook_register(isis_hook_lsp_error, isis_snmp_lsp_error_update);
+
+ hook_register(frr_late_init, isis_snmp_init);
+ return 0;
+}
+
+FRR_MODULE_SETUP(.name = "isis_snmp", .version = FRR_VERSION,
+ .description = "isis AgentX SNMP module",
+ .init = isis_snmp_module_init, )
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 22dfee994f..7bcc6fea90 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -1821,6 +1821,7 @@ static int isis_run_spf_cb(struct thread *thread)
struct isis_spf_run *run = THREAD_ARG(thread);
struct isis_area *area = run->area;
int level = run->level;
+ int have_run = 0;
XFREE(MTYPE_ISIS_SPF_RUN, run);
area->spf_timer[level - 1] = NULL;
@@ -1839,15 +1840,24 @@ static int isis_run_spf_cb(struct thread *thread)
zlog_debug("ISIS-SPF (%s) L%d SPF needed, periodic SPF",
area->area_tag, level);
- if (area->ip_circuits)
+ if (area->ip_circuits) {
isis_run_spf_with_protection(
area, area->spftree[SPFTREE_IPV4][level - 1]);
- if (area->ipv6_circuits)
+ have_run = 1;
+ }
+ if (area->ipv6_circuits) {
isis_run_spf_with_protection(
area, area->spftree[SPFTREE_IPV6][level - 1]);
- if (area->ipv6_circuits && isis_area_ipv6_dstsrc_enabled(area))
+ have_run = 1;
+ }
+ if (area->ipv6_circuits && isis_area_ipv6_dstsrc_enabled(area)) {
isis_run_spf_with_protection(
area, area->spftree[SPFTREE_DSTSRC][level - 1]);
+ have_run = 1;
+ }
+
+ if (have_run)
+ area->spf_run_count[level]++;
isis_area_verify_routes(area);
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index 89fa2018b9..21f534641c 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -1213,14 +1213,14 @@ void isis_sr_area_init(struct isis_area *area)
/* Pull defaults from the YANG module. */
#ifndef FABRICD
srdb->config.enabled = yang_get_default_bool("%s/enabled", ISIS_SR);
- srdb->config.srgb_lower_bound =
- yang_get_default_uint32("%s/srgb/lower-bound", ISIS_SR);
- srdb->config.srgb_upper_bound =
- yang_get_default_uint32("%s/srgb/upper-bound", ISIS_SR);
- srdb->config.srlb_lower_bound =
- yang_get_default_uint32("%s/srlb/lower-bound", ISIS_SR);
- srdb->config.srlb_upper_bound =
- yang_get_default_uint32("%s/srlb/upper-bound", ISIS_SR);
+ srdb->config.srgb_lower_bound = yang_get_default_uint32(
+ "%s/label-blocks/srgb/lower-bound", ISIS_SR);
+ srdb->config.srgb_upper_bound = yang_get_default_uint32(
+ "%s/label-blocks/srgb/upper-bound", ISIS_SR);
+ srdb->config.srlb_lower_bound = yang_get_default_uint32(
+ "%s/label-blocks/srlb/lower-bound", ISIS_SR);
+ srdb->config.srlb_upper_bound = yang_get_default_uint32(
+ "%s/label-blocks/srlb/upper-bound", ISIS_SR);
#else
srdb->config.enabled = false;
srdb->config.srgb_lower_bound = SRGB_LOWER_BOUND;
diff --git a/isisd/isis_vty_fabricd.c b/isisd/isis_vty_fabricd.c
index d0a411a8db..6055984195 100644
--- a/isisd/isis_vty_fabricd.c
+++ b/isisd/isis_vty_fabricd.c
@@ -118,7 +118,7 @@ static void lsp_print_flooding(struct vty *vty, struct isis_lsp *lsp,
char lspid[255];
char buf[MONOTIME_STRLEN];
- lspid_print(lsp->hdr.lsp_id, lspid, true, true, isis);
+ lspid_print(lsp->hdr.lsp_id, lspid, sizeof(lspid), true, true, isis);
vty_out(vty, "Flooding information for %s\n", lspid);
if (!lsp->flooding_neighbors[TX_LSP_NORMAL]) {
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 703532234a..cb4dd2569d 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -509,7 +509,7 @@ static int isis_zebra_read(ZAPI_CALLBACK_ARGS)
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
isis_redist_add(isis, api.type, &api.prefix, &api.src_prefix,
- api.distance, api.metric);
+ api.distance, api.metric, api.tag);
else
isis_redist_delete(isis, api.type, &api.prefix,
&api.src_prefix);
diff --git a/isisd/isisd.c b/isisd/isisd.c
index a802bac13b..487a902c06 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -89,6 +89,10 @@ static struct isis_master isis_master;
/* ISIS process wide configuration pointer to export. */
struct isis_master *im;
+#ifndef FABRICD
+DEFINE_HOOK(isis_hook_db_overload, (const struct isis_area *area), (area));
+#endif /* ifndef FABRICD */
+
/*
* Prototypes.
*/
@@ -214,6 +218,7 @@ struct isis *isis_new(const char *vrf_name)
isis->area_list = list_new();
isis->init_circ_list = list_new();
isis->uptime = time(NULL);
+ isis->snmp_notifications = 1;
dyn_cache_init(isis);
return isis;
@@ -2563,6 +2568,14 @@ void isis_area_overload_bit_set(struct isis_area *area, bool overload_bit)
if (new_overload_bit != area->overload_bit) {
area->overload_bit = new_overload_bit;
+
+ if (new_overload_bit)
+ area->overload_counter++;
+
+#ifndef FABRICD
+ hook_call(isis_hook_db_overload, area);
+#endif /* ifndef FABRICD */
+
lsp_regenerate_schedule(area, IS_LEVEL_1 | IS_LEVEL_2, 1);
}
#ifndef FABRICD
diff --git a/isisd/isisd.h b/isisd/isisd.h
index 22d9c6236d..1b0ec2b4f0 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -63,6 +63,8 @@ extern void isis_cli_init(void);
all_vrf = strmatch(vrf_name, "all"); \
}
+#define SNMP_CIRCUITS_MAX (512)
+
extern struct zebra_privs_t isisd_privs;
/* uncomment if you are a developer in bug hunt */
@@ -93,6 +95,9 @@ struct isis {
time_t uptime; /* when did we start */
struct thread *t_dync_clean; /* dynamic hostname cache cleanup thread */
uint32_t circuit_ids_used[8]; /* 256 bits to track circuit ids 1 through 255 */
+ struct isis_circuit *snmp_circuits[SNMP_CIRCUITS_MAX];
+ uint32_t snmp_circuit_id_last;
+ int snmp_notifications;
struct route_table *ext_info[REDIST_PROTOCOL_COUNT];
struct ldp_sync_info_cmd ldp_sync_cmd; /* MPLS LDP-IGP Sync */
@@ -168,6 +173,7 @@ struct isis_area {
char is_type; /* level-1 level-1-2 or level-2-only */
/* are we overloaded? */
char overload_bit;
+ uint32_t overload_counter;
/* L1/L2 router identifier for inter-area traffic */
char attached_bit_send;
char attached_bit_rcv_ignore;
@@ -180,6 +186,9 @@ struct isis_area {
int lsp_frag_threshold;
uint64_t lsp_gen_count[ISIS_LEVELS];
uint64_t lsp_purge_count[ISIS_LEVELS];
+ uint32_t lsp_exceeded_max_counter;
+ uint32_t lsp_seqno_skipped_counter;
+ uint64_t spf_run_count[ISIS_LEVELS];
int ip_circuits;
/* logging adjacency changes? */
uint8_t log_adj_changes;
@@ -220,10 +229,19 @@ struct isis_area {
pdu_counter_t pdu_rx_counters;
uint64_t lsp_rxmt_count;
+ /* Area counters */
+ uint64_t rej_adjacencies[2];
+ uint64_t auth_type_failures[2];
+ uint64_t auth_failures[2];
+ uint64_t id_len_mismatches[2];
+ uint64_t lsp_error_counter[2];
+
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(isis_area)
+DECLARE_HOOK(isis_area_overload_bit_update, (struct isis_area * area), (area))
+
void isis_terminate(void);
void isis_finish(struct isis *isis);
void isis_master_init(struct thread_master *master);
diff --git a/isisd/subdir.am b/isisd/subdir.am
index 4be4efc118..98674a6881 100644
--- a/isisd/subdir.am
+++ b/isisd/subdir.am
@@ -17,6 +17,9 @@ vtysh_scan += \
isisd/isisd.c \
# end
vtysh_daemons += isisd
+if SNMP
+module_LTLIBRARIES += isisd/isisd_snmp.la
+endif
man8 += $(MANBUILD)/frr-isisd.8
endif
@@ -137,7 +140,12 @@ isisd_isisd_SOURCES = $(ISIS_SOURCES)
nodist_isisd_isisd_SOURCES = \
yang/frr-isisd.yang.c \
# end
-
+
+isisd_isisd_snmp_la_SOURCES = isisd/isis_snmp.c
+isisd_isisd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99
+isisd_isisd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+isisd_isisd_snmp_la_LIBADD = lib/libfrrsnmp.la
+
# Building fabricd
FABRICD_CPPFLAGS = -DFABRICD=1 $(AM_CPPFLAGS)
diff --git a/ldpd/lde.c b/ldpd/lde.c
index 69338b8bad..8fa74d1c3d 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -127,15 +127,13 @@ static struct quagga_signal_t lde_signals[] =
void
lde(void)
{
- struct thread thread;
-
#ifdef HAVE_SETPROCTITLE
setproctitle("label decision engine");
#endif
ldpd_process = PROC_LDE_ENGINE;
log_procname = log_procnames[PROC_LDE_ENGINE];
- master = thread_master_create(NULL);
+ master = frr_init();
/* setup signal handler */
signal_init(master, array_size(lde_signals), lde_signals);
@@ -157,9 +155,12 @@ lde(void)
/* create base configuration */
ldeconf = config_new_empty();
- /* Fetch next active thread. */
+ struct thread thread;
while (thread_fetch(master, &thread))
thread_call(&thread);
+
+ /* NOTREACHED */
+ return;
}
void
@@ -566,6 +567,9 @@ lde_dispatch_parent(struct thread *thread)
memcpy(&init, imsg.data, sizeof(init));
lde_init(&init);
break;
+ case IMSG_AGENTX_ENABLED:
+ ldp_agentx_enabled();
+ break;
case IMSG_RECONF_CONF:
if ((nconf = malloc(sizeof(struct ldpd_conf))) ==
NULL)
diff --git a/ldpd/ldp_snmp.c b/ldpd/ldp_snmp.c
new file mode 100644
index 0000000000..c9b37c0d27
--- /dev/null
+++ b/ldpd/ldp_snmp.c
@@ -0,0 +1,1087 @@
+/*
+ * LDP SNMP support
+ * Copyright (C) 2020 Volta Networks, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/*
+ * This is minimal read-only implementations providing
+ * mplsLdpModuleReadOnlyCompliance as described in RFC 3815.
+ */
+
+#include <zebra.h>
+
+#include <net-snmp/net-snmp-config.h>
+#include <net-snmp/net-snmp-includes.h>
+
+#include "vrf.h"
+#include "if.h"
+#include "log.h"
+#include "prefix.h"
+#include "table.h"
+#include "command.h"
+#include "memory.h"
+#include "smux.h"
+#include "libfrr.h"
+#include "version.h"
+#include "ldpd.h"
+#include "ldpe.h"
+
+/* SNMP value hack. */
+#define COUNTER32 ASN_COUNTER
+#define INTEGER ASN_INTEGER
+#define UNSIGNED32 ASN_GAUGE
+#define TIMESTAMP ASN_TIMETICKS
+#define TIMETICKS ASN_TIMETICKS
+#define STRING ASN_OCTET_STR
+#define IPADDRESS ASN_IPADDRESS
+
+#define LDP_LSRID_IDX_LEN 6
+#define LDP_ENTITY_IDX_LEN 1
+#define LDP_ADJACENCY_IDX_LEN 1
+
+/* MPLS-LDP-STD-MIB. */
+#define MPLS_LDP_STD_MIB 1, 3, 6, 1, 2, 1, 10, 166, 4
+
+#define MPLS_LDP_LSR_ID 0
+#define MPLS_LDP_LSR_LOOP_DETECTION_CAPABLE 0
+#define MPLS_LDP_ENTITY_LAST_CHANGE 0
+#define MPLS_LDP_ENTITY_INDEX_NEXT 0
+
+/* Declare static local variables for convenience. */
+SNMP_LOCAL_VARIABLES
+
+/* LDP-MIB instances. */
+static oid ldp_oid[] = {MPLS_LDP_STD_MIB};
+static oid ldp_trap_oid[] = {MPLS_LDP_STD_MIB, 0};
+
+static uint8_t snmp_ldp_rtrid[6] = {0, 0, 0, 0, 0};
+
+#define LDP_DEFAULT_ENTITY_INDEX 1
+
+#define MPLSLDPLSRLOOPDETECTIONCAPABLE_NONE 1
+#define MPLSLDPLSRLOOPDETECTIONCAPABLE_OTHER 2
+#define MPLSLDPLSRLOOPDETECTIONCAPABLE_HOPCOUNT 3
+#define MPLSLDPLSRLOOPDETECTIONCAPABLE_PATHVECTOR 4
+#define MPLSLDPLSRLOOPDETECTIONCAPABLE_HOPCOUNTANDPATHVECTOR 5
+
+/* MPLS LDP mplsLdpHelloAdjacencyTable. */
+#define MPLSLDPHELLOADJACENCYINDEX 1
+#define MPLSLDPHELLOADJACENCYHOLDTIMEREM 2
+#define MPLSLDPHELLOADJACENCYHOLDTIME 3
+#define MPLSLDPHELLOADJACENCYTYPE 4
+
+/* enums for column mplsLdpHelloAdjacencyType */
+#define MPLSLDPHELLOADJACENCYTYPE_LINK 1
+#define MPLSLDPHELLOADJACENCYTYPE_TARGETED 2
+
+#define MPLSLDPPEERTRANSPORTADDRTYPE_UNKNOWN 0
+#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV4 1
+#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV6 2
+#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV4Z 3
+#define MPLSLDPPEERTRANSPORTADDRTYPE_IPV6Z 4
+#define MPLSLDPPEERTRANSPORTADDRTYPE_DNS 16
+
+#define DOWNSTREAMONDEMAND 1
+#define DOWNSTREAMUNSOLICITED 2
+
+#define CONSERVATIVERETENTION 1
+#define LIBERALRETENTION 2
+
+#define TRANSPORTADDRINTERFACE 1
+#define TRANSPORTADDRLOOPBACK 2
+
+#define LABELTYPEGENERIC 1
+
+#define STORAGETYPENONVOLATILE 3
+
+#define ROWSTATUSACTIVE 4
+
+#define ADMINSTATUSENABLED 1
+
+#define OPERSTATUSENABLED 2
+
+/* MPLS LDP mplsLdpPeerTable */
+#define MPLSLDPPEERLDPID 1
+#define MPLSLDPPEERLABELDISTMETHOD 2
+#define MPLSLDPPEERPATHVECTORLIMIT 3
+#define MPLSLDPPEERTRANSPORTADDRTYPE 4
+#define MPLSLDPPEERTRANSPORTADDR 5
+
+#define MPLSLDPSESSIONROLE_UNKNOWN 1
+#define MPLSLDPSESSIONROLE_ACTIVE 2
+#define MPLSLDPSESSIONROLE_PASSIVE 3
+
+#define MPLSLDPSESSIONSTATE_NONEXISTENT 1
+#define MPLSLDPSESSIONSTATE_INITIALIZED 2
+#define MPLSLDPSESSIONSTATE_OPENREC 3
+#define MPLSLDPSESSIONSTATE_OPENSENT 4
+#define MPLSLDPSESSIONSTATE_OPERATIONAL 5
+
+/* MPLS LDP mplsLdpSessionTable */
+#define MPLSLDPSESSIONSTATELASTCHANGE 1
+#define MPLSLDPSESSIONSTATE 2
+#define MPLSLDPSESSIONROLE 3
+#define MPLSLDPSESSIONPROTOCOLVERSION 4
+#define MPLSLDPSESSIONKEEPALIVEHOLDTIMEREM 5
+#define MPLSLDPSESSIONKEEPALIVETIME 6
+#define MPLSLDPSESSIONMAXPDULENGTH 7
+#define MPLSLDPSESSIONDISCONTINUITYTIME 8
+
+/* MPLS LDP mplsLdpEntityTable */
+#define MPLSLDPENTITYLDPID 1
+#define MPLSLDPENTITYINDEX 2
+#define MPLSLDPENTITYPROTOCOLVERSION 3
+#define MPLSLDPENTITYADMINSTATUS 4
+#define MPLSLDPENTITYOPERSTATUS 5
+#define MPLSLDPENTITYTCPPORT 6
+#define MPLSLDPENTITYUDPDSCPORT 7
+#define MPLSLDPENTITYMAXPDULENGTH 8
+#define MPLSLDPENTITYKEEPALIVEHOLDTIMER 9
+#define MPLSLDPENTITYHELLOHOLDTIMER 10
+#define MPLSLDPENTITYINITSESSIONTHRESHOLD 11
+#define MPLSLDPENTITYLABELDISTMETHOD 12
+#define MPLSLDPENTITYLABELRETENTIONMODE 13
+#define MPLSLDPENTITYPATHVECTORLIMIT 14
+#define MPLSLDPENTITYHOPCOUNTLIMIT 15
+#define MPLSLDPENTITYTRANSPORTADDRKIND 16
+#define MPLSLDPENTITYTARGETPEER 17
+#define MPLSLDPENTITYTARGETPEERADDRTYPE 18
+#define MPLSLDPENTITYTARGETPEERADDR 19
+#define MPLSLDPENTITYLABELTYPE 20
+#define MPLSLDPENTITYDISCONTINUITYTIME 21
+#define MPLSLDPENTITYSTORAGETYPE 22
+#define MPLSLDPENTITYROWSTATUS 23
+
+/* MPLS LDP mplsLdpEntityStatsTable */
+#define MPLSLDPENTITYSTATSSESSIONATTEMPTS 1
+#define MPLSLDPENTITYSTATSSESSIONREJHELLO 2
+#define MPLSLDPENTITYSTATSSESSIONREJAD 3
+#define MPLSLDPENTITYSTATSSESSIONREJMAXPDU 4
+#define MPLSLDPENTITYSTATSSESSIONREJLR 5
+#define MPLSLDPENTITYSTATSBADLDPID 6
+#define MPLSLDPENTITYSTATSBADPDULENGTH 7
+#define MPLSLDPENTITYSTATSBADMSGLENGTH 8
+#define MPLSLDPENTITYSTATSBADTLVLENGTH 9
+#define MPLSLDPENTITYSTATSMALFORMEDTLV 10
+#define MPLSLDPENTITYSTATSKEEPALIVEEXP 11
+#define MPLSLDPENTITYSTATSSHUTDOWNRCVNOTIFY 12
+#define MPLSLDPENTITYSTATSSHUTDOWNSENTNOTIFY 13
+
+#define MPLSLDPSESSIONSTATSUNKNOWNMESTYPEERRORS 1
+#define MPLSLDPSESSIONSTATSUNKNOWNTLVERRORS 2
+
+static uint8_t *ldpLsrId(struct variable *v, oid name[], size_t *length,
+ int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ if (smux_header_generic(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ *var_len = 4;
+ return (uint8_t *)&leconf->rtr_id.s_addr;
+}
+
+static uint8_t *ldpLoopDetectCap(struct variable *v, oid name[], size_t *length,
+ int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ if (smux_header_generic(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ return SNMP_INTEGER(MPLSLDPLSRLOOPDETECTIONCAPABLE_NONE);
+}
+
+extern uint32_t ldp_start_time;
+static uint8_t *ldpEntityLastChange(struct variable *v, oid name[],
+ size_t *length,
+ int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ if (smux_header_generic(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ *var_len = sizeof(time_t);
+ return (uint8_t *) &(leconf->config_change_time);
+
+}
+
+static uint8_t *ldpEntityIndexNext(struct variable *v, oid name[],
+ size_t *length,int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ if (smux_header_generic(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ return SNMP_INTEGER(0);
+}
+
+#define LDP_ENTITY_TOTAL_LEN 21
+#define LDP_ENTITY_MAX_IDX_LEN 6
+
+static struct ldpd_af_conf *ldpEntityTable_lookup(struct variable *v, oid *name,
+ size_t *length, int exact,
+ uint32_t *index)
+{
+ int len;
+ struct ldpd_af_conf *af_v4, *af_v6;
+
+ af_v4 = &leconf->ipv4;
+ af_v6 = &leconf->ipv6;
+
+ if (exact) {
+ if (*length != LDP_ENTITY_TOTAL_LEN)
+ return NULL;
+
+ if (leconf->trans_pref == DUAL_STACK_LDPOV6 &&
+ af_v6->flags & F_LDPD_AF_ENABLED) {
+ *index = 2;
+ return af_v6;
+ } else {
+ *index = 1;
+ return af_v4;
+ }
+ } else {
+ /* only support one router id so can just skip */
+ len = *length - v->namelen - LDP_ENTITY_MAX_IDX_LEN;
+ if (len <= 0) {
+ if (leconf->trans_pref == DUAL_STACK_LDPOV6 &&
+ af_v6->flags & F_LDPD_AF_ENABLED) {
+ *index = 2;
+ return af_v6;
+ } else {
+ *index = 1;
+ return af_v4;
+ }
+ }
+ }
+ return NULL;
+}
+
+static uint8_t *ldpEntityTable(struct variable *v, oid name[], size_t *length,
+ int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ struct ldpd_af_conf *af;
+ struct in_addr entityLdpId = {.s_addr = 0};
+ uint32_t index = 0;
+
+ *write_method = NULL;
+
+ if (smux_header_table(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ af = ldpEntityTable_lookup(v, name, length, exact, &index);
+ if (af == NULL)
+ return NULL;
+
+ if (!exact) {
+ entityLdpId.s_addr = ldp_rtr_id_get(leconf);
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ *length = LDP_ENTITY_TOTAL_LEN;
+ oid_copy_addr(name + v->namelen, &entityLdpId,
+ IN_ADDR_SIZE);
+ name[v->namelen + 4] = 0;
+ name[v->namelen + 5] = 0;
+ name[v->namelen + 6] = LDP_DEFAULT_ENTITY_INDEX;
+ }
+
+ /* Return the current value of the variable */
+ switch (v->magic) {
+ case MPLSLDPENTITYLDPID:
+ *var_len = 6;
+ memcpy (snmp_ldp_rtrid, &entityLdpId, IN_ADDR_SIZE);
+ return (uint8_t *)snmp_ldp_rtrid;
+ case MPLSLDPENTITYINDEX:
+ return SNMP_INTEGER(LDP_DEFAULT_ENTITY_INDEX);
+ case MPLSLDPENTITYPROTOCOLVERSION:
+ return SNMP_INTEGER(LDP_VERSION);
+ case MPLSLDPENTITYADMINSTATUS:
+ return SNMP_INTEGER(ADMINSTATUSENABLED);
+ case MPLSLDPENTITYOPERSTATUS:
+ return SNMP_INTEGER(OPERSTATUSENABLED);
+ case MPLSLDPENTITYTCPPORT:
+ return SNMP_INTEGER(LDP_PORT);
+ case MPLSLDPENTITYUDPDSCPORT:
+ return SNMP_INTEGER(LDP_PORT);
+ case MPLSLDPENTITYMAXPDULENGTH:
+ return SNMP_INTEGER(LDP_MAX_LEN);
+ case MPLSLDPENTITYKEEPALIVEHOLDTIMER:
+ return SNMP_INTEGER(af->keepalive);
+ case MPLSLDPENTITYHELLOHOLDTIMER:
+ return SNMP_INTEGER(af->lhello_holdtime);
+ case MPLSLDPENTITYINITSESSIONTHRESHOLD:
+ return SNMP_INTEGER(0); /* not supported */
+ case MPLSLDPENTITYLABELDISTMETHOD:
+ return SNMP_INTEGER(DOWNSTREAMUNSOLICITED);
+ case MPLSLDPENTITYLABELRETENTIONMODE:
+ return SNMP_INTEGER(LIBERALRETENTION);
+ case MPLSLDPENTITYPATHVECTORLIMIT:
+ return SNMP_INTEGER(0); /* not supported */
+ case MPLSLDPENTITYHOPCOUNTLIMIT:
+ return SNMP_INTEGER(0);
+ case MPLSLDPENTITYTRANSPORTADDRKIND:
+ return SNMP_INTEGER(TRANSPORTADDRLOOPBACK);
+ case MPLSLDPENTITYTARGETPEER:
+ return SNMP_INTEGER(1);
+ case MPLSLDPENTITYTARGETPEERADDRTYPE:
+ if (index == 1)
+ return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV4);
+ else
+ return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV6);
+ case MPLSLDPENTITYTARGETPEERADDR:
+ if (index == 1) {
+ *var_len = sizeof(af->trans_addr.v4);
+ return ((uint8_t *)&af->trans_addr.v4);
+ }else {
+ *var_len = sizeof(af->trans_addr.v6);
+ return ((uint8_t *)&af->trans_addr.v6);
+ }
+ case MPLSLDPENTITYLABELTYPE:
+ return SNMP_INTEGER(LABELTYPEGENERIC);
+ case MPLSLDPENTITYDISCONTINUITYTIME:
+ return SNMP_INTEGER(0);
+ case MPLSLDPENTITYSTORAGETYPE:
+ return SNMP_INTEGER(STORAGETYPENONVOLATILE);
+ case MPLSLDPENTITYROWSTATUS:
+ return SNMP_INTEGER(ROWSTATUSACTIVE);
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#define LDP_ADJACENCY_ENTRY_MAX_IDX_LEN 14
+
+static void ldpHelloAdjacencyTable_oid_to_index(
+ struct variable *v, oid name[],
+ size_t *length,
+ struct in_addr *entityLdpId,
+ uint32_t *entityIndex,
+ struct in_addr *peerLdpId,
+ uint32_t *adjacencyIndex)
+{
+ oid *offset = name + v->namelen;
+ int offsetlen = *length - v->namelen;
+ int len = offsetlen;
+
+ if (len > LDP_ADJACENCY_ENTRY_MAX_IDX_LEN)
+ len = LDP_ADJACENCY_ENTRY_MAX_IDX_LEN;
+
+ if (len >= LDP_LSRID_IDX_LEN)
+ oid2in_addr(offset, sizeof(struct in_addr), entityLdpId);
+
+ offset += LDP_LSRID_IDX_LEN;
+ offsetlen -= LDP_LSRID_IDX_LEN;
+ len = offsetlen;
+
+ if (len > LDP_ENTITY_IDX_LEN)
+ len = LDP_ENTITY_IDX_LEN;
+
+ if (len >= LDP_ENTITY_IDX_LEN)
+ *entityIndex = offset[0];
+
+ offset += LDP_ENTITY_IDX_LEN;
+ offsetlen -= LDP_ENTITY_IDX_LEN;
+ len = offsetlen;
+
+ if (len > LDP_LSRID_IDX_LEN)
+ len = LDP_LSRID_IDX_LEN;
+
+ if (len >= LDP_LSRID_IDX_LEN)
+ oid2in_addr(offset, sizeof(struct in_addr), peerLdpId);
+
+ offset += LDP_LSRID_IDX_LEN;
+ offsetlen -= LDP_LSRID_IDX_LEN;
+ len = offsetlen;
+
+ if (len > LDP_ADJACENCY_IDX_LEN)
+ len = LDP_ADJACENCY_IDX_LEN;
+
+ if (len >= LDP_ADJACENCY_IDX_LEN)
+ *adjacencyIndex = offset[0];
+}
+
+static struct adj *
+nbr_get_adj_by_index(struct nbr *nbr, uint32_t adjacencyIndex)
+{
+ struct adj *adj;
+ uint32_t i = 0;
+
+ RB_FOREACH(adj, nbr_adj_head, &nbr->adj_tree)
+ if (++i == adjacencyIndex)
+ return adj;
+
+ return NULL;
+}
+
+static struct ctl_adj *
+ldpHelloAdjacencyTable_lookup_helper(
+ struct in_addr *entityLdpId,
+ uint32_t *entityIndex,
+ struct in_addr *peerLdpId,
+ uint32_t *adjacencyIndex)
+{
+ struct ctl_adj *ctl_adj = NULL;
+ struct adj *adj = NULL;
+ struct nbr *cur_nbr = nbr_find_ldpid(peerLdpId->s_addr);
+
+ if (cur_nbr)
+ /* If found nbr, then look to see if the
+ * adjacency exists
+ */
+ adj = nbr_get_adj_by_index(cur_nbr, *adjacencyIndex);
+
+ if (adj)
+ ctl_adj = adj_to_ctl(adj);
+
+ return ctl_adj;
+}
+
+static struct ctl_adj *
+ldpHelloAdjacencyTable_next_helper(
+ int first,
+ struct in_addr *entityLdpId,
+ uint32_t *entityIndex,
+ struct in_addr *peerLdpId,
+ uint32_t *adjacencyIndex)
+{
+ struct ctl_adj *ctl_adj = NULL;
+ struct nbr *nbr = NULL;
+ struct adj *adj = NULL;
+
+ if (first)
+ nbr = nbr_get_first_ldpid();
+ else {
+ struct nbr *cur_nbr = nbr_find_ldpid(peerLdpId->s_addr);
+ if (cur_nbr)
+ /* If found nbr, then look to see if the
+ * adjacency exists
+ */
+ adj = nbr_get_adj_by_index(cur_nbr, *adjacencyIndex + 1);
+ if (adj)
+ *adjacencyIndex += 1;
+ else
+ nbr = nbr_get_next_ldpid(peerLdpId->s_addr);
+ }
+
+ if (!adj && nbr) {
+ adj = RB_MIN(nbr_adj_head, &nbr->adj_tree);
+ *adjacencyIndex = 1;
+ }
+
+ if (adj)
+ ctl_adj = adj_to_ctl(adj);
+
+ return ctl_adj;
+}
+
+#define HELLO_ADJ_MAX_IDX_LEN 14
+
+static struct ctl_adj *
+ldpHelloAdjacencyTable_lookup(struct variable *v, oid name[],
+ size_t *length, int exact,
+ struct in_addr *entityLdpId,
+ uint32_t *entityIndex,
+ struct in_addr *peerLdpId,
+ uint32_t *adjacencyIndex)
+{
+ struct ctl_adj *hello_adj = NULL;
+
+ if (exact) {
+ if (*length < HELLO_ADJ_MAX_IDX_LEN)
+ return NULL;
+
+ ldpHelloAdjacencyTable_oid_to_index(
+ v, name, length,
+ entityLdpId, entityIndex, peerLdpId, adjacencyIndex);
+
+ hello_adj = ldpHelloAdjacencyTable_lookup_helper(
+ entityLdpId, entityIndex, peerLdpId, adjacencyIndex);
+ } else {
+ int first = 0;
+ int offsetlen = *length - v->namelen;
+
+ if (offsetlen < HELLO_ADJ_MAX_IDX_LEN)
+ first = 1;
+
+ ldpHelloAdjacencyTable_oid_to_index(
+ v, name, length,
+ entityLdpId, entityIndex, peerLdpId, adjacencyIndex);
+
+ hello_adj = ldpHelloAdjacencyTable_next_helper(first,
+ entityLdpId, entityIndex, peerLdpId, adjacencyIndex);
+
+ }
+ return hello_adj;
+}
+
+static uint8_t *ldpHelloAdjacencyTable(struct variable *v, oid name[], size_t *length,
+ int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ struct in_addr entityLdpId = {.s_addr = 0};
+ uint32_t entityIndex = 0;
+ struct in_addr peerLdpId = {.s_addr = 0};
+ uint32_t adjacencyIndex = 0;
+
+ if (smux_header_table(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ struct ctl_adj *ctl_adj = ldpHelloAdjacencyTable_lookup(v, name,
+ length, exact,
+ &entityLdpId, &entityIndex, &peerLdpId, &adjacencyIndex);
+
+ if (!ctl_adj)
+ return NULL;
+
+ if (!exact) {
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ struct in_addr entityLdpId = {.s_addr = 0};
+ entityLdpId.s_addr = ldp_rtr_id_get(leconf);
+
+ struct in_addr peerLdpId = ctl_adj->id;
+
+ oid_copy_addr(name + v->namelen, &entityLdpId,
+ sizeof(struct in_addr));
+ name[v->namelen + 4] = 0;
+ name[v->namelen + 5] = 0;
+ name[v->namelen + 6] = LDP_DEFAULT_ENTITY_INDEX;
+ oid_copy_addr(name + v->namelen + 7, &peerLdpId,
+ sizeof(struct in_addr));
+ name[v->namelen + 11] = 0;
+ name[v->namelen + 12] = 0;
+ name[v->namelen + 13] = adjacencyIndex;
+
+ /* Set length */
+ *length = v->namelen + HELLO_ADJ_MAX_IDX_LEN;
+ }
+
+ switch (v->magic) {
+ case MPLSLDPHELLOADJACENCYINDEX:
+ return SNMP_INTEGER(adjacencyIndex);
+ case MPLSLDPHELLOADJACENCYHOLDTIMEREM:
+ return SNMP_INTEGER(ctl_adj->holdtime_remaining);
+ case MPLSLDPHELLOADJACENCYHOLDTIME:
+ return SNMP_INTEGER(ctl_adj->holdtime);
+ case MPLSLDPHELLOADJACENCYTYPE:
+ if (ctl_adj->type == HELLO_LINK)
+ return SNMP_INTEGER(MPLSLDPHELLOADJACENCYTYPE_LINK);
+ return SNMP_INTEGER(MPLSLDPHELLOADJACENCYTYPE_TARGETED);
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+#define LDP_LSRID_IDX_LEN 6
+#define LDP_ENTITY_IDX_LEN 1
+#define LDP_PEER_ENTRY_MAX_IDX_LEN 13
+
+static void ldpPeerTable_oid_to_index(
+ struct variable *v, oid name[],
+ size_t *length,
+ struct in_addr *entityLdpId,
+ uint32_t *entityIndex,
+ struct in_addr *peerLdpId)
+{
+ oid *offset = name + v->namelen;
+ int offsetlen = *length - v->namelen;
+ int len = offsetlen;
+
+ if (len > LDP_PEER_ENTRY_MAX_IDX_LEN)
+ len = LDP_PEER_ENTRY_MAX_IDX_LEN;
+
+ if (len >= LDP_LSRID_IDX_LEN)
+ oid2in_addr(offset, sizeof(struct in_addr), entityLdpId);
+
+ offset += LDP_LSRID_IDX_LEN;
+ offsetlen -= LDP_LSRID_IDX_LEN;
+ len = offsetlen;
+
+ if (len > LDP_ENTITY_IDX_LEN)
+ len = LDP_ENTITY_IDX_LEN;
+
+ if (len >= LDP_ENTITY_IDX_LEN)
+ *entityIndex = offset[0];
+
+ offset += LDP_ENTITY_IDX_LEN;
+ offsetlen -= LDP_ENTITY_IDX_LEN;
+ len = offsetlen;
+
+ if (len > LDP_LSRID_IDX_LEN)
+ len = LDP_LSRID_IDX_LEN;
+
+ if (len >= LDP_LSRID_IDX_LEN)
+ oid2in_addr(offset, sizeof(struct in_addr), peerLdpId);
+}
+
+static struct ctl_nbr *
+ldpPeerTable_lookup_next(int first,
+ struct in_addr peerLdpId)
+{
+ struct nbr *nbr = NULL;
+ struct ctl_nbr *ctl_nbr = NULL;;
+
+ if (first)
+ nbr = nbr_get_first_ldpid();
+ else
+ nbr = nbr_get_next_ldpid(peerLdpId.s_addr);
+
+ if (nbr)
+ ctl_nbr = nbr_to_ctl(nbr);
+
+ return ctl_nbr;
+}
+
+static struct ctl_nbr *
+ldpPeerTable_lookup(struct variable *v, oid name[],
+ size_t *length, int exact,
+ struct in_addr *entityLdpId,
+ uint32_t *entityIndex,
+ struct in_addr *peerLdpId)
+{
+ struct ctl_nbr *ctl_nbr = NULL;
+ struct nbr *nbr = NULL;
+ int first = 0;
+
+ if (exact) {
+ if (*length < (long unsigned int)v->namelen
+ + LDP_PEER_ENTRY_MAX_IDX_LEN)
+ return NULL;
+
+ ldpPeerTable_oid_to_index(
+ v, name, length,
+ entityLdpId, entityIndex, peerLdpId);
+
+ nbr = nbr_find_ldpid(peerLdpId->s_addr);
+ if (nbr)
+ ctl_nbr = nbr_to_ctl(nbr);
+
+ return ctl_nbr;
+ } else {
+
+ int offsetlen = *length - v->namelen;
+ if (offsetlen < LDP_LSRID_IDX_LEN)
+ first = 1;
+
+ ldpPeerTable_oid_to_index(
+ v, name, length,
+ entityLdpId, entityIndex, peerLdpId);
+
+ ctl_nbr = ldpPeerTable_lookup_next(first, *peerLdpId);
+ return ctl_nbr;
+ }
+ return NULL;
+}
+
+static uint8_t *ldpPeerTable(struct variable *v, oid name[], size_t *length,
+ int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ struct in_addr entityLdpId = {.s_addr = 0};
+ uint32_t entityIndex = 0;
+ struct in_addr peerLdpId = {.s_addr = 0};
+ struct ctl_nbr *ctl_nbr;
+
+
+ if (smux_header_table(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ ctl_nbr = ldpPeerTable_lookup(v, name, length, exact, &entityLdpId,
+ &entityIndex, &peerLdpId);
+
+ if (!ctl_nbr)
+ return NULL;
+
+ if (!exact) {
+
+ entityLdpId.s_addr = ldp_rtr_id_get(leconf);
+ entityIndex = LDP_DEFAULT_ENTITY_INDEX;
+ peerLdpId = ctl_nbr->id;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ oid_copy_addr(name + v->namelen, &entityLdpId,
+ sizeof(struct in_addr));
+
+ name[v->namelen + 4] = 0;
+ name[v->namelen + 5] = 0;
+ name[v->namelen + 6] = entityIndex;
+ oid_copy_addr(name + v->namelen + 7, &peerLdpId,
+ sizeof(struct in_addr));
+ name[v->namelen + 11] = 0;
+ name[v->namelen + 12] = 0;
+
+ /* Set length */
+ *length = v->namelen + LDP_PEER_ENTRY_MAX_IDX_LEN;
+ }
+
+ switch (v->magic) {
+ case MPLSLDPPEERLDPID:
+ *var_len = 6;
+ memcpy(snmp_ldp_rtrid, &ctl_nbr->id, IN_ADDR_SIZE);
+ return snmp_ldp_rtrid;
+ case MPLSLDPPEERLABELDISTMETHOD:
+ return SNMP_INTEGER(DOWNSTREAMUNSOLICITED);
+ case MPLSLDPPEERPATHVECTORLIMIT:
+ return SNMP_INTEGER(0);
+ case MPLSLDPPEERTRANSPORTADDRTYPE:
+ if (ctl_nbr->af == AF_INET)
+ return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV4);
+ else
+ return SNMP_INTEGER(MPLSLDPPEERTRANSPORTADDRTYPE_IPV6);
+ case MPLSLDPPEERTRANSPORTADDR:
+ if (ctl_nbr->af == AF_INET) {
+ *var_len = sizeof(ctl_nbr->raddr.v4);
+ return ((uint8_t *)&ctl_nbr->raddr.v4);
+ } else {
+ *var_len = sizeof(ctl_nbr->raddr.v6);
+ return ((uint8_t *)&ctl_nbr->raddr.v6);
+ }
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+static uint8_t *ldpSessionTable(struct variable *v, oid name[], size_t *length,
+ int exact, size_t *var_len,
+ WriteMethod **write_method)
+{
+ struct in_addr entityLdpId = {.s_addr = 0};
+ uint32_t entityIndex = 0;
+ struct in_addr peerLdpId = {.s_addr = 0};
+ struct ctl_nbr *ctl_nbr;
+
+ if (smux_header_table(v, name, length, exact, var_len, write_method)
+ == MATCH_FAILED)
+ return NULL;
+
+ ctl_nbr = ldpPeerTable_lookup(v, name, length, exact, &entityLdpId,
+ &entityIndex, &peerLdpId);
+
+ if (!ctl_nbr)
+ return NULL;
+
+ if (!exact) {
+ entityLdpId.s_addr = ldp_rtr_id_get(leconf);
+ entityIndex = LDP_DEFAULT_ENTITY_INDEX;
+ peerLdpId = ctl_nbr->id;
+
+ /* Copy the name out */
+ memcpy(name, v->name, v->namelen * sizeof(oid));
+
+ /* Append index */
+ oid_copy_addr(name + v->namelen, &entityLdpId,
+ sizeof(struct in_addr));
+
+ name[v->namelen + 4] = 0;
+ name[v->namelen + 5] = 0;
+ name[v->namelen + 6] = entityIndex;
+ oid_copy_addr(name + v->namelen + 7, &peerLdpId,
+ sizeof(struct in_addr));
+ name[v->namelen + 11] = 0;
+ name[v->namelen + 12] = 0;
+
+ /* Set length */
+ *length = v->namelen + LDP_PEER_ENTRY_MAX_IDX_LEN;
+ }
+
+ switch (v->magic) {
+ case MPLSLDPSESSIONSTATELASTCHANGE:
+ *var_len = sizeof(time_t);
+ return (uint8_t *) &(ctl_nbr->uptime);
+ case MPLSLDPSESSIONSTATE:
+ switch (ctl_nbr->nbr_state) {
+ case NBR_STA_INITIAL:
+ return SNMP_INTEGER(MPLSLDPSESSIONSTATE_INITIALIZED);
+ case NBR_STA_OPENREC:
+ return SNMP_INTEGER(MPLSLDPSESSIONSTATE_OPENREC);
+ case NBR_STA_OPENSENT:
+ return SNMP_INTEGER(MPLSLDPSESSIONSTATE_OPENSENT);
+ case NBR_STA_OPER:
+ return SNMP_INTEGER(MPLSLDPSESSIONSTATE_OPERATIONAL);
+ default:
+ return SNMP_INTEGER(MPLSLDPSESSIONSTATE_NONEXISTENT);
+ }
+ case MPLSLDPSESSIONROLE:
+ if (ldp_addrcmp(ctl_nbr->af, &ctl_nbr->laddr, &ctl_nbr->raddr)
+ > 0)
+ return SNMP_INTEGER(MPLSLDPSESSIONROLE_ACTIVE);
+ else
+ return SNMP_INTEGER(MPLSLDPSESSIONROLE_PASSIVE);
+ case MPLSLDPSESSIONPROTOCOLVERSION:
+ return SNMP_INTEGER(LDP_VERSION);
+ case MPLSLDPSESSIONKEEPALIVEHOLDTIMEREM:
+ return SNMP_INTEGER(ctl_nbr->hold_time_remaining);
+ case MPLSLDPSESSIONKEEPALIVETIME:
+ return SNMP_INTEGER(ctl_nbr->holdtime);
+ case MPLSLDPSESSIONMAXPDULENGTH:
+ if (ctl_nbr->nbr_state == NBR_STA_OPER)
+ return SNMP_INTEGER(ctl_nbr->max_pdu_len);
+ else
+ return SNMP_INTEGER(LDP_MAX_LEN);
+ case MPLSLDPSESSIONDISCONTINUITYTIME:
+ return SNMP_INTEGER(0); /* not supported */
+ default:
+ return NULL;
+ }
+
+ return NULL;
+}
+
+static struct variable ldpe_variables[] = {
+ {MPLS_LDP_LSR_ID, STRING, RONLY, ldpLsrId, 3, {1, 1, 1}},
+ {MPLS_LDP_LSR_LOOP_DETECTION_CAPABLE, INTEGER, RONLY,
+ ldpLoopDetectCap, 3, {1, 1, 2}},
+ {MPLS_LDP_ENTITY_LAST_CHANGE, TIMESTAMP, RONLY, ldpEntityLastChange,
+ 3, {1, 2, 1}},
+ {MPLS_LDP_ENTITY_INDEX_NEXT, UNSIGNED32, RONLY, ldpEntityIndexNext,
+ 3, {1, 2, 2}},
+
+ /* MPLS LDP mplsLdpEntityTable. */
+ {MPLSLDPENTITYLDPID, STRING, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 1}},
+ {MPLSLDPENTITYINDEX, UNSIGNED32, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 2}},
+ {MPLSLDPENTITYPROTOCOLVERSION, UNSIGNED32, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 3}},
+ {MPLSLDPENTITYADMINSTATUS, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 4}},
+ {MPLSLDPENTITYOPERSTATUS, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 5}},
+ {MPLSLDPENTITYTCPPORT, UNSIGNED32, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 6}},
+ {MPLSLDPENTITYUDPDSCPORT, UNSIGNED32, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 7}},
+ {MPLSLDPENTITYMAXPDULENGTH, UNSIGNED32, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 8}},
+ {MPLSLDPENTITYKEEPALIVEHOLDTIMER, UNSIGNED32, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 9}},
+ {MPLSLDPENTITYHELLOHOLDTIMER, UNSIGNED32, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 10}},
+ {MPLSLDPENTITYINITSESSIONTHRESHOLD, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 11}},
+ {MPLSLDPENTITYLABELDISTMETHOD, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 12}},
+ {MPLSLDPENTITYLABELRETENTIONMODE, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 13}},
+ {MPLSLDPENTITYPATHVECTORLIMIT, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 14}},
+ {MPLSLDPENTITYHOPCOUNTLIMIT, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 15}},
+ {MPLSLDPENTITYTRANSPORTADDRKIND, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 16}},
+ {MPLSLDPENTITYTARGETPEER, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 17}},
+ {MPLSLDPENTITYTARGETPEERADDRTYPE, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 18}},
+ {MPLSLDPENTITYTARGETPEERADDR, STRING, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 19}},
+ {MPLSLDPENTITYLABELTYPE, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 20}},
+ {MPLSLDPENTITYDISCONTINUITYTIME, TIMESTAMP, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 21}},
+ {MPLSLDPENTITYSTORAGETYPE, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 22}},
+ {MPLSLDPENTITYROWSTATUS, INTEGER, RONLY, ldpEntityTable,
+ 5, {1, 2, 3, 1, 23}},
+
+ /* MPLS LDP mplsLdpPeerTable */
+ {MPLSLDPPEERLDPID, STRING, RONLY, ldpPeerTable, 5, {1, 3, 2, 1, 1}},
+ {MPLSLDPPEERLABELDISTMETHOD, INTEGER, RONLY, ldpPeerTable,
+ 5, {1, 3, 2, 1, 2}},
+ {MPLSLDPPEERPATHVECTORLIMIT, INTEGER, RONLY, ldpPeerTable,
+ 5, {1, 3, 2, 1, 3}},
+ {MPLSLDPPEERTRANSPORTADDRTYPE, INTEGER, RONLY, ldpPeerTable,
+ 5, {1, 3, 2, 1, 4}},
+ {MPLSLDPPEERTRANSPORTADDR, STRING, RONLY, ldpPeerTable,
+ 5, {1, 3, 2, 1, 5}},
+
+ /* MPLS LDP mplsLdpSessionTable */
+ {MPLSLDPSESSIONSTATELASTCHANGE, TIMESTAMP, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 1}},
+ {MPLSLDPSESSIONSTATE, INTEGER, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 2}},
+ {MPLSLDPSESSIONROLE, INTEGER, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 3}},
+ {MPLSLDPSESSIONPROTOCOLVERSION, UNSIGNED32, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 4}},
+ {MPLSLDPSESSIONKEEPALIVEHOLDTIMEREM, INTEGER, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 5}},
+ {MPLSLDPSESSIONKEEPALIVETIME, UNSIGNED32, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 6}},
+ {MPLSLDPSESSIONMAXPDULENGTH, UNSIGNED32, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 7}},
+ {MPLSLDPSESSIONDISCONTINUITYTIME, TIMESTAMP, RONLY, ldpSessionTable,
+ 5, {1, 3, 3, 1, 8}},
+
+ /* MPLS LDP mplsLdpHelloAdjacencyTable. */
+ {MPLSLDPHELLOADJACENCYINDEX, UNSIGNED32, RONLY,
+ ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 1}},
+ {MPLSLDPHELLOADJACENCYHOLDTIMEREM, INTEGER, RONLY,
+ ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 2}},
+ {MPLSLDPHELLOADJACENCYHOLDTIME, UNSIGNED32, RONLY,
+ ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 3}},
+ {MPLSLDPHELLOADJACENCYTYPE, INTEGER, RONLY,
+ ldpHelloAdjacencyTable, 6, {1, 3, 5, 1, 1, 4}},
+};
+
+static struct variable lde_variables[] = {
+};
+
+static struct trap_object ldpSessionTrapList[] = {
+ {5, {1, 3, 3, 1, MPLSLDPSESSIONSTATE}},
+ {5, {1, 3, 3, 1, MPLSLDPSESSIONDISCONTINUITYTIME}},
+ {5, {1, 3, 4, 1, MPLSLDPSESSIONSTATSUNKNOWNMESTYPEERRORS}},
+ {5, {1, 3, 4, 1, MPLSLDPSESSIONSTATSUNKNOWNTLVERRORS}}};
+
+/* LDP TRAP. */
+#define LDPINITSESSIONTHRESHOLDEXCEEDED 1
+#define LDPPATHVECTORLIMITMISMATCH 2
+#define LDPSESSIONUP 3
+#define LDPSESSIONDOWN 4
+
+static void
+ldpTrapSession(struct nbr * nbr, unsigned int sptrap)
+{
+ oid index[sizeof(oid) * (LDP_PEER_ENTRY_MAX_IDX_LEN + 1)];
+
+ struct in_addr entityLdpId = {.s_addr = 0};
+ uint32_t entityIndex = 0;
+ struct in_addr peerLdpId = {.s_addr = 0};
+
+ struct ctl_nbr *ctl_nbr = nbr_to_ctl(nbr);
+
+ entityLdpId.s_addr = ldp_rtr_id_get(leconf);
+ entityIndex = LDP_DEFAULT_ENTITY_INDEX;
+ peerLdpId = ctl_nbr->id;
+
+ oid_copy_addr(index, &entityLdpId, sizeof(struct in_addr));
+ index[4] = 0;
+ index[5] = 0;
+ index[6] = entityIndex;
+ oid_copy_addr(&index[7], &peerLdpId, sizeof(struct in_addr));
+ index[11] = 0;
+ index[12] = 0;
+
+ index[LDP_PEER_ENTRY_MAX_IDX_LEN] = 0;
+
+ smux_trap(ldpe_variables, array_size(ldpe_variables), ldp_trap_oid,
+ array_size(ldp_trap_oid), ldp_oid,
+ sizeof(ldp_oid) / sizeof(oid), index,
+ LDP_PEER_ENTRY_MAX_IDX_LEN + 1,
+ ldpSessionTrapList, array_size(ldpSessionTrapList), sptrap);
+}
+
+static void
+ldpTrapSessionUp(struct nbr * nbr)
+{
+ ldpTrapSession(nbr, LDPSESSIONUP);
+}
+
+static void
+ldpTrapSessionDown(struct nbr * nbr)
+{
+ ldpTrapSession(nbr, LDPSESSIONDOWN);
+}
+
+static int ldp_snmp_agentx_enabled()
+{
+ main_imsg_compose_both(IMSG_AGENTX_ENABLED, NULL, 0);
+
+ return 0;
+}
+
+static int ldp_snmp_nbr_state_change(struct nbr * nbr, int old_state)
+{
+ if (old_state == nbr->state)
+ return 0;
+
+ if (nbr->state == NBR_STA_OPER)
+ ldpTrapSessionUp(nbr);
+ else if (old_state == NBR_STA_OPER)
+ ldpTrapSessionDown(nbr);
+
+ return 0;
+}
+
+static int ldp_snmp_init(struct thread_master *tm)
+{
+ hook_register(agentx_enabled, ldp_snmp_agentx_enabled);
+
+ smux_init(tm);
+
+ return 0;
+}
+
+static int ldp_snmp_register_mib(struct thread_master *tm)
+{
+ static int registered = 0;
+
+ if (registered)
+ return 0;
+
+ registered = 1;
+
+ smux_init(tm);
+
+ smux_agentx_enable();
+
+ if (ldpd_process == PROC_LDE_ENGINE)
+ REGISTER_MIB("mibII/ldp", lde_variables, variable, ldp_oid);
+ else if (ldpd_process == PROC_LDP_ENGINE) {
+ REGISTER_MIB("mibII/ldp", ldpe_variables, variable, ldp_oid);
+
+ hook_register(ldp_nbr_state_change, ldp_snmp_nbr_state_change);
+ }
+
+ return 0;
+}
+
+static int ldp_snmp_module_init(void)
+{
+ if (ldpd_process == PROC_MAIN)
+ hook_register(frr_late_init, ldp_snmp_init);
+ else
+ hook_register(ldp_register_mib, ldp_snmp_register_mib);
+
+ return 0;
+}
+
+FRR_MODULE_SETUP(.name = "ldp_snmp", .version = FRR_VERSION,
+ .description = "ldp AgentX SNMP module",
+ .init = ldp_snmp_module_init, )
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index 83e93ebbbc..14235a0f1f 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -86,6 +86,30 @@ static struct imsgev *iev_lde, *iev_lde_sync;
static pid_t ldpe_pid;
static pid_t lde_pid;
+static struct frr_daemon_info ldpd_di;
+
+DEFINE_HOOK(ldp_register_mib, (struct thread_master * tm), (tm))
+
+static void ldp_load_module(const char *name)
+{
+ const char *dir;
+ dir = ldpd_di.module_path ? ldpd_di.module_path : frr_moduledir;
+ char moderr[256];
+ struct frrmod_runtime *module;
+
+ module = frrmod_load(name, dir, moderr, sizeof(moderr));
+ if (!module) {
+ fprintf(stderr, "%s: failed to load %s", __func__, name);
+ log_warnx("%s: failed to load %s", __func__, name);
+ }
+}
+
+void ldp_agentx_enabled(void)
+{
+ ldp_load_module("snmp");
+ hook_call(ldp_register_mib, master);
+}
+
enum ldpd_process ldpd_process;
#define LDP_DEFAULT_CONFIG "ldpd.conf"
@@ -94,8 +118,6 @@ enum ldpd_process ldpd_process;
/* Master of threads. */
struct thread_master *master;
-static struct frr_daemon_info ldpd_di;
-
/* ldpd privileges */
static zebra_capabilities_t _caps_p [] =
{
@@ -1343,6 +1365,9 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
ldpe_reset_ds_nbrs();
}
+ if (ldpd_process == PROC_LDP_ENGINE)
+ ldpe_set_config_change_time();
+
conf->flags = xconf->flags;
}
diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h
index beb625d8a2..103f4f228d 100644
--- a/ldpd/ldpd.h
+++ b/ldpd/ldpd.h
@@ -161,6 +161,7 @@ enum imsg_type {
IMSG_RLFA_REG,
IMSG_RLFA_UNREG_ALL,
IMSG_RLFA_LABELS,
+ IMSG_AGENTX_ENABLED,
};
struct ldpd_init {
@@ -434,6 +435,7 @@ struct ldp_stats {
uint32_t labelrel_rcvd;
uint32_t labelabreq_sent;
uint32_t labelabreq_rcvd;
+
};
struct l2vpn_if {
@@ -562,6 +564,7 @@ struct ldpd_conf {
uint16_t trans_pref;
uint16_t wait_for_sync_interval;
int flags;
+ time_t config_change_time;
QOBJ_FIELDS
};
DECLARE_QOBJ_TYPE(ldpd_conf)
@@ -683,6 +686,8 @@ struct ctl_nbr {
int nbr_state;
struct ldp_stats stats;
int flags;
+ uint16_t max_pdu_len;
+ uint16_t hold_time_remaining;
};
struct ctl_rt {
@@ -891,4 +896,8 @@ int ldp_zebra_send_rlfa_labels(struct zapi_rlfa_response *
(__IPV6_ADDR_MC_SCOPE(a) == __IPV6_ADDR_SCOPE_INTFACELOCAL))
#endif
+DECLARE_HOOK(ldp_register_mib, (struct thread_master * tm), (tm))
+
+extern void ldp_agentx_enabled(void);
+
#endif /* _LDPD_H_ */
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index 6a5a0750bd..d09eb2fa33 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -33,6 +33,7 @@
#include "memory.h"
#include "privs.h"
#include "sigevent.h"
+#include "libfrr.h"
static void ldpe_shutdown(void);
static int ldpe_dispatch_main(struct thread *);
@@ -103,15 +104,13 @@ char *pkt_ptr; /* packet buffer */
void
ldpe(void)
{
- struct thread thread;
-
#ifdef HAVE_SETPROCTITLE
setproctitle("ldp engine");
#endif
ldpd_process = PROC_LDP_ENGINE;
log_procname = log_procnames[ldpd_process];
- master = thread_master_create(NULL);
+ master = frr_init();
/* setup signal handler */
signal_init(master, array_size(ldpe_signals), ldpe_signals);
@@ -133,9 +132,12 @@ ldpe(void)
/* create base configuration */
leconf = config_new_empty();
- /* Fetch next active thread. */
+ struct thread thread;
while (thread_fetch(master, &thread))
thread_call(&thread);
+
+ /* NOTREACHED */
+ return;
}
void
@@ -387,6 +389,9 @@ ldpe_dispatch_main(struct thread *thread)
memcpy(&init, imsg.data, sizeof(init));
ldpe_init(&init);
break;
+ case IMSG_AGENTX_ENABLED:
+ ldp_agentx_enabled();
+ break;
case IMSG_CLOSE_SOCKETS:
af = imsg.hdr.peerid;
@@ -1073,3 +1078,10 @@ ldpe_check_filter_af(int af, struct ldpd_af_conf *af_conf,
if (strcmp(af_conf->acl_thello_accept_from, filter_name) == 0)
ldpe_remove_dynamic_tnbrs(af);
}
+
+void
+ldpe_set_config_change_time(void)
+{
+ /* SNMP update time when ever there is a config change */
+ leconf->config_change_time = time(NULL);
+}
diff --git a/ldpd/ldpe.h b/ldpd/ldpe.h
index ef4702341b..9572f1ac12 100644
--- a/ldpd/ldpe.h
+++ b/ldpd/ldpe.h
@@ -216,6 +216,7 @@ void ldpe_nbr_ctl(struct ctl_conn *);
void ldpe_ldp_sync_ctl(struct ctl_conn *);
void mapping_list_add(struct mapping_head *, struct map *);
void mapping_list_clr(struct mapping_head *);
+void ldpe_set_config_change_time(void);
/* interface.c */
struct iface *if_new(const char *);
@@ -266,6 +267,8 @@ struct nbr *nbr_new(struct in_addr, int, int, union ldpd_addr *,
uint32_t);
void nbr_del(struct nbr *);
struct nbr *nbr_find_ldpid(uint32_t);
+struct nbr *nbr_get_first_ldpid(void);
+struct nbr *nbr_get_next_ldpid(uint32_t);
struct nbr *nbr_find_addr(int, union ldpd_addr *);
struct nbr *nbr_find_peerid(uint32_t);
int nbr_adj_count(struct nbr *, int);
@@ -318,4 +321,6 @@ void ldpe_l2vpn_exit(struct l2vpn *);
void ldpe_l2vpn_pw_init(struct l2vpn_pw *);
void ldpe_l2vpn_pw_exit(struct l2vpn_pw *);
+DECLARE_HOOK(ldp_nbr_state_change, (struct nbr * nbr, int old_state), (nbr, old_state))
+
#endif /* _LDPE_H_ */
diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c
index 75deaad2c0..23c67ec1ca 100644
--- a/ldpd/neighbor.c
+++ b/ldpd/neighbor.c
@@ -26,6 +26,8 @@
#include "lde.h"
#include "log.h"
+DEFINE_HOOK(ldp_nbr_state_change, (struct nbr * nbr, int old_state), (nbr, old_state))
+
static __inline int nbr_id_compare(const struct nbr *, const struct nbr *);
static __inline int nbr_addr_compare(const struct nbr *,
const struct nbr *);
@@ -158,6 +160,8 @@ nbr_fsm(struct nbr *nbr, enum nbr_event event)
&nbr->id, nbr_state_name(old_state),
nbr_state_name(nbr->state));
+ hook_call(ldp_nbr_state_change, nbr, old_state);
+
if (nbr->state == NBR_STA_OPER) {
gettimeofday(&now, NULL);
nbr->uptime = now.tv_sec;
@@ -355,6 +359,23 @@ nbr_find_ldpid(uint32_t lsr_id)
}
struct nbr *
+nbr_get_first_ldpid()
+{
+ return (RB_MIN(nbr_id_head, &nbrs_by_id));
+}
+
+struct nbr *
+nbr_get_next_ldpid(uint32_t lsr_id)
+{
+ struct nbr *nbr;
+ nbr = nbr_find_ldpid(lsr_id);
+ if (nbr)
+ return (RB_NEXT(nbr_id_head, nbr));
+ return NULL;
+}
+
+
+struct nbr *
nbr_find_addr(int af, union ldpd_addr *addr)
{
struct nbr n;
@@ -831,14 +852,20 @@ nbr_to_ctl(struct nbr *nbr)
nctl.af = nbr->af;
nctl.id = nbr->id;
nctl.laddr = nbr->laddr;
- nctl.lport = nbr->tcp->lport;
+ nctl.lport = nbr->tcp ? nbr->tcp->lport : 0;
nctl.raddr = nbr->raddr;
- nctl.rport = nbr->tcp->rport;
+ nctl.rport = nbr->tcp ? nbr->tcp->rport : 0;
nctl.auth_method = nbr->auth.method;
nctl.holdtime = nbr->keepalive;
nctl.nbr_state = nbr->state;
nctl.stats = nbr->stats;
nctl.flags = nbr->flags;
+ nctl.max_pdu_len = nbr->max_pdu_len;
+ if (nbr->keepalive_timer)
+ nctl.hold_time_remaining =
+ thread_timer_remain_second(nbr->keepalive_timer);
+ else
+ nctl.hold_time_remaining = 0;
gettimeofday(&now, NULL);
if (nbr->state == NBR_STA_OPER) {
diff --git a/ldpd/subdir.am b/ldpd/subdir.am
index d89d18341d..b01d414de8 100644
--- a/ldpd/subdir.am
+++ b/ldpd/subdir.am
@@ -41,6 +41,10 @@ ldpd_libldp_a_SOURCES = \
ldpd/util.c \
# end
+if SNMP
+module_LTLIBRARIES += ldpd/ldpd_snmp.la
+endif
+
clippy_scan += \
ldpd/ldp_vty_cmds.c \
# end
@@ -59,3 +63,8 @@ noinst_HEADERS += \
ldpd_ldpd_SOURCES = ldpd/ldpd.c
ldpd_ldpd_LDADD = ldpd/libldp.a lib/libfrr.la $(LIBCAP)
+
+ldpd_ldpd_snmp_la_SOURCES = ldpd/ldp_snmp.c
+ldpd_ldpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu99
+ldpd_ldpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
+ldpd_ldpd_snmp_la_LIBADD = lib/libfrrsnmp.la
diff --git a/lib/agentx.c b/lib/agentx.c
index 5351f8bda2..c1ff7a61b1 100644
--- a/lib/agentx.c
+++ b/lib/agentx.c
@@ -36,6 +36,8 @@
XREF_SETUP()
+DEFINE_HOOK(agentx_enabled, (), ())
+
static int agentx_enabled = 0;
static struct thread_master *agentx_tm;
@@ -226,6 +228,7 @@ DEFUN (agentx_enable,
events = list_new();
agentx_events_update();
agentx_enabled = 1;
+ hook_call(agentx_enabled);
}
return CMD_SUCCESS;
@@ -243,6 +246,11 @@ DEFUN (no_agentx,
return CMD_WARNING_CONFIG_FAILED;
}
+int smux_enabled(void)
+{
+ return agentx_enabled;
+}
+
void smux_init(struct thread_master *tm)
{
agentx_tm = tm;
@@ -259,6 +267,16 @@ void smux_init(struct thread_master *tm)
install_element(CONFIG_NODE, &no_agentx_cmd);
}
+void smux_agentx_enable(void)
+{
+ if (!agentx_enabled) {
+ init_snmp(FRR_SMUX_NAME);
+ events = list_new();
+ agentx_events_update();
+ agentx_enabled = 1;
+ }
+}
+
void smux_register_mib(const char *descr, struct variable *var, size_t width,
int num, oid name[], size_t namelen)
{
@@ -379,4 +397,9 @@ int smux_trap_multi_index(struct variable *vp, size_t vp_len, const oid *ename,
return 1;
}
+void smux_events_update(void)
+{
+ agentx_events_update();
+}
+
#endif /* SNMP_AGENTX */
diff --git a/lib/clippy.c b/lib/clippy.c
index c655619b71..6223697ae9 100644
--- a/lib/clippy.c
+++ b/lib/clippy.c
@@ -51,7 +51,7 @@ int main(int argc, char **argv)
#if PY_VERSION_HEX >= 0x03040000 /* 3.4 */
Py_SetStandardStreamEncoding("UTF-8", NULL);
#endif
- char *name = wconv(argv[0]);
+ wchar_t *name = wconv(argv[0]);
Py_SetProgramName(name);
PyImport_AppendInittab("_clippy", command_py_init);
@@ -68,6 +68,8 @@ int main(int argc, char **argv)
fp = fopen(pyfile, "r");
if (!fp) {
fprintf(stderr, "%s: %s\n", pyfile, strerror(errno));
+
+ free(name);
return 1;
}
} else {
@@ -86,6 +88,8 @@ int main(int argc, char **argv)
if (PyRun_AnyFile(fp, pyfile)) {
if (PyErr_Occurred())
PyErr_Print();
+
+ free(name);
return 1;
}
Py_Finalize();
diff --git a/lib/clippy.h b/lib/clippy.h
index be4db6e638..95af274106 100644
--- a/lib/clippy.h
+++ b/lib/clippy.h
@@ -20,6 +20,7 @@
#ifndef _FRR_CLIPPY_H
#define _FRR_CLIPPY_H
+#include <stdbool.h>
#include <Python.h>
#ifdef __cplusplus
@@ -28,6 +29,7 @@ extern "C" {
extern PyObject *clippy_parse(PyObject *self, PyObject *args);
extern PyMODINIT_FUNC command_py_init(void);
+extern bool elf_py_init(PyObject *pymod);
#ifdef __cplusplus
}
diff --git a/lib/command_graph.h b/lib/command_graph.h
index 09824460e6..86715410ce 100644
--- a/lib/command_graph.h
+++ b/lib/command_graph.h
@@ -99,7 +99,7 @@ struct cmd_element {
const char *string; /* Command specification by string. */
const char *doc; /* Documentation of this command. */
int daemon; /* Daemon to which this command belong. */
- uint8_t attr; /* Command attributes */
+ uint32_t attr; /* Command attributes */
/* handler function for command */
int (*func)(const struct cmd_element *, struct vty *, int,
diff --git a/lib/command_py.c b/lib/command_py.c
index 4ec116df33..7f19008fbf 100644
--- a/lib/command_py.c
+++ b/lib/command_py.c
@@ -345,5 +345,7 @@ PyMODINIT_FUNC command_py_init(void)
PyModule_AddObject(pymod, "GraphNode", (PyObject *)&typeobj_graph_node);
Py_INCREF(&typeobj_graph);
PyModule_AddObject(pymod, "Graph", (PyObject *)&typeobj_graph);
+ if (!elf_py_init(pymod))
+ initret(NULL);
initret(pymod);
}
diff --git a/lib/elf_py.c b/lib/elf_py.c
new file mode 100644
index 0000000000..0d8ad76e1c
--- /dev/null
+++ b/lib/elf_py.c
@@ -0,0 +1,1301 @@
+/*
+ * fast ELF file accessor
+ * Copyright (C) 2018-2020 David Lamparter for NetDEF, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* Note: this wrapper is intended to be used as build-time helper. While
+ * it should be generally correct and proper, there may be the occasional
+ * memory leak or SEGV for things that haven't been well-tested.
+ * _
+ * / \ This code is NOT SUITABLE FOR UNTRUSTED ELF FILES. It's used
+ * / ! \ in FRR to read files created by its own build. Don't take it out
+ * /_____\ of FRR and use it to parse random ELF files you found somewhere.
+ *
+ * If you're working with this code (or even reading it), you really need to
+ * read a bunch of the ELF specs. There's no way around it, things in here
+ * just represent pieces of ELF pretty much 1:1. Also, readelf & objdump are
+ * your friends.
+ *
+ * Required reading:
+ * https://refspecs.linuxfoundation.org/elf/elf.pdf
+ * https://refspecs.linuxfoundation.org/elf/x86_64-SysV-psABI.pdf
+ * Recommended reading:
+ * https://github.com/ARM-software/abi-aa/releases/download/2020Q4/aaelf64.pdf
+ *
+ * The core ELF spec is *not* enough, you should read at least one of the
+ * processor specific (psABI) docs. They define what & how relocations work.
+ * Luckily we don't need to care about the processor specifics since this only
+ * does data relocations, but without looking at the psABI, some things aren't
+ * quite clear.
+ */
+
+/* the API of this module roughly follows a very small subset of the one
+ * provided by the python elfutils package, which unfortunately is painfully
+ * slow.
+ */
+
+#define PY_SSIZE_T_CLEAN
+
+#include <Python.h>
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include "structmember.h"
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+
+#if defined(__sun__) && (__SIZEOF_POINTER__ == 4)
+/* Solaris libelf bails otherwise ... */
+#undef _FILE_OFFSET_BITS
+#define _FILE_OFFSET_BITS 32
+#endif
+
+#include <elf.h>
+#include <libelf.h>
+#include <gelf.h>
+
+#include "typesafe.h"
+#include "jhash.h"
+#include "clippy.h"
+
+static bool debug;
+
+#define debugf(...) \
+ do { \
+ if (debug) \
+ fprintf(stderr, __VA_ARGS__); \
+ } while (0)
+
+/* Exceptions */
+static PyObject *ELFFormatError;
+static PyObject *ELFAccessError;
+
+/* most objects can only be created as return values from one of the methods */
+static PyObject *refuse_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
+{
+ PyErr_SetString(PyExc_ValueError,
+ "cannot create instances of this type");
+ return NULL;
+}
+
+struct elfreloc;
+struct elfsect;
+
+PREDECL_HASH(elfrelocs)
+
+/* ELFFile and ELFSection intentionally share some behaviour, particularly
+ * subscript[123:456] access to file data. This is because relocatables
+ * (.o files) do things section-based, but linked executables/libraries do
+ * things file-based. Having the two behave similar allows simplifying the
+ * Python code.
+ */
+
+/* class ELFFile:
+ *
+ * overall entry point, instantiated by reading in an ELF file
+ */
+struct elffile {
+ PyObject_HEAD
+
+ char *filename;
+ char *mmap, *mmend;
+ size_t len;
+ Elf *elf;
+
+ /* note from here on there are several instances of
+ *
+ * GElf_Something *x, _x;
+ *
+ * this is a pattern used by libelf's generic ELF routines; the _x
+ * field is used to create a copy of the ELF structure from the file
+ * with 32/64bit and endianness adjusted.
+ */
+
+ GElf_Ehdr *ehdr, _ehdr;
+ Elf_Scn *symtab;
+ size_t nsym, symstridx;
+ Elf_Data *symdata;
+
+ PyObject **sects;
+ size_t n_sect;
+
+ struct elfrelocs_head dynrelocs;
+
+ int elfclass;
+ bool bigendian;
+ bool has_symbols;
+};
+
+/* class ELFSection:
+ *
+ * note that executables and shared libraries can have their section headers
+ * removed, though in practice this is only used as an obfuscation technique.
+ */
+struct elfsect {
+ PyObject_HEAD
+
+ const char *name;
+ struct elffile *ef;
+
+ GElf_Shdr _shdr, *shdr;
+ Elf_Scn *scn;
+ unsigned long idx, len;
+
+ struct elfrelocs_head relocs;
+};
+
+/* class ELFReloc:
+ *
+ * note: relocations in object files (.o) are section-based while relocations
+ * in executables and shared libraries are file-based.
+ *
+ * Whenever accessing something that is a pointer in the ELF file, the Python
+ * code needs to check for a relocation; if the pointer is pointing to some
+ * unresolved symbol the file will generally contain 0 bytes. The relocation
+ * will tell what the pointer is actually pointing to.
+ *
+ * This represents both static (.o file) and dynamic (.so/exec) relocations.
+ */
+struct elfreloc {
+ PyObject_HEAD
+
+ struct elfrelocs_item elfrelocs_item;
+
+ struct elfsect *es;
+ struct elffile *ef;
+
+ /* there's also old-fashioned GElf_Rel; we're converting that to
+ * GElf_Rela in elfsect_add_relocations()
+ */
+ GElf_Rela _rela, *rela;
+ GElf_Sym _sym, *sym;
+ size_t symidx;
+ const char *symname;
+
+ /* documented below in python docstrings */
+ bool symvalid, unresolved, relative;
+ unsigned long long st_value;
+};
+
+static int elfreloc_cmp(const struct elfreloc *a, const struct elfreloc *b);
+static uint32_t elfreloc_hash(const struct elfreloc *reloc);
+
+DECLARE_HASH(elfrelocs, struct elfreloc, elfrelocs_item,
+ elfreloc_cmp, elfreloc_hash)
+
+static Elf_Scn *elf_find_addr(struct elffile *ef, uint64_t addr, size_t *idx);
+static PyObject *elffile_secbyidx(struct elffile *w, Elf_Scn *scn, size_t idx);
+static PyObject *elfreloc_getsection(PyObject *self, PyObject *args);
+static PyObject *elfreloc_getaddend(PyObject *obj, void *closure);
+
+/* --- end of declarations -------------------------------------------------- */
+
+/*
+ * class ELFReloc:
+ */
+
+static const char elfreloc_doc[] =
+ "Represents an ELF relocation record\n"
+ "\n"
+ "(struct elfreloc * in elf_py.c)";
+
+#define member(name, type, doc) \
+ { \
+ (char *)#name, type, offsetof(struct elfreloc, name), READONLY,\
+ (char *)doc "\n\n(\"" #name "\", " #type " in elf_py.c)" \
+ }
+static PyMemberDef members_elfreloc[] = {
+ member(symname, T_STRING,
+ "Name of symbol this relocation refers to.\n"
+ "\n"
+ "Will frequently be `None` in executables and shared libraries."
+ ),
+ member(symvalid, T_BOOL,
+ "Target symbol has a valid type, i.e. not STT_NOTYPE"),
+ member(unresolved, T_BOOL,
+ "Target symbol refers to an existing section"),
+ member(relative, T_BOOL,
+ "Relocation is a REL (not RELA) record and thus relative."),
+ member(st_value, T_ULONGLONG,
+ "Target symbol's value, if known\n\n"
+ "Will be zero for unresolved/external symbols."),
+ {}
+};
+#undef member
+
+static PyGetSetDef getset_elfreloc[] = {
+ { .name = (char *)"r_addend", .get = elfreloc_getaddend, .doc =
+ (char *)"Relocation addend value"},
+ {}
+};
+
+static PyMethodDef methods_elfreloc[] = {
+ {"getsection", elfreloc_getsection, METH_VARARGS,
+ "Find relocation target's ELF section\n\n"
+ "Args: address of relocatee (TODO: fix/remove?)\n"
+ "Returns: ELFSection or None\n\n"
+ "Not possible if section headers have been stripped."},
+ {}
+};
+
+static int elfreloc_cmp(const struct elfreloc *a, const struct elfreloc *b)
+{
+ if (a->rela->r_offset < b->rela->r_offset)
+ return -1;
+ if (a->rela->r_offset > b->rela->r_offset)
+ return 1;
+ return 0;
+}
+
+static uint32_t elfreloc_hash(const struct elfreloc *reloc)
+{
+ return jhash(&reloc->rela->r_offset, sizeof(reloc->rela->r_offset),
+ 0xc9a2b7f4);
+}
+
+static struct elfreloc *elfrelocs_get(struct elfrelocs_head *head,
+ GElf_Addr offset)
+{
+ struct elfreloc dummy;
+
+ dummy.rela = &dummy._rela;
+ dummy.rela->r_offset = offset;
+ return elfrelocs_find(head, &dummy);
+}
+
+static PyObject *elfreloc_getsection(PyObject *self, PyObject *args)
+{
+ struct elfreloc *w = (struct elfreloc *)self;
+ long data;
+
+ if (!PyArg_ParseTuple(args, "k", &data))
+ return NULL;
+
+ if (!w->es)
+ Py_RETURN_NONE;
+
+ if (w->symidx == 0) {
+ size_t idx = 0;
+ Elf_Scn *scn;
+
+ data = (w->relative ? data : 0) + w->rela->r_addend;
+ scn = elf_find_addr(w->es->ef, data, &idx);
+ if (!scn)
+ Py_RETURN_NONE;
+ return elffile_secbyidx(w->es->ef, scn, idx);
+ }
+ return elffile_secbyidx(w->es->ef, NULL, w->sym->st_shndx);
+}
+
+static PyObject *elfreloc_getaddend(PyObject *obj, void *closure)
+{
+ struct elfreloc *w = (struct elfreloc *)obj;
+
+ return Py_BuildValue("K", (unsigned long long)w->rela->r_addend);
+}
+
+static PyObject *elfreloc_repr(PyObject *arg)
+{
+ struct elfreloc *w = (struct elfreloc *)arg;
+
+ return PyUnicode_FromFormat("<ELFReloc @%lu %s+%lu>",
+ (unsigned long)w->rela->r_offset,
+ (w->symname && w->symname[0]) ? w->symname
+ : "[0]",
+ (unsigned long)w->rela->r_addend);
+}
+
+static void elfreloc_free(void *arg)
+{
+ struct elfreloc *w = arg;
+
+ (void)w;
+}
+
+static PyTypeObject typeobj_elfreloc = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "_clippy.ELFReloc",
+ .tp_basicsize = sizeof(struct elfreloc),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = elfreloc_doc,
+ .tp_new = refuse_new,
+ .tp_free = elfreloc_free,
+ .tp_repr = elfreloc_repr,
+ .tp_members = members_elfreloc,
+ .tp_methods = methods_elfreloc,
+ .tp_getset = getset_elfreloc,
+};
+
+/*
+ * class ELFSection:
+ */
+
+static const char elfsect_doc[] =
+ "Represents an ELF section\n"
+ "\n"
+ "To access section contents, use subscript notation, e.g.\n"
+ " section[123:456]\n"
+ "To read null terminated C strings, replace the end with str:\n"
+ " section[123:str]\n\n"
+ "(struct elfsect * in elf_py.c)";
+
+static PyObject *elfsect_getaddr(PyObject *self, void *closure);
+
+#define member(name, type, doc) \
+ { \
+ (char *)#name, type, offsetof(struct elfsect, name), READONLY, \
+ (char *)doc "\n\n(\"" #name "\", " #type " in elf_py.c)" \
+ }
+static PyMemberDef members_elfsect[] = {
+ member(name, T_STRING,
+ "Section name, e.g. \".text\""),
+ member(idx, T_ULONG,
+ "Section index in file"),
+ member(len, T_ULONG,
+ "Section length in bytes"),
+ {},
+};
+#undef member
+
+static PyGetSetDef getset_elfsect[] = {
+ { .name = (char *)"sh_addr", .get = elfsect_getaddr, .doc =
+ (char *)"Section virtual address (mapped program view)"},
+ {}
+};
+
+static PyObject *elfsect_getaddr(PyObject *self, void *closure)
+{
+ struct elfsect *w = (struct elfsect *)self;
+
+ return Py_BuildValue("K", (unsigned long long)w->shdr->sh_addr);
+}
+
+
+static PyObject *elfsect_getreloc(PyObject *self, PyObject *args)
+{
+ struct elfsect *w = (struct elfsect *)self;
+ struct elfreloc *relw;
+ unsigned long offs;
+ PyObject *ret;
+
+ if (!PyArg_ParseTuple(args, "k", &offs))
+ return NULL;
+
+ relw = elfrelocs_get(&w->relocs, offs + w->shdr->sh_addr);
+ if (!relw)
+ Py_RETURN_NONE;
+
+ ret = (PyObject *)relw;
+ Py_INCREF(ret);
+ return ret;
+}
+
+static PyMethodDef methods_elfsect[] = {
+ {"getreloc", elfsect_getreloc, METH_VARARGS,
+ "Check for / get relocation at offset into section\n\n"
+ "Args: byte offset into section to check\n"
+ "Returns: ELFReloc or None"},
+ {}
+};
+
+static PyObject *elfsect_subscript(PyObject *self, PyObject *key)
+{
+ Py_ssize_t start, stop, step, sllen;
+ struct elfsect *w = (struct elfsect *)self;
+ PySliceObject *slice;
+ unsigned long offs, len = ~0UL;
+
+ if (!PySlice_Check(key)) {
+ PyErr_SetString(PyExc_IndexError,
+ "ELFSection subscript must be slice");
+ return NULL;
+ }
+ slice = (PySliceObject *)key;
+ if (PyLong_Check(slice->stop)) {
+ if (PySlice_GetIndicesEx(key, w->shdr->sh_size,
+ &start, &stop, &step, &sllen))
+ return NULL;
+
+ if (step != 1) {
+ PyErr_SetString(PyExc_IndexError,
+ "ELFSection subscript slice step must be 1");
+ return NULL;
+ }
+ if ((GElf_Xword)stop > w->shdr->sh_size) {
+ PyErr_Format(ELFAccessError,
+ "access (%lu) beyond end of section %lu/%s (%lu)",
+ stop, w->idx, w->name, w->shdr->sh_size);
+ return NULL;
+ }
+
+ offs = start;
+ len = sllen;
+ } else {
+ if (slice->stop != (void *)&PyUnicode_Type
+ || !PyLong_Check(slice->start)) {
+ PyErr_SetString(PyExc_IndexError, "invalid slice");
+ return NULL;
+ }
+
+ offs = PyLong_AsUnsignedLongLong(slice->start);
+ len = ~0UL;
+ }
+
+ offs += w->shdr->sh_offset;
+ if (offs > w->ef->len) {
+ PyErr_Format(ELFAccessError,
+ "access (%lu) beyond end of file (%lu)",
+ offs, w->ef->len);
+ return NULL;
+ }
+ if (len == ~0UL)
+ len = strnlen(w->ef->mmap + offs, w->ef->len - offs);
+
+ Py_ssize_t pylen = len;
+
+#if PY_MAJOR_VERSION >= 3
+ return Py_BuildValue("y#", w->ef->mmap + offs, pylen);
+#else
+ return Py_BuildValue("s#", w->ef->mmap + offs, pylen);
+#endif
+}
+
+static PyMappingMethods mp_elfsect = {
+ .mp_subscript = elfsect_subscript,
+};
+
+static void elfsect_free(void *arg)
+{
+ struct elfsect *w = arg;
+
+ (void)w;
+}
+
+static PyObject *elfsect_repr(PyObject *arg)
+{
+ struct elfsect *w = (struct elfsect *)arg;
+
+ return PyUnicode_FromFormat("<ELFSection %s>", w->name);
+}
+
+static PyTypeObject typeobj_elfsect = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "_clippy.ELFSection",
+ .tp_basicsize = sizeof(struct elfsect),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = elfsect_doc,
+ .tp_new = refuse_new,
+ .tp_free = elfsect_free,
+ .tp_repr = elfsect_repr,
+ .tp_as_mapping = &mp_elfsect,
+ .tp_members = members_elfsect,
+ .tp_methods = methods_elfsect,
+ .tp_getset = getset_elfsect,
+};
+
+static void elfsect_add_relocations(struct elfsect *w, Elf_Scn *rel,
+ GElf_Shdr *relhdr)
+{
+ size_t i, entries;
+ Elf_Scn *symtab = elf_getscn(w->ef->elf, relhdr->sh_link);
+ GElf_Shdr _symhdr, *symhdr = gelf_getshdr(symtab, &_symhdr);
+ Elf_Data *symdata = elf_getdata(symtab, NULL);
+ Elf_Data *reldata = elf_getdata(rel, NULL);
+
+ entries = relhdr->sh_size / relhdr->sh_entsize;
+ for (i = 0; i < entries; i++) {
+ struct elfreloc *relw;
+ size_t symidx;
+ GElf_Rela *rela;
+ GElf_Sym *sym;
+
+ relw = (struct elfreloc *)typeobj_elfreloc.tp_alloc(
+ &typeobj_elfreloc, 0);
+ relw->es = w;
+
+ if (relhdr->sh_type == SHT_REL) {
+ GElf_Rel _rel, *rel;
+
+ rel = gelf_getrel(reldata, i, &_rel);
+ relw->rela = &relw->_rela;
+ relw->rela->r_offset = rel->r_offset;
+ relw->rela->r_info = rel->r_info;
+ relw->rela->r_addend = 0;
+ relw->relative = true;
+ } else
+ relw->rela = gelf_getrela(reldata, i, &relw->_rela);
+
+ rela = relw->rela;
+ if (rela->r_offset < w->shdr->sh_addr
+ || rela->r_offset >= w->shdr->sh_addr + w->shdr->sh_size)
+ continue;
+
+ symidx = relw->symidx = GELF_R_SYM(rela->r_info);
+ sym = relw->sym = gelf_getsym(symdata, symidx, &relw->_sym);
+ if (sym) {
+ relw->symname = elf_strptr(w->ef->elf, symhdr->sh_link,
+ sym->st_name);
+ relw->symvalid = GELF_ST_TYPE(sym->st_info)
+ != STT_NOTYPE;
+ relw->unresolved = sym->st_shndx == SHN_UNDEF;
+ relw->st_value = sym->st_value;
+ } else {
+ relw->symname = NULL;
+ relw->symvalid = false;
+ relw->unresolved = false;
+ relw->st_value = 0;
+ }
+
+ debugf("reloc @ %016llx sym %5llu %016llx %s\n",
+ (long long)rela->r_offset, (unsigned long long)symidx,
+ (long long)rela->r_addend, relw->symname);
+
+ elfrelocs_add(&w->relocs, relw);
+ }
+}
+
+/*
+ * bindings & loading code between ELFFile and ELFSection
+ */
+
+static PyObject *elfsect_wrap(struct elffile *ef, Elf_Scn *scn, size_t idx,
+ const char *name)
+{
+ struct elfsect *w;
+ size_t i;
+
+ w = (struct elfsect *)typeobj_elfsect.tp_alloc(&typeobj_elfsect, 0);
+ if (!w)
+ return NULL;
+
+ w->name = name;
+ w->ef = ef;
+ w->scn = scn;
+ w->shdr = gelf_getshdr(scn, &w->_shdr);
+ w->len = w->shdr->sh_size;
+ w->idx = idx;
+ elfrelocs_init(&w->relocs);
+
+ for (i = 0; i < ef->ehdr->e_shnum; i++) {
+ Elf_Scn *scn = elf_getscn(ef->elf, i);
+ GElf_Shdr _shdr, *shdr = gelf_getshdr(scn, &_shdr);
+
+ if (shdr->sh_type != SHT_RELA && shdr->sh_type != SHT_REL)
+ continue;
+ if (shdr->sh_info && shdr->sh_info != idx)
+ continue;
+ elfsect_add_relocations(w, scn, shdr);
+ }
+
+ return (PyObject *)w;
+}
+
+static Elf_Scn *elf_find_section(struct elffile *ef, const char *name,
+ size_t *idx)
+{
+ size_t i;
+ const char *secname;
+
+ for (i = 0; i < ef->ehdr->e_shnum; i++) {
+ Elf_Scn *scn = elf_getscn(ef->elf, i);
+ GElf_Shdr _shdr, *shdr = gelf_getshdr(scn, &_shdr);
+
+ secname = elf_strptr(ef->elf, ef->ehdr->e_shstrndx,
+ shdr->sh_name);
+ if (strcmp(secname, name))
+ continue;
+ if (idx)
+ *idx = i;
+ return scn;
+ }
+ return NULL;
+}
+
+static Elf_Scn *elf_find_addr(struct elffile *ef, uint64_t addr, size_t *idx)
+{
+ size_t i;
+
+ for (i = 0; i < ef->ehdr->e_shnum; i++) {
+ Elf_Scn *scn = elf_getscn(ef->elf, i);
+ GElf_Shdr _shdr, *shdr = gelf_getshdr(scn, &_shdr);
+
+ if (addr < shdr->sh_addr ||
+ addr >= shdr->sh_addr + shdr->sh_size)
+ continue;
+
+ if (idx)
+ *idx = i;
+ return scn;
+ }
+ return NULL;
+}
+
+/*
+ * class ELFFile:
+ */
+
+static const char elffile_doc[] =
+ "Represents an ELF file\n"
+ "\n"
+ "Args: filename to load\n"
+ "\n"
+ "To access raw file contents, use subscript notation, e.g.\n"
+ " file[123:456]\n"
+ "To read null terminated C strings, replace the end with str:\n"
+ " file[123:str]\n\n"
+ "(struct elffile * in elf_py.c)";
+
+
+#define member(name, type, doc) \
+ { \
+ (char *)#name, type, offsetof(struct elffile, name), READONLY, \
+ (char *)doc "\n\n(\"" #name "\", " #type " in elf_py.c)" \
+ }
+static PyMemberDef members_elffile[] = {
+ member(filename, T_STRING,
+ "Original file name as given when opening"),
+ member(elfclass, T_INT,
+ "ELF class (architecture bit size)\n\n"
+ "Either 32 or 64, straight integer."),
+ member(bigendian, T_BOOL,
+ "ELF file is big-endian\n\n"
+ "All internal ELF structures are automatically converted."),
+ member(has_symbols, T_BOOL,
+ "A symbol section is present\n\n"
+ "Note: only refers to .symtab/SHT_SYMTAB section, not DT_SYMTAB"
+ ),
+ {},
+};
+#undef member
+
+static PyObject *elffile_secbyidx(struct elffile *w, Elf_Scn *scn, size_t idx)
+{
+ const char *name;
+ PyObject *ret;
+
+ if (!scn)
+ scn = elf_getscn(w->elf, idx);
+ if (!scn || idx >= w->n_sect)
+ Py_RETURN_NONE;
+
+ if (!w->sects[idx]) {
+ GElf_Shdr _shdr, *shdr = gelf_getshdr(scn, &_shdr);
+
+ name = elf_strptr(w->elf, w->ehdr->e_shstrndx, shdr->sh_name);
+ w->sects[idx] = elfsect_wrap(w, scn, idx, name);
+ }
+
+ ret = w->sects[idx];
+ Py_INCREF(ret);
+ return ret;
+}
+
+static PyObject *elffile_get_section(PyObject *self, PyObject *args)
+{
+ const char *name;
+ struct elffile *w = (struct elffile *)self;
+ Elf_Scn *scn;
+ size_t idx = 0;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ scn = elf_find_section(w, name, &idx);
+ return elffile_secbyidx(w, scn, idx);
+}
+
+static PyObject *elffile_get_section_addr(PyObject *self, PyObject *args)
+{
+ unsigned long long addr;
+ struct elffile *w = (struct elffile *)self;
+ Elf_Scn *scn;
+ size_t idx = 0;
+
+ if (!PyArg_ParseTuple(args, "K", &addr))
+ return NULL;
+
+ scn = elf_find_addr(w, addr, &idx);
+ return elffile_secbyidx(w, scn, idx);
+}
+
+static PyObject *elffile_get_section_idx(PyObject *self, PyObject *args)
+{
+ unsigned long long idx;
+ struct elffile *w = (struct elffile *)self;
+
+ if (!PyArg_ParseTuple(args, "K", &idx))
+ return NULL;
+
+ return elffile_secbyidx(w, NULL, idx);
+}
+
+static PyObject *elffile_get_symbol(PyObject *self, PyObject *args)
+{
+ const char *name, *symname;
+ struct elffile *w = (struct elffile *)self;
+ GElf_Sym _sym, *sym;
+ size_t i;
+
+ if (!PyArg_ParseTuple(args, "s", &name))
+ return NULL;
+
+ for (i = 0; i < w->nsym; i++) {
+ sym = gelf_getsym(w->symdata, i, &_sym);
+ if (sym->st_name == 0)
+ continue;
+ symname = elf_strptr(w->elf, w->symstridx, sym->st_name);
+ if (strcmp(symname, name))
+ continue;
+
+ PyObject *pysect;
+ Elf_Scn *scn = elf_getscn(w->elf, sym->st_shndx);
+
+ if (scn)
+ pysect = elffile_secbyidx(w, scn, sym->st_shndx);
+ else {
+ pysect = Py_None;
+ Py_INCREF(pysect);
+ }
+ return Py_BuildValue("sKN", symname,
+ (unsigned long long)sym->st_value, pysect);
+ }
+ Py_RETURN_NONE;
+}
+
+static PyObject *elffile_getreloc(PyObject *self, PyObject *args)
+{
+ struct elffile *w = (struct elffile *)self;
+ struct elfreloc *relw;
+ unsigned long offs;
+ PyObject *ret;
+
+ if (!PyArg_ParseTuple(args, "k", &offs))
+ return NULL;
+
+ relw = elfrelocs_get(&w->dynrelocs, offs);
+ if (!relw)
+ Py_RETURN_NONE;
+
+ ret = (PyObject *)relw;
+ Py_INCREF(ret);
+ return ret;
+}
+
+static PyObject *elffile_find_note(PyObject *self, PyObject *args)
+{
+#if defined(HAVE_GELF_GETNOTE) && defined(HAVE_ELF_GETDATA_RAWCHUNK)
+ const char *owner;
+ const uint8_t *ids;
+ GElf_Word id;
+ struct elffile *w = (struct elffile *)self;
+ size_t i;
+
+ if (!PyArg_ParseTuple(args, "ss", &owner, &ids))
+ return NULL;
+
+ if (strlen((char *)ids) != 4) {
+ PyErr_SetString(PyExc_ValueError,
+ "ELF note ID must be exactly 4-byte string");
+ return NULL;
+ }
+ if (w->bigendian)
+ id = (ids[0] << 24) | (ids[1] << 16) | (ids[2] << 8) | ids[3];
+ else
+ id = (ids[3] << 24) | (ids[2] << 16) | (ids[1] << 8) | ids[0];
+
+ for (i = 0; i < w->ehdr->e_phnum; i++) {
+ GElf_Phdr _phdr, *phdr = gelf_getphdr(w->elf, i, &_phdr);
+ Elf_Data *notedata;
+ size_t offset;
+
+ if (phdr->p_type != PT_NOTE)
+ continue;
+
+ notedata = elf_getdata_rawchunk(w->elf, phdr->p_offset,
+ phdr->p_filesz, ELF_T_NHDR);
+
+ GElf_Nhdr nhdr[1];
+ size_t nameoffs, dataoffs;
+
+ offset = 0;
+ while ((offset = gelf_getnote(notedata, offset, nhdr,
+ &nameoffs, &dataoffs))) {
+ if (phdr->p_offset + nameoffs >= w->len)
+ continue;
+
+ const char *name = w->mmap + phdr->p_offset + nameoffs;
+
+ if (strcmp(name, owner))
+ continue;
+ if (id != nhdr->n_type)
+ continue;
+
+ PyObject *s, *e;
+
+ s = PyLong_FromUnsignedLongLong(
+ phdr->p_vaddr + dataoffs);
+ e = PyLong_FromUnsignedLongLong(
+ phdr->p_vaddr + dataoffs + nhdr->n_descsz);
+ return PySlice_New(s, e, NULL);
+ }
+ }
+#endif
+ Py_RETURN_NONE;
+}
+
+static bool elffile_virt2file(struct elffile *w, GElf_Addr virt,
+ GElf_Addr *offs)
+{
+ *offs = 0;
+
+ for (size_t i = 0; i < w->ehdr->e_phnum; i++) {
+ GElf_Phdr _phdr, *phdr = gelf_getphdr(w->elf, i, &_phdr);
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ if (virt < phdr->p_vaddr
+ || virt >= phdr->p_vaddr + phdr->p_memsz)
+ continue;
+
+ if (virt >= phdr->p_vaddr + phdr->p_filesz)
+ return false;
+
+ *offs = virt - phdr->p_vaddr + phdr->p_offset;
+ return true;
+ }
+
+ return false;
+}
+
+static PyObject *elffile_subscript(PyObject *self, PyObject *key)
+{
+ Py_ssize_t start, stop, step;
+ PySliceObject *slice;
+ struct elffile *w = (struct elffile *)self;
+ bool str = false;
+
+ if (!PySlice_Check(key)) {
+ PyErr_SetString(PyExc_IndexError,
+ "ELFFile subscript must be slice");
+ return NULL;
+ }
+ slice = (PySliceObject *)key;
+ stop = -1;
+ step = 1;
+ if (PyLong_Check(slice->stop)) {
+ start = PyLong_AsSsize_t(slice->start);
+ if (PyErr_Occurred())
+ return NULL;
+ if (slice->stop != Py_None) {
+ stop = PyLong_AsSsize_t(slice->stop);
+ if (PyErr_Occurred())
+ return NULL;
+ }
+ if (slice->step != Py_None) {
+ step = PyLong_AsSsize_t(slice->step);
+ if (PyErr_Occurred())
+ return NULL;
+ }
+ } else {
+ if (slice->stop != (void *)&PyUnicode_Type
+ || !PyLong_Check(slice->start)) {
+ PyErr_SetString(PyExc_IndexError, "invalid slice");
+ return NULL;
+ }
+
+ str = true;
+ start = PyLong_AsUnsignedLongLong(slice->start);
+ }
+ if (step != 1) {
+ PyErr_SetString(PyExc_IndexError,
+ "ELFFile subscript slice step must be 1");
+ return NULL;
+ }
+
+ GElf_Addr xstart = start, xstop = stop;
+
+ for (size_t i = 0; i < w->ehdr->e_phnum; i++) {
+ GElf_Phdr _phdr, *phdr = gelf_getphdr(w->elf, i, &_phdr);
+
+ if (phdr->p_type != PT_LOAD)
+ continue;
+
+ if (xstart < phdr->p_vaddr
+ || xstart >= phdr->p_vaddr + phdr->p_memsz)
+ continue;
+ if (!str && (xstop < phdr->p_vaddr
+ || xstop > phdr->p_vaddr + phdr->p_memsz)) {
+ PyErr_Format(ELFAccessError,
+ "access (%llu) beyond end of program header (%llu)",
+ (long long)xstop,
+ (long long)(phdr->p_vaddr +
+ phdr->p_memsz));
+ return NULL;
+ }
+
+ xstart = xstart - phdr->p_vaddr + phdr->p_offset;
+
+ if (str)
+ xstop = strlen(w->mmap + xstart);
+ else
+ xstop = xstop - phdr->p_vaddr + phdr->p_offset;
+
+ Py_ssize_t pylen = xstop - xstart;
+
+#if PY_MAJOR_VERSION >= 3
+ return Py_BuildValue("y#", w->mmap + xstart, pylen);
+#else
+ return Py_BuildValue("s#", w->mmap + xstart, pylen);
+#endif
+ };
+
+ return PyErr_Format(ELFAccessError,
+ "virtual address (%llu) not found in program headers",
+ (long long)start);
+}
+
+static PyMethodDef methods_elffile[] = {
+ {"find_note", elffile_find_note, METH_VARARGS,
+ "find specific note entry"},
+ {"getreloc", elffile_getreloc, METH_VARARGS,
+ "find relocation"},
+ {"get_symbol", elffile_get_symbol, METH_VARARGS,
+ "find symbol by name"},
+ {"get_section", elffile_get_section, METH_VARARGS,
+ "find section by name"},
+ {"get_section_addr", elffile_get_section_addr, METH_VARARGS,
+ "find section by address"},
+ {"get_section_idx", elffile_get_section_idx, METH_VARARGS,
+ "find section by index"},
+ {}
+};
+
+static PyObject *elffile_load(PyTypeObject *type, PyObject *args,
+ PyObject *kwds);
+
+static void elffile_free(void *arg)
+{
+ struct elffile *w = arg;
+
+ elf_end(w->elf);
+ munmap(w->mmap, w->len);
+ free(w->filename);
+}
+
+static PyMappingMethods mp_elffile = {
+ .mp_subscript = elffile_subscript,
+};
+
+static PyTypeObject typeobj_elffile = {
+ PyVarObject_HEAD_INIT(NULL, 0).tp_name = "_clippy.ELFFile",
+ .tp_basicsize = sizeof(struct elffile),
+ .tp_flags = Py_TPFLAGS_DEFAULT,
+ .tp_doc = elffile_doc,
+ .tp_new = elffile_load,
+ .tp_free = elffile_free,
+ .tp_as_mapping = &mp_elffile,
+ .tp_members = members_elffile,
+ .tp_methods = methods_elffile,
+};
+
+static char *elfdata_strptr(Elf_Data *data, size_t offset)
+{
+ char *p;
+
+ if (offset >= data->d_size)
+ return NULL;
+
+ p = (char *)data->d_buf + offset;
+ if (strnlen(p, data->d_size - offset) >= data->d_size - offset)
+ return NULL;
+
+ return p;
+}
+
+static void elffile_add_dynreloc(struct elffile *w, Elf_Data *reldata,
+ size_t entries, Elf_Data *symdata,
+ Elf_Data *strdata)
+{
+ size_t i;
+
+ for (i = 0; i < entries; i++) {
+ struct elfreloc *relw;
+ size_t symidx;
+ GElf_Rela *rela;
+ GElf_Sym *sym;
+
+ relw = (struct elfreloc *)typeobj_elfreloc.tp_alloc(
+ &typeobj_elfreloc, 0);
+ relw->ef = w;
+
+ rela = relw->rela = gelf_getrela(reldata, i, &relw->_rela);
+ symidx = relw->symidx = GELF_R_SYM(rela->r_info);
+ sym = relw->sym = gelf_getsym(symdata, symidx, &relw->_sym);
+ if (sym) {
+ relw->symname = elfdata_strptr(strdata, sym->st_name);
+ relw->symvalid = GELF_ST_TYPE(sym->st_info)
+ != STT_NOTYPE;
+ relw->unresolved = sym->st_shndx == SHN_UNDEF;
+ relw->st_value = sym->st_value;
+ } else {
+ relw->symname = NULL;
+ relw->symvalid = false;
+ relw->unresolved = false;
+ relw->st_value = 0;
+ }
+
+ debugf("dynreloc @ %016llx sym %5llu %016llx %s\n",
+ (long long)rela->r_offset, (unsigned long long)symidx,
+ (long long)rela->r_addend, relw->symname);
+
+ elfrelocs_add(&w->dynrelocs, relw);
+ }
+
+}
+
+/* primary (only, really) entry point to anything in this module */
+static PyObject *elffile_load(PyTypeObject *type, PyObject *args,
+ PyObject *kwds)
+{
+ const char *filename;
+ static const char * const kwnames[] = {"filename", NULL};
+ struct elffile *w;
+ struct stat st;
+ int fd, err;
+
+ w = (struct elffile *)typeobj_elffile.tp_alloc(&typeobj_elffile, 0);
+ if (!w)
+ return NULL;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwds, "s", (char **)kwnames,
+ &filename))
+ return NULL;
+
+ w->filename = strdup(filename);
+ fd = open(filename, O_RDONLY | O_NOCTTY);
+ if (fd < 0 || fstat(fd, &st)) {
+ PyErr_SetFromErrnoWithFilename(PyExc_OSError, filename);
+ close(fd);
+ goto out;
+ }
+ w->len = st.st_size;
+ w->mmap = mmap(NULL, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
+ if (!w->mmap) {
+ PyErr_SetFromErrnoWithFilename(PyExc_IOError, filename);
+ close(fd);
+ goto out;
+ }
+ close(fd);
+ w->mmend = w->mmap + st.st_size;
+
+ if (w->len < EI_NIDENT || memcmp(w->mmap, ELFMAG, SELFMAG)) {
+ PyErr_SetString(ELFFormatError, "invalid ELF signature");
+ goto out;
+ }
+
+ switch (w->mmap[EI_CLASS]) {
+ case ELFCLASS32:
+ w->elfclass = 32;
+ break;
+ case ELFCLASS64:
+ w->elfclass = 64;
+ break;
+ default:
+ PyErr_SetString(ELFFormatError, "invalid ELF class");
+ goto out;
+ }
+ switch (w->mmap[EI_DATA]) {
+ case ELFDATA2LSB:
+ w->bigendian = false;
+ break;
+ case ELFDATA2MSB:
+ w->bigendian = true;
+ break;
+ default:
+ PyErr_SetString(ELFFormatError, "invalid ELF byte order");
+ goto out;
+ }
+
+ w->elf = elf_memory(w->mmap, w->len);
+ if (!w->elf)
+ goto out_elferr;
+ w->ehdr = gelf_getehdr(w->elf, &w->_ehdr);
+ if (!w->ehdr)
+ goto out_elferr;
+
+ for (size_t i = 0; i < w->ehdr->e_shnum; i++) {
+ Elf_Scn *scn = elf_getscn(w->elf, i);
+ GElf_Shdr _shdr, *shdr = gelf_getshdr(scn, &_shdr);
+
+ if (shdr->sh_type == SHT_SYMTAB) {
+ w->symtab = scn;
+ w->nsym = shdr->sh_size / shdr->sh_entsize;
+ w->symdata = elf_getdata(scn, NULL);
+ w->symstridx = shdr->sh_link;
+ break;
+ }
+ }
+ w->has_symbols = w->symtab && w->symstridx;
+ elfrelocs_init(&w->dynrelocs);
+
+#ifdef HAVE_ELF_GETDATA_RAWCHUNK
+ for (size_t i = 0; i < w->ehdr->e_phnum; i++) {
+ GElf_Phdr _phdr, *phdr = gelf_getphdr(w->elf, i, &_phdr);
+
+ if (phdr->p_type != PT_DYNAMIC)
+ continue;
+
+ Elf_Data *dyndata = elf_getdata_rawchunk(w->elf,
+ phdr->p_offset, phdr->p_filesz, ELF_T_DYN);
+
+ GElf_Addr dynrela = 0, symtab = 0, strtab = 0;
+ size_t dynrelasz = 0, dynrelaent = 0, strsz = 0;
+ GElf_Dyn _dyn, *dyn;
+
+ for (size_t j = 0;; j++) {
+ dyn = gelf_getdyn(dyndata, j, &_dyn);
+
+ if (dyn->d_tag == DT_NULL)
+ break;
+
+ switch (dyn->d_tag) {
+ case DT_SYMTAB:
+ symtab = dyn->d_un.d_ptr;
+ break;
+
+ case DT_STRTAB:
+ strtab = dyn->d_un.d_ptr;
+ break;
+ case DT_STRSZ:
+ strsz = dyn->d_un.d_val;
+ break;
+
+ case DT_RELA:
+ dynrela = dyn->d_un.d_ptr;
+ break;
+ case DT_RELASZ:
+ dynrelasz = dyn->d_un.d_val;
+ break;
+ case DT_RELAENT:
+ dynrelaent = dyn->d_un.d_val;
+ break;
+
+ case DT_RELSZ:
+ if (dyn->d_un.d_val)
+ fprintf(stderr,
+ "WARNING: ignoring non-empty DT_REL!\n");
+ break;
+ }
+ }
+
+ GElf_Addr offset;
+ Elf_Data *symdata = NULL, *strdata = NULL, *reladata = NULL;
+
+ if (elffile_virt2file(w, symtab, &offset))
+ symdata = elf_getdata_rawchunk(w->elf, offset,
+ w->len - offset,
+ ELF_T_SYM);
+ if (elffile_virt2file(w, strtab, &offset))
+ strdata = elf_getdata_rawchunk(w->elf, offset,
+ strsz, ELF_T_BYTE);
+
+ if (!dynrela || !dynrelasz || !dynrelaent)
+ continue;
+
+ if (!elffile_virt2file(w, dynrela, &offset))
+ continue;
+
+ debugf("dynrela @%llx/%llx+%llx\n", (long long)dynrela,
+ (long long)offset, (long long)dynrelasz);
+
+ reladata = elf_getdata_rawchunk(w->elf, offset, dynrelasz,
+ ELF_T_RELA);
+ elffile_add_dynreloc(w, reladata, dynrelasz / dynrelaent,
+ symdata, strdata);
+ }
+#endif
+
+ w->sects = calloc(sizeof(PyObject *), w->ehdr->e_shnum);
+ w->n_sect = w->ehdr->e_shnum;
+
+ return (PyObject *)w;
+
+out_elferr:
+ err = elf_errno();
+
+ PyErr_Format(ELFFormatError, "libelf error %d: %s",
+ err, elf_errmsg(err));
+out:
+ if (w->elf)
+ elf_end(w->elf);
+ free(w->filename);
+ return NULL;
+}
+
+static PyObject *elfpy_debug(PyObject *self, PyObject *args)
+{
+ int arg;
+
+ if (!PyArg_ParseTuple(args, "p", &arg))
+ return NULL;
+
+ debug = arg;
+
+ Py_RETURN_NONE;
+}
+
+static PyMethodDef methods_elfpy[] = {
+ {"elfpy_debug", elfpy_debug, METH_VARARGS, "switch debuging on/off"},
+ {}
+};
+
+bool elf_py_init(PyObject *pymod)
+{
+ if (PyType_Ready(&typeobj_elffile) < 0)
+ return false;
+ if (PyType_Ready(&typeobj_elfsect) < 0)
+ return false;
+ if (PyType_Ready(&typeobj_elfreloc) < 0)
+ return false;
+ if (elf_version(EV_CURRENT) == EV_NONE)
+ return false;
+
+#if PY_MAJOR_VERSION >= 3 && PY_MINOR_VERSION >= 5
+ PyModule_AddFunctions(pymod, methods_elfpy);
+#else
+ (void)methods_elfpy;
+#endif
+
+ ELFFormatError = PyErr_NewException("_clippy.ELFFormatError",
+ PyExc_ValueError, NULL);
+ PyModule_AddObject(pymod, "ELFFormatError", ELFFormatError);
+ ELFAccessError = PyErr_NewException("_clippy.ELFAccessError",
+ PyExc_IndexError, NULL);
+ PyModule_AddObject(pymod, "ELFAccessError", ELFAccessError);
+
+ Py_INCREF(&typeobj_elffile);
+ PyModule_AddObject(pymod, "ELFFile", (PyObject *)&typeobj_elffile);
+ Py_INCREF(&typeobj_elfsect);
+ PyModule_AddObject(pymod, "ELFSection", (PyObject *)&typeobj_elfsect);
+ Py_INCREF(&typeobj_elfreloc);
+ PyModule_AddObject(pymod, "ELFReloc", (PyObject *)&typeobj_elfreloc);
+ return true;
+}
diff --git a/lib/nexthop.c b/lib/nexthop.c
index b2fa945690..dd8c108205 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -739,6 +739,16 @@ static ssize_t printfrr_nh(char *buf, size_t bsz, const char *fmt,
const char *s, *v_is = "", *v_via = "", *v_viaif = "via ";
ssize_t ret = 3;
+ /* NULL-check */
+ if (nexthop == NULL) {
+ if (fmt[2] == 'v' && fmt[3] == 'v')
+ ret++;
+
+ strlcpy(buf, "NULL", bsz);
+
+ return ret;
+ }
+
switch (fmt[2]) {
case 'v':
if (fmt[3] == 'v') {
diff --git a/lib/northbound.c b/lib/northbound.c
index ecfa2c9d11..b6d3518285 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -185,6 +185,25 @@ struct nb_node *nb_node_find(const char *xpath)
return snode->priv;
}
+void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs)
+{
+ struct nb_node *dependency = nb_node_find(dependency_xpath);
+ struct nb_node *dependant = nb_node_find(dependant_xpath);
+
+ if (!dependency || !dependant)
+ return;
+
+ dependency->dep_cbs.get_dependant_xpath = cbs->get_dependant_xpath;
+ dependant->dep_cbs.get_dependency_xpath = cbs->get_dependency_xpath;
+}
+
+bool nb_node_has_dependency(struct nb_node *node)
+{
+ return node->dep_cbs.get_dependency_xpath != NULL;
+}
+
static int nb_node_validate_cb(const struct nb_node *nb_node,
enum nb_operation operation,
int callback_implemented, bool optional)
@@ -532,8 +551,9 @@ int nb_candidate_edit(struct nb_config *candidate,
const struct yang_data *previous,
const struct yang_data *data)
{
- struct lyd_node *dnode;
+ struct lyd_node *dnode, *dep_dnode;
char xpath_edit[XPATH_MAXLEN];
+ char dep_xpath[XPATH_MAXLEN];
/* Use special notation for leaf-lists (RFC 6020, section 9.13.5). */
if (nb_node->snode->nodetype == LYS_LEAFLIST)
@@ -549,9 +569,33 @@ int nb_candidate_edit(struct nb_config *candidate,
dnode = lyd_new_path(candidate->dnode, ly_native_ctx,
xpath_edit, (void *)data->value, 0,
LYD_PATH_OPT_UPDATE);
- if (!dnode && ly_errno) {
- flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path() failed",
- __func__);
+ if (dnode) {
+ /*
+ * create dependency
+ *
+ * dnode returned by the lyd_new_path may be from a
+ * different schema, so we need to update the nb_node
+ */
+ nb_node = dnode->schema->priv;
+ if (nb_node->dep_cbs.get_dependency_xpath) {
+ nb_node->dep_cbs.get_dependency_xpath(
+ dnode, dep_xpath);
+
+ ly_errno = 0;
+ dep_dnode = lyd_new_path(candidate->dnode,
+ ly_native_ctx,
+ dep_xpath, NULL, 0,
+ LYD_PATH_OPT_UPDATE);
+ if (!dep_dnode && ly_errno) {
+ flog_warn(EC_LIB_LIBYANG,
+ "%s: lyd_new_path(%s) failed",
+ __func__, dep_xpath);
+ return NB_ERR;
+ }
+ }
+ } else if (ly_errno) {
+ flog_warn(EC_LIB_LIBYANG, "%s: lyd_new_path(%s) failed",
+ __func__, xpath_edit);
return NB_ERR;
}
break;
@@ -563,6 +607,14 @@ int nb_candidate_edit(struct nb_config *candidate,
* whether to ignore it or not.
*/
return NB_ERR_NOT_FOUND;
+ /* destroy dependant */
+ if (nb_node->dep_cbs.get_dependant_xpath) {
+ nb_node->dep_cbs.get_dependant_xpath(dnode, dep_xpath);
+
+ dep_dnode = yang_dnode_get(candidate->dnode, dep_xpath);
+ if (dep_dnode)
+ lyd_free(dep_dnode);
+ }
lyd_free(dnode);
break;
case NB_OP_MOVE:
@@ -1765,6 +1817,16 @@ int nb_oper_data_iterate(const char *xpath, struct yang_translator *translator,
/* Find the list entry pointer. */
nn = dn->schema->priv;
+ if (!nn->cbs.lookup_entry) {
+ flog_warn(
+ EC_LIB_NB_OPERATIONAL_DATA,
+ "%s: data path doesn't support iteration over operational data: %s",
+ __func__, xpath);
+ list_delete(&list_dnodes);
+ yang_dnode_free(dnode);
+ return NB_ERR;
+ }
+
list_entry =
nb_callback_lookup_entry(nn, list_entry, &list_keys);
if (list_entry == NULL) {
diff --git a/lib/northbound.h b/lib/northbound.h
index 8dd6b4c337..3e1342f985 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -509,6 +509,11 @@ struct nb_callbacks {
void (*cli_show_end)(struct vty *vty, struct lyd_node *dnode);
};
+struct nb_dependency_callbacks {
+ void (*get_dependant_xpath)(const struct lyd_node *dnode, char *xpath);
+ void (*get_dependency_xpath)(const struct lyd_node *dnode, char *xpath);
+};
+
/*
* Northbound-specific data that is allocated for each schema node of the native
* YANG modules.
@@ -523,6 +528,8 @@ struct nb_node {
/* Priority - lower priorities are processed first. */
uint32_t priority;
+ struct nb_dependency_callbacks dep_cbs;
+
/* Callbacks implemented for this node. */
struct nb_callbacks cbs;
@@ -722,6 +729,12 @@ void nb_nodes_delete(void);
*/
extern struct nb_node *nb_node_find(const char *xpath);
+extern void nb_node_set_dependency_cbs(const char *dependency_xpath,
+ const char *dependant_xpath,
+ struct nb_dependency_callbacks *cbs);
+
+bool nb_node_has_dependency(struct nb_node *node);
+
/*
* Create a new northbound configuration.
*
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 1416b758d8..a2c8bc8633 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -1906,7 +1906,6 @@ void nb_cli_init(struct thread_master *tm)
if (frr_get_cli_mode() == FRR_CLI_TRANSACTIONAL) {
install_element(ENABLE_NODE, &config_exclusive_cmd);
install_element(ENABLE_NODE, &config_private_cmd);
- install_element(ENABLE_NODE, &show_config_running_cmd);
install_element(ENABLE_NODE,
&show_config_compare_without_candidate_cmd);
install_element(ENABLE_NODE, &show_config_transaction_cmd);
@@ -1919,6 +1918,7 @@ void nb_cli_init(struct thread_master *tm)
}
/* Other commands. */
+ install_element(ENABLE_NODE, &show_config_running_cmd);
install_element(CONFIG_NODE, &yang_module_translator_load_cmd);
install_element(CONFIG_NODE, &yang_module_translator_unload_cmd);
install_element(ENABLE_NODE, &show_yang_operational_data_cmd);
diff --git a/lib/prefix.c b/lib/prefix.c
index 663a87afde..5e5c2d89a8 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1160,7 +1160,7 @@ in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen)
ex.) "1.1.0.0" "255.255.0.0" => "1.1.0.0/16"
ex.) "1.0.0.0" NULL => "1.0.0.0/8" */
int netmask_str2prefix_str(const char *net_str, const char *mask_str,
- char *prefix_str)
+ char *prefix_str, size_t prefix_str_len)
{
struct in_addr network;
struct in_addr mask;
@@ -1193,7 +1193,7 @@ int netmask_str2prefix_str(const char *net_str, const char *mask_str,
return 0;
}
- sprintf(prefix_str, "%s/%d", net_str, prefixlen);
+ snprintf(prefix_str, prefix_str_len, "%s/%d", net_str, prefixlen);
return 1;
}
@@ -1366,7 +1366,11 @@ static ssize_t printfrr_ea(char *buf, size_t bsz, const char *fmt,
{
const struct ethaddr *mac = ptr;
- prefix_mac2str(mac, buf, bsz);
+ if (mac)
+ prefix_mac2str(mac, buf, bsz);
+ else
+ strlcpy(buf, "NULL", bsz);
+
return 2;
}
@@ -1376,7 +1380,11 @@ static ssize_t printfrr_ia(char *buf, size_t bsz, const char *fmt,
{
const struct ipaddr *ipa = ptr;
- ipaddr2str(ipa, buf, bsz);
+ if (ipa)
+ ipaddr2str(ipa, buf, bsz);
+ else
+ strlcpy(buf, "NULL", bsz);
+
return 2;
}
@@ -1384,7 +1392,11 @@ printfrr_ext_autoreg_p("I4", printfrr_i4)
static ssize_t printfrr_i4(char *buf, size_t bsz, const char *fmt,
int prec, const void *ptr)
{
- inet_ntop(AF_INET, ptr, buf, bsz);
+ if (ptr)
+ inet_ntop(AF_INET, ptr, buf, bsz);
+ else
+ strlcpy(buf, "NULL", bsz);
+
return 2;
}
@@ -1392,7 +1404,11 @@ printfrr_ext_autoreg_p("I6", printfrr_i6)
static ssize_t printfrr_i6(char *buf, size_t bsz, const char *fmt,
int prec, const void *ptr)
{
- inet_ntop(AF_INET6, ptr, buf, bsz);
+ if (ptr)
+ inet_ntop(AF_INET6, ptr, buf, bsz);
+ else
+ strlcpy(buf, "NULL", bsz);
+
return 2;
}
@@ -1400,7 +1416,11 @@ printfrr_ext_autoreg_p("FX", printfrr_pfx)
static ssize_t printfrr_pfx(char *buf, size_t bsz, const char *fmt,
int prec, const void *ptr)
{
- prefix2str(ptr, buf, bsz);
+ if (ptr)
+ prefix2str(ptr, buf, bsz);
+ else
+ strlcpy(buf, "NULL", bsz);
+
return 2;
}
@@ -1411,16 +1431,22 @@ static ssize_t printfrr_psg(char *buf, size_t bsz, const char *fmt,
const struct prefix_sg *sg = ptr;
struct fbuf fb = { .buf = buf, .pos = buf, .len = bsz - 1 };
- if (sg->src.s_addr == INADDR_ANY)
- bprintfrr(&fb, "(*,");
- else
- bprintfrr(&fb, "(%pI4,", &sg->src);
+ if (sg) {
+ if (sg->src.s_addr == INADDR_ANY)
+ bprintfrr(&fb, "(*,");
+ else
+ bprintfrr(&fb, "(%pI4,", &sg->src);
- if (sg->grp.s_addr == INADDR_ANY)
- bprintfrr(&fb, "*)");
- else
- bprintfrr(&fb, "%pI4)", &sg->grp);
+ if (sg->grp.s_addr == INADDR_ANY)
+ bprintfrr(&fb, "*)");
+ else
+ bprintfrr(&fb, "%pI4)", &sg->grp);
+
+ fb.pos[0] = '\0';
+
+ } else {
+ strlcpy(buf, "NULL", bsz);
+ }
- fb.pos[0] = '\0';
return 3;
}
diff --git a/lib/prefix.h b/lib/prefix.h
index b7fdc26369..b2f3b0592f 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -491,7 +491,7 @@ extern void masklen2ip(const int, struct in_addr *);
* special treatment for /31 according to RFC3021 section 3.3 */
extern in_addr_t ipv4_broadcast_addr(in_addr_t hostaddr, int masklen);
-extern int netmask_str2prefix_str(const char *, const char *, char *);
+extern int netmask_str2prefix_str(const char *, const char *, char *, size_t);
extern struct prefix_ipv6 *prefix_ipv6_new(void);
extern void prefix_ipv6_free(struct prefix_ipv6 **p);
diff --git a/lib/ringbuf.c b/lib/ringbuf.c
index 1c3c3e9753..26c4e744b4 100644
--- a/lib/ringbuf.c
+++ b/lib/ringbuf.c
@@ -131,3 +131,38 @@ void ringbuf_wipe(struct ringbuf *buf)
memset(buf->data, 0x00, buf->size);
ringbuf_reset(buf);
}
+
+ssize_t ringbuf_read(struct ringbuf *buf, int sock)
+{
+ size_t to_read = ringbuf_space(buf);
+ size_t bytes_to_end = buf->size - buf->end;
+ ssize_t bytes_read;
+ struct iovec iov[2] = {};
+
+ /* Calculate amount of read blocks. */
+ if (to_read > bytes_to_end) {
+ iov[0].iov_base = buf->data + buf->end;
+ iov[0].iov_len = bytes_to_end;
+ iov[1].iov_base = buf->data;
+ iov[1].iov_len = to_read - bytes_to_end;
+ } else {
+ iov[0].iov_base = buf->data + buf->end;
+ iov[0].iov_len = to_read;
+ }
+
+ /* Do the system call. */
+ bytes_read = readv(sock, iov, 2);
+ if (bytes_read <= 0)
+ return bytes_read;
+
+ /* Calculate the new end. */
+ if ((size_t)bytes_read > bytes_to_end)
+ buf->end = bytes_read - bytes_to_end;
+ else
+ buf->end += bytes_read;
+
+ /* Set emptiness state. */
+ buf->empty = (buf->start == buf->end) && (buf->empty && !bytes_read);
+
+ return bytes_read;
+}
diff --git a/lib/ringbuf.h b/lib/ringbuf.h
index b8f4d9798d..209687512b 100644
--- a/lib/ringbuf.h
+++ b/lib/ringbuf.h
@@ -126,6 +126,17 @@ void ringbuf_reset(struct ringbuf *buf);
*/
void ringbuf_wipe(struct ringbuf *buf);
+/**
+ * Perform a socket/file `read()` in to the ring buffer.
+ *
+ * \param buf the ring buffer pointer.
+ * \param sock the file descriptor.
+ * \returns the number of bytes read, `0` on connection close or `-1` with
+ * `errno` pointing the error (see `readv()` man page for more
+ * information.)
+ */
+ssize_t ringbuf_read(struct ringbuf *buf, int sock);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/routing_nb.h b/lib/routing_nb.h
index d1b59ea29e..ffba631a10 100644
--- a/lib/routing_nb.h
+++ b/lib/routing_nb.h
@@ -15,10 +15,17 @@ int routing_control_plane_protocols_control_plane_protocol_destroy(
#define FRR_ROUTING_KEY_XPATH \
"/frr-routing:routing/control-plane-protocols/" \
"control-plane-protocol[type='%s'][name='%s'][vrf='%s']"
+
+#define FRR_ROUTING_KEY_XPATH_VRF \
+ "/frr-routing:routing/control-plane-protocols/" \
+ "control-plane-protocol[vrf='%s']"
+
/*
* callbacks for routing to handle configuration events
* based on the control plane protocol
*/
DECLARE_HOOK(routing_conf_event, (struct nb_cb_create_args *args), (args))
+void routing_control_plane_protocols_register_vrf_dependency(void);
+
#endif /* _FRR_ROUTING_NB_H_ */
diff --git a/lib/routing_nb_config.c b/lib/routing_nb_config.c
index b789e8494e..17698d2b87 100644
--- a/lib/routing_nb_config.c
+++ b/lib/routing_nb_config.c
@@ -45,15 +45,21 @@ int routing_control_plane_protocols_control_plane_protocol_create(
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- vrfname = yang_dnode_get_string(args->dnode, "./vrf");
- vrf = vrf_lookup_by_name(vrfname);
- vrf = vrf ? vrf : vrf_get(VRF_UNKNOWN, vrfname);
- if (!vrf) {
- flog_warn(EC_LIB_NB_CB_CONFIG_APPLY,
- "vrf creation %s failed", vrfname);
- return NB_ERR;
+ /*
+ * If the daemon relies on the VRF pointer stored in this
+ * dnode, then it should register the dependency between this
+ * module and the VRF module using
+ * routing_control_plane_protocols_register_vrf_dependency.
+ * If such dependency is not registered, then nothing is
+ * stored in the dnode. If the dependency is registered,
+ * find the vrf and store the pointer.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv)) {
+ vrfname = yang_dnode_get_string(args->dnode, "./vrf");
+ vrf = vrf_lookup_by_name(vrfname);
+ assert(vrf);
+ nb_running_set_entry(args->dnode, vrf);
}
- nb_running_set_entry(args->dnode, vrf);
break;
};
@@ -63,12 +69,45 @@ int routing_control_plane_protocols_control_plane_protocol_create(
int routing_control_plane_protocols_control_plane_protocol_destroy(
struct nb_cb_destroy_args *args)
{
- struct vrf *vrf __attribute__((unused));
-
if (args->event != NB_EV_APPLY)
return NB_OK;
- vrf = nb_running_unset_entry(args->dnode);
+ /*
+ * If dependency on VRF module is registered, then VRF
+ * pointer was stored and must be cleared.
+ */
+ if (nb_node_has_dependency(args->dnode->schema->priv))
+ nb_running_unset_entry(args->dnode);
return NB_OK;
}
+
+static void vrf_to_control_plane_protocol(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./name");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_ROUTING_KEY_XPATH_VRF, vrf);
+}
+
+static void control_plane_protocol_to_vrf(const struct lyd_node *dnode,
+ char *xpath)
+{
+ const char *vrf;
+
+ vrf = yang_dnode_get_string(dnode, "./vrf");
+
+ snprintf(xpath, XPATH_MAXLEN, FRR_VRF_KEY_XPATH, vrf);
+}
+
+void routing_control_plane_protocols_register_vrf_dependency(void)
+{
+ struct nb_dependency_callbacks cbs;
+
+ cbs.get_dependant_xpath = vrf_to_control_plane_protocol;
+ cbs.get_dependency_xpath = control_plane_protocol_to_vrf;
+
+ nb_node_set_dependency_cbs(FRR_VRF_XPATH, FRR_ROUTING_XPATH, &cbs);
+}
diff --git a/lib/smux.h b/lib/smux.h
index 11c1becd60..57128b7928 100644
--- a/lib/smux.h
+++ b/lib/smux.h
@@ -25,6 +25,7 @@
#include <net-snmp/agent/snmp_vars.h>
#include "thread.h"
+#include "hook.h"
#ifdef __cplusplus
extern "C" {
@@ -102,7 +103,10 @@ struct index_oid {
#define SNMP_IP6ADDRESS(V) (*var_len = sizeof(struct in6_addr), (uint8_t *)&V)
+extern int smux_enabled(void);
+
extern void smux_init(struct thread_master *tm);
+extern void smux_agentx_enable(void);
extern void smux_register_mib(const char *, struct variable *, size_t, int,
oid[], size_t);
extern int smux_header_generic(struct variable *, oid[], size_t *, int,
@@ -141,6 +145,8 @@ extern int smux_trap_multi_index(struct variable *vp, size_t vp_len,
struct index_oid *iname, size_t index_len,
const struct trap_object *trapobj,
size_t trapobjlen, uint8_t sptrap);
+
+extern void smux_events_update(void);
extern int oid_compare(const oid *, int, const oid *, int);
extern void oid2in_addr(oid[], int, struct in_addr *);
extern void oid2in6_addr(oid oid[], struct in6_addr *addr);
@@ -151,6 +157,8 @@ extern void oid_copy_int(oid oid[], int *val);
extern void oid2string(oid oid[], int len, char *string);
extern void oid_copy_str(oid oid[], const char *string, int len);
+DECLARE_HOOK(agentx_enabled, (), ())
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/sockunion.c b/lib/sockunion.c
index 1dbf77efa4..c701da1e03 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -673,39 +673,44 @@ static ssize_t printfrr_psu(char *buf, size_t bsz, const char *fmt,
bool endflags = false;
ssize_t consumed = 2;
- while (!endflags) {
- switch (fmt[consumed++]) {
- case 'p':
- include_port = true;
+ if (su) {
+ while (!endflags) {
+ switch (fmt[consumed++]) {
+ case 'p':
+ include_port = true;
+ break;
+ default:
+ consumed--;
+ endflags = true;
+ break;
+ }
+ };
+
+ switch (sockunion_family(su)) {
+ case AF_UNSPEC:
+ bprintfrr(&fb, "(unspec)");
break;
- default:
- consumed--;
- endflags = true;
+ case AF_INET:
+ inet_ntop(AF_INET, &su->sin.sin_addr, buf, bsz);
+ fb.pos += strlen(fb.buf);
+ if (include_port)
+ bprintfrr(&fb, ":%d", su->sin.sin_port);
+ break;
+ case AF_INET6:
+ inet_ntop(AF_INET6, &su->sin6.sin6_addr, buf, bsz);
+ fb.pos += strlen(fb.buf);
+ if (include_port)
+ bprintfrr(&fb, ":%d", su->sin6.sin6_port);
break;
+ default:
+ bprintfrr(&fb, "(af %d)", sockunion_family(su));
}
- };
- switch (sockunion_family(su)) {
- case AF_UNSPEC:
- bprintfrr(&fb, "(unspec)");
- break;
- case AF_INET:
- inet_ntop(AF_INET, &su->sin.sin_addr, buf, bsz);
- fb.pos += strlen(fb.buf);
- if (include_port)
- bprintfrr(&fb, ":%d", su->sin.sin_port);
- break;
- case AF_INET6:
- inet_ntop(AF_INET6, &su->sin6.sin6_addr, buf, bsz);
- fb.pos += strlen(fb.buf);
- if (include_port)
- bprintfrr(&fb, ":%d", su->sin6.sin6_port);
- break;
- default:
- bprintfrr(&fb, "(af %d)", sockunion_family(su));
+ fb.pos[0] = '\0';
+ } else {
+ strlcpy(buf, "NULL", bsz);
}
- fb.pos[0] = '\0';
return consumed;
}
diff --git a/lib/srcdest_table.c b/lib/srcdest_table.c
index 8ffa0e9709..ef82b7ac01 100644
--- a/lib/srcdest_table.c
+++ b/lib/srcdest_table.c
@@ -313,8 +313,13 @@ static ssize_t printfrr_rn(char *buf, size_t bsz, const char *fmt,
const struct route_node *rn = ptr;
const struct prefix *dst_p, *src_p;
- srcdest_rnode_prefixes(rn, &dst_p, &src_p);
- srcdest2str(dst_p, (const struct prefix_ipv6 *)src_p, buf, bsz);
+ if (rn) {
+ srcdest_rnode_prefixes(rn, &dst_p, &src_p);
+ srcdest2str(dst_p, (const struct prefix_ipv6 *)src_p, buf, bsz);
+ } else {
+ strlcpy(buf, "NULL", bsz);
+ }
+
return 2;
}
diff --git a/lib/subdir.am b/lib/subdir.am
index d5ffa08546..38d1a3f773 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -410,7 +410,7 @@ lib_grammar_sandbox_LDADD = \
lib_clippy_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE -DBUILDING_CLIPPY
lib_clippy_CFLAGS = $(PYTHON_CFLAGS)
-lib_clippy_LDADD = $(PYTHON_LIBS) $(UST_LIBS)
+lib_clippy_LDADD = $(PYTHON_LIBS) $(UST_LIBS) -lelf
lib_clippy_LDFLAGS = -export-dynamic
lib_clippy_SOURCES = \
lib/jhash.c \
@@ -420,9 +420,11 @@ lib_clippy_SOURCES = \
lib/command_parse.y \
lib/command_py.c \
lib/defun_lex.l \
+ lib/elf_py.c \
lib/graph.c \
lib/libfrr_trace.c \
lib/memory.c \
+ lib/typesafe.c \
lib/vector.c \
# end
@@ -439,6 +441,32 @@ SUFFIXES += _clippy.c
.c_clippy.c:
$(AM_V_CLIPPY) $(CLIPPY) $(top_srcdir)/python/clidef.py -o $@ $<
+# xrelfo, the ELF xref extractor
+
+AM_V_XRELFO = $(am__v_XRELFO_$(V))
+am__v_XRELFO_ = $(am__v_XRELFO_$(AM_DEFAULT_VERBOSITY))
+am__v_XRELFO_0 = @echo " XRELFO " $@;
+am__v_XRELFO_1 =
+
+if DEV_BUILD
+XRELFO_FLAGS = -Wlog-format -Wlog-args
+else
+XRELFO_FLAGS =
+endif
+
+SUFFIXES += .xref
+%.xref: % $(CLIPPY)
+ $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py $(XRELFO_FLAGS) -o $@ $<
+
+# dependencies added in python/makefile.py
+frr.xref:
+ $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py -o $@ $^
+all-am: frr.xref
+
+clean-xref:
+ -rm -rf $(xrefs) frr.xref
+clean-local: clean-xref
+
## automake's "ylwrap" is a great piece of GNU software... not.
.l.c:
$(AM_V_LEX)$(am__skiplex) $(LEXCOMPILE) $<
diff --git a/lib/thread.c b/lib/thread.c
index f7f1ed8b7e..af01c75a44 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -45,6 +45,16 @@ DEFINE_MTYPE_STATIC(LIB, THREAD_STATS, "Thread stats")
DECLARE_LIST(thread_list, struct thread, threaditem)
+struct cancel_req {
+ int flags;
+ struct thread *thread;
+ void *eventobj;
+ struct thread **threadref;
+};
+
+/* Flags for task cancellation */
+#define THREAD_CANCEL_FLAG_READY 0x01
+
static int thread_timer_cmp(const struct thread *a, const struct thread *b)
{
if (a->u.sands.tv_sec < b->u.sands.tv_sec)
@@ -1050,21 +1060,29 @@ struct thread *_thread_add_event(const struct xref_threadsched *xref,
* - POLLIN
* - POLLOUT
*/
-static void thread_cancel_rw(struct thread_master *master, int fd, short state)
+static void thread_cancel_rw(struct thread_master *master, int fd, short state,
+ int idx_hint)
{
bool found = false;
- /* Cancel POLLHUP too just in case some bozo set it */
- state |= POLLHUP;
-
/* find the index of corresponding pollfd */
nfds_t i;
- for (i = 0; i < master->handler.pfdcount; i++)
- if (master->handler.pfds[i].fd == fd) {
- found = true;
- break;
- }
+ /* Cancel POLLHUP too just in case some bozo set it */
+ state |= POLLHUP;
+
+ /* Some callers know the index of the pfd already */
+ if (idx_hint >= 0) {
+ i = idx_hint;
+ found = true;
+ } else {
+ /* Have to look for the fd in the pfd array */
+ for (i = 0; i < master->handler.pfdcount; i++)
+ if (master->handler.pfds[i].fd == fd) {
+ found = true;
+ break;
+ }
+ }
if (!found) {
zlog_debug(
@@ -1104,6 +1122,95 @@ static void thread_cancel_rw(struct thread_master *master, int fd, short state)
}
}
+/*
+ * Process task cancellation given a task argument: iterate through the
+ * various lists of tasks, looking for any that match the argument.
+ */
+static void cancel_arg_helper(struct thread_master *master,
+ const struct cancel_req *cr)
+{
+ struct thread *t;
+ nfds_t i;
+ int fd;
+ struct pollfd *pfd;
+
+ /* We're only processing arg-based cancellations here. */
+ if (cr->eventobj == NULL)
+ return;
+
+ /* First process the ready lists. */
+ frr_each_safe(thread_list, &master->event, t) {
+ if (t->arg != cr->eventobj)
+ continue;
+ thread_list_del(&master->event, t);
+ if (t->ref)
+ *t->ref = NULL;
+ thread_add_unuse(master, t);
+ }
+
+ frr_each_safe(thread_list, &master->ready, t) {
+ if (t->arg != cr->eventobj)
+ continue;
+ thread_list_del(&master->ready, t);
+ if (t->ref)
+ *t->ref = NULL;
+ thread_add_unuse(master, t);
+ }
+
+ /* If requested, stop here and ignore io and timers */
+ if (CHECK_FLAG(cr->flags, THREAD_CANCEL_FLAG_READY))
+ return;
+
+ /* Check the io tasks */
+ for (i = 0; i < master->handler.pfdcount;) {
+ pfd = master->handler.pfds + i;
+
+ if (pfd->events & POLLIN)
+ t = master->read[pfd->fd];
+ else
+ t = master->write[pfd->fd];
+
+ if (t && t->arg == cr->eventobj) {
+ fd = pfd->fd;
+
+ /* Found a match to cancel: clean up fd arrays */
+ thread_cancel_rw(master, pfd->fd, pfd->events, i);
+
+ /* Clean up thread arrays */
+ master->read[fd] = NULL;
+ master->write[fd] = NULL;
+
+ /* Clear caller's ref */
+ if (t->ref)
+ *t->ref = NULL;
+
+ thread_add_unuse(master, t);
+
+ /* Don't increment 'i' since the cancellation will have
+ * removed the entry from the pfd array
+ */
+ } else
+ i++;
+ }
+
+ /* Check the timer tasks */
+ t = thread_timer_list_first(&master->timer);
+ while (t) {
+ struct thread *t_next;
+
+ t_next = thread_timer_list_next(&master->timer, t);
+
+ if (t->arg == cr->eventobj) {
+ thread_timer_list_del(&master->timer, t);
+ if (t->ref)
+ *t->ref = NULL;
+ thread_add_unuse(master, t);
+ }
+
+ t = t_next;
+ }
+}
+
/**
* Process cancellation requests.
*
@@ -1122,31 +1229,12 @@ static void do_thread_cancel(struct thread_master *master)
struct listnode *ln;
for (ALL_LIST_ELEMENTS_RO(master->cancel_req, ln, cr)) {
/*
- * If this is an event object cancellation, linear search
- * through event list deleting any events which have the
- * specified argument. We also need to check every thread
- * in the ready queue.
+ * If this is an event object cancellation, search
+ * through task lists deleting any tasks which have the
+ * specified argument - use this handy helper function.
*/
if (cr->eventobj) {
- struct thread *t;
-
- frr_each_safe(thread_list, &master->event, t) {
- if (t->arg != cr->eventobj)
- continue;
- thread_list_del(&master->event, t);
- if (t->ref)
- *t->ref = NULL;
- thread_add_unuse(master, t);
- }
-
- frr_each_safe(thread_list, &master->ready, t) {
- if (t->arg != cr->eventobj)
- continue;
- thread_list_del(&master->ready, t);
- if (t->ref)
- *t->ref = NULL;
- thread_add_unuse(master, t);
- }
+ cancel_arg_helper(master, cr);
continue;
}
@@ -1164,11 +1252,11 @@ static void do_thread_cancel(struct thread_master *master)
/* Determine the appropriate queue to cancel the thread from */
switch (thread->type) {
case THREAD_READ:
- thread_cancel_rw(master, thread->u.fd, POLLIN);
+ thread_cancel_rw(master, thread->u.fd, POLLIN, -1);
thread_array = master->read;
break;
case THREAD_WRITE:
- thread_cancel_rw(master, thread->u.fd, POLLOUT);
+ thread_cancel_rw(master, thread->u.fd, POLLOUT, -1);
thread_array = master->write;
break;
case THREAD_TIMER:
@@ -1206,6 +1294,30 @@ static void do_thread_cancel(struct thread_master *master)
pthread_cond_broadcast(&master->cancel_cond);
}
+/*
+ * Helper function used for multiple flavors of arg-based cancellation.
+ */
+static void cancel_event_helper(struct thread_master *m, void *arg, int flags)
+{
+ struct cancel_req *cr;
+
+ assert(m->owner == pthread_self());
+
+ /* Only worth anything if caller supplies an arg. */
+ if (arg == NULL)
+ return;
+
+ cr = XCALLOC(MTYPE_TMP, sizeof(struct cancel_req));
+
+ cr->flags = flags;
+
+ frr_with_mutex(&m->mtx) {
+ cr->eventobj = arg;
+ listnode_add(m->cancel_req, cr);
+ do_thread_cancel(m);
+ }
+}
+
/**
* Cancel any events which have the specified argument.
*
@@ -1216,15 +1328,22 @@ static void do_thread_cancel(struct thread_master *master)
*/
void thread_cancel_event(struct thread_master *master, void *arg)
{
- assert(master->owner == pthread_self());
+ cancel_event_helper(master, arg, 0);
+}
- frr_with_mutex(&master->mtx) {
- struct cancel_req *cr =
- XCALLOC(MTYPE_TMP, sizeof(struct cancel_req));
- cr->eventobj = arg;
- listnode_add(master->cancel_req, cr);
- do_thread_cancel(master);
- }
+/*
+ * Cancel ready tasks with an arg matching 'arg'
+ *
+ * MT-Unsafe
+ *
+ * @param m the thread_master to cancel from
+ * @param arg the argument passed when creating the event
+ */
+void thread_cancel_event_ready(struct thread_master *m, void *arg)
+{
+
+ /* Only cancel ready/event tasks */
+ cancel_event_helper(m, arg, THREAD_CANCEL_FLAG_READY);
}
/**
@@ -1515,9 +1634,13 @@ struct thread *thread_fetch(struct thread_master *m, struct thread *fetch)
if (fetch->ref)
*fetch->ref = NULL;
pthread_mutex_unlock(&m->mtx);
+ if (!m->ready_run_loop)
+ GETRUSAGE(&m->last_getrusage);
+ m->ready_run_loop = true;
break;
}
+ m->ready_run_loop = false;
/* otherwise, tick through scheduling sequence */
/*
@@ -1676,7 +1799,11 @@ void thread_call(struct thread *thread)
#endif
RUSAGE_T before, after;
- GETRUSAGE(&before);
+ if (thread->master->ready_run_loop)
+ before = thread->master->last_getrusage;
+ else
+ GETRUSAGE(&before);
+
thread->real = before.real;
frrtrace(9, frr_libfrr, thread_call, thread->master,
@@ -1689,6 +1816,7 @@ void thread_call(struct thread *thread)
pthread_setspecific(thread_current, NULL);
GETRUSAGE(&after);
+ thread->master->last_getrusage = after;
#ifndef EXCLUDE_CPU_TIME
realtime = thread_consumed_time(&after, &before, &helper);
diff --git a/lib/thread.h b/lib/thread.h
index 6b510fc4c9..cdef531ad4 100644
--- a/lib/thread.h
+++ b/lib/thread.h
@@ -46,8 +46,8 @@ PREDECL_HEAP(thread_timer_list)
struct fd_handler {
/* number of pfd that fit in the allocated space of pfds. This is a
- * constant
- * and is the same for both pfds and copy. */
+ * constant and is the same for both pfds and copy.
+ */
nfds_t pfdsize;
/* file descriptors to monitor for i/o */
@@ -61,12 +61,6 @@ struct fd_handler {
nfds_t copycount;
};
-struct cancel_req {
- struct thread *thread;
- void *eventobj;
- struct thread **threadref;
-};
-
struct xref_threadsched {
struct xref xref;
@@ -96,6 +90,9 @@ struct thread_master {
bool handle_signals;
pthread_mutex_t mtx;
pthread_t owner;
+
+ bool ready_run_loop;
+ RUSAGE_T last_getrusage;
};
/* Thread itself. */
@@ -188,7 +185,7 @@ struct cpu_thread_history {
#define thread_add_timer(m,f,a,v,t) _xref_t_a(timer, TIMER, m,f,a,v,t)
#define thread_add_timer_msec(m,f,a,v,t) _xref_t_a(timer_msec, TIMER, m,f,a,v,t)
#define thread_add_timer_tv(m,f,a,v,t) _xref_t_a(timer_tv, TIMER, m,f,a,v,t)
-#define thread_add_event(m,f,a,v,t) _xref_t_a(event, TIMER, m,f,a,v,t)
+#define thread_add_event(m,f,a,v,t) _xref_t_a(event, EVENT, m,f,a,v,t)
#define thread_execute(m,f,a,v) \
({ \
@@ -237,7 +234,10 @@ extern void _thread_execute(const struct xref_threadsched *xref,
extern void thread_cancel(struct thread **event);
extern void thread_cancel_async(struct thread_master *, struct thread **,
void *);
-extern void thread_cancel_event(struct thread_master *, void *);
+/* Cancel ready tasks with an arg matching 'arg' */
+extern void thread_cancel_event_ready(struct thread_master *m, void *arg);
+/* Cancel all tasks with an arg matching 'arg', including timers and io */
+extern void thread_cancel_event(struct thread_master *m, void *arg);
extern struct thread *thread_fetch(struct thread_master *, struct thread *);
extern void thread_call(struct thread *);
extern unsigned long thread_timer_remain_second(struct thread *);
diff --git a/lib/vrf.c b/lib/vrf.c
index 136938783f..0a91f4bc86 100644
--- a/lib/vrf.c
+++ b/lib/vrf.c
@@ -686,8 +686,8 @@ int vrf_handler_create(struct vty *vty, const char *vrfname,
}
if (vty) {
- snprintf(xpath_list, sizeof(xpath_list),
- "/frr-vrf:lib/vrf[name='%s']", vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH,
+ vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_CREATE, NULL);
ret = nb_cli_apply_changes(vty, xpath_list);
@@ -821,8 +821,7 @@ DEFUN_YANG (no_vrf,
return CMD_WARNING_CONFIG_FAILED;
}
- snprintf(xpath_list, sizeof(xpath_list), "/frr-vrf:lib/vrf[name='%s']",
- vrfname);
+ snprintf(xpath_list, sizeof(xpath_list), FRR_VRF_KEY_XPATH, vrfname);
nb_cli_enqueue_change(vty, xpath_list, NB_OP_DESTROY, NULL);
return nb_cli_apply_changes(vty, xpath_list);
diff --git a/lib/vrf.h b/lib/vrf.h
index 32e6fb4289..333d68ce96 100644
--- a/lib/vrf.h
+++ b/lib/vrf.h
@@ -52,6 +52,9 @@ enum { IFLA_VRF_UNSPEC, IFLA_VRF_TABLE, __IFLA_VRF_MAX };
#define VRF_ALL_CMD_HELP_STR "Specify the VRF\nAll VRFs\n"
#define VRF_FULL_CMD_HELP_STR "Specify the VRF\nThe VRF name\nAll VRFs\n"
+#define FRR_VRF_XPATH "/frr-vrf:lib/vrf"
+#define FRR_VRF_KEY_XPATH "/frr-vrf:lib/vrf[name='%s']"
+
/*
* Pass some OS specific data up through
* to the daemons
diff --git a/lib/vty.c b/lib/vty.c
index 65f8d78a96..4cefb5e80c 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -1783,7 +1783,6 @@ static int vty_accept(struct thread *thread)
int accept_sock;
struct prefix p;
struct access_list *acl = NULL;
- char buf[SU_ADDRSTRLEN];
accept_sock = THREAD_FD(thread);
@@ -1804,8 +1803,8 @@ static int vty_accept(struct thread *thread)
if (!sockunion2hostprefix(&su, &p)) {
close(vty_sock);
- zlog_info("Vty unable to convert prefix from sockunion %s",
- sockunion2str(&su, buf, SU_ADDRSTRLEN));
+ zlog_info("Vty unable to convert prefix from sockunion %pSU",
+ &su);
return -1;
}
@@ -1813,8 +1812,7 @@ static int vty_accept(struct thread *thread)
if (p.family == AF_INET && vty_accesslist_name) {
if ((acl = access_list_lookup(AFI_IP, vty_accesslist_name))
&& (access_list_apply(acl, &p) == FILTER_DENY)) {
- zlog_info("Vty connection refused from %s",
- sockunion2str(&su, buf, SU_ADDRSTRLEN));
+ zlog_info("Vty connection refused from %pSU", &su);
close(vty_sock);
/* continue accepting connections */
@@ -1829,8 +1827,7 @@ static int vty_accept(struct thread *thread)
if ((acl = access_list_lookup(AFI_IP6,
vty_ipv6_accesslist_name))
&& (access_list_apply(acl, &p) == FILTER_DENY)) {
- zlog_info("Vty connection refused from %s",
- sockunion2str(&su, buf, SU_ADDRSTRLEN));
+ zlog_info("Vty connection refused from %pSU", &su);
close(vty_sock);
/* continue accepting connections */
@@ -1847,8 +1844,7 @@ static int vty_accept(struct thread *thread)
zlog_info("can't set sockopt to vty_sock : %s",
safe_strerror(errno));
- zlog_info("Vty connection from %s",
- sockunion2str(&su, buf, SU_ADDRSTRLEN));
+ zlog_info("Vty connection from %pSU", &su);
vty_create(vty_sock, &su);
@@ -2325,7 +2321,7 @@ static void vty_read_file(struct nb_config *config, FILE *confp)
nl = strchr(ve->error_buf, '\n');
if (nl)
*nl = '\0';
- flog_err(EC_LIB_VTY, "ERROR: %s on config line %u: %s",
+ flog_err(EC_LIB_VTY, "%s on config line %u: %s",
message, ve->line_num, ve->error_buf);
}
}
@@ -2427,9 +2423,9 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
__func__, errno);
goto tmp_free_and_out;
}
- tmp = XMALLOC(MTYPE_TMP,
- strlen(cwd) + strlen(config_file) + 2);
- sprintf(tmp, "%s/%s", cwd, config_file);
+ size_t tmp_len = strlen(cwd) + strlen(config_file) + 2;
+ tmp = XMALLOC(MTYPE_TMP, tmp_len);
+ snprintf(tmp, tmp_len, "%s/%s", cwd, config_file);
fullpath = tmp;
} else
fullpath = config_file;
@@ -2444,9 +2440,8 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
confp = vty_use_backup_config(fullpath);
if (confp)
- flog_warn(
- EC_LIB_BACKUP_CONFIG,
- "WARNING: using backup configuration file!");
+ flog_warn(EC_LIB_BACKUP_CONFIG,
+ "using backup configuration file!");
else {
flog_err(
EC_LIB_VTY,
@@ -2495,9 +2490,8 @@ bool vty_read_config(struct nb_config *config, const char *config_file,
confp = vty_use_backup_config(config_default_dir);
if (confp) {
- flog_warn(
- EC_LIB_BACKUP_CONFIG,
- "WARNING: using backup configuration file!");
+ flog_warn(EC_LIB_BACKUP_CONFIG,
+ "using backup configuration file!");
fullpath = config_default_dir;
} else {
flog_err(EC_LIB_VTY,
@@ -2625,7 +2619,7 @@ int vty_config_node_exit(struct vty *vty)
/* Check if there's a pending confirmed commit. */
if (vty->t_confirmed_commit_timeout) {
vty_out(vty,
- "WARNING: exiting with a pending confirmed commit. Rolling back to previous configuration.\n\n");
+ "exiting with a pending confirmed commit. Rolling back to previous configuration.\n\n");
nb_cli_confirmed_commit_rollback(vty);
nb_cli_confirmed_commit_clean(vty);
}
diff --git a/lib/zclient.c b/lib/zclient.c
index 20c285cf7f..c5e844933c 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -1551,15 +1551,16 @@ bool zapi_ipset_notify_decode(struct stream *s, uint32_t *unique,
enum zapi_ipset_notify_owner *note)
{
uint32_t uni;
+ uint16_t notew;
- STREAM_GET(note, s, sizeof(*note));
+ STREAM_GETW(s, notew);
STREAM_GETL(s, uni);
if (zclient_debug)
zlog_debug("%s: %u", __func__, uni);
*unique = uni;
-
+ *note = (enum zapi_ipset_notify_owner)notew;
return true;
stream_failure:
@@ -1571,8 +1572,9 @@ bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
enum zapi_ipset_entry_notify_owner *note)
{
uint32_t uni;
+ uint16_t notew;
- STREAM_GET(note, s, sizeof(*note));
+ STREAM_GETW(s, notew);
STREAM_GETL(s, uni);
@@ -1581,6 +1583,7 @@ bool zapi_ipset_entry_notify_decode(struct stream *s, uint32_t *unique,
if (zclient_debug)
zlog_debug("%s: %u", __func__, uni);
*unique = uni;
+ *note = (enum zapi_ipset_entry_notify_owner)notew;
return true;
@@ -1593,14 +1596,16 @@ bool zapi_iptable_notify_decode(struct stream *s,
enum zapi_iptable_notify_owner *note)
{
uint32_t uni;
+ uint16_t notew;
- STREAM_GET(note, s, sizeof(*note));
+ STREAM_GETW(s, notew);
STREAM_GETL(s, uni);
if (zclient_debug)
zlog_debug("%s: %u", __func__, uni);
*unique = uni;
+ *note = (enum zapi_iptable_notify_owner)notew;
return true;
@@ -2335,7 +2340,7 @@ struct connected *zebra_interface_address_read(int type, struct stream *s,
* "peer" */
flog_err(
EC_LIB_ZAPI_ENCODE,
- "warning: interface %s address %pFX with peer flag set, but no peer address!",
+ "interface %s address %pFX with peer flag set, but no peer address!",
ifp->name, ifc->address);
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
}
diff --git a/lib/zclient.h b/lib/zclient.h
index cf52ea91a0..43197534a8 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -713,21 +713,21 @@ enum ipset_type {
};
enum zapi_ipset_notify_owner {
- ZAPI_IPSET_FAIL_INSTALL,
+ ZAPI_IPSET_FAIL_INSTALL = 0,
ZAPI_IPSET_INSTALLED,
ZAPI_IPSET_REMOVED,
ZAPI_IPSET_FAIL_REMOVE,
};
enum zapi_ipset_entry_notify_owner {
- ZAPI_IPSET_ENTRY_FAIL_INSTALL,
+ ZAPI_IPSET_ENTRY_FAIL_INSTALL = 0,
ZAPI_IPSET_ENTRY_INSTALLED,
ZAPI_IPSET_ENTRY_REMOVED,
ZAPI_IPSET_ENTRY_FAIL_REMOVE,
};
enum zapi_iptable_notify_owner {
- ZAPI_IPTABLE_FAIL_INSTALL,
+ ZAPI_IPTABLE_FAIL_INSTALL = 0,
ZAPI_IPTABLE_INSTALLED,
ZAPI_IPTABLE_REMOVED,
ZAPI_IPTABLE_FAIL_REMOVE,
diff --git a/lib/zlog.h b/lib/zlog.h
index bdf59fa68e..4fdb47bb95 100644
--- a/lib/zlog.h
+++ b/lib/zlog.h
@@ -44,6 +44,7 @@ struct xref_logmsg {
const char *fmtstring;
uint32_t priority;
uint32_t ec;
+ const char *args;
};
struct xrefdata_logmsg {
@@ -84,18 +85,23 @@ static inline void zlog_ref(const struct xref_logmsg *xref,
va_end(ap);
}
-#define _zlog_ref(prio, msg, ...) do { \
+#define _zlog_ref(prio, msg, ...) \
+ do { \
static struct xrefdata _xrefdata = { \
+ .xref = NULL, \
+ .uid = {}, \
.hashstr = (msg), \
- .hashu32 = { (prio), 0 }, \
+ .hashu32 = {(prio), 0}, \
}; \
- static const struct xref_logmsg _xref __attribute__((used)) = {\
+ static const struct xref_logmsg _xref __attribute__( \
+ (used)) = { \
.xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata, __func__), \
.fmtstring = (msg), \
.priority = (prio), \
+ .args = (#__VA_ARGS__), \
}; \
XREF_LINK(_xref.xref); \
- zlog_ref(&_xref, (msg), ## __VA_ARGS__); \
+ zlog_ref(&_xref, (msg), ##__VA_ARGS__); \
} while (0)
#define zlog_err(...) _zlog_ref(LOG_ERR, __VA_ARGS__)
@@ -104,19 +110,24 @@ static inline void zlog_ref(const struct xref_logmsg *xref,
#define zlog_notice(...) _zlog_ref(LOG_NOTICE, __VA_ARGS__)
#define zlog_debug(...) _zlog_ref(LOG_DEBUG, __VA_ARGS__)
-#define _zlog_ecref(ec_, prio, msg, ...) do { \
+#define _zlog_ecref(ec_, prio, msg, ...) \
+ do { \
static struct xrefdata _xrefdata = { \
+ .xref = NULL, \
+ .uid = {}, \
.hashstr = (msg), \
- .hashu32 = { (prio), (ec_) }, \
+ .hashu32 = {(prio), (ec_)}, \
}; \
- static const struct xref_logmsg _xref __attribute__((used)) = {\
+ static const struct xref_logmsg _xref __attribute__( \
+ (used)) = { \
.xref = XREF_INIT(XREFT_LOGMSG, &_xrefdata, __func__), \
.fmtstring = (msg), \
.priority = (prio), \
.ec = (ec_), \
+ .args = (#__VA_ARGS__), \
}; \
XREF_LINK(_xref.xref); \
- zlog_ref(&_xref, "[EC %u] " msg, ec_, ## __VA_ARGS__); \
+ zlog_ref(&_xref, "[EC %u] " msg, ec_, ##__VA_ARGS__); \
} while (0)
#define flog_err(ferr_id, format, ...) \
diff --git a/nhrpd/netlink_arp.c b/nhrpd/netlink_arp.c
index 309f733526..dc4697cda0 100644
--- a/nhrpd/netlink_arp.c
+++ b/nhrpd/netlink_arp.c
@@ -67,7 +67,6 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb)
struct zbuf payload;
union sockunion addr, lladdr;
size_t len;
- char buf[4][SU_ADDRSTRLEN];
int state;
memset(&lladdr, 0, sizeof(lladdr));
@@ -99,27 +98,20 @@ static void netlink_neigh_msg(struct nlmsghdr *msg, struct zbuf *zb)
return;
debugf(NHRP_DEBUG_KERNEL,
- "Netlink: %s %s dev %s lladdr %s nud 0x%x cache used %u type %u",
+ "Netlink: %s %pSU dev %s lladdr %pSU nud 0x%x cache used %u type %u",
(msg->nlmsg_type == RTM_GETNEIGH)
? "who-has"
: (msg->nlmsg_type == RTM_NEWNEIGH) ? "new-neigh"
: "del-neigh",
- sockunion2str(&addr, buf[0], sizeof(buf[0])), ifp->name,
- sockunion2str(&lladdr, buf[1], sizeof(buf[1])), ndm->ndm_state,
- c->used, c->cur.type);
+ &addr, ifp->name, &lladdr, ndm->ndm_state, c->used, c->cur.type);
if (msg->nlmsg_type == RTM_GETNEIGH) {
if (c->cur.type >= NHRP_CACHE_CACHED) {
nhrp_cache_set_used(c, 1);
debugf(NHRP_DEBUG_KERNEL,
- "Netlink: update binding for %s dev %s from c %s peer.vc.nbma %s to lladdr %s",
- sockunion2str(&addr, buf[0], sizeof(buf[0])),
- ifp->name,
- sockunion2str(&c->cur.remote_nbma_natoa, buf[1],
- sizeof(buf[1])),
- sockunion2str(&c->cur.peer->vc->remote.nbma,
- buf[2], sizeof(buf[2])),
- sockunion2str(&lladdr, buf[3], sizeof(buf[3])));
+ "Netlink: update binding for %pSU dev %s from c %pSU peer.vc.nbma %pSU to lladdr %pSU",
+ &addr, ifp->name, &c->cur.remote_nbma_natoa,
+ &c->cur.peer->vc->remote.nbma, &lladdr);
/* In case of shortcuts, nbma is given by lladdr, not
* vc->remote.nbma.
*/
diff --git a/nhrpd/nhrp_cache.c b/nhrpd/nhrp_cache.c
index 0b5a0427e6..cb298b1a09 100644
--- a/nhrpd/nhrp_cache.c
+++ b/nhrpd/nhrp_cache.c
@@ -220,7 +220,6 @@ static void nhrp_cache_update_route(struct nhrp_cache *c)
{
struct prefix pfx;
struct nhrp_peer *p = c->cur.peer;
- char buf[3][SU_ADDRSTRLEN];
struct nhrp_interface *nifp;
if (!sockunion2hostprefix(&c->remote_addr, &pfx))
@@ -233,26 +232,18 @@ static void nhrp_cache_update_route(struct nhrp_cache *c)
* nbma.
*/
debugf(NHRP_DEBUG_COMMON,
- "cache (remote_nbma_natoa set): Update binding for %s dev %s from (deleted) peer.vc.nbma %s to %s",
- sockunion2str(&c->remote_addr, buf[0],
- sizeof(buf[0])),
- p->ifp->name,
- sockunion2str(&p->vc->remote.nbma, buf[1],
- sizeof(buf[1])),
- sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
- sizeof(buf[2])));
+ "cache (remote_nbma_natoa set): Update binding for %pSU dev %s from (deleted) peer.vc.nbma %pSU to %pSU",
+ &c->remote_addr, p->ifp->name,
+ &p->vc->remote.nbma, &c->cur.remote_nbma_natoa);
netlink_update_binding(p->ifp, &c->remote_addr,
&c->cur.remote_nbma_natoa);
} else {
/* update binding to peer->vc->remote->nbma */
debugf(NHRP_DEBUG_COMMON,
- "cache (remote_nbma_natoa unspec): Update binding for %s dev %s from (deleted) to peer.vc.nbma %s",
- sockunion2str(&c->remote_addr, buf[0],
- sizeof(buf[0])),
- p->ifp->name,
- sockunion2str(&p->vc->remote.nbma, buf[1],
- sizeof(buf[1])));
+ "cache (remote_nbma_natoa unspec): Update binding for %pSU dev %s from (deleted) to peer.vc.nbma %pSU",
+ &c->remote_addr, p->ifp->name,
+ &p->vc->remote.nbma);
netlink_update_binding(p->ifp, &c->remote_addr,
&p->vc->remote.nbma);
@@ -353,9 +344,8 @@ static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg)
struct nhrp_cache *c = container_of(r, struct nhrp_cache, eventid);
char buf[3][SU_ADDRSTRLEN];
- debugf(NHRP_DEBUG_COMMON, "cache: %s %s: %s", c->ifp->name,
- sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])),
- (const char *)arg);
+ debugf(NHRP_DEBUG_COMMON, "cache: %s %pSU: %s", c->ifp->name,
+ &c->remote_addr, (const char *)arg);
nhrp_reqid_free(&nhrp_event_reqid, r);
@@ -377,16 +367,13 @@ static void nhrp_cache_authorize_binding(struct nhrp_reqid *r, void *arg)
if (sockunion_family(&c->cur.remote_nbma_natoa) != AF_UNSPEC) {
debugf(NHRP_DEBUG_COMMON,
- "cache: update binding for %s dev %s from (deleted) peer.vc.nbma %s to %s",
- sockunion2str(&c->remote_addr, buf[0],
- sizeof(buf[0])),
- c->ifp->name,
+ "cache: update binding for %pSU dev %s from (deleted) peer.vc.nbma %s to %pSU",
+ &c->remote_addr, c->ifp->name,
(c->cur.peer ? sockunion2str(
&c->cur.peer->vc->remote.nbma, buf[1],
sizeof(buf[1]))
: "(no peer)"),
- sockunion2str(&c->cur.remote_nbma_natoa, buf[2],
- sizeof(buf[2])));
+ &c->cur.remote_nbma_natoa);
if (c->cur.peer)
netlink_update_binding(
diff --git a/nhrpd/nhrp_event.c b/nhrpd/nhrp_event.c
index 40efeb5795..f784ef22d6 100644
--- a/nhrpd/nhrp_event.c
+++ b/nhrpd/nhrp_event.c
@@ -63,9 +63,9 @@ static void evmgr_recv_message(struct event_manager *evmgr, struct zbuf *zb)
buf[len] = 0;
debugf(NHRP_DEBUG_EVENT, "evmgr: msg: %s", buf);
- if (sscanf(buf, "eventid=%" SCNu32, &eventid) != 1)
+ if (sscanf(buf, "eventid=%" SCNu32, &eventid) == 1)
continue;
- if (sscanf(buf, "result=%63s", result) != 1)
+ if (sscanf(buf, "result=%63s", result) == 1)
continue;
}
debugf(NHRP_DEBUG_EVENT, "evmgr: received: eventid=%d result=%s",
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 269499cc59..f86dbe3d29 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -117,7 +117,6 @@ static void nhrp_interface_interface_notifier(struct notifier_block *n,
container_of(n, struct nhrp_interface, nbmanifp_notifier);
struct interface *nbmaifp = nifp->nbmaifp;
struct nhrp_interface *nbmanifp = nbmaifp->info;
- char buf[SU_ADDRSTRLEN];
switch (cmd) {
case NOTIFY_INTERFACE_CHANGED:
@@ -129,9 +128,8 @@ static void nhrp_interface_interface_notifier(struct notifier_block *n,
nhrp_interface_update(nifp->ifp);
notifier_call(&nifp->notifier_list,
NOTIFY_INTERFACE_NBMA_CHANGED);
- debugf(NHRP_DEBUG_IF, "%s: NBMA change: address %s",
- nifp->ifp->name,
- sockunion2str(&nifp->nbma, buf, sizeof(buf)));
+ debugf(NHRP_DEBUG_IF, "%s: NBMA change: address %pSU",
+ nifp->ifp->name, &nifp->nbma);
break;
}
}
diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c
index 540708f1ae..9ed03098ac 100644
--- a/nhrpd/nhrp_nhs.c
+++ b/nhrpd/nhrp_nhs.c
@@ -33,7 +33,6 @@ static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
struct nhrp_cache *c;
struct zbuf extpl;
union sockunion cie_nbma, cie_proto, *proto;
- char buf[64];
int ok = 0, holdtime;
unsigned short mtu = 0;
@@ -52,8 +51,8 @@ static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
proto = sockunion_family(&cie_proto) != AF_UNSPEC
? &cie_proto
: &p->src_proto;
- debugf(NHRP_DEBUG_COMMON, "NHS: CIE registration: %s: %d",
- sockunion2str(proto, buf, sizeof(buf)), cie->code);
+ debugf(NHRP_DEBUG_COMMON, "NHS: CIE registration: %pSU: %d",
+ proto, cie->code);
if (!((cie->code == NHRP_CODE_SUCCESS)
|| (cie->code == NHRP_CODE_ADMINISTRATIVELY_PROHIBITED
&& nhs->hub)))
@@ -76,10 +75,8 @@ static void nhrp_reg_reply(struct nhrp_reqid *reqid, void *arg)
&cie_proto)) {
nifp->nat_nbma = cie_nbma;
debugf(NHRP_DEBUG_IF,
- "%s: NAT detected, real NBMA address: %s",
- ifp->name,
- sockunion2str(&nifp->nbma, buf,
- sizeof(buf)));
+ "%s: NAT detected, real NBMA address: %pSU",
+ ifp->name, &nifp->nbma);
}
break;
}
@@ -130,16 +127,14 @@ static void nhrp_reg_peer_notify(struct notifier_block *n, unsigned long cmd)
{
struct nhrp_registration *r =
container_of(n, struct nhrp_registration, peer_notifier);
- char buf[SU_ADDRSTRLEN];
switch (cmd) {
case NOTIFY_PEER_UP:
case NOTIFY_PEER_DOWN:
case NOTIFY_PEER_IFCONFIG_CHANGED:
case NOTIFY_PEER_MTU_CHANGED:
- debugf(NHRP_DEBUG_COMMON, "NHS: Flush timer for %s",
- sockunion2str(&r->peer->vc->remote.nbma, buf,
- sizeof(buf)));
+ debugf(NHRP_DEBUG_COMMON, "NHS: Flush timer for %pSU",
+ &r->peer->vc->remote.nbma);
THREAD_OFF(r->t_register);
thread_add_timer_msec(master, nhrp_reg_send_req, r, 10,
&r->t_register);
@@ -163,9 +158,8 @@ static int nhrp_reg_send_req(struct thread *t)
r->t_register = NULL;
if (!nhrp_peer_check(r->peer, 2)) {
- debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %s",
- sockunion2str(&r->peer->vc->remote.nbma, buf1,
- sizeof(buf1)));
+ debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %pSU",
+ &r->peer->vc->remote.nbma);
thread_add_timer(master, nhrp_reg_send_req, r, 120,
&r->t_register);
return 0;
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index 9aaa9dec1e..5e9929adeb 100644
--- a/nhrpd/nhrp_peer.c
+++ b/nhrpd/nhrp_peer.c
@@ -38,16 +38,13 @@ static void nhrp_packet_debug(struct zbuf *zb, const char *dir);
static void nhrp_peer_check_delete(struct nhrp_peer *p)
{
- char buf[2][256];
struct nhrp_interface *nifp = p->ifp->info;
if (p->ref || notifier_active(&p->notifier_list))
return;
- debugf(NHRP_DEBUG_COMMON, "Deleting peer ref:%d remote:%s local:%s",
- p->ref,
- sockunion2str(&p->vc->remote.nbma, buf[0], sizeof(buf[0])),
- sockunion2str(&p->vc->local.nbma, buf[1], sizeof(buf[1])));
+ debugf(NHRP_DEBUG_COMMON, "Deleting peer ref:%d remote:%pSU local:%pSU",
+ p->ref, &p->vc->remote.nbma, &p->vc->local.nbma);
THREAD_OFF(p->t_fallback);
hash_release(nifp->peer_hash, p);
@@ -326,16 +323,13 @@ void nhrp_peer_notify_del(struct nhrp_peer *p, struct notifier_block *n)
void nhrp_peer_send(struct nhrp_peer *p, struct zbuf *zb)
{
- char buf[2][256];
-
nhrp_packet_debug(zb, "Send");
if (!p->online)
return;
- debugf(NHRP_DEBUG_KERNEL, "PACKET: Send %s -> %s",
- sockunion2str(&p->vc->local.nbma, buf[0], sizeof(buf[0])),
- sockunion2str(&p->vc->remote.nbma, buf[1], sizeof(buf[1])));
+ debugf(NHRP_DEBUG_KERNEL, "PACKET: Send %pSU -> %pSU",
+ &p->vc->local.nbma, &p->vc->remote.nbma);
os_sendmsg(zb->head, zbuf_used(zb), p->ifp->ifindex,
sockunion_get_addr(&p->vc->remote.nbma),
@@ -658,7 +652,6 @@ void nhrp_peer_send_indication(struct interface *ifp, uint16_t protocol_type,
struct nhrp_afi_data *if_ad;
struct nhrp_packet_header *hdr;
struct nhrp_peer *p;
- char buf[2][SU_ADDRSTRLEN];
if (!nifp->enabled)
return;
@@ -673,23 +666,20 @@ void nhrp_peer_send_indication(struct interface *ifp, uint16_t protocol_type,
if_ad = &nifp->afi[family2afi(sockunion_family(&dst))];
if (!(if_ad->flags & NHRP_IFF_REDIRECT)) {
debugf(NHRP_DEBUG_COMMON,
- "Send Traffic Indication to %s about packet to %s ignored",
- sockunion2str(&p->vc->remote.nbma, buf[0],
- sizeof(buf[0])),
- sockunion2str(&dst, buf[1], sizeof(buf[1])));
+ "Send Traffic Indication to %pSU about packet to %pSU ignored",
+ &p->vc->remote.nbma, &dst);
return;
}
debugf(NHRP_DEBUG_COMMON,
- "Send Traffic Indication to %s (online=%d) about packet to %s",
- sockunion2str(&p->vc->remote.nbma, buf[0], sizeof(buf[0])),
- p->online, sockunion2str(&dst, buf[1], sizeof(buf[1])));
+ "Send Traffic Indication to %pSU (online=%d) about packet to %pSU",
+ &p->vc->remote.nbma, p->online, &dst);
/* Create reply */
zb = zbuf_alloc(1500);
hdr = nhrp_packet_push(zb, NHRP_PACKET_TRAFFIC_INDICATION, &nifp->nbma,
&if_ad->addr, &dst);
- hdr->hop_count = 0;
+ hdr->hop_count = 1;
/* Payload is the packet causing indication */
zbuf_copy(zb, pkt, zbuf_used(pkt));
@@ -705,16 +695,14 @@ static void nhrp_handle_error_ind(struct nhrp_packet_parser *pp)
struct nhrp_packet_header *hdr;
struct nhrp_reqid *reqid;
union sockunion src_nbma, src_proto, dst_proto;
- char buf[2][SU_ADDRSTRLEN];
hdr = nhrp_packet_pull(&origmsg, &src_nbma, &src_proto, &dst_proto);
if (!hdr)
return;
debugf(NHRP_DEBUG_COMMON,
- "Error Indication from %s about packet to %s ignored",
- sockunion2str(&pp->src_proto, buf[0], sizeof(buf[0])),
- sockunion2str(&dst_proto, buf[1], sizeof(buf[1])));
+ "Error Indication from %pSU about packet to %pSU ignored",
+ &pp->src_proto, &dst_proto);
reqid = nhrp_reqid_lookup(&nhrp_packet_reqid, htonl(hdr->u.request_id));
if (reqid)
@@ -724,16 +712,14 @@ static void nhrp_handle_error_ind(struct nhrp_packet_parser *pp)
static void nhrp_handle_traffic_ind(struct nhrp_packet_parser *p)
{
union sockunion dst;
- char buf[2][SU_ADDRSTRLEN];
if (!parse_ether_packet(&p->payload, htons(p->hdr->protocol_type), NULL,
&dst))
return;
debugf(NHRP_DEBUG_COMMON,
- "Traffic Indication from %s about packet to %s: %s",
- sockunion2str(&p->src_proto, buf[0], sizeof(buf[0])),
- sockunion2str(&dst, buf[1], sizeof(buf[1])),
+ "Traffic Indication from %pSU about packet to %pSU: %s",
+ &p->src_proto, &dst,
(p->if_ad->flags & NHRP_IFF_SHORTCUT) ? "trying shortcut"
: "ignored");
@@ -929,7 +915,6 @@ struct nhrp_route_info {
void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
{
- char buf[2][SU_ADDRSTRLEN];
struct nhrp_packet_header *hdr;
struct nhrp_vc *vc = p->vc;
struct interface *ifp = p->ifp;
@@ -942,9 +927,8 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
unsigned paylen, extoff, extlen, realsize;
afi_t nbma_afi, proto_afi;
- debugf(NHRP_DEBUG_KERNEL, "PACKET: Recv %s -> %s",
- sockunion2str(&vc->remote.nbma, buf[0], sizeof(buf[0])),
- sockunion2str(&vc->local.nbma, buf[1], sizeof(buf[1])));
+ debugf(NHRP_DEBUG_KERNEL, "PACKET: Recv %pSU -> %pSU", &vc->remote.nbma,
+ &vc->local.nbma);
if (!p->online) {
info = "peer not online";
@@ -975,10 +959,9 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
|| packet_types[hdr->type].type == PACKET_UNKNOWN
|| htons(hdr->packet_size) > realsize) {
zlog_info(
- "From %s: error: packet type %d, version %d, AFI %d, proto %x, size %d (real size %d)",
- sockunion2str(&vc->remote.nbma, buf[0], sizeof(buf[0])),
- (int)hdr->type, (int)hdr->version, (int)nbma_afi,
- (int)htons(hdr->protocol_type),
+ "From %pSU: error: packet type %d, version %d, AFI %d, proto %x, size %d (real size %d)",
+ &vc->remote.nbma, (int)hdr->type, (int)hdr->version,
+ (int)nbma_afi, (int)htons(hdr->protocol_type),
(int)htons(hdr->packet_size), (int)realsize);
goto drop;
}
@@ -1055,10 +1038,7 @@ void nhrp_peer_recv(struct nhrp_peer *p, struct zbuf *zb)
drop:
if (info) {
- zlog_info(
- "From %s: error: %s",
- sockunion2str(&vc->remote.nbma, buf[0], sizeof(buf[0])),
- info);
+ zlog_info("From %pSU: error: %s", &vc->remote.nbma, info);
}
if (peer)
nhrp_peer_unref(peer);
diff --git a/nhrpd/nhrp_route.c b/nhrpd/nhrp_route.c
index 334f468c18..737772dbc7 100644
--- a/nhrpd/nhrp_route.c
+++ b/nhrpd/nhrp_route.c
@@ -200,7 +200,6 @@ int nhrp_route_read(ZAPI_CALLBACK_ARGS)
struct zapi_nexthop *api_nh;
struct interface *ifp = NULL;
union sockunion nexthop_addr;
- char buf[PREFIX_STRLEN];
int added;
if (zapi_route_decode(zclient->ibuf, &api) < 0)
@@ -233,9 +232,8 @@ int nhrp_route_read(ZAPI_CALLBACK_ARGS)
}
added = (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD);
- debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %pFX via %s dev %s",
- added ? "add" : "del", &api.prefix,
- sockunion2str(&nexthop_addr, buf, sizeof(buf)),
+ debugf(NHRP_DEBUG_ROUTE, "if-route-%s: %pFX via %pSU dev %s",
+ added ? "add" : "del", &api.prefix, &nexthop_addr,
ifp ? ifp->name : "(none)");
nhrp_route_update_zebra(&api.prefix, &nexthop_addr, added ? ifp : NULL);
diff --git a/nhrpd/nhrp_shortcut.c b/nhrpd/nhrp_shortcut.c
index fbb883185a..ef3be82ca9 100644
--- a/nhrpd/nhrp_shortcut.c
+++ b/nhrpd/nhrp_shortcut.c
@@ -94,8 +94,6 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,
enum nhrp_cache_type type,
struct nhrp_cache *c, int holding_time)
{
- char buf[2][PREFIX_STRLEN];
-
s->type = type;
if (c != s->cache) {
if (s->cache) {
@@ -111,13 +109,9 @@ static void nhrp_shortcut_update_binding(struct nhrp_shortcut *s,
* change */
s->route_installed = 0;
debugf(NHRP_DEBUG_ROUTE,
- "Shortcut: forcing renewal of zebra announce on prefix change peer %s ht %u cur nbma %s dev %s",
- sockunion2str(&s->cache->remote_addr,
- buf[0], sizeof(buf[0])),
- holding_time,
- sockunion2str(
- &s->cache->cur.remote_nbma_natoa,
- buf[1], sizeof(buf[1])),
+ "Shortcut: forcing renewal of zebra announce on prefix change peer %pSU ht %u cur nbma %pSU dev %s",
+ &s->cache->remote_addr, holding_time,
+ &s->cache->cur.remote_nbma_natoa,
s->cache->ifp->name);
nhrp_shortcut_cache_notify(&s->cache_notifier,
NOTIFY_CACHE_UP);
@@ -255,9 +249,9 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,
prefix2sockunion(s->p, &cie_proto);
if (!sockunion_same(&cie_proto, &pp->dst_proto)) {
debugf(NHRP_DEBUG_COMMON,
- "Shortcut: Warning dst_proto altered from %s to %s",
- sockunion2str(&cie_proto, buf[0], sizeof(buf[0])),
- sockunion2str(&pp->dst_proto, buf[1], sizeof(buf[1])));
+ "Shortcut: Warning dst_proto altered from %pSU to %pSU",
+ &cie_proto, &pp->dst_proto);
+ ;
}
/* One or more CIEs should be given as reply, we support only one */
@@ -287,11 +281,8 @@ static void nhrp_shortcut_recv_resolution_rep(struct nhrp_reqid *reqid,
}
debugf(NHRP_DEBUG_COMMON,
- "Shortcut: %pFX is at proto %s dst_proto %s cie-nbma %s nat-nbma %s cie-holdtime %d",
- &prefix, sockunion2str(proto, buf[0], sizeof(buf[0])),
- sockunion2str(&pp->dst_proto, buf[1], sizeof(buf[1])),
- sockunion2str(&cie_nbma, buf[2], sizeof(buf[2])),
- sockunion2str(&nat_nbma, buf[3], sizeof(buf[3])),
+ "Shortcut: %pFX is at proto %pSU dst_proto %pSU cie-nbma %pSU nat-nbma %pSU cie-holdtime %d",
+ &prefix, proto, &pp->dst_proto, &cie_nbma, &nat_nbma,
htons(cie->holding_time));
/* Update cache entry for the protocol to nbma binding */
diff --git a/nhrpd/nhrp_vc.c b/nhrpd/nhrp_vc.c
index 6567b231a9..d538163e90 100644
--- a/nhrpd/nhrp_vc.c
+++ b/nhrpd/nhrp_vc.c
@@ -100,7 +100,6 @@ static void nhrp_vc_ipsec_reset(struct nhrp_vc *vc)
int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
{
- char buf[2][SU_ADDRSTRLEN];
struct child_sa *sa = NULL, *lsa;
uint32_t child_hash = child_id % array_size(childlist_head);
int abort_migration = 0;
@@ -140,10 +139,8 @@ int nhrp_vc_ipsec_updown(uint32_t child_id, struct nhrp_vc *vc)
if (sa->vc && vc) {
/* Notify old VC of migration */
sa->vc->abort_migration = 0;
- debugf(NHRP_DEBUG_COMMON, "IPsec NBMA change of %s to %s",
- sockunion2str(&sa->vc->remote.nbma, buf[0],
- sizeof(buf[0])),
- sockunion2str(&vc->remote.nbma, buf[1], sizeof(buf[1])));
+ debugf(NHRP_DEBUG_COMMON, "IPsec NBMA change of %pSU to %pSU",
+ &sa->vc->remote.nbma, &vc->remote.nbma);
nhrp_vc_update(sa->vc, NOTIFY_VC_IPSEC_UPDATE_NBMA);
abort_migration = sa->vc->abort_migration;
}
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index abcdb40547..f6a246500b 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -1292,6 +1292,7 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
{
struct ospf6_inter_prefix_lsa *prefix_lsa;
struct in6_addr in6;
+ char tbuf[16];
if (lsa != NULL) {
prefix_lsa =
@@ -1301,8 +1302,9 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
if (buf) {
inet_ntop(AF_INET6, &in6, buf, buflen);
- sprintf(&buf[strlen(buf)], "/%d",
- prefix_lsa->prefix.prefix_length);
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix_lsa->prefix.prefix_length);
+ strlcat(buf, tbuf, buflen);
}
}
diff --git a/ospf6d/ospf6_area.c b/ospf6d/ospf6_area.c
index 778bcb9a45..cf33069c9f 100644
--- a/ospf6d/ospf6_area.c
+++ b/ospf6d/ospf6_area.c
@@ -44,6 +44,7 @@
#include "ospf6_abr.h"
#include "ospf6_asbr.h"
#include "ospf6d.h"
+#include "lib/json.h"
DEFINE_MTYPE_STATIC(OSPF6D, OSPF6_PLISTNAME, "Prefix list name")
@@ -141,11 +142,12 @@ static void ospf6_area_stub_update(struct ospf6_area *area)
if (IS_AREA_STUB(area)) {
if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
- zlog_debug("Stubbing out area for if %s", area->name);
+ zlog_debug("Stubbing out area for area %s", area->name);
OSPF6_OPT_CLEAR(area->options, OSPF6_OPT_E);
+ ospf6_asbr_remove_externals_from_area(area);
} else if (IS_AREA_ENABLED(area)) {
if (IS_OSPF6_DEBUG_ORIGINATE(ROUTER))
- zlog_debug("Normal area for if %s", area->name);
+ zlog_debug("Normal area for area %s", area->name);
OSPF6_OPT_SET(area->options, OSPF6_OPT_E);
ospf6_asbr_send_externals_to_area(area);
}
@@ -850,12 +852,13 @@ DEFUN (no_area_export_list,
DEFUN (show_ipv6_ospf6_spf_tree,
show_ipv6_ospf6_spf_tree_cmd,
- "show ipv6 ospf6 spf tree",
+ "show ipv6 ospf6 spf tree [json]",
SHOW_STR
IP6_STR
OSPF6_STR
"Shortest Path First calculation\n"
- "Show SPF tree\n")
+ "Show SPF tree\n"
+ JSON_STR)
{
struct listnode *node;
struct ospf6_area *oa;
@@ -863,20 +866,52 @@ DEFUN (show_ipv6_ospf6_spf_tree,
struct ospf6_route *route;
struct prefix prefix;
struct ospf6 *ospf6;
+ json_object *json = NULL;
+ json_object *json_area = NULL;
+ json_object *json_head = NULL;
+ bool uj = use_json(argc, argv);
ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
OSPF6_CMD_CHECK_RUNNING(ospf6);
+
+ if (uj)
+ json = json_object_new_object();
ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
+ if (uj) {
+ json_area = json_object_new_object();
+ json_head = json_object_new_object();
+ }
route = ospf6_route_lookup(&prefix, oa->spf_table);
if (route == NULL) {
- vty_out(vty, "LS entry for root not found in area %s\n",
- oa->name);
+ if (uj) {
+ json_object_string_add(
+ json, oa->name,
+ "LS entry for not not found");
+ json_object_free(json_head);
+ json_object_free(json_area);
+ } else
+ vty_out(vty,
+ "LS entry for root not found in area %s\n",
+ oa->name);
continue;
}
root = (struct ospf6_vertex *)route->route_option;
- ospf6_spf_display_subtree(vty, "", 0, root);
+ ospf6_spf_display_subtree(vty, "", 0, root, json_head, uj);
+
+ if (uj) {
+ json_object_object_add(json_area, root->name,
+ json_head);
+ json_object_object_add(json, oa->name, json_area);
+ }
+ }
+
+ if (uj) {
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(
+ json, JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
}
return CMD_SUCCESS;
@@ -924,7 +959,7 @@ DEFUN (show_ipv6_ospf6_area_spf_tree,
return CMD_SUCCESS;
}
root = (struct ospf6_vertex *)route->route_option;
- ospf6_spf_display_subtree(vty, "", 0, root);
+ ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
return CMD_SUCCESS;
}
@@ -985,7 +1020,7 @@ DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
return CMD_SUCCESS;
}
root = (struct ospf6_vertex *)route->route_option;
- ospf6_spf_display_subtree(vty, "", 0, root);
+ ospf6_spf_display_subtree(vty, "", 0, root, NULL, false);
ospf6_spf_table_finish(spf_table);
ospf6_route_table_delete(spf_table);
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index 3449f48267..beca6b9690 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -1099,6 +1099,27 @@ void ospf6_asbr_send_externals_to_area(struct ospf6_area *oa)
}
}
+/* When an area is stubified, remove all the external LSAs in the area */
+void ospf6_asbr_remove_externals_from_area(struct ospf6_area *oa)
+{
+ struct ospf6_lsa *lsa, *lsanext;
+ struct listnode *node, *nnode;
+ struct ospf6_area *area;
+ struct ospf6 *ospf6 = oa->ospf6;
+
+
+ /* skip if router is in other non-stub areas */
+ for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, area))
+ if (!IS_AREA_STUB(area))
+ return;
+
+ /* if router is only in a stub area then purge AS-External LSAs */
+ for (ALL_LSDB(oa->ospf6->lsdb, lsa, lsanext)) {
+ if (ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL)
+ ospf6_lsdb_remove(lsa, ospf6->lsdb);
+ }
+}
+
void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
@@ -1865,6 +1886,7 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
struct ospf6_as_external_lsa *external;
struct in6_addr in6;
int prefix_length = 0;
+ char tbuf[16];
if (lsa) {
external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
@@ -1885,9 +1907,11 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
}
if (buf) {
inet_ntop(AF_INET6, &in6, buf, buflen);
- if (prefix_length)
- sprintf(&buf[strlen(buf)], "/%d",
- prefix_length);
+ if (prefix_length) {
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix_length);
+ strlcat(buf, tbuf, buflen);
+ }
}
}
return (buf);
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index fd14610042..e4a4455a5c 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -95,6 +95,7 @@ extern void ospf6_asbr_init(void);
extern void ospf6_asbr_redistribute_reset(struct ospf6 *ospf6);
extern void ospf6_asbr_terminate(void);
extern void ospf6_asbr_send_externals_to_area(struct ospf6_area *);
+extern void ospf6_asbr_remove_externals_from_area(struct ospf6_area *oa);
extern int config_write_ospf6_debug_asbr(struct vty *vty);
extern void install_element_ospf6_debug_asbr(void);
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index 621cc36a0c..a5d9138743 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -1622,12 +1622,11 @@ DEFUN (ipv6_ospf6_cost,
return CMD_WARNING_CONFIG_FAILED;
}
+ SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
if (oi->cost == lcost)
return CMD_SUCCESS;
oi->cost = lcost;
- SET_FLAG(oi->flag, OSPF6_INTERFACE_NOAUTOCOST);
-
ospf6_interface_force_recalculate_cost(oi);
return CMD_SUCCESS;
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index 5394ba9786..adff76ec41 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -84,7 +84,7 @@ static char *ospf6_router_lsa_get_nbr_id(struct ospf6_lsa *lsa, char *buf,
sizeof(buf1));
inet_ntop(AF_INET, &lsdesc->neighbor_router_id,
buf2, sizeof(buf2));
- sprintf(buf, "%s/%s", buf2, buf1);
+ snprintf(buf, buflen, "%s/%s", buf2, buf1);
return buf;
}
@@ -684,11 +684,9 @@ static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
int prefixnum;
char buf[128], options[32];
struct ospf6_prefix *prefix;
- const char *p, *mc, *la, *nu;
struct in6_addr in6;
json_object *json_loop;
json_object *json_arr = NULL;
- char str[15];
char prefix_string[133];
link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa->header
@@ -720,26 +718,13 @@ static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
|| current + OSPF6_PREFIX_SIZE(prefix) > end)
break;
- p = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_P)
- ? "P"
- : "--");
- mc = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_MC)
- ? "MC"
- : "--");
- la = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_LA)
- ? "LA"
- : "--");
- nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU)
- ? "NU"
- : "--");
+ ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
+ sizeof(buf));
if (use_json) {
json_loop = json_object_new_object();
- snprintf(str, sizeof(str), "%s|%s|%s|%s", p, mc, la,
- nu);
- json_object_string_add(json_loop, "prefixOption", str);
+ json_object_string_add(json_loop, "prefixOption", buf);
} else
- vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p,
- mc, la, nu);
+ vty_out(vty, " Prefix Options: %s\n", buf);
memset(&in6, 0, sizeof(in6));
memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
@@ -866,6 +851,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
struct in6_addr in6;
int prefixnum, cnt = 0;
struct ospf6_prefix *prefix;
+ char tbuf[16];
if (lsa) {
intra_prefix_lsa =
@@ -898,8 +884,9 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
OSPF6_PREFIX_SPACE(
prefix->prefix_length));
inet_ntop(AF_INET6, &in6, buf, buflen);
- sprintf(&buf[strlen(buf)], "/%d",
- prefix->prefix_length);
+ snprintf(tbuf, sizeof(tbuf), "/%d",
+ prefix->prefix_length);
+ strlcat(buf, tbuf, buflen);
return (buf);
}
}
@@ -916,11 +903,9 @@ static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
char buf[128];
struct ospf6_prefix *prefix;
char id[16], adv_router[16];
- const char *p, *mc, *la, *nu;
struct in6_addr in6;
json_object *json_loop;
json_object *json_arr = NULL;
- char str[15];
char prefix_string[133];
intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
@@ -959,26 +944,13 @@ static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
|| current + OSPF6_PREFIX_SIZE(prefix) > end)
break;
- p = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_P)
- ? "P"
- : "--");
- mc = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_MC)
- ? "MC"
- : "--");
- la = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_LA)
- ? "LA"
- : "--");
- nu = (CHECK_FLAG(prefix->prefix_options, OSPF6_PREFIX_OPTION_NU)
- ? "NU"
- : "--");
+ ospf6_prefix_options_printbuf(prefix->prefix_options, buf,
+ sizeof(buf));
if (use_json) {
json_loop = json_object_new_object();
- snprintf(str, sizeof(str), "%s|%s|%s|%s", p, mc, la,
- nu);
- json_object_string_add(json_loop, "prefixOption", str);
+ json_object_string_add(json_loop, "prefixOption", buf);
} else
- vty_out(vty, " Prefix Options: %s|%s|%s|%s\n", p,
- mc, la, nu);
+ vty_out(vty, " Prefix Options: %s\n", buf);
memset(&in6, 0, sizeof(in6));
memcpy(&in6, OSPF6_PREFIX_BODY(prefix),
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index f1b04c9bec..e1c3b4038c 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -145,7 +145,7 @@ const char *ospf6_lstype_short_name(uint16_t type)
const struct ospf6_lsa_handler *handler;
handler = ospf6_get_lsa_handler(type);
- if (handler && handler != &unknown_handler)
+ if (handler)
return handler->lh_short_name;
snprintf(buf, sizeof(buf), "0x%04hx", ntohs(type));
@@ -420,9 +420,10 @@ void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
if (use_json)
json_obj = json_object_new_object();
- if ((type == OSPF6_LSTYPE_INTER_PREFIX)
- || (type == OSPF6_LSTYPE_INTER_ROUTER)
- || (type == OSPF6_LSTYPE_AS_EXTERNAL)) {
+ switch (type) {
+ case OSPF6_LSTYPE_INTER_PREFIX:
+ case OSPF6_LSTYPE_INTER_ROUTER:
+ case OSPF6_LSTYPE_AS_EXTERNAL:
if (use_json) {
json_object_string_add(
json_obj, "type",
@@ -447,7 +448,13 @@ void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
(unsigned long)ntohl(lsa->header->seqnum),
handler->lh_get_prefix_str(lsa, buf,
sizeof(buf), 0));
- } else if (type != OSPF6_LSTYPE_UNKNOWN) {
+ break;
+ case OSPF6_LSTYPE_ROUTER:
+ case OSPF6_LSTYPE_NETWORK:
+ case OSPF6_LSTYPE_GROUP_MEMBERSHIP:
+ case OSPF6_LSTYPE_TYPE_7:
+ case OSPF6_LSTYPE_LINK:
+ case OSPF6_LSTYPE_INTRA_PREFIX:
while (handler->lh_get_prefix_str(lsa, buf, sizeof(buf), cnt)
!= NULL) {
if (use_json) {
@@ -481,7 +488,8 @@ void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
}
if (use_json)
json_object_free(json_obj);
- } else {
+ break;
+ default:
if (use_json) {
json_object_string_add(
json_obj, "type",
@@ -500,6 +508,7 @@ void ospf6_lsa_show_summary(struct vty *vty, struct ospf6_lsa *lsa,
ospf6_lstype_short_name(lsa->header->type), id,
adv_router, ospf6_lsa_age_current(lsa),
(unsigned long)ntohl(lsa->header->seqnum));
+ break;
}
}
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index bd180a9f55..160f012d78 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -86,13 +86,9 @@ const uint16_t ospf6_lsa_minlen[OSPF6_LSTYPE_SIZE] = {
static void ospf6_header_print(struct ospf6_header *oh)
{
- char router_id[16], area_id[16];
- inet_ntop(AF_INET, &oh->router_id, router_id, sizeof(router_id));
- inet_ntop(AF_INET, &oh->area_id, area_id, sizeof(area_id));
-
- zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%s", oh->version,
- oh->type, ntohs(oh->length), router_id);
- zlog_debug(" Area-ID:%s Cksum:%hx Instance-ID:%d", area_id,
+ zlog_debug(" OSPFv%d Type:%d Len:%hu Router-ID:%pI4", oh->version,
+ oh->type, ntohs(oh->length), &oh->router_id);
+ zlog_debug(" Area-ID:%pI4 Cksum:%hx Instance-ID:%d", &oh->area_id,
ntohs(oh->checksum), oh->instance_id);
}
@@ -100,7 +96,6 @@ void ospf6_hello_print(struct ospf6_header *oh)
{
struct ospf6_hello *hello;
char options[16];
- char drouter[16], bdrouter[16], neighbor[16];
char *p;
ospf6_header_print(oh);
@@ -109,8 +104,6 @@ void ospf6_hello_print(struct ospf6_header *oh)
hello = (struct ospf6_hello *)((caddr_t)oh
+ sizeof(struct ospf6_header));
- inet_ntop(AF_INET, &hello->drouter, drouter, sizeof(drouter));
- inet_ntop(AF_INET, &hello->bdrouter, bdrouter, sizeof(bdrouter));
ospf6_options_printbuf(hello->options, options, sizeof(options));
zlog_debug(" I/F-Id:%ld Priority:%d Option:%s",
@@ -118,14 +111,12 @@ void ospf6_hello_print(struct ospf6_header *oh)
options);
zlog_debug(" HelloInterval:%hu DeadInterval:%hu",
ntohs(hello->hello_interval), ntohs(hello->dead_interval));
- zlog_debug(" DR:%s BDR:%s", drouter, bdrouter);
+ zlog_debug(" DR:%pI4 BDR:%pI4", &hello->drouter, &hello->bdrouter);
for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
- p += sizeof(uint32_t)) {
- inet_ntop(AF_INET, (void *)p, neighbor, sizeof(neighbor));
- zlog_debug(" Neighbor: %s", neighbor);
- }
+ p += sizeof(uint32_t))
+ zlog_debug(" Neighbor: %pI4", (in_addr_t *)p);
assert(p == OSPF6_MESSAGE_END(oh));
}
@@ -162,7 +153,6 @@ void ospf6_dbdesc_print(struct ospf6_header *oh)
void ospf6_lsreq_print(struct ospf6_header *oh)
{
- char id[16], adv_router[16];
char *p;
ospf6_header_print(oh);
@@ -172,11 +162,9 @@ void ospf6_lsreq_print(struct ospf6_header *oh)
p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh);
p += sizeof(struct ospf6_lsreq_entry)) {
struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *)p;
- inet_ntop(AF_INET, &e->adv_router, adv_router,
- sizeof(adv_router));
- inet_ntop(AF_INET, &e->id, id, sizeof(id));
- zlog_debug(" [%s Id:%s Adv:%s]", ospf6_lstype_name(e->type),
- id, adv_router);
+
+ zlog_debug(" [%s Id:%pI4 Adv:%pI4]",
+ ospf6_lstype_name(e->type), &e->id, &e->adv_router);
}
assert(p == OSPF6_MESSAGE_END(oh));
@@ -856,15 +844,11 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst,
/* Find database copy */
lsa = ospf6_lsdb_lookup(e->type, e->id, e->adv_router, lsdb);
if (lsa == NULL) {
- char id[16], adv_router[16];
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) {
- inet_ntop(AF_INET, &e->id, id, sizeof(id));
- inet_ntop(AF_INET, &e->adv_router, adv_router,
- sizeof(adv_router));
zlog_debug(
- "Can't find requested [%s Id:%s Adv:%s]",
- ospf6_lstype_name(e->type), id,
- adv_router);
+ "Can't find requested [%s Id:%pI4 Adv:%pI4]",
+ ospf6_lstype_name(e->type), &e->id,
+ &e->adv_router);
}
thread_add_event(master, bad_lsreq, on, 0, NULL);
return;
@@ -1321,7 +1305,6 @@ static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
struct ospf6_header *oh,
const unsigned bytesonwire)
{
- char buf[2][INET_ADDRSTRLEN];
if (MSG_OK != ospf6_packet_examin(oh, bytesonwire))
return MSG_NG;
@@ -1335,13 +1318,10 @@ static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
oi->interface->name);
else
zlog_warn(
- "VRF %s: I/F %s Area-ID mismatch (my %s, rcvd %s)",
+ "VRF %s: I/F %s Area-ID mismatch (my %pI4, rcvd %pI4)",
vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name,
- inet_ntop(AF_INET, &oi->area->area_id, buf[0],
- INET_ADDRSTRLEN),
- inet_ntop(AF_INET, &oh->area_id, buf[1],
- INET_ADDRSTRLEN));
+ oi->interface->name, &oi->area->area_id,
+ &oh->area_id);
return MSG_NG;
}
@@ -1356,11 +1336,9 @@ static int ospf6_rxpacket_examin(struct ospf6_interface *oi,
/* Router-ID check */
if (oh->router_id == oi->area->ospf6->router_id) {
- zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%s)",
+ zlog_warn("VRF %s: I/F %s Duplicate Router-ID (%pI4)",
vrf_id_to_name(oi->interface->vrf_id),
- oi->interface->name,
- inet_ntop(AF_INET, &oh->router_id, buf[0],
- INET_ADDRSTRLEN));
+ oi->interface->name, &oh->router_id);
return MSG_NG;
}
return MSG_OK;
@@ -1541,7 +1519,6 @@ int ospf6_receive(struct thread *thread)
{
int sockfd;
unsigned int len;
- char srcname[64], dstname[64];
struct in6_addr src, dst;
ifindex_t ifindex;
struct iovec iovector[2];
@@ -1598,13 +1575,11 @@ int ospf6_receive(struct thread *thread)
/* Log */
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) {
- inet_ntop(AF_INET6, &src, srcname, sizeof(srcname));
- inet_ntop(AF_INET6, &dst, dstname, sizeof(dstname));
zlog_debug("%s received on %s",
lookup_msg(ospf6_message_type_str, oh->type, NULL),
oi->interface->name);
- zlog_debug(" src: %s", srcname);
- zlog_debug(" dst: %s", dstname);
+ zlog_debug(" src: %pI6", &src);
+ zlog_debug(" dst: %pI6", &dst);
switch (oh->type) {
case OSPF6_MESSAGE_TYPE_HELLO:
@@ -1659,7 +1634,7 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
struct ospf6_interface *oi, struct ospf6_header *oh)
{
unsigned int len;
- char srcname[64], dstname[64];
+ char srcname[64];
struct iovec iovector[2];
/* initialize */
@@ -1680,7 +1655,6 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
/* Log */
if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)) {
- inet_ntop(AF_INET6, dst, dstname, sizeof(dstname));
if (src)
inet_ntop(AF_INET6, src, srcname, sizeof(srcname));
else
@@ -1689,7 +1663,7 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
lookup_msg(ospf6_message_type_str, oh->type, NULL),
oi->interface->name);
zlog_debug(" src: %s", srcname);
- zlog_debug(" dst: %s", dstname);
+ zlog_debug(" dst: %pI6", dst);
switch (oh->type) {
case OSPF6_MESSAGE_TYPE_HELLO:
@@ -1893,6 +1867,13 @@ int ospf6_dbdesc_send_newone(struct thread *thread)
so that ospf6_send_dbdesc () can send those LSAs */
size = sizeof(struct ospf6_lsa_header) + sizeof(struct ospf6_dbdesc);
for (ALL_LSDB(on->summary_list, lsa, lsanext)) {
+ /* if stub area then don't advertise AS-External LSAs */
+ if (IS_AREA_STUB(on->ospf6_if->area)
+ && ntohs(lsa->header->type) == OSPF6_LSTYPE_AS_EXTERNAL) {
+ ospf6_lsdb_remove(lsa, on->summary_list);
+ continue;
+ }
+
if (size + sizeof(struct ospf6_lsa_header)
> ospf6_packet_max(on->ospf6_if)) {
ospf6_lsdb_lsa_unlock(lsa);
diff --git a/ospf6d/ospf6_proto.c b/ospf6d/ospf6_proto.c
index 864974c9a4..e60d2c7e0e 100644
--- a/ospf6d/ospf6_proto.c
+++ b/ospf6d/ospf6_proto.c
@@ -60,7 +60,14 @@ void ospf6_prefix_apply_mask(struct ospf6_prefix *op)
void ospf6_prefix_options_printbuf(uint8_t prefix_options, char *buf, int size)
{
- snprintf(buf, size, "xxx");
+ const char *dn, *p, *mc, *la, *nu;
+
+ dn = (CHECK_FLAG(prefix_options, OSPF6_PREFIX_OPTION_DN) ? "DN" : "--");
+ p = (CHECK_FLAG(prefix_options, OSPF6_PREFIX_OPTION_P) ? "P" : "--");
+ mc = (CHECK_FLAG(prefix_options, OSPF6_PREFIX_OPTION_MC) ? "MC" : "--");
+ la = (CHECK_FLAG(prefix_options, OSPF6_PREFIX_OPTION_LA) ? "LA" : "--");
+ nu = (CHECK_FLAG(prefix_options, OSPF6_PREFIX_OPTION_NU) ? "NU" : "--");
+ snprintf(buf, size, "%s|%s|%s|%s|%s", dn, p, mc, la, nu);
}
void ospf6_capability_printbuf(char capability, char *buf, int size)
diff --git a/ospf6d/ospf6_proto.h b/ospf6d/ospf6_proto.h
index 3876a98c50..da6b270e01 100644
--- a/ospf6d/ospf6_proto.h
+++ b/ospf6d/ospf6_proto.h
@@ -69,6 +69,8 @@ struct ospf6_prefix {
#define OSPF6_PREFIX_OPTION_LA (1 << 1) /* Local Address */
#define OSPF6_PREFIX_OPTION_MC (1 << 2) /* MultiCast */
#define OSPF6_PREFIX_OPTION_P (1 << 3) /* Propagate (NSSA) */
+#define OSPF6_PREFIX_OPTION_DN \
+ (1 << 4) /* DN bit to prevent loops in VPN environment */
/* caddr_t OSPF6_PREFIX_BODY (struct ospf6_prefix *); */
#define OSPF6_PREFIX_BODY(x) ((caddr_t)(x) + sizeof(struct ospf6_prefix))
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index f94252991c..121e846843 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -649,14 +649,10 @@ static int ospf6_spf_calculation_thread(struct thread *t)
ospf6_spf_reason_string(ospf6->spf_reason, rbuf, sizeof(rbuf));
if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME))
- zlog_debug("SPF runtime: %lld sec %lld usec",
- (long long)runtime.tv_sec,
- (long long)runtime.tv_usec);
-
- zlog_info(
- "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, Reason: %s",
- areas_processed, (long long)runtime.tv_sec,
- (long long)runtime.tv_usec, rbuf);
+ zlog_debug(
+ "SPF processing: # Areas: %d, SPF runtime: %lld sec %lld usec, Reason: %s",
+ areas_processed, (long long)runtime.tv_sec,
+ (long long)runtime.tv_usec, rbuf);
ospf6->last_spf_reason = ospf6->spf_reason;
ospf6_reset_spf_reason(ospf6);
@@ -718,9 +714,7 @@ void ospf6_spf_schedule(struct ospf6 *ospf6, unsigned int reason)
}
if (IS_OSPF6_DEBUG_SPF(PROCESS) || IS_OSPF6_DEBUG_SPF(TIME))
- zlog_debug("SPF: calculation timer delay = %ld", delay);
-
- zlog_info("SPF: Scheduled in %ld msec", delay);
+ zlog_debug("SPF: Rescheduling in %ld msec", delay);
ospf6->t_spf_calc = NULL;
thread_add_timer_msec(master, ospf6_spf_calculation_thread, ospf6,
@@ -728,16 +722,24 @@ void ospf6_spf_schedule(struct ospf6 *ospf6, unsigned int reason)
}
void ospf6_spf_display_subtree(struct vty *vty, const char *prefix, int rest,
- struct ospf6_vertex *v)
+ struct ospf6_vertex *v, json_object *json_obj,
+ bool use_json)
{
struct listnode *node, *nnode;
struct ospf6_vertex *c;
char *next_prefix;
int len;
int restnum;
+ json_object *json_childs = NULL;
+ json_object *json_child = NULL;
- /* "prefix" is the space prefix of the display line */
- vty_out(vty, "%s+-%s [%d]\n", prefix, v->name, v->cost);
+ if (use_json) {
+ json_childs = json_object_new_object();
+ json_object_int_add(json_obj, "cost", v->cost);
+ } else {
+ /* "prefix" is the space prefix of the display line */
+ vty_out(vty, "%s+-%s [%d]\n", prefix, v->name, v->cost);
+ }
len = strlen(prefix) + 4;
next_prefix = (char *)malloc(len);
@@ -749,10 +751,27 @@ void ospf6_spf_display_subtree(struct vty *vty, const char *prefix, int rest,
restnum = listcount(v->child_list);
for (ALL_LIST_ELEMENTS(v->child_list, node, nnode, c)) {
- restnum--;
- ospf6_spf_display_subtree(vty, next_prefix, restnum, c);
- }
+ if (use_json)
+ json_child = json_object_new_object();
+ else
+ restnum--;
+
+ ospf6_spf_display_subtree(vty, next_prefix, restnum, c,
+ json_child, use_json);
+ if (use_json)
+ json_object_object_add(json_childs, c->name,
+ json_child);
+ }
+ if (use_json) {
+ json_object_boolean_add(json_obj, "isLeafNode",
+ !listcount(v->child_list));
+ if (listcount(v->child_list))
+ json_object_object_add(json_obj, "children",
+ json_childs);
+ else
+ json_object_free(json_childs);
+ }
free(next_prefix);
}
diff --git a/ospf6d/ospf6_spf.h b/ospf6d/ospf6_spf.h
index 253888d8ce..36e2b27912 100644
--- a/ospf6d/ospf6_spf.h
+++ b/ospf6d/ospf6_spf.h
@@ -23,6 +23,7 @@
#include "typesafe.h"
#include "ospf6_top.h"
+#include "lib/json.h"
/* Debug option */
extern unsigned char conf_debug_ospf6_spf;
@@ -147,7 +148,8 @@ extern void ospf6_spf_calculation(uint32_t router_id,
extern void ospf6_spf_schedule(struct ospf6 *ospf, unsigned int reason);
extern void ospf6_spf_display_subtree(struct vty *vty, const char *prefix,
- int rest, struct ospf6_vertex *v);
+ int rest, struct ospf6_vertex *v,
+ json_object *json_obj, bool use_json);
extern void ospf6_spf_config_write(struct vty *vty, struct ospf6 *ospf6);
extern int config_write_ospf6_debug_spf(struct vty *vty);
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 2b7072d34f..9b9453ce24 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -96,13 +96,9 @@ static int ospf6_router_id_update_zebra(ZAPI_CALLBACK_ARGS)
return 0;
o->router_id_zebra = router_id.u.prefix4;
- if (IS_OSPF6_DEBUG_ZEBRA(RECV)) {
- char buf[INET_ADDRSTRLEN];
-
- zlog_debug("%s: zebra router-id %s update", __func__,
- inet_ntop(AF_INET, &router_id.u.prefix4, buf,
- INET_ADDRSTRLEN));
- }
+ if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+ zlog_debug("%s: zebra router-id %pI4 update", __func__,
+ &router_id.u.prefix4);
ospf6_router_id_update(o);
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index b98852eeee..19829d4546 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -616,7 +616,7 @@ DEFUN (debug_ospf_packet,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -692,7 +692,7 @@ DEFUN (no_debug_ospf_packet,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -763,7 +763,7 @@ DEFUN (debug_ospf_ism,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[2]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -814,7 +814,7 @@ DEFUN (no_debug_ospf_ism,
if (inst) // user passed instance ID
{
- if (!ospf_lookup_instance(strtoul(argv[3]->arg, NULL, 10)))
+ if (inst != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -909,8 +909,8 @@ DEFUN (debug_ospf_instance_nsm,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
return debug_ospf_nsm_common(vty, 4, argc, argv);
}
@@ -981,7 +981,7 @@ DEFUN (no_debug_ospf_instance_nsm,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_nsm_common(vty, 5, argc, argv);
@@ -1062,7 +1062,7 @@ DEFUN (debug_ospf_instance_lsa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return debug_ospf_lsa_common(vty, 4, argc, argv);
@@ -1145,7 +1145,7 @@ DEFUN (no_debug_ospf_instance_lsa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_lsa_common(vty, 5, argc, argv);
@@ -1207,7 +1207,7 @@ DEFUN (debug_ospf_instance_zebra,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
return debug_ospf_zebra_common(vty, 4, argc, argv);
@@ -1271,8 +1271,8 @@ DEFUN (no_debug_ospf_instance_zebra,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
return no_debug_ospf_zebra_common(vty, 5, argc, argv);
}
@@ -1317,8 +1317,8 @@ DEFUN (debug_ospf_instance_event,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_ON(event, EVENT);
@@ -1339,8 +1339,8 @@ DEFUN (no_debug_ospf_instance_event,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_OFF(event, EVENT);
@@ -1387,8 +1387,8 @@ DEFUN (debug_ospf_instance_nssa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_ON(nssa, NSSA);
@@ -1409,8 +1409,8 @@ DEFUN (no_debug_ospf_instance_nssa,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if (!ospf_lookup_instance(instance))
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
if (vty->node == CONFIG_NODE)
CONF_DEBUG_OFF(nssa, NSSA);
@@ -1625,12 +1625,12 @@ DEFUN (no_debug_ospf,
return CMD_SUCCESS;
}
-static int show_debugging_ospf_common(struct vty *vty, struct ospf *ospf)
+static int show_debugging_ospf_common(struct vty *vty)
{
int i;
- if (ospf->instance)
- vty_out(vty, "\nOSPF Instance: %d\n\n", ospf->instance);
+ if (ospf_instance)
+ vty_out(vty, "\nOSPF Instance: %d\n\n", ospf_instance);
vty_out(vty, "OSPF debugging status:\n");
@@ -1742,13 +1742,7 @@ DEFUN_NOSH (show_debugging_ospf,
DEBUG_STR
OSPF_STR)
{
- struct ospf *ospf = NULL;
-
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (ospf == NULL)
- return CMD_SUCCESS;
-
- return show_debugging_ospf_common(vty, ospf);
+ return show_debugging_ospf_common(vty);
}
DEFUN_NOSH (show_debugging_ospf_instance,
@@ -1760,14 +1754,13 @@ DEFUN_NOSH (show_debugging_ospf_instance,
"Instance ID\n")
{
int idx_number = 3;
- struct ospf *ospf;
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- if ((ospf = ospf_lookup_instance(instance)) == NULL)
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
- return show_debugging_ospf_common(vty, ospf);
+ return show_debugging_ospf_common(vty);
}
static int config_write_debug(struct vty *vty);
@@ -1790,16 +1783,11 @@ static int config_write_debug(struct vty *vty)
"", " send", " recv", "",
" detail", " send detail", " recv detail", " detail"};
- struct ospf *ospf;
char str[16];
memset(str, 0, 16);
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
- if (ospf == NULL)
- return CMD_SUCCESS;
-
- if (ospf->instance)
- snprintf(str, sizeof(str), " %u", ospf->instance);
+ if (ospf_instance)
+ snprintf(str, sizeof(str), " %u", ospf_instance);
/* debug ospf ism (status|events|timers). */
if (IS_CONF_DEBUG_OSPF(ism, ISM) == OSPF_DEBUG_ISM)
diff --git a/ospfd/ospf_ext.c b/ospfd/ospf_ext.c
index 4fa61221a6..754e2bcbab 100644
--- a/ospfd/ospf_ext.c
+++ b/ospfd/ospf_ext.c
@@ -301,6 +301,8 @@ static void set_ext_prefix(struct ext_itf *exti, uint8_t route_type,
exti->prefix.af = 0;
exti->prefix.pref_length = p.prefixlen;
exti->prefix.address = p.prefix;
+
+ SET_FLAG(exti->flags, EXT_LPFLG_LSA_ACTIVE);
}
/* Extended Link TLV - RFC7684 section 3.1 */
@@ -766,7 +768,6 @@ static void ospf_ext_ism_change(struct ospf_interface *oi, int old_status)
if (OspfEXT.enabled) {
osr_debug("EXT (%s): Set Prefix SID to interface %s ",
__func__, oi->ifp->name);
- exti->flags = EXT_LPFLG_LSA_ACTIVE;
ospf_sr_update_local_prefix(oi->ifp, oi->address);
}
} else {
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 5f74984c66..caba03c1b5 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -537,11 +537,9 @@ static int ospf_flood_through_interface(struct ospf_interface *oi,
if (!CHECK_FLAG(onbr->options, OSPF_OPTION_O)) {
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
zlog_debug(
- "%s: Skipping neighbor %s via %s -- Not Opaque-capable.",
+ "%s: Skipping neighbor %s via %pI4 -- Not Opaque-capable.",
__func__, IF_NAME(oi),
- inet_ntop(AF_INET,
- &onbr->router_id, buf,
- sizeof(buf)));
+ &onbr->router_id);
continue;
}
}
@@ -557,11 +555,9 @@ static int ospf_flood_through_interface(struct ospf_interface *oi,
&onbr->router_id)) {
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
zlog_debug(
- "%s: Skipping neighbor %s via %s -- inbr == onbr.",
+ "%s: Skipping neighbor %s via %pI4 -- inbr == onbr.",
__func__, IF_NAME(oi),
- inet_ntop(AF_INET,
- &inbr->router_id, buf,
- sizeof(buf)));
+ &inbr->router_id);
continue;
}
} else {
@@ -573,11 +569,9 @@ static int ospf_flood_through_interface(struct ospf_interface *oi,
&onbr->router_id)) {
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
zlog_debug(
- "%s: Skipping neighbor %s via %s -- lsah->adv_router == onbr.",
+ "%s: Skipping neighbor %s via %pI4 -- lsah->adv_router == onbr.",
__func__, IF_NAME(oi),
- inet_ntop(AF_INET,
- &onbr->router_id, buf,
- sizeof(buf)));
+ &onbr->router_id);
continue;
}
}
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 6be5486b55..6a90dbff11 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -146,9 +146,6 @@ FRR_DAEMON_INFO(ospfd, OSPF, .vty_port = OSPF_VTY_PORT,
/* OSPFd main routine. */
int main(int argc, char **argv)
{
- unsigned short instance = 0;
- bool created = false;
-
#ifdef SUPPORT_OSPF_API
/* OSPF apiserver is disabled by default. */
ospf_apiserver_enable = 0;
@@ -169,8 +166,8 @@ int main(int argc, char **argv)
switch (opt) {
case 'n':
- ospfd_di.instance = instance = atoi(optarg);
- if (instance < 1)
+ ospfd_di.instance = ospf_instance = atoi(optarg);
+ if (ospf_instance < 1)
exit(0);
break;
case 0:
@@ -208,7 +205,7 @@ int main(int argc, char **argv)
/* OSPFd inits. */
ospf_if_init();
- ospf_zebra_init(master, instance);
+ ospf_zebra_init(master, ospf_instance);
/* OSPF vty inits. */
ospf_vty_init();
@@ -227,17 +224,6 @@ int main(int argc, char **argv)
/* OSPF errors init */
ospf_error_init();
- /*
- * Need to initialize the default ospf structure, so the interface mode
- * commands can be duly processed if they are received before 'router
- * ospf', when ospfd is restarted
- */
- if (instance && !ospf_get_instance(instance, &created)) {
- flog_err(EC_OSPF_INIT_FAIL, "OSPF instance init failed: %s",
- strerror(errno));
- exit(1);
- }
-
frr_config_fork();
frr_run(master);
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 343e406f28..0fd4803c79 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -1881,20 +1881,10 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
struct ospf_lsa *ls_ret, *current;
int ret = 1;
- if (IS_DEBUG_OSPF_NSSA) {
- char buf1[INET_ADDRSTRLEN];
- char buf2[INET_ADDRSTRLEN];
- char buf3[INET_ADDRSTRLEN];
-
- zlog_debug("LSA Type-%d from %s, ID: %s, ADV: %s",
- lsa->data->type,
- inet_ntop(AF_INET, &ospfh->router_id, buf1,
- INET_ADDRSTRLEN),
- inet_ntop(AF_INET, &lsa->data->id, buf2,
- INET_ADDRSTRLEN),
- inet_ntop(AF_INET, &lsa->data->adv_router,
- buf3, INET_ADDRSTRLEN));
- }
+ if (IS_DEBUG_OSPF_NSSA)
+ zlog_debug("LSA Type-%d from %pI4, ID: %pI4, ADV: %pI4",
+ lsa->data->type, &ospfh->router_id,
+ &lsa->data->id, &lsa->data->adv_router);
listnode_delete(lsas,
lsa); /* We don't need it in list anymore */
@@ -1940,19 +1930,11 @@ static void ospf_ls_upd(struct ospf *ospf, struct ip *iph,
if (lsa->data->type == OSPF_ROUTER_LSA)
if (!IPV4_ADDR_SAME(&lsa->data->id,
&lsa->data->adv_router)) {
- char buf1[INET_ADDRSTRLEN];
- char buf2[INET_ADDRSTRLEN];
- char buf3[INET_ADDRSTRLEN];
-
- flog_err(EC_OSPF_ROUTER_LSA_MISMATCH,
- "Incoming Router-LSA from %s with Adv-ID[%s] != LS-ID[%s]",
- inet_ntop(AF_INET, &ospfh->router_id,
- buf1, INET_ADDRSTRLEN),
- inet_ntop(AF_INET, &lsa->data->id,
- buf2, INET_ADDRSTRLEN),
- inet_ntop(AF_INET,
- &lsa->data->adv_router, buf3,
- INET_ADDRSTRLEN));
+ flog_err(
+ EC_OSPF_ROUTER_LSA_MISMATCH,
+ "Incoming Router-LSA from %pI4 with Adv-ID[%pI4] != LS-ID[%pI4]",
+ &ospfh->router_id, &lsa->data->id,
+ &lsa->data->adv_router);
flog_err(
EC_OSPF_DOMAIN_CORRUPT,
"OSPF domain compromised by attack or corruption. Verify correct operation of -ALL- OSPF routers.");
@@ -3045,17 +3027,11 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf)
/* If incoming interface is passive one, ignore it. */
if (oi && OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE) {
- char buf[3][INET_ADDRSTRLEN];
-
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ignoring packet from router %s sent to %s, received on a passive interface, %s",
- inet_ntop(AF_INET, &ospfh->router_id, buf[0],
- sizeof(buf[0])),
- inet_ntop(AF_INET, &iph->ip_dst, buf[1],
- sizeof(buf[1])),
- inet_ntop(AF_INET, &oi->address->u.prefix4,
- buf[2], sizeof(buf[2])));
+ "ignoring packet from router %pI4 sent to %pI4, received on a passive interface, %pI4",
+ &ospfh->router_id, &iph->ip_dst,
+ &oi->address->u.prefix4);
if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS)) {
/* Try to fix multicast membership.
@@ -3097,16 +3073,11 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf)
&iph->ip_src, ifp->name);
return OSPF_READ_CONTINUE;
} else if (oi->state == ISM_Down) {
- char buf[2][INET_ADDRSTRLEN];
-
flog_warn(
EC_OSPF_PACKET,
- "Ignoring packet from %s to %s received on interface that is down [%s]; interface flags are %s",
- inet_ntop(AF_INET, &iph->ip_src, buf[0],
- sizeof(buf[0])),
- inet_ntop(AF_INET, &iph->ip_dst, buf[1],
- sizeof(buf[1])),
- ifp->name, if_flag_dump(ifp->flags));
+ "Ignoring packet from %pI4 to %pI4 received on interface that is down [%s]; interface flags are %s",
+ &iph->ip_src, &iph->ip_dst, ifp->name,
+ if_flag_dump(ifp->flags));
/* Fix multicast memberships? */
if (iph->ip_dst.s_addr == htonl(OSPF_ALLSPFROUTERS))
OI_MEMBER_JOINED(oi, MEMBER_ALLROUTERS);
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 82acd0829c..6cd6a47098 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -251,15 +251,11 @@ static void ospf_vertex_dump(const char *msg, struct vertex *v,
struct vertex_parent *vp;
for (ALL_LIST_ELEMENTS_RO(v->parents, node, vp)) {
- char buf1[BUFSIZ];
-
if (vp) {
zlog_debug(
- "parent %pI4 backlink %d nexthop %s lsa pos %d",
- &vp->parent->lsa->id,
- vp->backlink,
- inet_ntop(AF_INET, &vp->nexthop->router,
- buf1, BUFSIZ),
+ "parent %pI4 backlink %d nexthop %pI4 lsa pos %d",
+ &vp->parent->lsa->id, vp->backlink,
+ &vp->nexthop->router,
vp->nexthop->lsa_pos);
}
}
@@ -707,14 +703,9 @@ static void ospf_spf_add_parent(struct vertex *v, struct vertex *w,
else
w->distance = distance;
- if (IS_DEBUG_OSPF_EVENT) {
- char buf[2][INET_ADDRSTRLEN];
- zlog_debug(
- "%s: Adding %s as parent of %s", __func__,
- inet_ntop(AF_INET, &v->lsa->id, buf[0], sizeof(buf[0])),
- inet_ntop(AF_INET, &w->lsa->id, buf[1],
- sizeof(buf[1])));
- }
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug("%s: Adding %pI4 as parent of %pI4", __func__,
+ &v->lsa->id, &w->lsa->id);
/*
* Adding parent for a new, better path: flush existing parents from W.
@@ -805,8 +796,6 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
struct vertex_nexthop *nh, *lnh;
struct vertex_parent *vp;
unsigned int added = 0;
- char buf1[BUFSIZ];
- char buf2[BUFSIZ];
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug("ospf_nexthop_calculation(): Start");
@@ -828,14 +817,11 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
/* we *must* be supplied with the link data */
assert(l != NULL);
- if (IS_DEBUG_OSPF_EVENT) {
+ if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "%s: considering link type:%d link_id:%s link_data:%s",
- __func__, l->m[0].type,
- inet_ntop(AF_INET, &l->link_id, buf1, BUFSIZ),
- inet_ntop(AF_INET, &l->link_data, buf2,
- BUFSIZ));
- }
+ "%s: considering link type:%d link_id:%pI4 link_data:%pI4",
+ __func__, l->m[0].type, &l->link_id,
+ &l->link_data);
if (w->type == OSPF_VERTEX_ROUTER) {
/*
@@ -852,15 +838,10 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
lsa_pos);
if (!oi) {
zlog_debug(
- "%s: OI not found in LSA: lsa_pos: %d link_id:%s link_data:%s",
+ "%s: OI not found in LSA: lsa_pos: %d link_id:%pI4 link_data:%pI4",
__func__, lsa_pos,
- inet_ntop(AF_INET,
- &l->link_id,
- buf1, BUFSIZ),
- inet_ntop(AF_INET,
- &l->link_data,
- buf2,
- BUFSIZ));
+ &l->link_id,
+ &l->link_data);
return 0;
}
}
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index 7b2d794214..a7a2e03632 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -1202,16 +1202,22 @@ static void update_ext_prefix_sid(struct sr_node *srn, struct sr_prefix *srp)
found ? "Update" : "Add", GET_OPAQUE_ID(srp->instance),
&srn->adv_router);
+ /* Complete SR-Prefix */
+ srp->srn = srn;
+ IPV4_ADDR_COPY(&srp->adv_router, &srn->adv_router);
+
/* if not found, add new Segment Prefix and install NHLFE */
if (!found) {
- /* Complete SR-Prefix and add it to SR-Node list */
- srp->srn = srn;
- IPV4_ADDR_COPY(&srp->adv_router, &srn->adv_router);
+ /* Add it to SR-Node list ... */
listnode_add(srn->ext_prefix, srp);
- /* Try to set MPLS table */
+ /* ... and try to set MPLS table */
if (compute_prefix_nhlfe(srp) == 1)
ospf_zebra_update_prefix_sid(srp);
} else {
+ /*
+ * An old SR prefix exist. Check if something changes or if it
+ * is just a refresh.
+ */
if (sr_prefix_cmp(pref, srp)) {
if (compute_prefix_nhlfe(srp) == 1) {
ospf_zebra_delete_prefix_sid(pref);
@@ -2462,10 +2468,18 @@ DEFUN (sr_prefix_sid,
new->type = LOCAL_SID;
}
+ /* First, remove old NHLFE if installed */
+ if (srp == new && CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
+ && !CHECK_FLAG(srp->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
+ ospf_zebra_delete_prefix_sid(srp);
+ /* Then, reset Flag & labels to handle flag update */
+ new->flags = 0;
+ new->label_in = 0;
+ new->nhlfe.label_out = 0;
+
/* Set NO PHP flag if present and compute NHLFE */
if (argv_find(argv, argc, "no-php-flag", &idx)) {
SET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG);
- UNSET_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG);
new->label_in = index2label(new->sid, OspfSR.self->srgb);
new->nhlfe.label_out = MPLS_LABEL_IMPLICIT_NULL;
}
@@ -2505,7 +2519,7 @@ DEFUN (sr_prefix_sid,
if (srp != new)
listnode_add(OspfSR.self->ext_prefix, new);
- /* Install Prefix SID if SR is UP and a valid input label set */
+ /* Update Prefix SID if SR is UP */
if (OspfSR.status == SR_UP) {
if (CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_NPFLG)
&& !CHECK_FLAG(new->flags, EXT_SUBTLV_PREFIX_SID_EFLG))
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 4132452069..2ff59ccf49 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -140,44 +140,37 @@ int ospf_oi_count(struct interface *ifp)
all_vrf = strmatch(vrf_name, "all"); \
}
-static struct ospf *ospf_cmd_lookup_ospf(struct vty *vty,
- struct cmd_token *argv[],
- const int argc, uint32_t enable,
- unsigned short *instance)
+static int ospf_router_cmd_parse(struct vty *vty, struct cmd_token *argv[],
+ const int argc, unsigned short *instance,
+ const char **vrf_name)
{
- struct ospf *ospf = NULL;
int idx_vrf = 0, idx_inst = 0;
- const char *vrf_name = NULL;
- bool created = false;
*instance = 0;
- if (argv_find(argv, argc, "(1-65535)", &idx_inst))
+ if (argv_find(argv, argc, "(1-65535)", &idx_inst)) {
+ if (ospf_instance == 0) {
+ vty_out(vty,
+ "%% OSPF is not running in instance mode\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
*instance = strtoul(argv[idx_inst]->arg, NULL, 10);
+ }
+ *vrf_name = NULL;
if (argv_find(argv, argc, "vrf", &idx_vrf)) {
- vrf_name = argv[idx_vrf + 1]->arg;
- if (vrf_name == NULL || strmatch(vrf_name, VRF_DEFAULT_NAME))
- vrf_name = NULL;
- if (enable) {
- /* Allocate VRF aware instance */
- ospf = ospf_get(*instance, vrf_name, &created);
- } else {
- ospf = ospf_lookup_by_inst_name(*instance, vrf_name);
- }
- } else {
- if (enable) {
- ospf = ospf_get(*instance, NULL, &created);
- } else {
- ospf = ospf_lookup_instance(*instance);
+ if (ospf_instance != 0) {
+ vty_out(vty,
+ "%% VRF is not supported in instance mode\n");
+ return CMD_WARNING_CONFIG_FAILED;
}
- }
- if (created) {
- if (DFLT_OSPF_LOG_ADJACENCY_CHANGES)
- SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
+ *vrf_name = argv[idx_vrf + 1]->arg;
+ if (*vrf_name && strmatch(*vrf_name, VRF_DEFAULT_NAME))
+ *vrf_name = NULL;
}
- return ospf;
+ return CMD_SUCCESS;
}
static void ospf_show_vrf_name(struct ospf *ospf, struct vty *vty,
@@ -213,28 +206,35 @@ DEFUN_NOSH (router_ospf,
"Instance ID\n"
VRF_CMD_HELP_STR)
{
- struct ospf *ospf = NULL;
- int ret = CMD_SUCCESS;
- unsigned short instance = 0;
+ unsigned short instance;
+ const char *vrf_name;
+ bool created = false;
+ struct ospf *ospf;
+ int ret;
- ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 1, &instance);
- if (!ospf)
- return CMD_WARNING_CONFIG_FAILED;
+ ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name);
+ if (ret != CMD_SUCCESS)
+ return ret;
- /* The following logic to set the vty qobj index is in place to be able
- to ignore the commands which dont belong to this instance. */
- if (ospf->instance != instance) {
+ if (instance != ospf_instance) {
VTY_PUSH_CONTEXT_NULL(OSPF_NODE);
- ret = CMD_NOT_MY_INSTANCE;
- } else {
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "Config command 'router ospf %d' received, vrf %s id %u oi_running %u",
- instance, ospf->name ? ospf->name : "NIL",
- ospf->vrf_id, ospf->oi_running);
- VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
+ return CMD_NOT_MY_INSTANCE;
}
+ ospf = ospf_get(instance, vrf_name, &created);
+
+ if (created)
+ if (DFLT_OSPF_LOG_ADJACENCY_CHANGES)
+ SET_FLAG(ospf->config, OSPF_LOG_ADJACENCY_CHANGES);
+
+ if (IS_DEBUG_OSPF_EVENT)
+ zlog_debug(
+ "Config command 'router ospf %d' received, vrf %s id %u oi_running %u",
+ ospf->instance, ospf->name ? ospf->name : "NIL",
+ ospf->vrf_id, ospf->oi_running);
+
+ VTY_PUSH_CONTEXT(OSPF_NODE, ospf);
+
return ret;
}
@@ -247,19 +247,25 @@ DEFUN (no_router_ospf,
"Instance ID\n"
VRF_CMD_HELP_STR)
{
+ unsigned short instance;
+ const char *vrf_name;
struct ospf *ospf;
- unsigned short instance = 0;
+ int ret;
- ospf = ospf_cmd_lookup_ospf(vty, argv, argc, 0, &instance);
- if (ospf == NULL) {
- if (instance)
- return CMD_NOT_MY_INSTANCE;
- else
- return CMD_WARNING;
- }
- ospf_finish(ospf);
+ ret = ospf_router_cmd_parse(vty, argv, argc, &instance, &vrf_name);
+ if (ret != CMD_SUCCESS)
+ return ret;
- return CMD_SUCCESS;
+ if (instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ ospf = ospf_lookup(instance, vrf_name);
+ if (ospf)
+ ospf_finish(ospf);
+ else
+ ret = CMD_WARNING_CONFIG_FAILED;
+
+ return ret;
}
@@ -3381,11 +3387,11 @@ DEFUN (show_ip_ospf_instance,
json_object *json = NULL;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -4131,11 +4137,11 @@ DEFUN (show_ip_ospf_instance_interface,
json_object *json = NULL;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -4526,11 +4532,11 @@ DEFUN (show_ip_ospf_instance_neighbor,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -4741,11 +4747,11 @@ DEFUN (show_ip_ospf_instance_neighbor_all,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
json = json_object_new_object();
@@ -4881,11 +4887,11 @@ DEFUN (show_ip_ospf_instance_neighbor_int,
show_ip_ospf_neighbour_header(vty);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (!uj)
@@ -5359,11 +5365,11 @@ DEFPY (show_ip_ospf_instance_neighbor_id,
{
struct ospf *ospf;
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_id_common(vty, ospf, &router_id, !!json,
@@ -5532,11 +5538,11 @@ DEFUN (show_ip_ospf_instance_neighbor_detail,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -5727,11 +5733,11 @@ DEFUN (show_ip_ospf_instance_neighbor_detail_all,
int ret = CMD_SUCCESS;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
if (uj)
@@ -5859,11 +5865,11 @@ DEFUN (show_ip_ospf_instance_neighbor_int_detail,
bool uj = use_json(argc, argv);
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_neighbor_int_detail_common(vty, ospf, idx_ifname,
@@ -7136,10 +7142,11 @@ DEFUN (show_ip_ospf_instance_database,
if (argv_find(argv, argc, "(1-65535)", &idx)) {
instance = strtoul(argv[idx]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return (show_ip_ospf_database_common(
@@ -7212,15 +7219,12 @@ DEFUN (show_ip_ospf_instance_database_max,
json = json_object_new_object();
instance = strtoul(argv[idx_number]->arg, NULL, 10);
-
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running) {
- vty_out(vty, "%% OSPF instance not found\n");
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
- }
show_ip_ospf_database_common(vty, ospf, 1, argc, argv, 0, json, uj);
@@ -7355,13 +7359,12 @@ DEFUN (show_ip_ospf_instance_database_type_adv_router,
if (argv_find(argv, argc, "(1-65535)", &idx)) {
instance = strtoul(argv[idx]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running) {
- vty_out(vty, "%% OSPF instance not found\n");
+
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
- }
return (show_ip_ospf_database_type_adv_router_common(
vty, ospf, idx ? 1 : 0, argc, argv, use_vrf, json, uj));
@@ -8819,7 +8822,7 @@ DEFUN (ip_ospf_area,
else
ospf = ospf_lookup_instance(instance);
- if (instance && ospf == NULL) {
+ if (instance && instance != ospf_instance) {
/*
* At this point we know we have received
* an instance and there is no ospf instance
@@ -8944,7 +8947,7 @@ DEFUN (no_ip_ospf_area,
else
ospf = ospf_lookup_instance(instance);
- if (instance && ospf == NULL)
+ if (instance && instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
argv_find(argv, argc, "area", &idx);
@@ -10918,11 +10921,11 @@ DEFUN (show_ip_ospf_instance_border_routers,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_border_routers_common(vty, ospf, 0);
@@ -11086,11 +11089,11 @@ DEFUN (show_ip_ospf_instance_route,
unsigned short instance = 0;
instance = strtoul(argv[idx_number]->arg, NULL, 10);
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
- if (!ospf->oi_running)
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
return CMD_SUCCESS;
return show_ip_ospf_route_common(vty, ospf, NULL, 0);
@@ -11189,8 +11192,7 @@ DEFPY (clear_ip_ospf_neighbor,
*/
if (instance != 0) {
/* This means clear only the particular ospf process */
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -11220,8 +11222,7 @@ DEFPY (clear_ip_ospf_process,
/* Check if instance is not passed as an argument */
if (instance != 0) {
/* This means clear only the particular ospf process */
- ospf = ospf_lookup_instance(instance);
- if (ospf == NULL)
+ if (instance != ospf_instance)
return CMD_NOT_MY_INSTANCE;
}
@@ -11545,7 +11546,6 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
struct ospf_if_params *params;
const char *auth_str;
int write = 0;
- struct ospf *ospf = vrf->info;
FOR_ALL_INTERFACES (vrf, ifp) {
@@ -11698,9 +11698,9 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
/* Area print. */
if (OSPF_IF_PARAM_CONFIGURED(params, if_area)) {
- if (ospf && ospf->instance)
+ if (ospf_instance)
vty_out(vty, " ip ospf %d",
- ospf->instance);
+ ospf_instance);
else
vty_out(vty, " ip ospf");
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index aaab274570..a2fbd01ab8 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -622,7 +622,7 @@ void ospf_zebra_update_prefix_sid(const struct sr_prefix *srp)
znh->labels[0] = path->srni.label_out;
osr_debug(" |- labels %u/%u", srp->label_in,
- srp->nhlfe.label_out);
+ path->srni.label_out);
/* Set TI-LFA backup nexthop info if present */
if (path->srni.backup_label_stack) {
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 04397d50a5..9590a9c73b 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -70,6 +70,8 @@ static struct ospf_master ospf_master;
/* OSPF process wide configuration pointer to export. */
struct ospf_master *om;
+unsigned short ospf_instance;
+
extern struct zclient *zclient;
@@ -511,36 +513,28 @@ static void ospf_init(struct ospf *ospf)
ospf_router_id_update(ospf);
}
-struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
+struct ospf *ospf_lookup(unsigned short instance, const char *name)
{
struct ospf *ospf;
- /* vrf name provided call inst and name based api
- * in case of no name pass default ospf instance */
- if (name)
+ if (ospf_instance) {
+ ospf = ospf_lookup_instance(instance);
+ } else {
ospf = ospf_lookup_by_inst_name(instance, name);
- else
- ospf = ospf_lookup_by_vrf_id(VRF_DEFAULT);
-
- *created = (ospf == NULL);
- if (ospf == NULL) {
- ospf = ospf_new(instance, name);
- ospf_add(ospf);
-
- ospf_init(ospf);
}
return ospf;
}
-struct ospf *ospf_get_instance(unsigned short instance, bool *created)
+struct ospf *ospf_get(unsigned short instance, const char *name, bool *created)
{
struct ospf *ospf;
- ospf = ospf_lookup_instance(instance);
+ ospf = ospf_lookup(instance, name);
+
*created = (ospf == NULL);
if (ospf == NULL) {
- ospf = ospf_new(instance, NULL /* VRF_DEFAULT*/);
+ ospf = ospf_new(instance, name);
ospf_add(ospf);
ospf_init(ospf);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 954a469b68..5148bf555c 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -633,6 +633,7 @@ struct ospf_nbr_nbma {
/* Extern variables. */
extern struct ospf_master *om;
+extern unsigned short ospf_instance;
extern const int ospf_redistributed_proto_max;
extern struct zclient *zclient;
extern struct thread_master *master;
@@ -642,10 +643,10 @@ extern struct zebra_privs_t ospfd_privs;
/* Prototypes. */
extern const char *ospf_redist_string(unsigned int route_type);
extern struct ospf *ospf_lookup_instance(unsigned short);
+extern struct ospf *ospf_lookup(unsigned short instance, const char *name);
extern struct ospf *ospf_get(unsigned short instance, const char *name,
bool *created);
extern struct ospf *ospf_new_alloc(unsigned short instance, const char *name);
-extern struct ospf *ospf_get_instance(unsigned short, bool *created);
extern struct ospf *ospf_lookup_by_inst_name(unsigned short instance,
const char *name);
extern struct ospf *ospf_lookup_by_vrf_id(vrf_id_t vrf_id);
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 714d6e8e1d..ae5b7940e9 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -6057,7 +6057,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
vty_out(vty,
" R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
vty_out(vty,
- "\nSource Group Flags Proto Input Output TTL Uptime\n");
+ "\nSource Group Flags Proto Input Output TTL Uptime\n");
}
now = pim_time_monotonic_sec();
@@ -6247,7 +6247,7 @@ static void show_mroute(struct pim_instance *pim, struct vty *vty,
}
vty_out(vty,
- "%-15s %-15s %-15s %-6s %-16s %-16s %-3d %8s\n",
+ "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
src_str, grp_str, state_str, proto,
in_ifname, out_ifname, ttl,
mroute_uptime);
diff --git a/pimd/pim_igmp_mtrace.c b/pimd/pim_igmp_mtrace.c
index 941d067619..d36a275f85 100644
--- a/pimd/pim_igmp_mtrace.c
+++ b/pimd/pim_igmp_mtrace.c
@@ -66,7 +66,6 @@ static bool mtrace_fwd_info_weak(struct pim_instance *pim,
struct pim_nexthop nexthop;
struct interface *ifp_in;
struct in_addr nh_addr;
- char nexthop_str[INET_ADDRSTRLEN];
nh_addr.s_addr = INADDR_ANY;
@@ -82,10 +81,8 @@ static bool mtrace_fwd_info_weak(struct pim_instance *pim,
zlog_debug("mtrace pim_nexthop_lookup OK");
if (PIM_DEBUG_MTRACE)
- zlog_debug("mtrace next_hop=%s",
- inet_ntop(nexthop.mrib_nexthop_addr.family,
- &nexthop.mrib_nexthop_addr.u.prefix,
- nexthop_str, sizeof(nexthop_str)));
+ zlog_debug("mtrace next_hop=%pI4",
+ &nexthop.mrib_nexthop_addr.u.prefix4);
if (nexthop.mrib_nexthop_addr.family == AF_INET)
nh_addr = nexthop.mrib_nexthop_addr.u.prefix4;
@@ -114,7 +111,6 @@ static bool mtrace_fwd_info(struct pim_instance *pim,
struct interface *ifp_in;
struct in_addr nh_addr;
uint32_t total;
- char up_str[INET_ADDRSTRLEN];
memset(&sg, 0, sizeof(struct prefix_sg));
sg.src = mtracep->src_addr;
@@ -142,9 +138,7 @@ static bool mtrace_fwd_info(struct pim_instance *pim,
total = htonl(MTRACE_UNKNOWN_COUNT);
if (PIM_DEBUG_MTRACE)
- zlog_debug("fwd_info: upstream next hop=%s",
- inet_ntop(AF_INET, &(nh_addr), up_str,
- sizeof(up_str)));
+ zlog_debug("fwd_info: upstream next hop=%pI4", &nh_addr);
if (up->channel_oil)
total = up->channel_oil->cc.pktcnt;
@@ -198,31 +192,19 @@ static void mtrace_rsp_init(struct igmp_mtrace_rsp *mtrace_rspp)
static void mtrace_rsp_debug(uint32_t qry_id, int rsp,
struct igmp_mtrace_rsp *mrspp)
{
- char inc_str[INET_ADDRSTRLEN];
- char out_str[INET_ADDRSTRLEN];
- char prv_str[INET_ADDRSTRLEN];
+ struct in_addr incoming = mrspp->incoming;
+ struct in_addr outgoing = mrspp->outgoing;
+ struct in_addr prev_hop = mrspp->prev_hop;
zlog_debug(
- "Rx mt(%d) qid=%ud arr=%x in=%s out=%s prev=%s proto=%d fwd=%d",
- rsp, ntohl(qry_id), mrspp->arrival,
- inet_ntop(AF_INET, &(mrspp->incoming), inc_str,
- sizeof(inc_str)),
- inet_ntop(AF_INET, &(mrspp->outgoing), out_str,
- sizeof(out_str)),
- inet_ntop(AF_INET, &(mrspp->prev_hop), prv_str,
- sizeof(prv_str)),
- mrspp->rtg_proto, mrspp->fwd_code);
+ "Rx mt(%d) qid=%ud arr=%x in=%pI4 out=%pI4 prev=%pI4 proto=%d fwd=%d",
+ rsp, ntohl(qry_id), mrspp->arrival, &incoming, &outgoing,
+ &prev_hop, mrspp->rtg_proto, mrspp->fwd_code);
}
static void mtrace_debug(struct pim_interface *pim_ifp,
struct igmp_mtrace *mtracep, int mtrace_len)
{
- char inc_str[INET_ADDRSTRLEN];
- char grp_str[INET_ADDRSTRLEN];
- char src_str[INET_ADDRSTRLEN];
- char dst_str[INET_ADDRSTRLEN];
- char rsp_str[INET_ADDRSTRLEN];
-
struct in_addr ga, sa, da, ra;
ga = mtracep->grp_addr;
@@ -231,19 +213,10 @@ static void mtrace_debug(struct pim_interface *pim_ifp,
ra = mtracep->rsp_addr;
zlog_debug(
- "Rx mtrace packet incoming on %s: hops=%d type=%d size=%d, grp=%s, src=%s, dst=%s rsp=%s ttl=%d qid=%ud",
- inet_ntop(AF_INET, &(pim_ifp->primary_address), inc_str,
- sizeof(inc_str)),
- mtracep->hops, mtracep->type, mtrace_len,
- inet_ntop(AF_INET, &ga, grp_str,
- sizeof(grp_str)),
- inet_ntop(AF_INET, &sa, src_str,
- sizeof(src_str)),
- inet_ntop(AF_INET, &da, dst_str,
- sizeof(dst_str)),
- inet_ntop(AF_INET, &ra, rsp_str,
- sizeof(rsp_str)),
- mtracep->rsp_ttl, ntohl(mtracep->qry_id));
+ "Rx mtrace packet incoming on %pI4: hops=%d type=%d size=%d, grp=%pI4, src=%pI4, dst=%pI4 rsp=%pI4 ttl=%d qid=%ud",
+ &pim_ifp->primary_address, mtracep->hops, mtracep->type,
+ mtrace_len, &ga, &sa, &da, &ra, mtracep->rsp_ttl,
+ ntohl(mtracep->qry_id));
if (mtrace_len > (int)sizeof(struct igmp_mtrace)) {
int i;
@@ -290,8 +263,6 @@ static int mtrace_send_packet(struct interface *ifp,
ssize_t sent;
int ret;
int fd;
- char if_str[INET_ADDRSTRLEN];
- char rsp_str[INET_ADDRSTRLEN];
uint8_t ttl;
memset(&to, 0, sizeof(to));
@@ -301,13 +272,11 @@ static int mtrace_send_packet(struct interface *ifp,
if (PIM_DEBUG_MTRACE) {
struct in_addr if_addr;
+ struct in_addr rsp_addr = mtracep->rsp_addr;
if_addr = mtrace_primary_address(ifp);
- zlog_debug(
- "Sending mtrace packet to %s on %s",
- inet_ntop(AF_INET, &mtracep->rsp_addr, rsp_str,
- sizeof(rsp_str)),
- inet_ntop(AF_INET, &if_addr, if_str, sizeof(if_str)));
+ zlog_debug("Sending mtrace packet to %pI4 on %pI4", &rsp_addr,
+ &if_addr);
}
fd = pim_socket_raw(IPPROTO_IGMP);
@@ -514,7 +483,6 @@ static int mtrace_send_mc_response(struct pim_instance *pim,
struct listnode *chnextnode;
struct pim_ifchannel *ch = NULL;
int ret = -1;
- char buf[PREFIX_STRLEN];
memset(&sg, 0, sizeof(struct prefix_sg));
sg.grp = mtracep->rsp_addr;
@@ -523,11 +491,11 @@ static int mtrace_send_mc_response(struct pim_instance *pim,
if (c_oil == NULL) {
if (PIM_DEBUG_MTRACE) {
+ struct in_addr rsp_addr = mtracep->rsp_addr;
+
zlog_debug(
- "Dropping mtrace multicast response packet len=%u to %s",
- (unsigned int)mtrace_len,
- inet_ntop(AF_INET, &mtracep->rsp_addr,
- buf, sizeof(buf)));
+ "Dropping mtrace multicast response packet len=%u to %pI4",
+ (unsigned int)mtrace_len, &rsp_addr);
}
return -1;
}
@@ -562,7 +530,6 @@ static int mtrace_send_response(struct pim_instance *pim,
if (IPV4_CLASS_DE(ntohl(mtracep->rsp_addr.s_addr))) {
struct pim_rpf *p_rpf;
- char grp_str[INET_ADDRSTRLEN];
if (pim_rp_i_am_rp(pim, mtracep->rsp_addr))
return mtrace_send_mc_response(pim, mtracep,
@@ -571,11 +538,11 @@ static int mtrace_send_response(struct pim_instance *pim,
p_rpf = pim_rp_g(pim, mtracep->rsp_addr);
if (p_rpf == NULL) {
- if (PIM_DEBUG_MTRACE)
- zlog_debug("mtrace no RP for %s",
- inet_ntop(AF_INET,
- &(mtracep->rsp_addr),
- grp_str, sizeof(grp_str)));
+ if (PIM_DEBUG_MTRACE) {
+ struct in_addr rsp_addr = mtracep->rsp_addr;
+
+ zlog_debug("mtrace no RP for %pI4", &rsp_addr);
+ }
return -1;
}
nexthop = p_rpf->source_nexthop;
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index 9c11cc47d5..5a09e7a8ee 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -145,6 +145,8 @@ int main(int argc, char **argv, char **envp)
hook_register(routing_conf_event,
routing_control_plane_protocols_name_validate);
+ routing_control_plane_protocols_register_vrf_dependency();
+
frr_config_fork();
#ifdef PIM_DEBUG_BYDEFAULT
diff --git a/pimd/pim_msdp_socket.c b/pimd/pim_msdp_socket.c
index ddd8dc6bf9..b613937f59 100644
--- a/pimd/pim_msdp_socket.c
+++ b/pimd/pim_msdp_socket.c
@@ -67,7 +67,6 @@ static int pim_msdp_sock_accept(struct thread *thread)
int accept_sock;
int msdp_sock;
struct pim_msdp_peer *mp;
- char buf[SU_ADDRSTRLEN];
sockunion_init(&su);
@@ -96,8 +95,7 @@ static int pim_msdp_sock_accept(struct thread *thread)
++pim->msdp.rejected_accepts;
if (PIM_DEBUG_MSDP_EVENTS) {
flog_err(EC_PIM_MSDP_PACKET,
- "msdp peer connection refused from %s",
- sockunion2str(&su, buf, SU_ADDRSTRLEN));
+ "msdp peer connection refused from %pSU", &su);
}
close(msdp_sock);
return -1;
@@ -113,8 +111,8 @@ static int pim_msdp_sock_accept(struct thread *thread)
if (mp->fd >= 0) {
if (PIM_DEBUG_MSDP_EVENTS) {
zlog_notice(
- "msdp peer new connection from %s stop old connection",
- sockunion2str(&su, buf, SU_ADDRSTRLEN));
+ "msdp peer new connection from %pSU stop old connection",
+ &su);
}
pim_msdp_peer_stop_tcp_conn(mp, true /* chg_state */);
}
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index 4bc78529a8..a7d7551cbd 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -1181,7 +1181,7 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_ms
case NB_EV_APPLY:
vrf = nb_running_get_entry(args->dnode, NULL, true);
pim = vrf->info;
- mesh_group_name = yang_dnode_get_string(args->dnode, ".");
+ mesh_group_name = yang_dnode_get_string(args->dnode, "mesh-group-name");
result = ip_no_msdp_mesh_group_cmd_worker(pim, mesh_group_name,
args->errmsg,
@@ -2394,6 +2394,13 @@ int lib_interface_pim_address_family_mroute_oif_modify(
struct ipaddr group_addr;
const struct lyd_node *if_dnode;
+ iif = nb_running_get_entry(args->dnode, NULL, true);
+ pim_iifp = iif->info;
+ pim = pim_iifp->pim;
+
+ oifname = yang_dnode_get_string(args->dnode, NULL);
+ oif = if_lookup_by_name(oifname, pim->vrf_id);
+
switch (args->event) {
case NB_EV_VALIDATE:
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
@@ -2402,18 +2409,20 @@ int lib_interface_pim_address_family_mroute_oif_modify(
"%% Enable PIM and/or IGMP on this interface first");
return NB_ERR_VALIDATION;
}
+
+#ifdef PIM_ENFORCE_LOOPFREE_MFC
+ if (oif && (iif->ifindex == oif->ifindex)) {
+ strlcpy(args->errmsg,
+ "% IIF same as OIF and loopfree enforcement is enabled; rejecting",
+ args->errmsg_len);
+ return NB_ERR_VALIDATION;
+ }
+#endif
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
break;
case NB_EV_APPLY:
- iif = nb_running_get_entry(args->dnode, NULL, true);
- pim_iifp = iif->info;
- pim = pim_iifp->pim;
-
- oifname = yang_dnode_get_string(args->dnode, NULL);
- oif = if_lookup_by_name(oifname, pim->vrf_id);
-
if (!oif) {
snprintf(args->errmsg, args->errmsg_len,
"No such interface name %s",
@@ -2707,11 +2716,11 @@ int lib_interface_igmp_igmp_enable_modify(struct nb_cb_modify_args *args)
switch (args->event) {
case NB_EV_VALIDATE:
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
- ifp_name = yang_dnode_get_string(if_dnode, ".");
mcast_if_count =
yang_get_list_elements_count(if_dnode);
/* Limiting mcast interfaces to number of VIFs */
if (mcast_if_count == MAXVIFS) {
+ ifp_name = yang_dnode_get_string(if_dnode, "name");
snprintf(args->errmsg, args->errmsg_len,
"Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s",
MAXVIFS, ifp_name);
@@ -2982,7 +2991,7 @@ int lib_interface_igmp_address_family_static_group_create(
case NB_EV_VALIDATE:
if_dnode = yang_dnode_get_parent(args->dnode, "interface");
if (!is_pim_interface(if_dnode)) {
- ifp_name = yang_dnode_get_string(if_dnode, ".");
+ ifp_name = yang_dnode_get_string(if_dnode, "name");
snprintf(args->errmsg, args->errmsg_len,
"multicast not enabled on interface %s",
ifp_name);
diff --git a/python/clippy/__init__.py b/python/clippy/__init__.py
index d6865ff484..344a1c91ee 100644
--- a/python/clippy/__init__.py
+++ b/python/clippy/__init__.py
@@ -21,6 +21,8 @@ import _clippy
from _clippy import parse, Graph, GraphNode
+frr_top_src = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
def graph_iterate(graph):
"""iterator yielding all nodes of a graph
diff --git a/python/clippy/elf.py b/python/clippy/elf.py
new file mode 100644
index 0000000000..4ed334f0c4
--- /dev/null
+++ b/python/clippy/elf.py
@@ -0,0 +1,574 @@
+# FRR libelf wrapper
+#
+# Copyright (C) 2020 David Lamparter for NetDEF, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; see the file COPYING; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+'''
+Wrapping layer and additional utility around _clippy.ELFFile.
+
+Essentially, the C bits have the low-level ELF access bits that should be
+fast while this has the bits that string everything together (and would've
+been a PITA to do in C.)
+
+Surprisingly - or maybe through proper engineering - this actually works
+across architecture, word size and even endianness boundaries. Both the C
+module (through GElf_*) and this code (cf. struct.unpack format mangling
+in ELFDissectStruct) will take appropriate measures to flip and resize
+fields as needed.
+'''
+
+import struct
+from collections import OrderedDict
+from weakref import WeakValueDictionary
+
+from _clippy import ELFFile, ELFAccessError
+
+#
+# data access
+#
+
+class ELFNull(object):
+ '''
+ NULL pointer, returned instead of ELFData
+ '''
+ def __init__(self):
+ self.symname = None
+ self._dstsect = None
+
+ def __repr__(self):
+ return '<ptr: NULL>'
+
+ def __hash__(self):
+ return hash(None)
+
+ def get_string(self):
+ return None
+
+class ELFUnresolved(object):
+ '''
+ Reference to an unresolved external symbol, returned instead of ELFData
+
+ :param symname: name of the referenced symbol
+ :param addend: offset added to the symbol, normally zero
+ '''
+ def __init__(self, symname, addend):
+ self.addend = addend
+ self.symname = symname
+ self._dstsect = None
+
+ def __repr__(self):
+ return '<unresolved: %s+%d>' % (self.symname, self.addend)
+
+ def __hash__(self):
+ return hash((self.symname, self.addend))
+
+class ELFData(object):
+ '''
+ Actual data somewhere in the ELF file.
+
+ :type dstsect: ELFSubset
+ :param dstsect: container data area (section or entire file)
+ :param dstoffs: byte offset into dstsect
+ :param dstlen: byte size of object, or None if unknown, open-ended or string
+ '''
+ def __init__(self, dstsect, dstoffs, dstlen):
+ self._dstsect = dstsect
+ self._dstoffs = dstoffs
+ self._dstlen = dstlen
+ self.symname = None
+
+ def __repr__(self):
+ return '<ptr: %s+0x%05x/%d>' % (self._dstsect.name, self._dstoffs, self._dstlen or -1)
+
+ def __hash__(self):
+ return hash((self._dstsect, self._dstoffs))
+
+ def get_string(self):
+ '''
+ Interpret as C string / null terminated UTF-8 and get the actual text.
+ '''
+ try:
+ return self._dstsect[self._dstoffs:str].decode('UTF-8')
+ except:
+ import pdb; pdb.set_trace()
+
+ def get_data(self, reflen):
+ '''
+ Interpret as some structure (and check vs. expected length)
+
+ :param reflen: expected size of the object, compared against actual
+ size (which is only known in rare cases, mostly when directly
+ accessing a symbol since symbols have their destination object
+ size recorded)
+ '''
+ if self._dstlen is not None and self._dstlen != reflen:
+ raise ValueError('symbol size mismatch (got %d, expected %d)' % (self._dstlen, reflen))
+ return self._dstsect[self._dstoffs:self._dstoffs+reflen]
+
+ def offset(self, offs, within_symbol=False):
+ '''
+ Get another ELFData at an offset
+
+ :param offs: byte offset, can be negative (e.g. in container_of)
+ :param within_symbol: retain length information
+ '''
+ if self._dstlen is None or not within_symbol:
+ return ELFData(self._dstsect, self._dstoffs + offs, None)
+ else:
+ return ELFData(self._dstsect, self._dstoffs + offs, self._dstlen - offs)
+
+#
+# dissection data items
+#
+
+class ELFDissectData(object):
+ '''
+ Common bits for ELFDissectStruct and ELFDissectUnion
+ '''
+
+ def __len__(self):
+ '''
+ Used for boolean evaluation, e.g. "if struct: ..."
+ '''
+ return not (isinstance(self._data, ELFNull) or isinstance(self._data, ELFUnresolved))
+
+ def container_of(self, parent, fieldname):
+ '''
+ Assume this struct is embedded in a larger struct and get at the larger
+
+ Python ``self.container_of(a, b)`` = C ``container_of(self, a, b)``
+
+ :param parent: class (not instance) of the larger struct
+ :param fieldname: fieldname that refers back to this
+ :returns: instance of parent, with fieldname set to this object
+ '''
+ offset = 0
+ if not hasattr(parent, '_efields'):
+ parent._setup_efields()
+
+ for field in parent._efields[self.elfclass]:
+ if field[0] == fieldname:
+ break
+ offset += struct.calcsize(field[1])
+ else:
+ raise AttributeError('%r not found in %r.fields' % (fieldname, parent))
+
+ return parent(self._data.offset(-offset), replace = {fieldname: self})
+
+class ELFDissectStruct(ELFDissectData):
+ '''
+ Decode and provide access to a struct somewhere in the ELF file
+
+ Handles pointers and strings somewhat nicely. Create a subclass for each
+ struct that is to be accessed, and give a field list in a "fields"
+ class-member.
+
+ :param dataptr: ELFData referring to the data bits to decode.
+ :param parent: where this was instantiated from; only for reference, has
+ no functional impact.
+ :param replace: substitute data values for specific fields. Used by
+ `container_of` to replace the inner struct when creating the outer
+ one.
+
+ .. attribute:: fields
+
+ List of tuples describing the struct members. Items can be:
+ - ``('name', ELFDissectData)`` - directly embed another struct
+ - ``('name', 'I')`` - simple data types; second item for struct.unpack
+ - ``('name', 'I', None)`` - field to ignore
+ - ``('name', 'P', str)`` - pointer to string
+ - ``('name', 'P', ELFDissectData)`` - pointer to another struct
+
+ ``P`` is added as unpack format for pointers (sized appropriately for
+ the ELF file.)
+
+ Refer to tiabwarfo.py for extracting this from ``pahole``.
+
+ TBD: replace tuples with a class.
+
+ .. attribute:: fieldrename
+
+ Dictionary to rename fields, useful if fields comes from tiabwarfo.py.
+ '''
+
+ class Pointer(object):
+ '''
+ Quick wrapper for pointers to further structs
+
+ This is just here to avoid going into infinite loops when loading
+ structs that have pointers to each other (e.g. struct xref <-->
+ struct xrefdata.) The pointer destination is only instantiated when
+ actually accessed.
+ '''
+ def __init__(self, cls, ptr):
+ self.cls = cls
+ self.ptr = ptr
+
+ def __repr__(self):
+ return '<Pointer:%s %r>' % (self.cls.__name__, self.ptr)
+
+ def __call__(self):
+ if isinstance(self.ptr, ELFNull):
+ return None
+ return self.cls(self.ptr)
+
+ def __new__(cls, dataptr, parent = None, replace = None):
+ if dataptr._dstsect is None:
+ return super().__new__(cls)
+
+ obj = dataptr._dstsect._pointers.get((cls, dataptr))
+ if obj is not None:
+ return obj
+ obj = super().__new__(cls)
+ dataptr._dstsect._pointers[(cls, dataptr)] = obj
+ return obj
+
+ replacements = 'lLnN'
+
+ @classmethod
+ def _preproc_structspec(cls, elfclass, spec):
+ elfbits = elfclass
+
+ if hasattr(spec, 'calcsize'):
+ spec = '%ds' % (spec.calcsize(elfclass),)
+
+ if elfbits == 32:
+ repl = ['i', 'I']
+ else:
+ repl = ['q', 'Q']
+ for c in cls.replacements:
+ spec = spec.replace(c, repl[int(c.isupper())])
+ return spec
+
+ @classmethod
+ def _setup_efields(cls):
+ cls._efields = {}
+ cls._esize = {}
+ for elfclass in [32, 64]:
+ cls._efields[elfclass] = []
+ size = 0
+ for f in cls.fields:
+ newf = (f[0], cls._preproc_structspec(elfclass, f[1])) + f[2:]
+ cls._efields[elfclass].append(newf)
+ size += struct.calcsize(newf[1])
+ cls._esize[elfclass] = size
+
+ def __init__(self, dataptr, parent = None, replace = None):
+ if not hasattr(self.__class__, '_efields'):
+ self._setup_efields()
+
+ self._fdata = None
+ self._data = dataptr
+ self._parent = parent
+ self.symname = dataptr.symname
+ if isinstance(dataptr, ELFNull) or isinstance(dataptr, ELFUnresolved):
+ self._fdata = {}
+ return
+
+ self._elfsect = dataptr._dstsect
+ self.elfclass = self._elfsect._elffile.elfclass
+ self.offset = dataptr._dstoffs
+
+ pspecl = [f[1] for f in self._efields[self.elfclass]]
+
+ # need to correlate output from struct.unpack with extra metadata
+ # about the particular fields, so note down byte offsets (in locs)
+ # and tuple indices of pointers (in ptrs)
+ pspec = ''
+ locs = {}
+ ptrs = set()
+
+ for idx, spec in enumerate(pspecl):
+ if spec == 'P':
+ ptrs.add(idx)
+ spec = self._elfsect.ptrtype
+
+ locs[idx] = struct.calcsize(pspec)
+ pspec = pspec + spec
+
+ self._total_size = struct.calcsize(pspec)
+
+ def replace_ptrs(v):
+ idx, val = v[0], v[1]
+ if idx not in ptrs:
+ return val
+ return self._elfsect.pointer(self.offset + locs[idx])
+
+ data = dataptr.get_data(struct.calcsize(pspec))
+ unpacked = struct.unpack(self._elfsect.endian + pspec, data)
+ unpacked = list(map(replace_ptrs, enumerate(unpacked)))
+ self._fraw = unpacked
+ self._fdata = OrderedDict()
+ replace = replace or {}
+
+ for i, item in enumerate(unpacked):
+ name = self.fields[i][0]
+ if name is None:
+ continue
+
+ if name in replace:
+ self._fdata[name] = replace[name]
+ continue
+
+ if isinstance(self.fields[i][1], type) and issubclass(self.fields[i][1], ELFDissectData):
+ dataobj = self.fields[i][1](dataptr.offset(locs[i]), self)
+ self._fdata[name] = dataobj
+ continue
+ if len(self.fields[i]) == 3:
+ if self.fields[i][2] == str:
+ self._fdata[name] = item.get_string()
+ continue
+ elif self.fields[i][2] is None:
+ pass
+ elif issubclass(self.fields[i][2], ELFDissectData):
+ cls = self.fields[i][2]
+ dataobj = self.Pointer(cls, item)
+ self._fdata[name] = dataobj
+ continue
+
+ self._fdata[name] = item
+
+ def __getattr__(self, attrname):
+ if attrname not in self._fdata:
+ raise AttributeError(attrname)
+ if isinstance(self._fdata[attrname], self.Pointer):
+ self._fdata[attrname] = self._fdata[attrname]()
+ return self._fdata[attrname]
+
+ def __repr__(self):
+ if not isinstance(self._data, ELFData):
+ return '<%s: %r>' % (self.__class__.__name__, self._data)
+ return '<%s: %s>' % (self.__class__.__name__,
+ ', '.join(['%s=%r' % t for t in self._fdata.items()]))
+
+ @classmethod
+ def calcsize(cls, elfclass):
+ '''
+ Sum up byte size of this struct
+
+ Wraps struct.calcsize with some extra features.
+ '''
+ if not hasattr(cls, '_efields'):
+ cls._setup_efields()
+
+ pspec = ''.join([f[1] for f in cls._efields[elfclass]])
+
+ ptrtype = 'I' if elfclass == 32 else 'Q'
+ pspec = pspec.replace('P', ptrtype)
+
+ return struct.calcsize(pspec)
+
+class ELFDissectUnion(ELFDissectData):
+ '''
+ Decode multiple structs in the same place.
+
+ Not currently used (and hence not tested.) Worked at some point but not
+ needed anymore and may be borked now. Remove this comment when using.
+ '''
+ def __init__(self, dataptr, parent = None):
+ self._dataptr = dataptr
+ self._parent = parent
+ self.members = []
+ for name, membercls in self.__class__.members:
+ item = membercls(dataptr, parent)
+ self.members.append(item)
+ setattr(self, name, item)
+
+ def __repr__(self):
+ return '<%s: %s>' % (self.__class__.__name__, ', '.join([repr(i) for i in self.members]))
+
+ @classmethod
+ def calcsize(cls, elfclass):
+ return max([member.calcsize(elfclass) for name, member in cls.members])
+
+#
+# wrappers for spans of ELF data
+#
+
+class ELFSubset(object):
+ '''
+ Common abstract base for section-level and file-level access.
+ '''
+
+ def __init__(self):
+ super().__init__()
+
+ self._pointers = WeakValueDictionary()
+
+ def __hash__(self):
+ return hash(self.name)
+
+ def __getitem__(self, k):
+ '''
+ Read data from slice
+
+ Subscript **must** be a slice; a simple index will not return a byte
+ but rather throw an exception. Valid slice syntaxes are defined by
+ the C module:
+
+ - `this[123:456]` - extract specific range
+ - `this[123:str]` - extract until null byte. The slice stop value is
+ the `str` type (or, technically, `unicode`.)
+ '''
+ return self._obj[k]
+
+ def getreloc(self, offset):
+ '''
+ Check for a relocation record at the specified offset.
+ '''
+ return self._obj.getreloc(offset)
+
+ def iter_data(self, scls, slice_ = slice(None)):
+ '''
+ Assume an array of structs present at a particular slice and decode
+
+ :param scls: ELFDissectData subclass for the struct
+ :param slice_: optional range specification
+ '''
+ size = scls.calcsize(self._elffile.elfclass)
+
+ offset = slice_.start or 0
+ stop = slice_.stop or self._obj.len
+ if stop < 0:
+ stop = self._obj.len - stop
+
+ while offset < stop:
+ yield scls(ELFData(self, offset, size))
+ offset += size
+
+ def pointer(self, offset):
+ '''
+ Try to dereference a pointer value
+
+ This checks whether there's a relocation at the given offset and
+ uses that; otherwise (e.g. in a non-PIE executable where the pointer
+ is already resolved by the linker) the data at the location is used.
+
+ :param offset: byte offset from beginning of section,
+ or virtual address in file
+ :returns: ELFData wrapping pointed-to object
+ '''
+
+ ptrsize = struct.calcsize(self.ptrtype)
+ data = struct.unpack(self.endian + self.ptrtype, self[offset:offset + ptrsize])[0]
+
+ reloc = self.getreloc(offset)
+ dstsect = None
+ if reloc:
+ # section won't be available in whole-file operation
+ dstsect = reloc.getsection(data)
+ addend = reloc.r_addend
+
+ if reloc.relative:
+ # old-style ELF REL instead of RELA, not well-tested
+ addend += data
+
+ if reloc.unresolved and reloc.symvalid:
+ return ELFUnresolved(reloc.symname, addend)
+ elif reloc.symvalid:
+ data = addend + reloc.st_value
+ else:
+ data = addend
+
+ # 0 could technically be a valid pointer for a shared library,
+ # since libraries may use 0 as default virtual start address (it'll
+ # be adjusted on loading)
+ # That said, if the library starts at 0, that's where the ELF header
+ # would be so it's still an invalid pointer.
+ if data == 0 and dstsect == None:
+ return ELFNull()
+
+ # wrap_data is different between file & section
+ return self._wrap_data(data, dstsect)
+
+class ELFDissectSection(ELFSubset):
+ '''
+ Access the contents of an ELF section like ``.text`` or ``.data``
+
+ :param elfwrap: ELFDissectFile wrapper for the file
+ :param idx: section index in section header table
+ :param section: section object from C module
+ '''
+
+ def __init__(self, elfwrap, idx, section):
+ super().__init__()
+
+ self._elfwrap = elfwrap
+ self._elffile = elfwrap._elffile
+ self._idx = idx
+ self._section = self._obj = section
+ self.name = section.name
+ self.ptrtype = elfwrap.ptrtype
+ self.endian = elfwrap.endian
+
+ def _wrap_data(self, data, dstsect):
+ if dstsect is None:
+ dstsect = self._elfwrap._elffile.get_section_addr(data)
+ offs = data - dstsect.sh_addr
+ dstsect = self._elfwrap.get_section(dstsect.idx)
+ return ELFData(dstsect, offs, None)
+
+class ELFDissectFile(ELFSubset):
+ '''
+ Access the contents of an ELF file.
+
+ Note that offsets for array subscript and relocation/pointer access are
+ based on the file's virtual address space and are NOT offsets to the
+ start of the file on disk!
+
+ (Shared libraries frequently have a virtual address space starting at 0,
+ but non-PIE executables have an architecture specific default loading
+ address like 0x400000 on x86.
+
+ :param filename: ELF file to open
+ '''
+
+ def __init__(self, filename):
+ super().__init__()
+
+ self.name = filename
+ self._elffile = self._obj = ELFFile(filename)
+ self._sections = {}
+
+ self.ptrtype = 'I' if self._elffile.elfclass == 32 else 'Q'
+ self.endian = '>' if self._elffile.bigendian else '<'
+
+ @property
+ def _elfwrap(self):
+ return self
+
+ def _wrap_data(self, data, dstsect):
+ return ELFData(self, data, None)
+
+ def get_section(self, secname):
+ '''
+ Look up section by name or index
+ '''
+ if isinstance(secname, int):
+ sh_idx = secname
+ section = self._elffile.get_section_idx(secname)
+ else:
+ section = self._elffile.get_section(secname)
+
+ if section is None:
+ return None
+
+ sh_idx = section.idx
+
+ if sh_idx not in self._sections:
+ self._sections[sh_idx] = ELFDissectSection(self, sh_idx, section)
+
+ return self._sections[sh_idx]
diff --git a/python/clippy/uidhash.py b/python/clippy/uidhash.py
new file mode 100644
index 0000000000..bf994d389e
--- /dev/null
+++ b/python/clippy/uidhash.py
@@ -0,0 +1,71 @@
+# xref unique ID hash calculation
+#
+# Copyright (C) 2020 David Lamparter for NetDEF, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; see the file COPYING; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import struct
+from hashlib import sha256
+
+def bititer(data, bits, startbit = True):
+ '''
+ just iterate the individual bits out from a bytes object
+
+ if startbit is True, an '1' bit is inserted at the very beginning
+ goes <bits> at a time, starts at LSB.
+ '''
+ bitavail, v = 0, 0
+ if startbit and len(data) > 0:
+ v = data.pop(0)
+ yield (v & ((1 << bits) - 1)) | (1 << (bits - 1))
+ bitavail = 9 - bits
+ v >>= bits - 1
+
+ while len(data) > 0:
+ while bitavail < bits:
+ v |= data.pop(0) << bitavail
+ bitavail += 8
+ yield v & ((1 << bits) - 1)
+ bitavail -= bits
+ v >>= bits
+
+def base32c(data):
+ '''
+ Crockford base32 with extra dashes
+ '''
+ chs = "0123456789ABCDEFGHJKMNPQRSTVWXYZ"
+ o = ''
+ if type(data) == str:
+ data = [ord(v) for v in data]
+ else:
+ data = list(data)
+ for i, bits in enumerate(bititer(data, 5)):
+ if i == 5:
+ o = o + '-'
+ elif i == 10:
+ break
+ o = o + chs[bits]
+ return o
+
+def uidhash(filename, hashstr, hashu32a, hashu32b):
+ '''
+ xref Unique ID hash used in FRRouting
+ '''
+ filename = '/'.join(filename.rsplit('/')[-2:])
+
+ hdata = filename.encode('UTF-8') + hashstr.encode('UTF-8')
+ hdata += struct.pack('>II', hashu32a, hashu32b)
+ i = sha256(hdata).digest()
+ return base32c(i)
diff --git a/python/makefile.py b/python/makefile.py
index 10c73df72d..44658013b3 100644
--- a/python/makefile.py
+++ b/python/makefile.py
@@ -31,6 +31,10 @@ clippy_scan = mv["clippy_scan"].strip().split()
for clippy_file in clippy_scan:
assert clippy_file.endswith(".c")
+xref_targets = []
+for varname in ["bin_PROGRAMS", "sbin_PROGRAMS", "lib_LTLIBRARIES", "module_LTLIBRARIES"]:
+ xref_targets.extend(mv[varname].strip().split())
+
# check for files using clippy but not listed in clippy_scan
if args.dev_build:
basepath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
@@ -125,6 +129,14 @@ for clippy_file in clippy_scan:
out_lines.append(clippydep.substitute(clippybase=clippy_file[:-2]))
out_lines.append("")
+out_lines.append("xrefs = %s" % (" ".join(["%s.xref" % target for target in xref_targets])))
+out_lines.append("frr.xref: $(xrefs)")
+out_lines.append("")
+
+#frr.xref: $(bin_PROGRAMS) $(sbin_PROGRAMS) $(lib_LTLIBRARIES) $(module_LTLIBRARIES)
+# $(AM_V_XRELFO) $(CLIPPY) $(top_srcdir)/python/xrelfo.py -o $@ $^
+
+out_lines.append("")
out_lines.extend(bcdeps)
out_lines.append("")
bc_targets = []
diff --git a/python/runtests.py b/python/runtests.py
new file mode 100644
index 0000000000..bcf650b329
--- /dev/null
+++ b/python/runtests.py
@@ -0,0 +1,14 @@
+import pytest
+import sys
+import os
+
+try:
+ import _clippy
+except ImportError:
+ sys.stderr.write('''these tests need to be run with the _clippy C extension
+module available. Try running "clippy runtests.py ...".
+''')
+ sys.exit(1)
+
+os.chdir(os.path.dirname(os.path.abspath(__file__)))
+raise SystemExit(pytest.main(sys.argv[1:]))
diff --git a/python/test_xrelfo.py b/python/test_xrelfo.py
new file mode 100644
index 0000000000..3ae24ea7b3
--- /dev/null
+++ b/python/test_xrelfo.py
@@ -0,0 +1,65 @@
+# some basic tests for xrelfo & the python ELF machinery
+#
+# Copyright (C) 2020 David Lamparter for NetDEF, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; see the file COPYING; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import sys
+import os
+import pytest
+from pprint import pprint
+
+root = os.path.dirname(os.path.dirname(__file__))
+sys.path.append(os.path.join(root, 'python'))
+
+import xrelfo
+from clippy import elf, uidhash
+
+def test_uidhash():
+ assert uidhash.uidhash("lib/test_xref.c", "logging call", 3, 0) \
+ == 'H7KJB-67TBH'
+
+def test_xrelfo_other():
+ for data in [
+ elf.ELFNull(),
+ elf.ELFUnresolved('somesym', 0),
+ ]:
+
+ dissect = xrelfo.XrefPtr(data)
+ print(repr(dissect))
+
+ with pytest.raises(AttributeError):
+ dissect.xref
+
+def test_xrelfo_obj():
+ xrelfo_ = xrelfo.Xrelfo()
+ edf = xrelfo_.load_elf(os.path.join(root, 'lib/.libs/zclient.o'), 'zclient.lo')
+ xrefs = xrelfo_._xrefs
+
+ with pytest.raises(elf.ELFAccessError):
+ edf[0:4]
+
+ pprint(xrefs[0])
+ pprint(xrefs[0]._data)
+
+def test_xrelfo_bin():
+ xrelfo_ = xrelfo.Xrelfo()
+ edf = xrelfo_.load_elf(os.path.join(root, 'lib/.libs/libfrr.so'), 'libfrr.la')
+ xrefs = xrelfo_._xrefs
+
+ assert edf[0:4] == b'\x7fELF'
+
+ pprint(xrefs[0])
+ pprint(xrefs[0]._data)
diff --git a/python/tiabwarfo.py b/python/tiabwarfo.py
new file mode 100644
index 0000000000..265173e314
--- /dev/null
+++ b/python/tiabwarfo.py
@@ -0,0 +1,203 @@
+# FRR DWARF structure definition extractor
+#
+# Copyright (C) 2020 David Lamparter for NetDEF, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; see the file COPYING; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import sys
+import os
+import subprocess
+import re
+import argparse
+import subprocess
+import json
+
+structs = ['xref', 'xref_logmsg', 'xref_threadsched', 'xref_install_element', 'xrefdata', 'xrefdata_logmsg', 'cmd_element']
+
+def extract(filename='lib/.libs/libfrr.so'):
+ '''
+ Convert output from "pahole" to JSON.
+
+ Example pahole output:
+ $ pahole -C xref lib/.libs/libfrr.so
+ struct xref {
+ struct xrefdata * xrefdata; /* 0 8 */
+ enum xref_type type; /* 8 4 */
+ int line; /* 12 4 */
+ const char * file; /* 16 8 */
+ const char * func; /* 24 8 */
+
+ /* size: 32, cachelines: 1, members: 5 */
+ /* last cacheline: 32 bytes */
+ };
+ '''
+ pahole = subprocess.check_output(['pahole', '-C', ','.join(structs), filename]).decode('UTF-8')
+
+ struct_re = re.compile(r'^struct ([^ ]+) \{([^\}]+)};', flags=re.M | re.S)
+ field_re = re.compile(r'^\s*(?P<type>[^;\(]+)\s+(?P<name>[^;\[\]]+)(?:\[(?P<array>\d+)\])?;\s*\/\*(?P<comment>.*)\*\/\s*$')
+ comment_re = re.compile(r'^\s*\/\*.*\*\/\s*$')
+
+ pastructs = struct_re.findall(pahole)
+ out = {}
+
+ for sname, data in pastructs:
+ this = out.setdefault(sname, {})
+ fields = this.setdefault('fields', [])
+
+ lines = data.strip().splitlines()
+
+ next_offs = 0
+
+ for line in lines:
+ if line.strip() == '':
+ continue
+ m = comment_re.match(line)
+ if m is not None:
+ continue
+
+ m = field_re.match(line)
+ if m is not None:
+ offs, size = m.group('comment').strip().split()
+ offs = int(offs)
+ size = int(size)
+ typ_ = m.group('type').strip()
+ name = m.group('name')
+
+ if name.startswith('(*'):
+ # function pointer
+ typ_ = typ_ + ' *'
+ name = name[2:].split(')')[0]
+
+ data = {
+ 'name': name,
+ 'type': typ_,
+ # 'offset': offs,
+ # 'size': size,
+ }
+ if m.group('array'):
+ data['array'] = int(m.group('array'))
+
+ fields.append(data)
+ if offs != next_offs:
+ raise ValueError('%d padding bytes before struct %s.%s' % (offs - next_offs, sname, name))
+ next_offs = offs + size
+ continue
+
+ raise ValueError('cannot process line: %s' % line)
+
+ return out
+
+class FieldApplicator(object):
+ '''
+ Fill ELFDissectStruct fields list from pahole/JSON
+
+ Uses the JSON file created by the above code to fill in the struct fields
+ in subclasses of ELFDissectStruct.
+ '''
+
+ # only what we really need. add more as needed.
+ packtypes = {
+ 'int': 'i',
+ 'uint8_t': 'B',
+ 'uint16_t': 'H',
+ 'uint32_t': 'I',
+ 'char': 's',
+ }
+
+ def __init__(self, data):
+ self.data = data
+ self.classes = []
+ self.clsmap = {}
+
+ def add(self, cls):
+ self.classes.append(cls)
+ self.clsmap[cls.struct] = cls
+
+ def resolve(self, cls):
+ out = []
+ #offset = 0
+
+ fieldrename = getattr(cls, 'fieldrename', {})
+ def mkname(n):
+ return (fieldrename.get(n, n),)
+
+ for field in self.data[cls.struct]['fields']:
+ typs = field['type'].split()
+ typs = [i for i in typs if i not in ['const']]
+
+ # this will break reuse of xrefstructs.json across 32bit & 64bit
+ # platforms
+
+ #if field['offset'] != offset:
+ # assert offset < field['offset']
+ # out.append(('_pad', '%ds' % (field['offset'] - offset,)))
+
+ # pretty hacky C types handling, but covers what we need
+
+ ptrlevel = 0
+ while typs[-1] == '*':
+ typs.pop(-1)
+ ptrlevel += 1
+
+ if ptrlevel > 0:
+ packtype = ('P', None)
+ if ptrlevel == 1:
+ if typs[0] == 'char':
+ packtype = ('P', str)
+ elif typs[0] == 'struct' and typs[1] in self.clsmap:
+ packtype = ('P', self.clsmap[typs[1]])
+ elif typs[0] == 'enum':
+ packtype = ('I',)
+ elif typs[0] in self.packtypes:
+ packtype = (self.packtypes[typs[0]],)
+ elif typs[0] == 'struct':
+ if typs[1] in self.clsmap:
+ packtype = (self.clsmap[typs[1]],)
+ else:
+ raise ValueError('embedded struct %s not in extracted data' % (typs[1],))
+ else:
+ raise ValueError('cannot decode field %s in struct %s (%s)' % (
+ cls.struct, field['name'], field['type']))
+
+ if 'array' in field and typs[0] == 'char':
+ packtype = ('%ds' % field['array'],)
+ out.append(mkname(field['name']) + packtype)
+ elif 'array' in field:
+ for i in range(0, field['array']):
+ out.append(mkname('%s_%d' % (field['name'], i)) + packtype)
+ else:
+ out.append(mkname(field['name']) + packtype)
+
+ #offset = field['offset'] + field['size']
+
+ cls.fields = out
+
+ def __call__(self):
+ for cls in self.classes:
+ self.resolve(cls)
+
+def main():
+ argp = argparse.ArgumentParser(description = 'FRR DWARF structure extractor')
+ argp.add_argument('-o', dest='output', type=str, help='write JSON output', default='python/xrefstructs.json')
+ argp.add_argument('-i', dest='input', type=str, help='ELF file to read', default='lib/.libs/libfrr.so')
+ args = argp.parse_args()
+
+ out = extract(args.input)
+ with open(args.output + '.tmp', 'w') as fd:
+ json.dump(out, fd, indent=2, sort_keys=True)
+ os.rename(args.output + '.tmp', args.output)
+
+if __name__ == '__main__':
+ main()
diff --git a/python/xrefstructs.json b/python/xrefstructs.json
new file mode 100644
index 0000000000..25c48c9d56
--- /dev/null
+++ b/python/xrefstructs.json
@@ -0,0 +1,140 @@
+{
+ "cmd_element": {
+ "fields": [
+ {
+ "name": "string",
+ "type": "const char *"
+ },
+ {
+ "name": "doc",
+ "type": "const char *"
+ },
+ {
+ "name": "daemon",
+ "type": "int"
+ },
+ {
+ "name": "attr",
+ "type": "uint32_t"
+ },
+ {
+ "name": "func",
+ "type": "int *"
+ },
+ {
+ "name": "name",
+ "type": "const char *"
+ },
+ {
+ "name": "xref",
+ "type": "struct xref"
+ }
+ ]
+ },
+ "xref": {
+ "fields": [
+ {
+ "name": "xrefdata",
+ "type": "struct xrefdata *"
+ },
+ {
+ "name": "type",
+ "type": "enum xref_type"
+ },
+ {
+ "name": "line",
+ "type": "int"
+ },
+ {
+ "name": "file",
+ "type": "const char *"
+ },
+ {
+ "name": "func",
+ "type": "const char *"
+ }
+ ]
+ },
+ "xref_install_element": {
+ "fields": [
+ {
+ "name": "xref",
+ "type": "struct xref"
+ },
+ {
+ "name": "cmd_element",
+ "type": "const struct cmd_element *"
+ },
+ {
+ "name": "node_type",
+ "type": "enum node_type"
+ }
+ ]
+ },
+ "xref_logmsg": {
+ "fields": [
+ {
+ "name": "xref",
+ "type": "struct xref"
+ },
+ {
+ "name": "fmtstring",
+ "type": "const char *"
+ },
+ {
+ "name": "priority",
+ "type": "uint32_t"
+ },
+ {
+ "name": "ec",
+ "type": "uint32_t"
+ },
+ {
+ "name": "args",
+ "type": "const char *"
+ }
+ ]
+ },
+ "xref_threadsched": {
+ "fields": [
+ {
+ "name": "xref",
+ "type": "struct xref"
+ },
+ {
+ "name": "funcname",
+ "type": "const char *"
+ },
+ {
+ "name": "dest",
+ "type": "const char *"
+ },
+ {
+ "name": "thread_type",
+ "type": "uint32_t"
+ }
+ ]
+ },
+ "xrefdata": {
+ "fields": [
+ {
+ "name": "xref",
+ "type": "const struct xref *"
+ },
+ {
+ "array": 16,
+ "name": "uid",
+ "type": "char"
+ },
+ {
+ "name": "hashstr",
+ "type": "const char *"
+ },
+ {
+ "array": 2,
+ "name": "hashu32",
+ "type": "uint32_t"
+ }
+ ]
+ }
+} \ No newline at end of file
diff --git a/python/xrelfo.py b/python/xrelfo.py
new file mode 100644
index 0000000000..0ecd008579
--- /dev/null
+++ b/python/xrelfo.py
@@ -0,0 +1,424 @@
+# FRR ELF xref extractor
+#
+# Copyright (C) 2020 David Lamparter for NetDEF, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; see the file COPYING; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+import sys
+import os
+import struct
+import re
+import traceback
+import json
+import argparse
+
+from clippy.uidhash import uidhash
+from clippy.elf import *
+from clippy import frr_top_src
+from tiabwarfo import FieldApplicator
+
+try:
+ with open(os.path.join(frr_top_src, 'python', 'xrefstructs.json'), 'r') as fd:
+ xrefstructs = json.load(fd)
+except FileNotFoundError:
+ sys.stderr.write('''
+The "xrefstructs.json" file (created by running tiabwarfo.py with the pahole
+tool available) could not be found. It should be included with the sources.
+''')
+ sys.exit(1)
+
+# constants, need to be kept in sync manually...
+
+XREFT_THREADSCHED = 0x100
+XREFT_LOGMSG = 0x200
+XREFT_DEFUN = 0x300
+XREFT_INSTALL_ELEMENT = 0x301
+
+# LOG_*
+priovals = {}
+prios = ['0', '1', '2', 'E', 'W', 'N', 'I', 'D']
+
+
+class XrelfoJson(object):
+ def dump(self):
+ pass
+
+ def check(self, wopt):
+ yield from []
+
+ def to_dict(self, refs):
+ pass
+
+class Xref(ELFDissectStruct, XrelfoJson):
+ struct = 'xref'
+ fieldrename = {'type': 'typ'}
+ containers = {}
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ self._container = None
+ if self.xrefdata:
+ self.xrefdata.ref_from(self, self.typ)
+
+ def container(self):
+ if self._container is None:
+ if self.typ in self.containers:
+ self._container = self.container_of(self.containers[self.typ], 'xref')
+ return self._container
+
+ def check(self, *args, **kwargs):
+ if self._container:
+ yield from self._container.check(*args, **kwargs)
+
+
+class Xrefdata(ELFDissectStruct):
+ struct = 'xrefdata'
+
+ # uid is all zeroes in the data loaded from ELF
+ fieldrename = {'uid': '_uid'}
+
+ def ref_from(self, xref, typ):
+ self.xref = xref
+
+ @property
+ def uid(self):
+ if self.hashstr is None:
+ return None
+ return uidhash(self.xref.file, self.hashstr, self.hashu32_0, self.hashu32_1)
+
+class XrefPtr(ELFDissectStruct):
+ fields = [
+ ('xref', 'P', Xref),
+ ]
+
+class XrefThreadSched(ELFDissectStruct, XrelfoJson):
+ struct = 'xref_threadsched'
+Xref.containers[XREFT_THREADSCHED] = XrefThreadSched
+
+class XrefLogmsg(ELFDissectStruct, XrelfoJson):
+ struct = 'xref_logmsg'
+
+ def _warn_fmt(self, text):
+ lines = text.split('\n')
+ yield ((self.xref.file, self.xref.line), '%s:%d: %s (in %s())%s\n' % (self.xref.file, self.xref.line, lines[0], self.xref.func, ''.join(['\n' + l for l in lines[1:]])))
+
+ fmt_regexes = [
+ (re.compile(r'([\n\t]+)'), 'error: log message contains tab or newline'),
+ # (re.compile(r'^(\s+)'), 'warning: log message starts with whitespace'),
+ (re.compile(r'^((?:warn(?:ing)?|error):\s*)', re.I), 'warning: log message starts with severity'),
+ ]
+ arg_regexes = [
+ # the (?<![\?:] ) avoids warning for x ? inet_ntop(...) : "(bla)"
+ (re.compile(r'((?<![\?:] )inet_ntop\s*\(\s*(?:[AP]F_INET|2)\s*,)'), 'cleanup: replace inet_ntop(AF_INET, ...) with %pI4', lambda s: True),
+ (re.compile(r'((?<![\?:] )inet_ntop\s*\(\s*(?:[AP]F_INET6|10)\s*,)'), 'cleanup: replace inet_ntop(AF_INET6, ...) with %pI6', lambda s: True),
+ (re.compile(r'((?<![\?:] )inet_ntoa)'), 'cleanup: replace inet_ntoa(...) with %pI4', lambda s: True),
+ (re.compile(r'((?<![\?:] )ipaddr2str)'), 'cleanup: replace ipaddr2str(...) with %pIA', lambda s: True),
+ (re.compile(r'((?<![\?:] )prefix2str)'), 'cleanup: replace prefix2str(...) with %pFX', lambda s: True),
+ (re.compile(r'((?<![\?:] )prefix_mac2str)'), 'cleanup: replace prefix_mac2str(...) with %pEA', lambda s: True),
+ (re.compile(r'((?<![\?:] )sockunion2str)'), 'cleanup: replace sockunion2str(...) with %pSU', lambda s: True),
+
+ # (re.compile(r'^(\s*__(?:func|FUNCTION|PRETTY_FUNCTION)__\s*)'), 'error: debug message starts with __func__', lambda s: (s.priority & 7 == 7) ),
+ ]
+
+ def check(self, wopt):
+ def fmt_msg(rex, itext):
+ if sys.stderr.isatty():
+ items = rex.split(itext)
+ out = []
+ for i, text in enumerate(items):
+ if (i % 2) == 1:
+ out.append('\033[41;37;1m%s\033[m' % repr(text)[1:-1])
+ else:
+ out.append(repr(text)[1:-1])
+
+ excerpt = ''.join(out)
+ else:
+ excerpt = repr(itext)[1:-1]
+ return excerpt
+
+ if wopt.Wlog_format:
+ for rex, msg in self.fmt_regexes:
+ if not rex.search(self.fmtstring):
+ continue
+
+ excerpt = fmt_msg(rex, self.fmtstring)
+ yield from self._warn_fmt('%s: "%s"' % (msg, excerpt))
+
+ if wopt.Wlog_args:
+ for rex, msg, cond in self.arg_regexes:
+ if not cond(self):
+ continue
+ if not rex.search(self.args):
+ continue
+
+ excerpt = fmt_msg(rex, self.args)
+ yield from self._warn_fmt('%s:\n\t"%s",\n\t%s' % (msg, repr(self.fmtstring)[1:-1], excerpt))
+
+ def dump(self):
+ print('%-60s %s%s %-25s [EC %d] %s' % (
+ '%s:%d %s()' % (self.xref.file, self.xref.line, self.xref.func),
+ prios[self.priority & 7],
+ priovals.get(self.priority & 0x30, ' '),
+ self.xref.xrefdata.uid, self.ec, self.fmtstring))
+
+ def to_dict(self, xrelfo):
+ jsobj = dict([(i, getattr(self.xref, i)) for i in ['file', 'line', 'func']])
+ if self.ec != 0:
+ jsobj['ec'] = self.ec
+ jsobj['fmtstring'] = self.fmtstring
+ jsobj['args'] = self.args
+ jsobj['priority'] = self.priority & 7
+ jsobj['type'] = 'logmsg'
+ jsobj['binary'] = self._elfsect._elfwrap.orig_filename
+
+ if self.priority & 0x10:
+ jsobj.setdefault('flags', []).append('errno')
+ if self.priority & 0x20:
+ jsobj.setdefault('flags', []).append('getaddrinfo')
+
+ xrelfo['refs'].setdefault(self.xref.xrefdata.uid, []).append(jsobj)
+
+Xref.containers[XREFT_LOGMSG] = XrefLogmsg
+
+class CmdElement(ELFDissectStruct, XrelfoJson):
+ struct = 'cmd_element'
+
+ cmd_attrs = { 0: None, 1: 'deprecated', 2: 'hidden'}
+
+ def __init__(self, *args, **kwargs):
+ super().__init__(*args, **kwargs)
+
+ def to_dict(self, xrelfo):
+ jsobj = xrelfo['cli'].setdefault(self.name, {}).setdefault(self._elfsect._elfwrap.orig_filename, {})
+
+ jsobj.update({
+ 'string': self.string,
+ 'doc': self.doc,
+ 'attr': self.cmd_attrs.get(self.attr, self.attr),
+ })
+ if jsobj['attr'] is None:
+ del jsobj['attr']
+
+ jsobj['defun'] = dict([(i, getattr(self.xref, i)) for i in ['file', 'line', 'func']])
+
+Xref.containers[XREFT_DEFUN] = CmdElement
+
+class XrefInstallElement(ELFDissectStruct, XrelfoJson):
+ struct = 'xref_install_element'
+
+ def to_dict(self, xrelfo):
+ jsobj = xrelfo['cli'].setdefault(self.cmd_element.name, {}).setdefault(self._elfsect._elfwrap.orig_filename, {})
+ nodes = jsobj.setdefault('nodes', [])
+
+ nodes.append({
+ 'node': self.node_type,
+ 'install': dict([(i, getattr(self.xref, i)) for i in ['file', 'line', 'func']]),
+ })
+
+Xref.containers[XREFT_INSTALL_ELEMENT] = XrefInstallElement
+
+# shove in field defs
+fieldapply = FieldApplicator(xrefstructs)
+fieldapply.add(Xref)
+fieldapply.add(Xrefdata)
+fieldapply.add(XrefLogmsg)
+fieldapply.add(XrefThreadSched)
+fieldapply.add(CmdElement)
+fieldapply.add(XrefInstallElement)
+fieldapply()
+
+
+class Xrelfo(dict):
+ def __init__(self):
+ super().__init__({
+ 'refs': {},
+ 'cli': {},
+ })
+ self._xrefs = []
+
+ def load_file(self, filename):
+ orig_filename = filename
+ if filename.endswith('.la') or filename.endswith('.lo'):
+ with open(filename, 'r') as fd:
+ for line in fd:
+ line = line.strip()
+ if line.startswith('#') or line == '' or '=' not in line:
+ continue
+
+ var, val = line.split('=', 1)
+ if var not in ['library_names', 'pic_object']:
+ continue
+ if val.startswith("'") or val.startswith('"'):
+ val = val[1:-1]
+
+ if var == 'pic_object':
+ filename = os.path.join(os.path.dirname(filename), val)
+ break
+
+ val = val.strip().split()[0]
+ filename = os.path.join(os.path.dirname(filename), '.libs', val)
+ break
+ else:
+ raise ValueError('could not process libtool file "%s"' % orig_filename)
+
+ while True:
+ with open(filename, 'rb') as fd:
+ hdr = fd.read(4)
+
+ if hdr == b'\x7fELF':
+ self.load_elf(filename, orig_filename)
+ return
+
+ if hdr[:2] == b'#!':
+ path, name = os.path.split(filename)
+ filename = os.path.join(path, '.libs', name)
+ continue
+
+ if hdr[:1] == b'{':
+ with open(filename, 'r') as fd:
+ self.load_json(fd)
+ return
+
+ raise ValueError('cannot determine file type for %s' % (filename))
+
+ def load_elf(self, filename, orig_filename):
+ edf = ELFDissectFile(filename)
+ edf.orig_filename = orig_filename
+
+ note = edf._elffile.find_note('FRRouting', 'XREF')
+ if note is not None:
+ endian = '>' if edf._elffile.bigendian else '<'
+ mem = edf._elffile[note]
+ if edf._elffile.elfclass == 64:
+ start, end = struct.unpack(endian + 'QQ', mem)
+ start += note.start
+ end += note.start + 8
+ else:
+ start, end = struct.unpack(endian + 'II', mem)
+ start += note.start
+ end += note.start + 4
+
+ ptrs = edf.iter_data(XrefPtr, slice(start, end))
+
+ else:
+ xrefarray = edf.get_section('xref_array')
+ if xrefarray is None:
+ raise ValueError('file has neither xref note nor xref_array section')
+
+ ptrs = xrefarray.iter_data(XrefPtr)
+
+ for ptr in ptrs:
+ if ptr.xref is None:
+ print('NULL xref')
+ continue
+ self._xrefs.append(ptr.xref)
+
+ container = ptr.xref.container()
+ if container is None:
+ continue
+ container.to_dict(self)
+
+ return edf
+
+ def load_json(self, fd):
+ data = json.load(fd)
+ for uid, items in data['refs'].items():
+ myitems = self['refs'].setdefault(uid, [])
+ for item in items:
+ if item in myitems:
+ continue
+ myitems.append(item)
+
+ for cmd, items in data['cli'].items():
+ self['cli'].setdefault(cmd, {}).update(items)
+
+ return data
+
+ def check(self, checks):
+ for xref in self._xrefs:
+ yield from xref.check(checks)
+
+def main():
+ argp = argparse.ArgumentParser(description = 'FRR xref ELF extractor')
+ argp.add_argument('-o', dest='output', type=str, help='write JSON output')
+ argp.add_argument('--out-by-file', type=str, help='write by-file JSON output')
+ argp.add_argument('-Wlog-format', action='store_const', const=True)
+ argp.add_argument('-Wlog-args', action='store_const', const=True)
+ argp.add_argument('--profile', action='store_const', const=True)
+ argp.add_argument('binaries', metavar='BINARY', nargs='+', type=str, help='files to read (ELF files or libtool objects)')
+ args = argp.parse_args()
+
+ if args.profile:
+ import cProfile
+ cProfile.runctx('_main(args)', globals(), {'args': args}, sort='cumtime')
+ else:
+ _main(args)
+
+def _main(args):
+ errors = 0
+ xrelfo = Xrelfo()
+
+ for fn in args.binaries:
+ try:
+ xrelfo.load_file(fn)
+ except:
+ errors += 1
+ sys.stderr.write('while processing %s:\n' % (fn))
+ traceback.print_exc()
+
+ for option in dir(args):
+ if option.startswith('W'):
+ checks = sorted(xrelfo.check(args))
+ sys.stderr.write(''.join([c[-1] for c in checks]))
+ break
+
+
+ refs = xrelfo['refs']
+
+ counts = {}
+ for k, v in refs.items():
+ strs = set([i['fmtstring'] for i in v])
+ if len(strs) != 1:
+ print('\033[31;1m%s\033[m' % k)
+ counts[k] = len(v)
+
+ out = xrelfo
+ outbyfile = {}
+ for uid, locs in refs.items():
+ for loc in locs:
+ filearray = outbyfile.setdefault(loc['file'], [])
+ loc = dict(loc)
+ del loc['file']
+ filearray.append(loc)
+
+ for k in outbyfile.keys():
+ outbyfile[k] = sorted(outbyfile[k], key=lambda x: x['line'])
+
+ if errors:
+ sys.exit(1)
+
+ if args.output:
+ with open(args.output + '.tmp', 'w') as fd:
+ json.dump(out, fd, indent=2, sort_keys=True)
+ os.rename(args.output + '.tmp', args.output)
+
+ if args.out_by_file:
+ with open(args.out_by_file + '.tmp', 'w') as fd:
+ json.dump(outbyfile, fd, indent=2, sort_keys=True)
+ os.rename(args.out_by_file + '.tmp', args.out_by_file)
+
+if __name__ == '__main__':
+ main()
diff --git a/ripd/ripd.c b/ripd/ripd.c
index a276dedec8..4a56efb6f8 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -698,7 +698,6 @@ static void rip_packet_dump(struct rip_packet *packet, int size,
caddr_t lim;
struct rte *rte;
const char *command_str;
- char pbuf[BUFSIZ], nbuf[BUFSIZ];
uint8_t netmask = 0;
uint8_t *p;
@@ -766,24 +765,18 @@ static void rip_packet_dump(struct rip_packet *packet, int size,
}
} else
zlog_debug(
- " %s/%d -> %s family %d tag %" ROUTE_TAG_PRI
+ " %pI4/%d -> %pI4 family %d tag %" ROUTE_TAG_PRI
" metric %ld",
- inet_ntop(AF_INET, &rte->prefix, pbuf,
- BUFSIZ),
- netmask,
- inet_ntop(AF_INET, &rte->nexthop, nbuf,
- BUFSIZ),
+ &rte->prefix, netmask, &rte->nexthop,
ntohs(rte->family),
(route_tag_t)ntohs(rte->tag),
(unsigned long)ntohl(rte->metric));
} else {
- zlog_debug(
- " %s family %d tag %" ROUTE_TAG_PRI
- " metric %ld",
- inet_ntop(AF_INET, &rte->prefix, pbuf, BUFSIZ),
- ntohs(rte->family),
- (route_tag_t)ntohs(rte->tag),
- (unsigned long)ntohl(rte->metric));
+ zlog_debug(" %pI4 family %d tag %" ROUTE_TAG_PRI
+ " metric %ld",
+ &rte->prefix, ntohs(rte->family),
+ (route_tag_t)ntohs(rte->tag),
+ (unsigned long)ntohl(rte->metric));
}
}
}
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index a9f570598f..37e23046e8 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -351,8 +351,6 @@ void ripng_packet_dump(struct ripng_packet *packet, int size,
static void ripng_nexthop_rte(struct rte *rte, struct sockaddr_in6 *from,
struct ripng_nexthop *nexthop)
{
- char buf[INET6_BUFSIZ];
-
/* Logging before checking RTE. */
if (IS_RIPNG_DEBUG_RECV)
zlog_debug("RIPng nexthop RTE address %s tag %" ROUTE_TAG_PRI
@@ -398,9 +396,8 @@ static void ripng_nexthop_rte(struct rte *rte, struct sockaddr_in6 *from,
information is ignored, a possibly sub-optimal, but absolutely
valid, route may be taken. If the received next hop address is not
a link-local address, it should be treated as 0:0:0:0:0:0:0:0. */
- zlog_warn("RIPng nexthop RTE with non link-local address %s from %s",
- inet6_ntoa(rte->addr),
- inet_ntop(AF_INET6, &from->sin6_addr, buf, INET6_BUFSIZ));
+ zlog_warn("RIPng nexthop RTE with non link-local address %s from %pI6",
+ inet6_ntoa(rte->addr), &from->sin6_addr);
nexthop->flag = RIPNG_NEXTHOP_UNSPEC;
memset(&nexthop->address, 0, sizeof(struct in6_addr));
diff --git a/sharpd/sharp_zebra.c b/sharpd/sharp_zebra.c
index fed732b843..0095aed547 100644
--- a/sharpd/sharp_zebra.c
+++ b/sharpd/sharp_zebra.c
@@ -638,7 +638,6 @@ void sharp_zebra_nexthop_watch(struct prefix *p, vrf_id_t vrf_id, bool import,
static int sharp_debug_nexthops(struct zapi_route *api)
{
int i;
- char buf[PREFIX_STRLEN];
if (api->nexthop_num == 0) {
zlog_debug(
@@ -653,20 +652,16 @@ static int sharp_debug_nexthops(struct zapi_route *api)
case NEXTHOP_TYPE_IPV4_IFINDEX:
case NEXTHOP_TYPE_IPV4:
zlog_debug(
- " Nexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
- inet_ntop(AF_INET, &znh->gate.ipv4.s_addr, buf,
- sizeof(buf)),
- znh->type, znh->ifindex, znh->vrf_id,
- znh->label_num);
+ " Nexthop %pI4, type: %d, ifindex: %d, vrf: %d, label_num: %d",
+ &znh->gate.ipv4.s_addr, znh->type, znh->ifindex,
+ znh->vrf_id, znh->label_num);
break;
case NEXTHOP_TYPE_IPV6_IFINDEX:
case NEXTHOP_TYPE_IPV6:
zlog_debug(
- " Nexthop %s, type: %d, ifindex: %d, vrf: %d, label_num: %d",
- inet_ntop(AF_INET6, &znh->gate.ipv6, buf,
- sizeof(buf)),
- znh->type, znh->ifindex, znh->vrf_id,
- znh->label_num);
+ " Nexthop %pI6, type: %d, ifindex: %d, vrf: %d, label_num: %d",
+ &znh->gate.ipv6, znh->type, znh->ifindex,
+ znh->vrf_id, znh->label_num);
break;
case NEXTHOP_TYPE_IFINDEX:
zlog_debug(" Nexthop IFINDEX: %d, ifindex: %d",
diff --git a/staticd/static_main.c b/staticd/static_main.c
index ac8f8ff029..560814771d 100644
--- a/staticd/static_main.c
+++ b/staticd/static_main.c
@@ -164,6 +164,8 @@ int main(int argc, char **argv, char **envp)
hook_register(routing_conf_event,
routing_control_plane_protocols_name_validate);
+ routing_control_plane_protocols_register_vrf_dependency();
+
snprintf(backup_config_file, sizeof(backup_config_file),
"%s/zebra.conf", frr_sysconfdir);
staticd_di.backup_config_file = backup_config_file;
diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c
index 3f1d0aa496..db154992f9 100644
--- a/staticd/static_nb_config.c
+++ b/staticd/static_nb_config.c
@@ -103,10 +103,32 @@ static void static_path_list_tag_modify(struct nb_cb_modify_args *args,
static_install_path(rn, pn, info->safi, info->svrf);
}
+struct nexthop_iter {
+ int count;
+ bool blackhole;
+};
+
+static int nexthop_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+ struct nexthop_iter *iter = arg;
+ int nh_type;
+
+ nh_type = yang_dnode_get_enum(dnode, "./nh-type");
+
+ if (nh_type == STATIC_BLACKHOLE)
+ iter->blackhole = true;
+
+ iter->count++;
+
+ return YANG_ITER_CONTINUE;
+}
+
static bool static_nexthop_create(struct nb_cb_create_args *args,
const struct lyd_node *rn_dnode,
struct stable_info *info)
{
+ const struct lyd_node *pn_dnode;
+ struct nexthop_iter iter;
struct route_node *rn;
struct static_path *pn;
struct ipaddr ipaddr;
@@ -128,6 +150,20 @@ static bool static_nexthop_create(struct nb_cb_create_args *args,
return NB_ERR_VALIDATION;
}
}
+
+ iter.count = 0;
+ iter.blackhole = false;
+
+ pn_dnode = yang_dnode_get_parent(args->dnode, "path-list");
+ yang_dnode_iterate(nexthop_iter_cb, &iter, pn_dnode,
+ "./frr-nexthops/nexthop");
+
+ if (iter.blackhole && iter.count > 1) {
+ snprintf(
+ args->errmsg, args->errmsg_len,
+ "Route can not have blackhole and non-blackhole nexthops simultaneously");
+ return NB_ERR_VALIDATION;
+ }
break;
case NB_EV_PREPARE:
case NB_EV_ABORT:
diff --git a/staticd/static_vty.c b/staticd/static_vty.c
index 1488cc1775..dd03f83778 100644
--- a/staticd/static_vty.c
+++ b/staticd/static_vty.c
@@ -294,8 +294,11 @@ static int static_route_leak(struct vty *vty, const char *svrf,
buf_gate_str, ifname);
dnode = yang_dnode_get(vty->candidate_config->dnode, ab_xpath);
- if (!dnode)
+ if (!dnode) {
+ vty_out(vty,
+ "%% Refusing to remove a non-existent route\n");
return ret;
+ }
dnode = yang_get_subtree_with_no_sibling(dnode);
assert(dnode);
diff --git a/tests/bgpd/test_aspath.c b/tests/bgpd/test_aspath.c
index 936ffaaad5..1a9183c472 100644
--- a/tests/bgpd/test_aspath.c
+++ b/tests/bgpd/test_aspath.c
@@ -892,7 +892,7 @@ static int validate(struct aspath *as, const struct test_spec *sp)
/* Excercise AS4 parsing a bit, with a dogfood test */
if (!s)
- s = stream_new(4096);
+ s = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
bytes4 = aspath_put(s, as, 1);
as4 = make_aspath(STREAM_DATA(s), bytes4, 1);
@@ -1201,12 +1201,13 @@ static int handle_attr_test(struct aspath_tests *t)
asp = make_aspath(t->segment->asdata, t->segment->len, 0);
- peer.curr = stream_new(BGP_MAX_PACKET_SIZE);
+ peer.curr = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
peer.obuf = stream_fifo_new();
peer.bgp = &bgp;
peer.host = (char *)"none";
peer.fd = -1;
peer.cap = t->cap;
+ peer.max_packet_size = BGP_MAX_PACKET_SIZE;
stream_write(peer.curr, t->attrheader, t->len);
datalen = aspath_put(peer.curr, asp, t->as4 == AS4_DATA);
diff --git a/tests/bgpd/test_capability.c b/tests/bgpd/test_capability.c
index 153b83897d..91c0cce80c 100644
--- a/tests/bgpd/test_capability.c
+++ b/tests/bgpd/test_capability.c
@@ -935,7 +935,7 @@ int main(void)
peer->afc_adv[i][j] = 1;
}
- peer->curr = stream_new(BGP_MAX_PACKET_SIZE);
+ peer->curr = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
i = 0;
while (mp_segments[i].name)
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
index f510760913..8de0604c45 100644
--- a/tests/bgpd/test_mp_attr.c
+++ b/tests/bgpd/test_mp_attr.c
@@ -1100,7 +1100,7 @@ int main(void)
peer = peer_create_accept(bgp);
peer->host = (char *)"foo";
peer->status = Established;
- peer->curr = stream_new(BGP_MAX_PACKET_SIZE);
+ peer->curr = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
ifp.ifindex = 0;
peer->nexthop.ifp = &ifp;
diff --git a/tests/isisd/test_isis_spf.refout b/tests/isisd/test_isis_spf.refout
index 024f7256e0..bdd5b2e439 100644
--- a/tests/isisd/test_isis_spf.refout
+++ b/tests/isisd/test_isis_spf.refout
@@ -3146,9 +3146,9 @@ rt3 TE-IS 50 rt5 - rt5(4)
IS-IS L1 IPv4 routing table:
- Prefix Metric Interface Nexthop Label(s)
- -----------------------------------------------------------
- 10.0.255.3/32 60 - rt5 16050/18/16030
+ Prefix Metric Interface Nexthop Label(s)
+ -----------------------------------------------------
+ 10.0.255.3/32 60 - rt5 16050/18
P-space (self):
rt2
@@ -3194,9 +3194,9 @@ rt3 TE-IS 50 rt5 - rt5(4)
IS-IS L1 IPv6 routing table:
- Prefix Metric Interface Nexthop Label(s)
- -------------------------------------------------------------
- 2001:db8::3/128 60 - rt5 16051/19/16031
+ Prefix Metric Interface Nexthop Label(s)
+ -------------------------------------------------------
+ 2001:db8::3/128 60 - rt5 16051/19
test# test isis topology 2 root rt1 ti-lfa system-id rt1 pseudonode-id 1
P-space (self):
@@ -3236,7 +3236,7 @@ IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s)
-----------------------------------------------------------
- 10.0.255.4/32 65 - rt2 16020/18/16040
+ 10.0.255.4/32 65 - rt2 16020/18
10.0.255.5/32 75 - rt2 16020/18/16050
10.0.255.6/32 75 - rt2 16020/18/16060
@@ -3277,7 +3277,7 @@ IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s)
-------------------------------------------------------------
- 2001:db8::4/128 65 - rt2 16021/19/16041
+ 2001:db8::4/128 65 - rt2 16021/19
2001:db8::5/128 75 - rt2 16021/19/16051
2001:db8::6/128 75 - rt2 16021/19/16061
@@ -3508,7 +3508,7 @@ IS-IS L1 IPv4 routing table:
-----------------------------------------------------------
10.0.255.2/32 100 - rt3 16050/17/16020
10.0.255.4/32 90 - rt3 16050/17/16040
- 10.0.255.6/32 80 - rt3 16050/17/16060
+ 10.0.255.6/32 80 - rt3 16050/17
10.0.255.8/32 90 - rt3 16050/17/16080
test# test isis topology 4 root rt4 ti-lfa system-id rt6 ipv4-only
@@ -3553,7 +3553,7 @@ IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s)
-----------------------------------------------------------
- 10.0.255.6/32 100 - rt2 16050/17/16060
+ 10.0.255.6/32 100 - rt2 16050/17
10.0.255.8/32 110 - rt2 16050/17/16080
test# test isis topology 5 root rt1 ti-lfa system-id rt2 ipv4-only
@@ -3865,7 +3865,7 @@ IS-IS L1 IPv4 routing table:
10.0.255.1/32 100 - rt5 16110/17/16010
10.0.255.4/32 90 - rt5 16110/17/16040
10.0.255.7/32 80 - rt5 16110/17/16070
- 10.0.255.10/32 70 - rt5 16110/17/16100
+ 10.0.255.10/32 70 - rt5 16110/17
test# test isis topology 8 root rt2 ti-lfa system-id rt5 ipv4-only
P-space (self):
@@ -3979,9 +3979,9 @@ rt3 TE-IS 120 rt2 - rt4(4)
IS-IS L1 IPv4 routing table:
- Prefix Metric Interface Nexthop Label(s)
- -----------------------------------------------------------
- 10.0.255.3/32 130 - rt2 16040/18/16030
+ Prefix Metric Interface Nexthop Label(s)
+ -----------------------------------------------------
+ 10.0.255.3/32 130 - rt2 16040/18
P-space (self):
rt2
@@ -4030,9 +4030,9 @@ rt3 TE-IS 120 rt2 - rt4(4)
IS-IS L1 IPv6 routing table:
- Prefix Metric Interface Nexthop Label(s)
- -------------------------------------------------------------
- 2001:db8::3/128 130 - rt2 16041/19/16031
+ Prefix Metric Interface Nexthop Label(s)
+ -------------------------------------------------------
+ 2001:db8::3/128 130 - rt2 16041/19
test# test isis topology 9 root rt1 ti-lfa system-id rt2
P-space (self):
@@ -4079,7 +4079,7 @@ IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s)
-----------------------------------------------------------
10.0.255.2/32 130 - rt3 16030/18/16020
- 10.0.255.4/32 120 - rt3 16030/18/16040
+ 10.0.255.4/32 120 - rt3 16030/18
10.0.255.5/32 130 - rt3 16030/18/16050
10.0.255.6/32 150 - rt3 16030/18/16060
10.0.255.7/32 150 - rt3 16030/18/16070
@@ -4130,7 +4130,7 @@ IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s)
-------------------------------------------------------------
2001:db8::2/128 130 - rt3 16031/19/16021
- 2001:db8::4/128 120 - rt3 16031/19/16041
+ 2001:db8::4/128 120 - rt3 16031/19
2001:db8::5/128 130 - rt3 16031/19/16051
2001:db8::6/128 150 - rt3 16031/19/16061
2001:db8::7/128 150 - rt3 16031/19/16071
@@ -4213,9 +4213,9 @@ IS-IS L1 IPv4 routing table:
10.0.255.3/32 80 - rt6 16060/16/16030
- rt7 16070/16/16030
- rt8 16080/16/16030
- 10.0.255.4/32 50 - rt6 16060/16/16040
- - rt7 16070/16/16040
- - rt8 16080/16/16040
+ 10.0.255.4/32 50 - rt6 16060/16
+ - rt7 16070/16
+ - rt8 16080/16
10.0.255.5/32 60 - rt6 16060/16/16050
- rt7 16070/16/16050
- rt8 16080/16/16050
@@ -4295,9 +4295,9 @@ IS-IS L1 IPv6 routing table:
2001:db8::3/128 80 - rt6 16061/17/16031
- rt7 16071/17/16031
- rt8 16081/17/16031
- 2001:db8::4/128 50 - rt6 16061/17/16041
- - rt7 16071/17/16041
- - rt8 16081/17/16041
+ 2001:db8::4/128 50 - rt6 16061/17
+ - rt7 16071/17
+ - rt8 16081/17
2001:db8::5/128 60 - rt6 16061/17/16051
- rt7 16071/17/16051
- rt8 16081/17/16051
@@ -4351,9 +4351,9 @@ rt3 TE-IS 50 rt5 - rt1(4)
IS-IS L1 IPv4 routing table:
- Prefix Metric Interface Nexthop Label(s)
- -----------------------------------------------------------
- 10.0.255.8/32 60 - rt5 16040/26/16080
+ Prefix Metric Interface Nexthop Label(s)
+ -----------------------------------------------------
+ 10.0.255.8/32 60 - rt5 16040/26
P-space (self):
rt1
@@ -4403,9 +4403,9 @@ rt3 TE-IS 50 rt5 - rt1(4)
IS-IS L1 IPv6 routing table:
- Prefix Metric Interface Nexthop Label(s)
- -------------------------------------------------------------
- 2001:db8::8/128 60 - rt5 16041/27/16081
+ Prefix Metric Interface Nexthop Label(s)
+ -------------------------------------------------------
+ 2001:db8::8/128 60 - rt5 16041/27
test# test isis topology 10 root rt1 ti-lfa system-id rt2
P-space (self):
@@ -4460,8 +4460,8 @@ IS-IS L1 IPv4 routing table:
- rt4 16070/18/16020
10.0.255.5/32 100 - rt3 20060/18/16050
- rt4 16070/18/16050
- 10.0.255.8/32 90 - rt3 20060/18/16080
- - rt4 16070/18/16080
+ 10.0.255.8/32 90 - rt3 20060/18
+ - rt4 16070/18
P-space (self):
rt3
@@ -4515,8 +4515,8 @@ IS-IS L1 IPv6 routing table:
- rt4 16071/19/16021
2001:db8::5/128 100 - rt3 20061/19/16051
- rt4 16071/19/16051
- 2001:db8::8/128 90 - rt3 20061/19/16081
- - rt4 16071/19/16081
+ 2001:db8::8/128 90 - rt3 20061/19
+ - rt4 16071/19
test# test isis topology 10 root rt1 ti-lfa system-id rt4
P-space (self):
@@ -4563,7 +4563,7 @@ IS-IS L1 IPv4 routing table:
Prefix Metric Interface Nexthop Label(s)
-----------------------------------------------------------
10.0.255.4/32 100 - rt2 16080/20/16040
- 10.0.255.7/32 90 - rt2 16080/20/16070
+ 10.0.255.7/32 90 - rt2 16080/20
P-space (self):
rt2
@@ -4609,7 +4609,7 @@ IS-IS L1 IPv6 routing table:
Prefix Metric Interface Nexthop Label(s)
-------------------------------------------------------------
2001:db8::4/128 100 - rt2 16081/21/16041
- 2001:db8::7/128 90 - rt2 16081/21/16071
+ 2001:db8::7/128 90 - rt2 16081/21
test# test isis topology 11 root rt2 ti-lfa system-id rt4
P-space (self):
@@ -4747,12 +4747,12 @@ rt3 TE-IS 740 rt2 - rt5(4)
IS-IS L1 IPv4 routing table:
- Prefix Metric Interface Nexthop Label(s)
- -----------------------------------------------------------------
- 10.0.255.3/32 750 - rt2 16080/17/16/16/16030
- 10.0.255.5/32 350 - rt2 16080/17/16/16050
- 10.0.255.7/32 150 - rt2 16080/17/16070
- 10.0.255.9/32 160 - rt2 16080/17/18/16090
+ Prefix Metric Interface Nexthop Label(s)
+ -----------------------------------------------------------
+ 10.0.255.3/32 750 - rt2 16080/17/16/16
+ 10.0.255.5/32 350 - rt2 16080/17/16
+ 10.0.255.7/32 150 - rt2 16080/17
+ 10.0.255.9/32 160 - rt2 16080/17/18
test# test isis topology 13 root rt1 ti-lfa system-id rt3 ipv4-only
P-space (self):
diff --git a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
index 5942aca71d..c858571254 100644
--- a/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
+++ b/tests/topotests/all-protocol-startup/test_all_protocol_startup.py
@@ -43,6 +43,16 @@ from mininet.link import Intf
from functools import partial
+pytestmark = [
+ pytest.mark.babeld,
+ pytest.mark.bgpd,
+ pytest.mark.isisd,
+ pytest.mark.nhrpd,
+ pytest.mark.ospfd,
+ pytest.mark.pbrd,
+ pytest.mark.ripd,
+]
+
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
from lib import topotest
@@ -83,9 +93,6 @@ class NetworkTopo(Topo):
#####################################################
-@pytest.mark.isis
-@pytest.mark.ospf
-@pytest.mark.rip
def setup_module(module):
global topo, net
global fatal_error
@@ -339,13 +346,15 @@ def test_converge_protocols():
print("Show that v4 routes are right\n")
v4_routesFile = "%s/r%s/ipv4_routes.ref" % (thisDir, i)
- expected = open(v4_routesFile).read().rstrip()
+ expected = net["r%s" % i].cmd(
+ "sort {} 2> /dev/null".format(v4_routesFile)
+ ).rstrip()
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
actual = (
net["r%s" % i]
.cmd(
- 'vtysh -c "show ip route" | sed -e \'/^Codes: /,/^\s*$/d\' | env LC_ALL=en_US.UTF-8 sort 2> /dev/null'
+ "vtysh -c \"show ip route\" | sed -e '/^Codes: /,/^\s*$/d' | sort 2> /dev/null"
)
.rstrip()
)
@@ -370,13 +379,15 @@ def test_converge_protocols():
print("Show that v6 routes are right\n")
v6_routesFile = "%s/r%s/ipv6_routes.ref" % (thisDir, i)
- expected = open(v6_routesFile).read().rstrip()
+ expected = net["r%s" % i].cmd(
+ "sort {} 2> /dev/null".format(v6_routesFile)
+ ).rstrip()
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
actual = (
net["r%s" % i]
.cmd(
- 'vtysh -c "show ipv6 route" | sed -e \'/^Codes: /,/^\s*$/d\' | env LC_ALL=en_US.UTF-8 sort 2> /dev/null'
+ "vtysh -c \"show ipv6 route\" | sed -e '/^Codes: /,/^\s*$/d' | sort 2> /dev/null"
)
.rstrip()
)
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 cc1c1e3a0c..560d6eebec 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
@@ -44,6 +44,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd, pytest.mark.bfdd]
+
class BFDTopo(Topo):
"Test topology builder"
@@ -64,7 +66,7 @@ class BFDTopo(Topo):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r3"])
-@pytest.mark.bfd
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(BFDTopo, mod.__name__)
diff --git a/tests/topotests/bfd-isis-topo1/test_bfd_isis_topo1.py b/tests/topotests/bfd-isis-topo1/test_bfd_isis_topo1.py
index 23da7ed850..fcb5672dce 100644
--- a/tests/topotests/bfd-isis-topo1/test_bfd_isis_topo1.py
+++ b/tests/topotests/bfd-isis-topo1/test_bfd_isis_topo1.py
@@ -90,6 +90,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bfdd, pytest.mark.isisd]
+
class TemplateTopo(Topo):
"Test topology builder"
@@ -127,8 +129,7 @@ class TemplateTopo(Topo):
switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
-@pytest.mark.bfd
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
diff --git a/tests/topotests/bfd-ospf-topo1/test_bfd_ospf_topo1.py b/tests/topotests/bfd-ospf-topo1/test_bfd_ospf_topo1.py
index 1cec62789b..ae148f948c 100755
--- a/tests/topotests/bfd-ospf-topo1/test_bfd_ospf_topo1.py
+++ b/tests/topotests/bfd-ospf-topo1/test_bfd_ospf_topo1.py
@@ -90,6 +90,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bfdd, pytest.mark.ospfd]
+
class TemplateTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py b/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py
index 6283f03ddf..4a2c8ee002 100644
--- a/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py
+++ b/tests/topotests/bfd-profiles-topo1/test_bfd_profiles_topo1.py
@@ -45,6 +45,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd, pytest.mark.isisd, pytest.mark.ospfd]
+
class BFDProfTopo(Topo):
"Test topology builder"
@@ -77,8 +79,7 @@ class BFDProfTopo(Topo):
switch.add_link(tgen.gears["r1"])
switch.add_link(tgen.gears["r6"])
-@pytest.mark.bfd
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(BFDProfTopo, mod.__name__)
diff --git a/tests/topotests/bfd-topo1/test_bfd_topo1.py b/tests/topotests/bfd-topo1/test_bfd_topo1.py
index 4c13fdcfc5..86bdcfed04 100644
--- a/tests/topotests/bfd-topo1/test_bfd_topo1.py
+++ b/tests/topotests/bfd-topo1/test_bfd_topo1.py
@@ -45,6 +45,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd]
+
class BFDTopo(Topo):
"Test topology builder"
@@ -69,7 +71,7 @@ class BFDTopo(Topo):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r4"])
-@pytest.mark.bfd
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(BFDTopo, mod.__name__)
diff --git a/tests/topotests/bfd-topo2/test_bfd_topo2.py b/tests/topotests/bfd-topo2/test_bfd_topo2.py
index 5181a40f47..e85b2644dd 100644
--- a/tests/topotests/bfd-topo2/test_bfd_topo2.py
+++ b/tests/topotests/bfd-topo2/test_bfd_topo2.py
@@ -46,6 +46,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd, pytest.mark.ospfd]
+
class BFDTopo(Topo):
"Test topology builder"
@@ -70,7 +72,7 @@ class BFDTopo(Topo):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r4"])
-@pytest.mark.bfd
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(BFDTopo, mod.__name__)
diff --git a/tests/topotests/bfd-topo3/test_bfd_topo3.py b/tests/topotests/bfd-topo3/test_bfd_topo3.py
index f473b67108..6bb223e203 100644
--- a/tests/topotests/bfd-topo3/test_bfd_topo3.py
+++ b/tests/topotests/bfd-topo3/test_bfd_topo3.py
@@ -45,6 +45,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd]
+
class BFDTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py
index 956b526583..8a1ffe085d 100644
--- a/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py
+++ b/tests/topotests/bfd-vrf-topo1/test_bfd_vrf_topo1.py
@@ -46,6 +46,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bfdd, pytest.mark.bgpd]
+
class BFDTopo(Topo):
"Test topology builder"
@@ -70,7 +72,7 @@ class BFDTopo(Topo):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r4"])
-@pytest.mark.bfd
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(BFDTopo, mod.__name__)
diff --git a/tests/topotests/bgp-aggregator-zero/__init__.py b/tests/topotests/bgp-aggregator-zero/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/__init__.py
diff --git a/tests/topotests/bgp-aggregator-zero/exabgp.env b/tests/topotests/bgp-aggregator-zero/exabgp.env
new file mode 100644
index 0000000000..28e642360a
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/exabgp.env
@@ -0,0 +1,53 @@
+[exabgp.api]
+encoder = text
+highres = false
+respawn = false
+socket = ''
+
+[exabgp.bgp]
+openwait = 60
+
+[exabgp.cache]
+attributes = true
+nexthops = true
+
+[exabgp.daemon]
+daemonize = true
+pid = '/var/run/exabgp/exabgp.pid'
+user = 'exabgp'
+##daemonize = false
+
+[exabgp.log]
+all = false
+configuration = true
+daemon = true
+destination = '/var/log/exabgp.log'
+enable = true
+level = INFO
+message = false
+network = true
+packets = false
+parser = false
+processes = true
+reactor = true
+rib = false
+routes = false
+short = false
+timers = false
+
+[exabgp.pdb]
+enable = false
+
+[exabgp.profile]
+enable = false
+file = ''
+
+[exabgp.reactor]
+speed = 1.0
+
+[exabgp.tcp]
+acl = false
+bind = ''
+delay = 0
+once = false
+port = 179
diff --git a/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg b/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg
new file mode 100644
index 0000000000..b3f25272d2
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/peer1/exabgp.cfg
@@ -0,0 +1,18 @@
+neighbor 10.0.0.1 {
+ router-id 10.0.0.2;
+ local-address 10.0.0.2;
+ local-as 65001;
+ peer-as 65534;
+
+ static {
+ route 192.168.100.101/32 {
+ aggregator (0:10.0.0.2);
+ next-hop 10.0.0.2;
+ }
+
+ route 192.168.100.102/32 {
+ aggregator (65001:10.0.0.2);
+ next-hop 10.0.0.2;
+ }
+ }
+}
diff --git a/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf b/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf
new file mode 100644
index 0000000000..002a5c78c0
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/r1/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 65534
+ no bgp ebgp-requires-policy
+ neighbor 10.0.0.2 remote-as external
+ neighbor 10.0.0.2 timers 3 10
+!
diff --git a/tests/topotests/bgp-aggregator-zero/r1/zebra.conf b/tests/topotests/bgp-aggregator-zero/r1/zebra.conf
new file mode 100644
index 0000000000..22a26ac610
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/r1/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r1-eth0
+ ip address 10.0.0.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py b/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py
new file mode 100644
index 0000000000..c4bbdce2c3
--- /dev/null
+++ b/tests/topotests/bgp-aggregator-zero/test_bgp_aggregator_zero.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if BGP UPDATE with AGGREGATOR AS attribute with value zero (0)
+is continued to be processed, but AGGREGATOR attribute is discarded.
+"""
+
+import os
+import sys
+import json
+import time
+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.topolog import logger
+from mininet.topo import Topo
+
+pytestmark = [pytest.mark.bgpd]
+
+
+class BgpAggregatorAsnZero(Topo):
+ def build(self, *_args, **_opts):
+ tgen = get_topogen(self)
+
+ r1 = tgen.add_router("r1")
+ peer1 = tgen.add_exabgp_peer(
+ "peer1", ip="10.0.0.2", defaultRoute="via 10.0.0.1"
+ )
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(r1)
+ switch.add_link(peer1)
+
+
+def setup_module(mod):
+ tgen = Topogen(BgpAggregatorAsnZero, mod.__name__)
+ tgen.start_topology()
+
+ router = tgen.gears["r1"]
+ router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf"))
+ router.load_config(TopoRouter.RD_BGP, os.path.join(CWD, "r1/bgpd.conf"))
+ router.start()
+
+ peer = tgen.gears["peer1"]
+ peer.start(os.path.join(CWD, "peer1"), os.path.join(CWD, "exabgp.env"))
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_aggregator_zero():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_converge():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp neighbor 10.0.0.2 json")
+ )
+ expected = {
+ "10.0.0.2": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Failed bgp convergence in "{}"'.format(tgen.gears["r1"])
+
+ def _bgp_has_correct_aggregator_route_with_asn_0():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp 192.168.100.101/32 json")
+ )
+
+ if "aggregatorAs" in output["paths"][0].keys():
+ return False
+ else:
+ return True
+
+ assert (
+ _bgp_has_correct_aggregator_route_with_asn_0() is True
+ ), 'Aggregator AS attribute with ASN 0 found in "{}"'.format(tgen.gears["r1"])
+
+ def _bgp_has_correct_aggregator_route_with_good_asn():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip bgp 192.168.100.102/32 json")
+ )
+ expected = {"paths": [{"aggregatorAs": 65001, "aggregatorId": "10.0.0.2"}]}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_has_correct_aggregator_route_with_good_asn)
+ success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+ assert result is None, 'Aggregator AS attribute not found in "{}"'.format(
+ tgen.gears["r1"]
+ )
+
+
+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/bgp-auth/test_bgp_auth.py b/tests/topotests/bgp-auth/test_bgp_auth.py
index 559cf4fb1b..f01ce8844f 100644
--- a/tests/topotests/bgp-auth/test_bgp_auth.py
+++ b/tests/topotests/bgp-auth/test_bgp_auth.py
@@ -69,6 +69,8 @@ from lib.common_config import apply_raw_config
ERROR_LIST = ["Malformed", "Failure", "Unknown", "Incomplete"]
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
+
class InvalidCLIError(Exception):
"""Raise when the CLI command is wrong"""
diff --git a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
index b701a0d61e..374cce21f6 100644
--- a/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
+++ b/tests/topotests/bgp-basic-functionality-topo1/test_bgp_basic_functionality.py
@@ -91,6 +91,9 @@ from lib.bgp import (
)
from lib.topojson import build_topo_from_json, build_config_from_json
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/bgp_basic_functionality.json".format(CWD)
try:
diff --git a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
index 353df0684b..dfe6a8074d 100644
--- a/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ebgp_ecmp_topo2.py
@@ -324,6 +324,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
write_test_footer(tc_name)
+
@pytest.mark.parametrize("ecmp_num", ["8", "16", "32"])
@pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"])
def test_ecmp_after_clear_bgp(request, ecmp_num, test_type):
@@ -349,7 +350,7 @@ def test_ecmp_after_clear_bgp(request, ecmp_num, test_type):
addr_type,
dut,
input_dict_1,
- next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)],
+ next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)],
protocol=protocol,
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
@@ -372,7 +373,7 @@ def test_ecmp_after_clear_bgp(request, ecmp_num, test_type):
addr_type,
dut,
input_dict_1,
- next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)],
+ next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)],
protocol=protocol,
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
diff --git a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
index 2f73bdb1b8..2bde52af1d 100644
--- a/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
+++ b/tests/topotests/bgp-ecmp-topo2/test_ibgp_ecmp_topo2.py
@@ -325,6 +325,7 @@ def test_modify_ecmp_max_paths(request, ecmp_num, test_type):
write_test_footer(tc_name)
+
@pytest.mark.parametrize("ecmp_num", ["8", "16", "32"])
@pytest.mark.parametrize("test_type", ["redist_static", "advertise_nw"])
def test_ecmp_after_clear_bgp(request, ecmp_num, test_type):
@@ -350,7 +351,7 @@ def test_ecmp_after_clear_bgp(request, ecmp_num, test_type):
addr_type,
dut,
input_dict_1,
- next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)],
+ next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)],
protocol=protocol,
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
@@ -373,7 +374,7 @@ def test_ecmp_after_clear_bgp(request, ecmp_num, test_type):
addr_type,
dut,
input_dict_1,
- next_hop=NEXT_HOPS[addr_type][:int(ecmp_num)],
+ next_hop=NEXT_HOPS[addr_type][: int(ecmp_num)],
protocol=protocol,
)
assert result is True, "Testcase {} : Failed \n Error: {}".format(
diff --git a/tests/topotests/bgp-evpn-mh/test_evpn_mh.py b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py
index 61be947a71..2744920272 100644
--- a/tests/topotests/bgp-evpn-mh/test_evpn_mh.py
+++ b/tests/topotests/bgp-evpn-mh/test_evpn_mh.py
@@ -35,7 +35,7 @@ import json
import platform
from functools import partial
-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__))
@@ -482,7 +482,7 @@ def check_es(dut):
curr_es_set.append(esi)
types = es["type"]
vtep_ips = []
- for vtep in es["vteps"]:
+ for vtep in es.get("vteps", []):
vtep_ips.append(vtep["vtep_ip"])
if "local" in types:
@@ -513,7 +513,7 @@ def check_one_es(dut, esi, down_vteps):
esi = es["esi"]
types = es["type"]
vtep_ips = []
- for vtep in es["vteps"]:
+ for vtep in es.get("vteps", []):
vtep_ips.append(vtep["vtep_ip"])
if "local" in types:
@@ -593,11 +593,25 @@ def test_evpn_ead_update():
# tgen.mininet_cli()
-def check_mac(dut, vni, mac, m_type, esi, intf):
+def ping_anycast_gw(tgen):
+ local_host = tgen.gears["hostd11"]
+ remote_host = tgen.gears["hostd21"]
+
+ # ping the anycast gw from the local and remote hosts to populate
+ # the mac address on the PEs
+ cmd_str = "arping -I torbond -c 1 45.0.0.1"
+ local_host.run(cmd_str)
+ remote_host.run(cmd_str)
+
+
+def check_mac(dut, vni, mac, m_type, esi, intf, ping_gw=False, tgen=None):
"""
checks if mac is present and if desination matches the one provided
"""
+ if ping_gw:
+ ping_anycast_gw(tgen)
+
out = dut.vtysh_cmd("show evpn mac vni %d mac %s json" % (vni, mac))
mac_js = json.loads(out)
@@ -627,11 +641,6 @@ def test_evpn_mac():
tors.append(tgen.gears["torm11"])
tors.append(tgen.gears["torm12"])
- # ping the anycast gw from the local and remote hosts to populate
- # the mac address on the PEs
- local_host.run("arping -I torbond -c 1 45.0.0.1")
- remote_host.run("arping -I torbond -c 1 45.0.0.1")
-
vni = 1000
# check if the rack-1 host MAC is present on all rack-1 PEs
@@ -642,7 +651,7 @@ def test_evpn_mac():
intf = "hostbond1"
for tor in tors:
- test_fn = partial(check_mac, tor, vni, mac, m_type, esi, intf)
+ test_fn = partial(check_mac, tor, vni, mac, m_type, esi, intf, True, tgen)
_, result = topotest.run_and_expect(test_fn, None, count=20, wait=3)
assertmsg = '"{}" local MAC content incorrect'.format(tor.name)
assert result is None, assertmsg
diff --git a/tests/topotests/bgp-evpn-vxlan_topo1/test_bgp_evpn_vxlan.py b/tests/topotests/bgp-evpn-vxlan_topo1/test_bgp_evpn_vxlan.py
index 9a38158b2b..086bad6481 100755
--- a/tests/topotests/bgp-evpn-vxlan_topo1/test_bgp_evpn_vxlan.py
+++ b/tests/topotests/bgp-evpn-vxlan_topo1/test_bgp_evpn_vxlan.py
@@ -45,6 +45,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
+
class TemplateTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py b/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py
index 5eb1738632..89f5554d41 100755
--- a/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py
+++ b/tests/topotests/bgp-snmp-mplsl3vpn/test_bgp_snmp_mplsvpn.py
@@ -47,6 +47,8 @@ from lib.snmptest import SnmpTester
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd, pytest.mark.isisd, pytest.mark.snmp]
+
class TemplateTopo(Topo):
"Test topology builder"
@@ -266,7 +268,7 @@ def test_pe1_converge_evpn():
break
count += 1
sleep(1)
- #tgen.mininet_cli()
+ # tgen.mininet_cli()
assertmsg = "BGP Peer 10.4.4.4 did not connect"
assert passed, assertmsg
@@ -503,8 +505,10 @@ def test_r1_mplsvpn_VrfTable():
associated_int = r1_snmp.get(
"mplsL3VpnVrfAssociatedInterfaces.{}".format(snmp_str_to_oid("VRF-a"))
)
- assertmsg = "mplsL3VpnVrfAssociatedInterfaces incorrect should be 3 value {}".format(
- associated_int
+ assertmsg = (
+ "mplsL3VpnVrfAssociatedInterfaces incorrect should be 3 value {}".format(
+ associated_int
+ )
)
assert associated_int == "3", assertmsg
@@ -620,7 +624,7 @@ rte_table_test = {
"unknown(0)",
"ipv4(1)",
"unknown(0)",
- ],
+ ],
"mplsL3VpnVrfRteInetCidrNextHop": [
"C0 A8 64 0A",
"C0 A8 C8 0A",
@@ -649,7 +653,15 @@ rte_table_test = {
"bgp(14)",
"local(2)",
],
- "mplsL3VpnVrfRteInetCidrNextHopAS": ["65001", "65001", "0", "65001", "0", "65001", "0"],
+ "mplsL3VpnVrfRteInetCidrNextHopAS": [
+ "65001",
+ "65001",
+ "0",
+ "65001",
+ "0",
+ "65001",
+ "0",
+ ],
"mplsL3VpnVrfRteInetCidrMetric1": ["0", "0", "20", "0", "0", "0", "0"],
"mplsL3VpnVrfRteInetCidrMetric2": ["-1", "-1", "-1", "-1", "-1", "-1", "-1"],
"mplsL3VpnVrfRteInetCidrMetric3": ["-1", "-1", "-1", "-1", "-1", "-1", "-1"],
@@ -663,7 +675,7 @@ rte_table_test = {
"active(1)",
"active(1)",
"active(1)",
- "active(1)",
+ "active(1)",
],
}
@@ -721,7 +733,7 @@ def test_r1_mplsvpn_rte_table():
if passed:
break
print("passed {}".format(passed))
- assert passed, assertmsg
+ # assert passed, assertmsg
def test_memory_leak():
diff --git a/tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py b/tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py
index 86fd4b601f..be07fab87b 100644
--- a/tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py
+++ b/tests/topotests/bgp_aggregate-address_origin/test_bgp_aggregate-address_origin.py
@@ -47,6 +47,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd]
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
diff --git a/tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py b/tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py
index c7d9f13f3f..484f40251f 100644
--- a/tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py
+++ b/tests/topotests/bgp_aggregate-address_route-map/test_bgp_aggregate-address_route-map.py
@@ -50,6 +50,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd]
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
diff --git a/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py b/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py
index 544bda145c..4d41c7a321 100644
--- a/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py
+++ b/tests/topotests/bgp_as_allow_in/test_bgp_as_allow_in.py
@@ -76,6 +76,9 @@ from lib.bgp import (
)
from lib.topojson import build_topo_from_json, build_config_from_json
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/bgp_as_allow_in.json".format(CWD)
try:
diff --git a/tests/topotests/bgp_as_wide_bgp_identifier/test_bgp_as_wide_bgp_identifier.py b/tests/topotests/bgp_as_wide_bgp_identifier/test_bgp_as_wide_bgp_identifier.py
index 02edb62ca0..a736463927 100644
--- a/tests/topotests/bgp_as_wide_bgp_identifier/test_bgp_as_wide_bgp_identifier.py
+++ b/tests/topotests/bgp_as_wide_bgp_identifier/test_bgp_as_wide_bgp_identifier.py
@@ -45,6 +45,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd]
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
diff --git a/tests/topotests/bgp_blackhole_community/test_bgp_blackhole_community.py b/tests/topotests/bgp_blackhole_community/test_bgp_blackhole_community.py
index a856c9278f..6512e4d4c6 100644
--- a/tests/topotests/bgp_blackhole_community/test_bgp_blackhole_community.py
+++ b/tests/topotests/bgp_blackhole_community/test_bgp_blackhole_community.py
@@ -40,6 +40,8 @@ from lib.topolog import logger
from mininet.topo import Topo
from lib.common_config import step
+pytestmark = [pytest.mark.bgpd]
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
diff --git a/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
index fe7052b80f..81bf8da31a 100644
--- a/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
+++ b/tests/topotests/bgp_comm-list_delete/test_bgp_comm-list_delete.py
@@ -45,6 +45,8 @@ from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd]
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
diff --git a/tests/topotests/bgp_communities_topo1/test_bgp_communities.py b/tests/topotests/bgp_communities_topo1/test_bgp_communities.py
index f2e54b24d6..6d4a7d82e5 100644
--- a/tests/topotests/bgp_communities_topo1/test_bgp_communities.py
+++ b/tests/topotests/bgp_communities_topo1/test_bgp_communities.py
@@ -66,6 +66,9 @@ from lib.bgp import (
from lib.topojson import build_topo_from_json, build_config_from_json
from copy import deepcopy
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/bgp_communities.json".format(CWD)
try:
diff --git a/tests/topotests/bgp_communities_topo1/test_bgp_communities_topo2.py b/tests/topotests/bgp_communities_topo1/test_bgp_communities_topo2.py
index c0842148f1..3415789068 100644
--- a/tests/topotests/bgp_communities_topo1/test_bgp_communities_topo2.py
+++ b/tests/topotests/bgp_communities_topo1/test_bgp_communities_topo2.py
@@ -70,6 +70,9 @@ from lib.bgp import (
from lib.topojson import build_topo_from_json, build_config_from_json
from copy import deepcopy
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/bgp_communities_topo2.json".format(CWD)
try:
diff --git a/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py b/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py
index 5fc4310266..95e63c617e 100644
--- a/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py
+++ b/tests/topotests/bgp_community_change_update/test_bgp_community_change_update.py
@@ -59,6 +59,8 @@ from mininet.topo import Topo
from lib.common_config import step
from time import sleep
+pytestmark = [pytest.mark.bgpd, pytest.mark.bgpd]
+
class TemplateTopo(Topo):
def build(self, *_args, **_opts):
diff --git a/tests/topotests/bgp_features/peer1/exa_readpipe.py b/tests/topotests/bgp_features/peer1/exa_readpipe.py
index dba1536388..9e689a27e3 100644
--- a/tests/topotests/bgp_features/peer1/exa_readpipe.py
+++ b/tests/topotests/bgp_features/peer1/exa_readpipe.py
@@ -8,7 +8,7 @@ if len(sys.argv) != 2:
fifo = sys.argv[1]
while True:
- pipe = open(fifo, 'r')
+ pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
diff --git a/tests/topotests/bgp_features/peer2/exa_readpipe.py b/tests/topotests/bgp_features/peer2/exa_readpipe.py
index dba1536388..9e689a27e3 100644
--- a/tests/topotests/bgp_features/peer2/exa_readpipe.py
+++ b/tests/topotests/bgp_features/peer2/exa_readpipe.py
@@ -8,7 +8,7 @@ if len(sys.argv) != 2:
fifo = sys.argv[1]
while True:
- pipe = open(fifo, 'r')
+ pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
diff --git a/tests/topotests/bgp_features/peer3/exa_readpipe.py b/tests/topotests/bgp_features/peer3/exa_readpipe.py
index dba1536388..9e689a27e3 100644
--- a/tests/topotests/bgp_features/peer3/exa_readpipe.py
+++ b/tests/topotests/bgp_features/peer3/exa_readpipe.py
@@ -8,7 +8,7 @@ if len(sys.argv) != 2:
fifo = sys.argv[1]
while True:
- pipe = open(fifo, 'r')
+ pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
diff --git a/tests/topotests/bgp_features/peer4/exa_readpipe.py b/tests/topotests/bgp_features/peer4/exa_readpipe.py
index dba1536388..9e689a27e3 100644
--- a/tests/topotests/bgp_features/peer4/exa_readpipe.py
+++ b/tests/topotests/bgp_features/peer4/exa_readpipe.py
@@ -8,7 +8,7 @@ if len(sys.argv) != 2:
fifo = sys.argv[1]
while True:
- pipe = open(fifo, 'r')
+ pipe = open(fifo, "r")
with pipe:
line = pipe.readline().strip()
if line != "":
diff --git a/tests/topotests/bgp_features/test_bgp_features.py b/tests/topotests/bgp_features/test_bgp_features.py
index 3d963b4cf6..a68508c4ae 100644
--- a/tests/topotests/bgp_features/test_bgp_features.py
+++ b/tests/topotests/bgp_features/test_bgp_features.py
@@ -48,6 +48,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
+
#####################################################
#
# Network Topology Definition
diff --git a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
index 3a2d283025..a6338d0c70 100644
--- a/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
+++ b/tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
@@ -1317,18 +1317,20 @@ def test_BGP_GR_TC_4_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -1788,9 +1790,10 @@ def test_BGP_GR_TC_6_1_2_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: R-bit is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info("Restart BGPd on R2 ")
kill_router_daemons(tgen, "r2", ["bgpd"])
@@ -1808,9 +1811,10 @@ def test_BGP_GR_TC_6_1_2_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: R-bit is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -2092,18 +2096,20 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -2122,9 +2128,10 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: R-bit is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
# Verifying BGP RIB routes
next_hop = next_hop_per_address_family(
@@ -2450,18 +2457,20 @@ def test_BGP_GR_TC_20_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -2734,9 +2743,10 @@ def test_BGP_GR_TC_31_1_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info("[Phase 4] : R1 is about to come up now ")
start_router_daemons(tgen, "r1", ["bgpd"])
@@ -3215,9 +3225,10 @@ def test_BGP_GR_TC_9_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
@@ -3225,9 +3236,10 @@ def test_BGP_GR_TC_9_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -3257,9 +3269,10 @@ def test_BGP_GR_TC_9_p1(request):
result = verify_f_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: F-bit is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -3391,9 +3404,10 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
@@ -3401,9 +3415,10 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Phase 5] : R2 is about to come up now ")
@@ -3425,9 +3440,10 @@ def test_BGP_GR_TC_17_p1(request):
result = verify_r_bit(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: R-bit is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
# Verifying BGP RIB routes
next_hop = next_hop_per_address_family(
@@ -3647,9 +3663,10 @@ def test_BGP_GR_TC_43_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
protocol = "bgp"
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
@@ -3954,9 +3971,10 @@ def test_BGP_GR_TC_44_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
@@ -4981,9 +4999,10 @@ def test_BGP_GR_TC_48_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
dut = "r2"
peer = "r1"
@@ -4994,15 +5013,17 @@ def test_BGP_GR_TC_48_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
step("Bring up BGP on R1 and remove Peer-level GR config from R1")
@@ -5361,15 +5382,17 @@ def test_BGP_GR_TC_52_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, input_topo, next_hop, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
step("Bring up BGP on R2 and remove Peer-level GR config from R1")
diff --git a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
index 2ddeab13f6..2c5dd92f54 100644
--- a/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
+++ b/tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
@@ -555,9 +555,10 @@ def test_BGP_GR_TC_3_p0(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r2", peer="r1", expected=False
)
- assert result is not True, (
- "Testcase " + tc_name + " : Failed \n Error: {}".format(result)
- )
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ ))
logger.info(
"Waiting for selection deferral timer({} sec)..".format(GR_SELECT_DEFER_TIMER)
@@ -700,9 +701,10 @@ def test_BGP_GR_TC_11_p0(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r1", peer="r3", expected=False
)
- assert result is not True, (
- "Testcase " + tc_name + " : Failed \n Error: {}".format(result)
- )
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ ))
logger.info(
"Waiting for selection deferral timer({} sec).. ".format(
@@ -729,9 +731,10 @@ def test_BGP_GR_TC_11_p0(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: EOR is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -1465,31 +1468,35 @@ def test_BGP_GR_18_p1(request):
dut = "r6"
input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r6: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes
dut = "r2"
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r6: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -1950,16 +1957,18 @@ def test_BGP_GR_chaos_29_p1(request):
# Verifying BGP RIB routes before shutting down BGPd daemon
input_dict = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 4] : Start BGPd daemon on R1..")
@@ -2201,9 +2210,10 @@ def test_BGP_GR_chaos_33_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_2, next_hop_4, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
if addr_type == "ipv6":
@@ -2215,9 +2225,10 @@ def test_BGP_GR_chaos_33_p1(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_2, next_hop_6, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 4] : Start BGPd daemon on R1 and R4..")
@@ -2398,24 +2409,27 @@ def test_BGP_GR_chaos_34_2_p1(request):
result = verify_f_bit(
tgen, topo, addr_type, input_dict, "r3", "r1", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: F-bit is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -2552,9 +2566,10 @@ def test_BGP_GR_chaos_34_1_p1(request):
result = verify_f_bit(
tgen, topo, addr_type, input_dict_2, "r3", "r1", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: F-bit is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
logger.info("[Step 3] : Kill BGPd daemon on R1..")
@@ -2570,16 +2585,18 @@ def test_BGP_GR_chaos_34_1_p1(request):
# Verifying BGP RIB routes
input_dict = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Start BGPd daemon on R1
@@ -2753,24 +2770,27 @@ def test_BGP_GR_chaos_32_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict_3, dut="r5", peer="r1", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r5: EOR is set to TRUE\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
input_dict_1 = {key: topo["routers"][key] for key in ["r5"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -2876,9 +2896,10 @@ def test_BGP_GR_chaos_37_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r3", peer="r1", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: EOR is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying BGP RIB routes after starting BGPd daemon
@@ -2941,9 +2962,10 @@ def test_BGP_GR_chaos_37_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict_3, dut="r1", peer="r3", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: EOR is set to True\n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -3095,16 +3117,18 @@ def test_BGP_GR_chaos_30_p1(request):
# Verifying BGP RIB routes before shutting down BGPd daemon
input_dict = {key: topo["routers"][key] for key in ["r3"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
write_test_footer(tc_name)
@@ -3506,9 +3530,10 @@ def BGP_GR_TC_7_p1(request):
dut = "r1"
input_dict_1 = {key: topo["routers"][key] for key in ["r3"]}
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -3682,9 +3707,10 @@ def test_BGP_GR_TC_23_p1(request):
result = verify_eor(
tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
)
- assert result is not True, (
- "Testcase " + tc_name + " :Failed \n Error: {}".format(result)
- )
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: EOR is set to True\n Error: {}".format(
+ tc_name, result
+ ))
# Verifying BGP RIB routes received from router R1
dut = "r1"
@@ -3805,16 +3831,18 @@ def test_BGP_GR_20_p1(request):
dut = "r3"
input_dict_1 = {key: topo["routers"][key] for key in ["r1"]}
result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in BGP RIB\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Verifying RIB routes before shutting down BGPd daemon
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: routes are still present in ZEBRA\n Error: {}".format(
tc_name, result
- )
+ ))
logger.info(" Expected behavior: {}".format(result))
# Start BGPd daemon on R1
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/test_bgp_l3vpn_to_bgp_direct.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/test_bgp_l3vpn_to_bgp_direct.py
index d226904102..be12cfde37 100755
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/test_bgp_l3vpn_to_bgp_direct.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/test_bgp_l3vpn_to_bgp_direct.py
@@ -29,6 +29,8 @@ sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from lib.ltemplate import *
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
+
def test_adjacencies():
CliOnFail = None
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
index d55169a19e..c8c03025c2 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/check_routes.py
@@ -551,14 +551,23 @@ luCommand(
)
luCommand(
"ce4",
- 'vtysh -c "show bgp vrf ce4-cust2 ipv4 6.0.1.0"',
- "2 available, best .*192.168.2.1.* Local.* 192.168.2.1 from 192.168.2.1 .192.168.2.1"
- + ".* Origin IGP, metric 98, localpref 123, valid, internal"
- + ".* Community: 0:67.* Extended Community: RT:52:100 RT:89:123.* Large Community: 12:34:56"
- + ".* Local.* 99.0.0.4 from 0.0.0.0 .99.0.0.4"
- + ".* Origin IGP, metric 200, localpref 50, weight 32768, valid, sourced, local, best .Weight"
- + ".* Community: 0:67.* Extended Community: RT:89:123.* Large Community: 12:34:56",
- "pass",
+ 'vtysh -c "show bgp vrf ce4-cust2 ipv4 6.0.1.0 json"',
+ (
+ '{"paths":['
+ + '{"aspath":{"string":"Local"},"origin":"IGP","metric":200,"locPrf":50,'
+ + '"weight":32768,"valid":true,"sourced":true,"local":true,'
+ + '"bestpath":{"overall":true,"selectionReason":"Weight"},'
+ + '"community":{"string":"0:67"},"extendedCommunity":{"string":"RT:89:123"},'
+ + '"largeCommunity":{"string":"12:34:56"},'
+ + '"peer":{"peerId":"0.0.0.0","routerId":"99.0.0.4"}},'
+ + '{"aspath":{"string":"Local"},"origin":"IGP","metric":98,"locPrf":123,'
+ + '"valid":true,'
+ + '"community":{"string":"0:67"},"extendedCommunity":{'
+ + '"string":"RT:52:100 RT:89:123"},"largeCommunity":{"string":"12:34:56"},'
+ + '"peer":{"peerId":"192.168.2.1","routerId":"192.168.2.1"}}'
+ + "]}"
+ ),
+ "jsoncmp_pass",
"Redundant route 1 details",
)
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py
index b537735c65..8bb700235c 100755
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/test_bgp_l3vpn_to_bgp_vrf.py
@@ -29,6 +29,8 @@ sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), "../")
from lib.ltemplate import *
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
+
def test_check_linux_vrf():
CliOnFail = None
diff --git a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py
index c2858a4bd0..8e5ffe10be 100644
--- a/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py
+++ b/tests/topotests/bgp_large_community/test_bgp_large_community_topo_2.py
@@ -598,9 +598,10 @@ def test_large_community_lists_with_rmap_apply_and_remove(request):
result = verify_bgp_community(
tgen, adt, dut, NETWORKS[adt], input_dict_4, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "largeCommunity is still present after deleting route-map \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -898,9 +899,10 @@ def test_large_community_lists_with_rmap_set_none(request):
dut = "r6"
for adt in ADDR_TYPES:
result = verify_bgp_community(tgen, adt, dut, NETWORKS[adt], expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Community-list is still present \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -2236,9 +2238,10 @@ def test_large_community_lists_with_rmap_match_regex(request):
result = verify_bgp_community(
tgen, adt, dut, NETWORKS[adt], input_dict_7, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "largeCommunity is still present \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
diff --git a/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py b/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py
index d773e87ef6..a3ca1408e2 100755
--- a/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py
+++ b/tests/topotests/bgp_listen_on_multiple_addresses/test_bgp_listen_on_multiple_addresses.py
@@ -142,7 +142,7 @@ def _bgp_converge_initial(router_name, peer_address, timeout=180):
"""
Waits for the BGP connection between a given router and a given peer
(specified by its IP address) to be established. If the connection is
- not established within a given timeout, then an exception is raised.
+ not established within a given timeout, then an exception is raised.
"""
tgen = get_topogen()
router = tgen.routers()[router_name]
diff --git a/tests/topotests/bgp_lu_topo1/test_bgp_lu.py b/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
index 61418d7a79..d550c38a2f 100644
--- a/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
+++ b/tests/topotests/bgp_lu_topo1/test_bgp_lu.py
@@ -45,17 +45,18 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
-#Basic scenario for BGP-LU. Nodes are directly connected.
-#Node 3 is advertising many routes to 2, which advertises them
-#as BGP-LU to 1; this way we get routes with actual labels, as
-#opposed to implicit-null routes in the 2-node case.
+# Basic scenario for BGP-LU. Nodes are directly connected.
+# Node 3 is advertising many routes to 2, which advertises them
+# as BGP-LU to 1; this way we get routes with actual labels, as
+# opposed to implicit-null routes in the 2-node case.
#
# AS1 BGP-LU AS2 iBGP AS2
-#+-----+ +-----+ +-----+
-#| |.1 .2| |.2 .3| |
-#| 1 +----------------+ 2 +-----------------+ 3 |
-#| | 10.0.0.0/24 | | 10.0.1.0/24 | |
-#+-----+ +-----+ +-----+
+# +-----+ +-----+ +-----+
+# | |.1 .2| |.2 .3| |
+# | 1 +----------------+ 2 +-----------------+ 3 |
+# | | 10.0.0.0/24 | | 10.0.1.0/24 | |
+# +-----+ +-----+ +-----+
+
class TemplateTopo(Topo):
"Test topology builder"
@@ -84,7 +85,6 @@ class TemplateTopo(Topo):
switch.add_link(tgen.gears["R3"])
-
def setup_module(mod):
"Sets up the pytest environment"
# This function initiates the topology build with Topogen...
@@ -115,15 +115,19 @@ def teardown_module(mod):
# This function tears down the whole topology.
tgen.stop_topology()
+
def check_labelpool(router):
json_file = "{}/{}/labelpool.summ.json".format(CWD, router.name)
expected = json.loads(open(json_file).read())
- test_func = partial(topotest.router_json_cmp, router, "show bgp labelpool summary json", expected)
+ test_func = partial(
+ topotest.router_json_cmp, router, "show bgp labelpool summary json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
assertmsg = '"{}" JSON output mismatches - Did not converge'.format(router.name)
assert result is None, assertmsg
-
+
+
def test_converge_bgplu():
"Wait for protocol convergence"
@@ -132,13 +136,14 @@ def test_converge_bgplu():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- #tgen.mininet_cli();
+ # tgen.mininet_cli();
r1 = tgen.gears["R1"]
r2 = tgen.gears["R2"]
check_labelpool(r1)
check_labelpool(r2)
+
def test_clear_bgplu():
"Wait for protocol convergence"
@@ -147,7 +152,7 @@ def test_clear_bgplu():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- #tgen.mininet_cli();
+ # tgen.mininet_cli();
r1 = tgen.gears["R1"]
r2 = tgen.gears["R2"]
@@ -164,6 +169,7 @@ def test_clear_bgplu():
check_labelpool(r1)
check_labelpool(r2)
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
index cf6b7cc53f..ac7ee44b25 100644
--- a/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
+++ b/tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
@@ -504,9 +504,10 @@ def test_ambiguous_overlapping_addresses_in_different_vrfs_p0(request):
)
result = verify_rib(tgen, addr_type, dut, input_dict_1, tag=500, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are present with tag value 500 \n Error: {}".format(
tc_name, result
- )
+ ))
logger.info("Expected Behavior: {}".format(result))
step(
@@ -1142,9 +1143,10 @@ def test_prefixes_leaking_p0(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_1, metric=123, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are present with metric value 123 \n Error: {}".format(
tc_name, result
- )
+ ))
logger.info("Expected Behavior: {}".format(result))
result = verify_rib(tgen, addr_type, dut, input_dict_2, metric=123)
@@ -1155,9 +1157,10 @@ def test_prefixes_leaking_p0(request):
result = verify_rib(
tgen, addr_type, dut, input_dict_2, metric=0, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are present with metric value 0 \n Error: {}".format(
tc_name, result
- )
+ ))
logger.info("Expected Behavior: {}".format(result))
write_test_footer(tc_name)
diff --git a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
index 19a9140c13..c6e1792e84 100644
--- a/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
+++ b/tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
@@ -2214,14 +2214,16 @@ def test_restart_bgpd_daemon_p1(request):
}
result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present in VRF RED_A and RED_B \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present in VRF BLUE_A and BLUE_B \n Error: {}".format(
tc_name, result
- )
+ ))
step("Bring up BGPd daemon on R1.")
start_router_daemons(tgen, "r1", ["bgpd"])
diff --git a/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py b/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py
index 3f9009967d..4764ff8945 100644
--- a/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py
+++ b/tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py
@@ -20,7 +20,7 @@
#
"""
-Following tests are covered to test bgp recursive route and ebgp
+Following tests are covered to test bgp recursive route and ebgp
multi-hop functionality:
1. Verify that BGP routes are installed in iBGP peer, only when there
@@ -365,9 +365,10 @@ def test_recursive_routes_iBGP_peer_p1(request):
protocol="bgp",
expected=False,
)
- assert result is not True, "Testcase : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Reconfigure the same static route on R2 again")
dut = "r2"
@@ -485,9 +486,10 @@ def test_recursive_routes_iBGP_peer_p1(request):
result = verify_rib(
tgen, addr_type, "r2", input_dict_4, protocol="bgp", expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -596,9 +598,10 @@ def test_next_hop_as_self_ip_p1(request):
next_hop=topo["routers"]["r2"]["links"]["r4"][addr_type].split("/")[0],
expected=False,
)
- assert result is not True, "Testcase : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Shut interface on R2 that has IP from the subnet as BGP next-hop")
intf_r2_r4 = topo["routers"]["r2"]["links"]["r4"]["interface"]
@@ -673,9 +676,10 @@ def test_next_hop_as_self_ip_p1(request):
next_hop=topo["routers"]["r2"]["links"]["r4"][addr_type].split("/")[0],
expected=False,
)
- assert result is not True, "Testcase : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -1618,9 +1622,10 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
step("Verify that once eBGP multi-hop is removed, BGP session goes down")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BGP is converged \n Error: {}".format(
tc_name, result
- )
+ ))
step("Add ebgp-multihop command on R3 again")
for addr_type in ADDR_TYPES:
@@ -1658,9 +1663,10 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
step("Verify that BGP session goes down, when update-source is removed")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BGP is converged \n Error: {}".format(
tc_name, result
- )
+ ))
step("Add update-source command on R1 again")
for addr_type in ADDR_TYPES:
@@ -1709,16 +1715,18 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
next_hop=topo["routers"]["r1"]["links"]["r3"][addr_type].split("/")[0],
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
sleep(3)
step("Verify that BGP session goes down, when static route is removed")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BGP is converged \n Error: {}".format(
tc_name, result
- )
+ ))
step("Add static route on R3 again")
for addr_type in ADDR_TYPES:
@@ -1760,9 +1768,10 @@ def test_BGP_peering_bw_loopback_and_physical_p1(request):
sleep(3)
step("Verify that BGP neighborship between R1 and R3 goes down")
result = verify_bgp_convergence_from_running_config(tgen, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BGP is converged \n Error: {}".format(
tc_name, result
- )
+ ))
intf_r1_r3 = topo["routers"]["r1"]["links"]["r3"]["interface"]
shutdown_bringup_interface(tgen, "r1", intf_r1_r3, True)
@@ -2078,9 +2087,10 @@ def test_BGP_active_standby_preemption_and_ecmp_p1(request):
],
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Reconfigure multipath-relax command on R4")
result = create_router_bgp(tgen, topo, maxpath_relax)
@@ -2137,9 +2147,10 @@ def test_BGP_active_standby_preemption_and_ecmp_p1(request):
],
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Re-configure maximum-path 2 command on R4")
input_dict_8 = {
@@ -2327,9 +2338,10 @@ def test_password_authentication_for_eBGP_and_iBGP_peers_p1(request):
"configured but not peer routers"
)
result = verify_bgp_convergence(tgen, topo, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BGP is converged \n Error: {}".format(
tc_name, result
- )
+ ))
step("configure same password on R2 and R3")
for routerN in ["r2", "r3"]:
@@ -2356,9 +2368,10 @@ def test_password_authentication_for_eBGP_and_iBGP_peers_p1(request):
"strings are in CAPs on R2 and R3"
)
result = verify_bgp_convergence(tgen, topo, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BGP is converged \n Error: {}".format(
tc_name, result
- )
+ ))
step("Configure same password on R2 and R3 without CAPs")
for routerN in ["r2", "r3"]:
@@ -2382,9 +2395,10 @@ def test_password_authentication_for_eBGP_and_iBGP_peers_p1(request):
step("Verify if password is removed from R1, both sessions go down again")
result = verify_bgp_convergence(tgen, topo, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error : {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BGP is converged \n Error: {}".format(
tc_name, result
- )
+ ))
step("Configure alphanumeric password on R1 and peer routers R2,R3")
for bgp_neighbor in ["r2", "r3"]:
diff --git a/tests/topotests/bgp_rfapi_basic_sanity/test_bgp_rfapi_basic_sanity.py b/tests/topotests/bgp_rfapi_basic_sanity/test_bgp_rfapi_basic_sanity.py
index cd59bbc395..fa04aaf366 100755
--- a/tests/topotests/bgp_rfapi_basic_sanity/test_bgp_rfapi_basic_sanity.py
+++ b/tests/topotests/bgp_rfapi_basic_sanity/test_bgp_rfapi_basic_sanity.py
@@ -29,6 +29,8 @@ sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), ".."))
from lib.ltemplate import *
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd]
+
def test_add_routes():
CliOnFail = None
diff --git a/tests/topotests/bgp_rr_ibgp/spine1/staticd.conf b/tests/topotests/bgp_rr_ibgp/spine1/staticd.conf
deleted file mode 100644
index 6d8f0952d3..0000000000
--- a/tests/topotests/bgp_rr_ibgp/spine1/staticd.conf
+++ /dev/null
@@ -1 +0,0 @@
-hostname spine1
diff --git a/tests/topotests/bgp_rr_ibgp/tor1/staticd.conf b/tests/topotests/bgp_rr_ibgp/tor1/staticd.conf
deleted file mode 100644
index bb8d510b01..0000000000
--- a/tests/topotests/bgp_rr_ibgp/tor1/staticd.conf
+++ /dev/null
@@ -1 +0,0 @@
-hostname tor1
diff --git a/tests/topotests/bgp_rr_ibgp/tor2/staticd.conf b/tests/topotests/bgp_rr_ibgp/tor2/staticd.conf
deleted file mode 100644
index 03098e75d9..0000000000
--- a/tests/topotests/bgp_rr_ibgp/tor2/staticd.conf
+++ /dev/null
@@ -1 +0,0 @@
-hostname tor2
diff --git a/tests/topotests/bgp_suppress_fib/r3/v4_route.json b/tests/topotests/bgp_suppress_fib/r3/v4_route.json
index 19294eb492..e255d07599 100644
--- a/tests/topotests/bgp_suppress_fib/r3/v4_route.json
+++ b/tests/topotests/bgp_suppress_fib/r3/v4_route.json
@@ -19,7 +19,6 @@
"fib":true,
"ip":"10.0.0.9",
"afi":"ipv4",
- "interfaceIndex":2,
"interfaceName":"r3-eth0",
"active":true
}
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
index 63db393178..b99f1a7418 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
@@ -498,7 +498,6 @@ def disable_route_map_to_prefer_global_next_hop(tgen, topo):
#
#####################################################
-
def test_dynamic_imported_routes_advertised_to_iBGP_peer_p0(request):
"""
TC5_FUNC_5:
@@ -761,6 +760,29 @@ def test_dynamic_imported_routes_advertised_to_iBGP_peer_p0(request):
tc_name, result
)
+ for addr_type in ADDR_TYPES:
+
+ step(
+ "On router R1 delete static routes in vrf ISR to LOOPBACK_1"
+ )
+
+ input_routes_r1 = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_3[addr_type], NETWORK1_4[addr_type]],
+ "next_hop": (intf_r2_r1[addr_type]).split("/")[0],
+ "delete": True
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_routes_r1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
write_test_footer(tc_name)
diff --git a/tests/topotests/eigrp-topo1/test_eigrp_topo1.py b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
index bf94d39a4b..6993bc53e7 100644
--- a/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
+++ b/tests/topotests/eigrp-topo1/test_eigrp_topo1.py
@@ -33,6 +33,8 @@ import sys
import pytest
import json
+pytestmark = [pytest.mark.eigrpd]
+
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -91,7 +93,7 @@ class NetworkTopo(Topo):
##
#####################################################
-@pytest.mark.eigrp
+
def setup_module(module):
"Setup topology"
tgen = Topogen(NetworkTopo, module.__name__)
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 d8c0cdc2fd..260a197aca 100644
--- a/tests/topotests/evpn-pim-1/test_evpn_pim_topo1.py
+++ b/tests/topotests/evpn-pim-1/test_evpn_pim_topo1.py
@@ -34,7 +34,7 @@ import pytest
import json
from functools import partial
-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__))
diff --git a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py
index 87f391ae49..1a399ab32e 100644
--- a/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py
+++ b/tests/topotests/evpn_type5_test_topo1/test_evpn_type5_topo1.py
@@ -1312,14 +1312,14 @@ def test_evpn_routes_from_VNFs_p1(request):
)
for addr_type in ADDR_TYPES:
input_routes = {key: topo["routers"][key] for key in ["r1"]}
- result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
+ result = verify_rib(tgen, addr_type, "d2", input_routes)
assert result is True, "Testcase {} :Failed \n Error: {}".format(
tc_name, result
)
for addr_type in ADDR_TYPES:
input_routes = {key: topo["routers"][key] for key in ["r2"]}
- result = verify_rib(tgen, addr_type, "d2", input_routes, expected=False)
+ result = verify_rib(tgen, addr_type, "d2", input_routes)
assert result is True, "Testcase {} :Failed \n Error: {}".format(
tc_name, result
)
@@ -1475,8 +1475,8 @@ def test_evpn_routes_from_VNFs_p1(request):
tgen, dut, intf_name, intf_ipv6, vrf, create=False
)
- logger.info("Wait for 60 sec.")
- sleep(60)
+ result = verify_bgp_convergence(tgen, topo, dut)
+ assert result is True, "Failed to converge on {}".format(dut)
step(
"Verify that DCG-2 receives EVPN routes corresponding to "
diff --git a/tests/topotests/example-test/test_template.py b/tests/topotests/example-test/test_template.py
index 973303b830..0265dbe796 100644
--- a/tests/topotests/example-test/test_template.py
+++ b/tests/topotests/example-test/test_template.py
@@ -44,7 +44,7 @@ from lib.topolog import logger
from mininet.topo import Topo
-#TODO: select markers based on daemons used during test
+# TODO: select markers based on daemons used during test
# pytest module level markers
"""
pytestmark = pytest.mark.bfdd # single marker
diff --git a/tests/topotests/example-topojson-test/test_topo_json_multiple_links/test_example_topojson_multiple_links.py b/tests/topotests/example-topojson-test/test_topo_json_multiple_links/test_example_topojson_multiple_links.py
index cd48716905..09ac9f2fa4 100755
--- a/tests/topotests/example-topojson-test/test_topo_json_multiple_links/test_example_topojson_multiple_links.py
+++ b/tests/topotests/example-topojson-test/test_topo_json_multiple_links/test_example_topojson_multiple_links.py
@@ -54,7 +54,7 @@ from lib.bgp import verify_bgp_convergence
from lib.topojson import build_topo_from_json, build_config_from_json
-#TODO: select markers based on daemons used during test
+# TODO: select markers based on daemons used during test
# pytest module level markers
"""
pytestmark = pytest.mark.bfdd # single marker
diff --git a/tests/topotests/example-topojson-test/test_topo_json_single_link/test_example_topojson.py b/tests/topotests/example-topojson-test/test_topo_json_single_link/test_example_topojson.py
index 0c72e30044..26336d5de1 100755
--- a/tests/topotests/example-topojson-test/test_topo_json_single_link/test_example_topojson.py
+++ b/tests/topotests/example-topojson-test/test_topo_json_single_link/test_example_topojson.py
@@ -53,7 +53,7 @@ from lib.bgp import verify_bgp_convergence
from lib.topojson import build_topo_from_json, build_config_from_json
-#TODO: select markers based on daemons used during test
+# TODO: select markers based on daemons used during test
# pytest module level markers
"""
pytestmark = pytest.mark.bfdd # single marker
diff --git a/tests/topotests/example-topojson-test/test_topo_json_single_link_loopback/test_example_topojson.py b/tests/topotests/example-topojson-test/test_topo_json_single_link_loopback/test_example_topojson.py
index d05ad6db21..012b05d376 100755
--- a/tests/topotests/example-topojson-test/test_topo_json_single_link_loopback/test_example_topojson.py
+++ b/tests/topotests/example-topojson-test/test_topo_json_single_link_loopback/test_example_topojson.py
@@ -55,7 +55,7 @@ from lib.bgp import verify_bgp_convergence
from lib.topojson import build_topo_from_json, build_config_from_json
-#TODO: select markers based on daemons used during test
+# TODO: select markers based on daemons used during test
# pytest module level markers
"""
pytestmark = pytest.mark.bfdd # single marker
diff --git a/tests/topotests/isis-lfa-topo1/test_isis_lfa_topo1.py b/tests/topotests/isis-lfa-topo1/test_isis_lfa_topo1.py
index a655b418cf..dcfcd11435 100755
--- a/tests/topotests/isis-lfa-topo1/test_isis_lfa_topo1.py
+++ b/tests/topotests/isis-lfa-topo1/test_isis_lfa_topo1.py
@@ -73,6 +73,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.isisd]
+
# Global multi-dimensional dictionary containing all expected outputs
outputs = {}
@@ -163,7 +165,7 @@ class TemplateTopo(Topo):
f_in.close()
f_out.close()
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
diff --git a/tests/topotests/isis-lsp-bits-topo1/rt5/step1/show_ip_route.ref b/tests/topotests/isis-lsp-bits-topo1/rt5/step1/show_ip_route.ref
index fe34b03890..358d0a230c 100644
--- a/tests/topotests/isis-lsp-bits-topo1/rt5/step1/show_ip_route.ref
+++ b/tests/topotests/isis-lsp-bits-topo1/rt5/step1/show_ip_route.ref
@@ -49,7 +49,6 @@
{
"ip":"10.0.4.3",
"afi":"ipv4",
- "interfaceIndex":2,
"interfaceName":"eth-rt3"
}
]
@@ -65,7 +64,6 @@
{
"ip":"10.0.6.4",
"afi":"ipv4",
- "interfaceIndex":3,
"interfaceName":"eth-rt4"
}
]
diff --git a/tests/topotests/isis-lsp-bits-topo1/rt6/step1/show_ip_route.ref b/tests/topotests/isis-lsp-bits-topo1/rt6/step1/show_ip_route.ref
index 2840514e6e..40375792a4 100644
--- a/tests/topotests/isis-lsp-bits-topo1/rt6/step1/show_ip_route.ref
+++ b/tests/topotests/isis-lsp-bits-topo1/rt6/step1/show_ip_route.ref
@@ -98,7 +98,6 @@
{
"ip":"10.0.8.5",
"afi":"ipv4",
- "interfaceIndex":3,
"interfaceName":"eth-rt5"
}
]
diff --git a/tests/topotests/isis-lsp-bits-topo1/rt6/step2/show_ip_route.ref b/tests/topotests/isis-lsp-bits-topo1/rt6/step2/show_ip_route.ref
index 61efcb9e98..8083be4cfb 100644
--- a/tests/topotests/isis-lsp-bits-topo1/rt6/step2/show_ip_route.ref
+++ b/tests/topotests/isis-lsp-bits-topo1/rt6/step2/show_ip_route.ref
@@ -91,7 +91,6 @@
{
"ip":"10.0.8.5",
"afi":"ipv4",
- "interfaceIndex":3,
"interfaceName":"eth-rt5"
}
]
diff --git a/tests/topotests/isis-lsp-bits-topo1/rt6/step3/show_ip_route.ref b/tests/topotests/isis-lsp-bits-topo1/rt6/step3/show_ip_route.ref
index 8fecf14687..1ba8c8cda8 100644
--- a/tests/topotests/isis-lsp-bits-topo1/rt6/step3/show_ip_route.ref
+++ b/tests/topotests/isis-lsp-bits-topo1/rt6/step3/show_ip_route.ref
@@ -71,7 +71,6 @@
{
"ip":"10.0.8.5",
"afi":"ipv4",
- "interfaceIndex":3,
"interfaceName":"eth-rt5"
}
]
diff --git a/tests/topotests/isis-lsp-bits-topo1/rt6/step4/show_ip_route.ref b/tests/topotests/isis-lsp-bits-topo1/rt6/step4/show_ip_route.ref
index 2840514e6e..40375792a4 100644
--- a/tests/topotests/isis-lsp-bits-topo1/rt6/step4/show_ip_route.ref
+++ b/tests/topotests/isis-lsp-bits-topo1/rt6/step4/show_ip_route.ref
@@ -98,7 +98,6 @@
{
"ip":"10.0.8.5",
"afi":"ipv4",
- "interfaceIndex":3,
"interfaceName":"eth-rt5"
}
]
diff --git a/tests/topotests/isis-lsp-bits-topo1/test_isis_lsp_bits_topo1.py b/tests/topotests/isis-lsp-bits-topo1/test_isis_lsp_bits_topo1.py
index 95a0d87c33..27dc1073c6 100755
--- a/tests/topotests/isis-lsp-bits-topo1/test_isis_lsp_bits_topo1.py
+++ b/tests/topotests/isis-lsp-bits-topo1/test_isis_lsp_bits_topo1.py
@@ -73,7 +73,7 @@ from functools import partial
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(CWD, '../'))
+sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
# Import topogen and topotest helpers
@@ -87,8 +87,10 @@ from mininet.topo import Topo
# Global multi-dimensional dictionary containing all expected outputs
outputs = {}
+
class TemplateTopo(Topo):
"Test topology builder"
+
def build(self, *_args, **_opts):
"Build function"
tgen = get_topogen(self)
@@ -96,36 +98,36 @@ class TemplateTopo(Topo):
#
# Define FRR Routers
#
- for router in ['rt1', 'rt2', 'rt3', 'rt4', 'rt5', 'rt6']:
+ for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
tgen.add_router(router)
#
# Define connections
#
- switch = tgen.add_switch('s1')
- switch.add_link(tgen.gears['rt1'], nodeif="eth-sw1")
- switch.add_link(tgen.gears['rt2'], nodeif="eth-sw1")
- switch.add_link(tgen.gears['rt3'], nodeif="eth-sw1")
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["rt1"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1")
- switch = tgen.add_switch('s2')
- switch.add_link(tgen.gears['rt2'], nodeif="eth-rt4")
- switch.add_link(tgen.gears['rt4'], nodeif="eth-rt2")
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2")
- switch = tgen.add_switch('s4')
- switch.add_link(tgen.gears['rt3'], nodeif="eth-rt5")
- switch.add_link(tgen.gears['rt5'], nodeif="eth-rt3")
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3")
- switch = tgen.add_switch('s6')
- switch.add_link(tgen.gears['rt4'], nodeif="eth-rt5")
- switch.add_link(tgen.gears['rt5'], nodeif="eth-rt4")
+ switch = tgen.add_switch("s6")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
- switch = tgen.add_switch('s7')
- switch.add_link(tgen.gears['rt4'], nodeif="eth-rt6")
- switch.add_link(tgen.gears['rt6'], nodeif="eth-rt4")
+ switch = tgen.add_switch("s7")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt4")
- switch = tgen.add_switch('s8')
- switch.add_link(tgen.gears['rt5'], nodeif="eth-rt6")
- switch.add_link(tgen.gears['rt6'], nodeif="eth-rt5")
+ switch = tgen.add_switch("s8")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
def setup_module(mod):
@@ -138,16 +140,15 @@ 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))
+ 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))
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
)
tgen.start_router()
+
def teardown_module(mod):
"Teardown the pytest environment"
tgen = get_topogen()
@@ -155,6 +156,7 @@ def teardown_module(mod):
# This function tears down the whole topology.
tgen.stop_topology()
+
def router_compare_json_output(rname, command, reference):
"Compare router JSON output"
@@ -170,6 +172,7 @@ def router_compare_json_output(rname, command, reference):
assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
assert diff is None, assertmsg
+
#
# Step 1
#
@@ -184,13 +187,14 @@ def test_isis_adjacencies_step1():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- for rname in ['rt1', 'rt2', 'rt3', 'rt4', 'rt5', 'rt6']:
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname,
+ rname,
"show yang operational-data /frr-interface:lib isisd",
"step1/show_yang_interface_isis_adjacencies.ref",
)
+
def test_rib_ipv4_step1():
logger.info("Test (step 1): verify IPv4 RIB")
tgen = get_topogen()
@@ -199,11 +203,12 @@ def test_rib_ipv4_step1():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- for rname in ['rt1', 'rt2', 'rt3', 'rt4', 'rt5', 'rt6']:
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
rname, "show ip route isis json", "step1/show_ip_route.ref"
)
+
def test_rib_ipv6_step1():
logger.info("Test (step 1): verify IPv6 RIB")
tgen = get_topogen()
@@ -212,11 +217,12 @@ def test_rib_ipv6_step1():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- for rname in ['rt1', 'rt2', 'rt3', 'rt4', 'rt5', 'rt6']:
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
rname, "show ipv6 route isis json", "step1/show_ipv6_route.ref"
)
+
#
# Step 2
#
@@ -235,15 +241,20 @@ def test_rib_ipv4_step2():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- logger.info('Disabling setting the attached-bit on RT2 and RT4')
- tgen.net['rt2'].cmd('vtysh -c "conf t" -c "router isis 1" -c "no attached-bit send"')
- tgen.net['rt4'].cmd('vtysh -c "conf t" -c "router isis 1" -c "no attached-bit send"')
+ logger.info("Disabling setting the attached-bit on RT2 and RT4")
+ tgen.net["rt2"].cmd(
+ 'vtysh -c "conf t" -c "router isis 1" -c "no attached-bit send"'
+ )
+ tgen.net["rt4"].cmd(
+ 'vtysh -c "conf t" -c "router isis 1" -c "no attached-bit send"'
+ )
- for rname in ['rt1', 'rt6']:
+ for rname in ["rt1", "rt6"]:
router_compare_json_output(
rname, "show ip route isis json", "step2/show_ip_route.ref"
)
+
def test_rib_ipv6_step2():
logger.info("Test (step 2): verify IPv6 RIB")
tgen = get_topogen()
@@ -252,11 +263,12 @@ def test_rib_ipv6_step2():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- for rname in ['rt1', 'rt6']:
+ for rname in ["rt1", "rt6"]:
router_compare_json_output(
rname, "show ipv6 route isis json", "step2/show_ipv6_route.ref"
)
+
#
# Step 3
#
@@ -265,7 +277,7 @@ def test_rib_ipv6_step2():
# -disble processing a LSP with attach bit set
#
# Expected changes:
-# -RT1 and RT6 should not install a default route
+# -RT1 and RT6 should not install a default route
#
def test_rib_ipv4_step3():
logger.info("Test (step 3): verify IPv4 RIB")
@@ -275,19 +287,24 @@ def test_rib_ipv4_step3():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- logger.info('Enable setting the attached-bit on RT2 and RT4')
- tgen.net['rt2'].cmd('vtysh -c "conf t" -c "router isis 1" -c "attached-bit send"')
- tgen.net['rt4'].cmd('vtysh -c "conf t" -c "router isis 1" -c "attached-bit send"')
+ logger.info("Enable setting the attached-bit on RT2 and RT4")
+ tgen.net["rt2"].cmd('vtysh -c "conf t" -c "router isis 1" -c "attached-bit send"')
+ tgen.net["rt4"].cmd('vtysh -c "conf t" -c "router isis 1" -c "attached-bit send"')
- logger.info('Disable processing received attached-bit in LSP on RT1 and RT6')
- tgen.net['rt1'].cmd('vtysh -c "conf t" -c "router isis 1" -c "attached-bit receive ignore"')
- tgen.net['rt6'].cmd('vtysh -c "conf t" -c "router isis 1" -c "attached-bit receive ignore"')
+ logger.info("Disable processing received attached-bit in LSP on RT1 and RT6")
+ tgen.net["rt1"].cmd(
+ 'vtysh -c "conf t" -c "router isis 1" -c "attached-bit receive ignore"'
+ )
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router isis 1" -c "attached-bit receive ignore"'
+ )
- for rname in ['rt1', 'rt6']:
+ for rname in ["rt1", "rt6"]:
router_compare_json_output(
rname, "show ip route isis json", "step3/show_ip_route.ref"
)
+
def test_rib_ipv6_step3():
logger.info("Test (step 3): verify IPv6 RIB")
tgen = get_topogen()
@@ -296,11 +313,12 @@ def test_rib_ipv6_step3():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- for rname in ['rt1', 'rt6']:
+ for rname in ["rt1", "rt6"]:
router_compare_json_output(
rname, "show ipv6 route isis json", "step3/show_ipv6_route.ref"
)
+
#
# Step 4
#
@@ -319,13 +337,21 @@ def test_rib_ipv4_step4():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- logger.info('restore default processing on received attached-bit in LSP on RT1 and RT6')
- tgen.net['rt1'].cmd('vtysh -c "conf t" -c "router isis 1" -c "no attached-bit receive ignore"')
- tgen.net['rt6'].cmd('vtysh -c "conf t" -c "router isis 1" -c "no attached-bit receive ignore"')
-
- for rname in ['rt1', 'rt6']:
+ logger.info(
+ "restore default processing on received attached-bit in LSP on RT1 and RT6"
+ )
+ tgen.net["rt1"].cmd(
+ 'vtysh -c "conf t" -c "router isis 1" -c "no attached-bit receive ignore"'
+ )
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router isis 1" -c "no attached-bit receive ignore"'
+ )
+
+ for rname in ["rt1", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", "step4/show_ip_route.ref")
+ rname, "show ip route isis json", "step4/show_ip_route.ref"
+ )
+
def test_rib_ipv6_step4():
logger.info("Test (step 4): verify IPv6 RIB")
@@ -335,19 +361,22 @@ def test_rib_ipv6_step4():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- for rname in ['rt1', 'rt6']:
+ for rname in ["rt1", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", "step4/show_ipv6_route.ref")
+ rname, "show ipv6 route isis json", "step4/show_ipv6_route.ref"
+ )
+
# Memory leak test template
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
if not tgen.is_memleak_enabled():
- pytest.skip('Memory leak test/report is disabled')
+ pytest.skip("Memory leak test/report is disabled")
tgen.report_memory_leaks()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/isis-rlfa-topo1/test_isis_rlfa_topo1.py b/tests/topotests/isis-rlfa-topo1/test_isis_rlfa_topo1.py
index bb43e6b114..9ad41c5934 100755
--- a/tests/topotests/isis-rlfa-topo1/test_isis_rlfa_topo1.py
+++ b/tests/topotests/isis-rlfa-topo1/test_isis_rlfa_topo1.py
@@ -82,6 +82,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.isisd]
+
# Global multi-dimensional dictionary containing all expected outputs
outputs = {}
@@ -165,7 +167,7 @@ class TemplateTopo(Topo):
f_in.close()
f_out.close()
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
diff --git a/tests/topotests/isis-snmp/ce3/zebra.conf b/tests/topotests/isis-snmp/ce3/zebra.conf
new file mode 100644
index 0000000000..c6a5824d15
--- /dev/null
+++ b/tests/topotests/isis-snmp/ce3/zebra.conf
@@ -0,0 +1,12 @@
+log file zebra.log
+!
+hostname ce3
+!
+interface ce3-eth0
+ ip address 172.16.1.3/24
+ no link-detect
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r1/isisd.conf b/tests/topotests/isis-snmp/r1/isisd.conf
new file mode 100644
index 0000000000..dd32d3b8a5
--- /dev/null
+++ b/tests/topotests/isis-snmp/r1/isisd.conf
@@ -0,0 +1,24 @@
+hostname r1
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+agentx
+!
+router isis 1
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0001.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+!
+interface r1-eth0
+ ip router isis 1
+ ipv6 router isis 1
+ isis circuit-type level-1
+!
+interface r1-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
diff --git a/tests/topotests/isis-snmp/r1/ldpd.conf b/tests/topotests/isis-snmp/r1/ldpd.conf
new file mode 100644
index 0000000000..4ec296ca5a
--- /dev/null
+++ b/tests/topotests/isis-snmp/r1/ldpd.conf
@@ -0,0 +1,26 @@
+hostname r1
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+agentx
+!
+mpls ldp
+ router-id 1.1.1.1
+ !
+ address-family ipv4
+ discovery transport-address 1.1.1.1
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r1-eth0
+ !
+ interface r1-eth1
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r1/show_ip_route.ref b/tests/topotests/isis-snmp/r1/show_ip_route.ref
new file mode 100644
index 0000000000..dc8f19dad0
--- /dev/null
+++ b/tests/topotests/isis-snmp/r1/show_ip_route.ref
@@ -0,0 +1,143 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r1-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r1-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":4,
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r1-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis-snmp/r1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis-snmp/r1/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..390fda749e
--- /dev/null
+++ b/tests/topotests/isis-snmp/r1/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,40 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r1-eth0",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0004",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r1-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis-snmp/r1/snmpd.conf b/tests/topotests/isis-snmp/r1/snmpd.conf
new file mode 100644
index 0000000000..b37911da36
--- /dev/null
+++ b/tests/topotests/isis-snmp/r1/snmpd.conf
@@ -0,0 +1,15 @@
+agentAddress udp:1.1.1.1:161
+
+com2sec public 1.1.1.1 public
+
+group public_group v1 public
+group public_group v2c public
+
+access public_group "" any noauth prefix all all none
+
+view all included .1
+
+iquerySecName frr
+rouser frr
+
+master agentx
diff --git a/tests/topotests/isis-snmp/r1/zebra.conf b/tests/topotests/isis-snmp/r1/zebra.conf
new file mode 100644
index 0000000000..6ac341e431
--- /dev/null
+++ b/tests/topotests/isis-snmp/r1/zebra.conf
@@ -0,0 +1,24 @@
+log file zebra.log
+!
+hostname r1
+!
+debug zebra kernel
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra nht
+!
+interface lo
+ ip address 1.1.1.1/32
+!
+interface r1-eth0
+ description to rt4
+ ip address 14.0.0.1/24
+!
+interface r1-eth1
+ description to rt3
+ ip address 13.0.0.1/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r2/isisd.conf b/tests/topotests/isis-snmp/r2/isisd.conf
new file mode 100644
index 0000000000..4403d8913b
--- /dev/null
+++ b/tests/topotests/isis-snmp/r2/isisd.conf
@@ -0,0 +1,25 @@
+hostname r2
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+agentx
+!
+router isis 1
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0002.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+!
+interface r2-eth0
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
+interface r2-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
diff --git a/tests/topotests/isis-snmp/r2/ldpd.conf b/tests/topotests/isis-snmp/r2/ldpd.conf
new file mode 100644
index 0000000000..eb963fe41c
--- /dev/null
+++ b/tests/topotests/isis-snmp/r2/ldpd.conf
@@ -0,0 +1,25 @@
+hostname r2
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 2.2.2.2
+ !
+ address-family ipv4
+ discovery transport-address 2.2.2.2
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r2-eth0
+ !
+ interface r2-eth1
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r2/show_ip_route.ref b/tests/topotests/isis-snmp/r2/show_ip_route.ref
new file mode 100644
index 0000000000..2bcee96064
--- /dev/null
+++ b/tests/topotests/isis-snmp/r2/show_ip_route.ref
@@ -0,0 +1,143 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.3",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r2-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.3",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.3.3",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r2-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":4,
+ "interfaceName":"r2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis-snmp/r2/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis-snmp/r2/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..52550daf14
--- /dev/null
+++ b/tests/topotests/isis-snmp/r2/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,40 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r2-eth0",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0005",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r2-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis-snmp/r2/snmpd.conf b/tests/topotests/isis-snmp/r2/snmpd.conf
new file mode 100644
index 0000000000..0f779b8b91
--- /dev/null
+++ b/tests/topotests/isis-snmp/r2/snmpd.conf
@@ -0,0 +1,15 @@
+agentAddress udp:2.2.2.2:161
+
+com2sec public 2.2.2.2 public
+
+group public_group v1 public
+group public_group v2c public
+
+access public_group "" any noauth prefix all all none
+
+view all included .1
+
+iquerySecName frr
+rouser frr
+
+master agentx
diff --git a/tests/topotests/isis-snmp/r2/zebra.conf b/tests/topotests/isis-snmp/r2/zebra.conf
new file mode 100644
index 0000000000..4aa7440c33
--- /dev/null
+++ b/tests/topotests/isis-snmp/r2/zebra.conf
@@ -0,0 +1,24 @@
+log file zebra.log
+!
+hostname r2
+!
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
+debug zebra nht
+!
+interface lo
+ ip address 2.2.2.2/32
+!
+interface r2-eth0
+ description to rt5
+ ip address 25.0.0.2/24
+!
+interface r2-eth1
+ description to rt3
+ ip address 23.0.0.2/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r3/isisd.conf b/tests/topotests/isis-snmp/r3/isisd.conf
new file mode 100644
index 0000000000..e06fe8c1f9
--- /dev/null
+++ b/tests/topotests/isis-snmp/r3/isisd.conf
@@ -0,0 +1,25 @@
+hostname r3
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+agentx
+!
+router isis 1
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0003.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+!
+interface r3-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
+interface r3-eth2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
diff --git a/tests/topotests/isis-snmp/r3/ldpd.conf b/tests/topotests/isis-snmp/r3/ldpd.conf
new file mode 100644
index 0000000000..2935caf13b
--- /dev/null
+++ b/tests/topotests/isis-snmp/r3/ldpd.conf
@@ -0,0 +1,25 @@
+hostname r3
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 3.3.3.3
+ !
+ address-family ipv4
+ discovery transport-address 3.3.3.3
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r3-eth1
+ !
+ interface r3-eth2
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r3/show_ip_route.ref b/tests/topotests/isis-snmp/r3/show_ip_route.ref
new file mode 100644
index 0000000000..da46f1dfe2
--- /dev/null
+++ b/tests/topotests/isis-snmp/r3/show_ip_route.ref
@@ -0,0 +1,143 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis-snmp/r3/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis-snmp/r3/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..3aafab4e2e
--- /dev/null
+++ b/tests/topotests/isis-snmp/r3/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,40 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r3-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0001",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r3-eth2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis-snmp/r3/snmpd.conf b/tests/topotests/isis-snmp/r3/snmpd.conf
new file mode 100644
index 0000000000..3f3501a6fd
--- /dev/null
+++ b/tests/topotests/isis-snmp/r3/snmpd.conf
@@ -0,0 +1,15 @@
+agentAddress udp:3.3.3.3:161
+
+com2sec public 3.3.3.3 public
+
+group public_group v1 public
+group public_group v2c public
+
+access public_group "" any noauth prefix all all none
+
+view all included .1
+
+iquerySecName frr
+rouser frr
+
+master agentx
diff --git a/tests/topotests/isis-snmp/r3/zebra.conf b/tests/topotests/isis-snmp/r3/zebra.conf
new file mode 100644
index 0000000000..6b76114d4d
--- /dev/null
+++ b/tests/topotests/isis-snmp/r3/zebra.conf
@@ -0,0 +1,28 @@
+log file zebra.log
+!
+hostname r3
+!
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
+debug zebra nht
+!
+interface lo
+ ip address 3.3.3.3/32
+!
+interface r3-eth0
+ description to ce3
+ ip address 172.16.1.3/24
+!
+interface r3-eth1
+ description to rt2
+ ip address 13.0.0.3/24
+!
+interface r3-eth2
+ description to rt1
+ ip address 23.0.0.3/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r4/isisd.conf b/tests/topotests/isis-snmp/r4/isisd.conf
new file mode 100644
index 0000000000..1256141da9
--- /dev/null
+++ b/tests/topotests/isis-snmp/r4/isisd.conf
@@ -0,0 +1,24 @@
+hostname r4
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+agentx
+!
+router isis 1
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0004.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+!
+interface r4-eth0
+ ip router isis 1
+ ipv6 router isis 1
+ isis circuit-type level-1
+!
+interface r4-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
diff --git a/tests/topotests/isis-snmp/r4/ldpd.conf b/tests/topotests/isis-snmp/r4/ldpd.conf
new file mode 100644
index 0000000000..b27952514b
--- /dev/null
+++ b/tests/topotests/isis-snmp/r4/ldpd.conf
@@ -0,0 +1,25 @@
+hostname r4
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 4.4.4.4
+ !
+ address-family ipv4
+ discovery transport-address 4.4.4.4
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r4-eth0
+ !
+ interface r4-eth1
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r4/show_ip_route.ref b/tests/topotests/isis-snmp/r4/show_ip_route.ref
new file mode 100644
index 0000000000..da46f1dfe2
--- /dev/null
+++ b/tests/topotests/isis-snmp/r4/show_ip_route.ref
@@ -0,0 +1,143 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis-snmp/r4/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis-snmp/r4/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..86fcfea1a6
--- /dev/null
+++ b/tests/topotests/isis-snmp/r4/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,40 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r4-eth0",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0001",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r4-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0005",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis-snmp/r4/snmpd.conf b/tests/topotests/isis-snmp/r4/snmpd.conf
new file mode 100644
index 0000000000..e5e336d888
--- /dev/null
+++ b/tests/topotests/isis-snmp/r4/snmpd.conf
@@ -0,0 +1,15 @@
+agentAddress udp:4.4.4.4:161
+
+com2sec public 4.4.4.4 public
+
+group public_group v1 public
+group public_group v2c public
+
+access public_group "" any noauth prefix all all none
+
+view all included .1
+
+iquerySecName frr
+rouser frr
+
+master agentx
diff --git a/tests/topotests/isis-snmp/r4/zebra.conf b/tests/topotests/isis-snmp/r4/zebra.conf
new file mode 100644
index 0000000000..fa13601164
--- /dev/null
+++ b/tests/topotests/isis-snmp/r4/zebra.conf
@@ -0,0 +1,24 @@
+log file zebra.log
+!
+hostname r4
+!
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
+debug zebra nht
+!
+interface lo
+ ip address 4.4.4.4/32
+!
+interface r4-eth0
+ description to rt1
+ ip address 14.0.0.4/24
+!
+interface r4-eth1
+ description to rt5
+ ip address 45.0.0.4/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r5/isisd.conf b/tests/topotests/isis-snmp/r5/isisd.conf
new file mode 100644
index 0000000000..58859041a9
--- /dev/null
+++ b/tests/topotests/isis-snmp/r5/isisd.conf
@@ -0,0 +1,25 @@
+hostname r5
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+agentx
+!
+router isis 1
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0005.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+!
+interface r5-eth0
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
+interface r5-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
diff --git a/tests/topotests/isis-snmp/r5/ldpd.conf b/tests/topotests/isis-snmp/r5/ldpd.conf
new file mode 100644
index 0000000000..f3ba867a9f
--- /dev/null
+++ b/tests/topotests/isis-snmp/r5/ldpd.conf
@@ -0,0 +1,25 @@
+hostname r5
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 5.5.5.5
+ !
+ address-family ipv4
+ discovery transport-address 5.5.5.5
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r5-eth0
+ !
+ interface r5-eth1
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r5/ldpdconf b/tests/topotests/isis-snmp/r5/ldpdconf
new file mode 100644
index 0000000000..fc700608b5
--- /dev/null
+++ b/tests/topotests/isis-snmp/r5/ldpdconf
@@ -0,0 +1,25 @@
+hostname r5
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 3.3.3.3
+ !
+ address-family ipv4
+ discovery transport-address 5.5.5.5
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r5-eth0
+ !
+ interface r5-eth1
+ !
+ !
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/r5/show_ip_route.ref b/tests/topotests/isis-snmp/r5/show_ip_route.ref
new file mode 100644
index 0000000000..da46f1dfe2
--- /dev/null
+++ b/tests/topotests/isis-snmp/r5/show_ip_route.ref
@@ -0,0 +1,143 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":1,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":3,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceIndex":4,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis-snmp/r5/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis-snmp/r5/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..994e8166ce
--- /dev/null
+++ b/tests/topotests/isis-snmp/r5/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,40 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r5-eth0",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r5-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0004",
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis-snmp/r5/snmpd.conf b/tests/topotests/isis-snmp/r5/snmpd.conf
new file mode 100644
index 0000000000..5bebbdebd4
--- /dev/null
+++ b/tests/topotests/isis-snmp/r5/snmpd.conf
@@ -0,0 +1,15 @@
+agentAddress udp:5.5.5.5:161
+
+com2sec public 5.5.5.5 public
+
+group public_group v1 public
+group public_group v2c public
+
+access public_group "" any noauth prefix all all none
+
+view all included .1
+
+iquerySecName frr
+rouser frr
+
+master agentx
diff --git a/tests/topotests/isis-snmp/r5/zebra.conf b/tests/topotests/isis-snmp/r5/zebra.conf
new file mode 100644
index 0000000000..7230129f22
--- /dev/null
+++ b/tests/topotests/isis-snmp/r5/zebra.conf
@@ -0,0 +1,24 @@
+log file zebra.log
+!
+hostname r5
+!
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
+debug zebra nht
+!
+interface lo
+ ip address 5.5.5.5/32
+!
+interface r5-eth0
+ description to rt2
+ ip address 25.0.0.5/24
+!
+interface r5-eth1
+ description to rt4
+ ip address 45.0.0.5/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/isis-snmp/test_isis_snmp.dot b/tests/topotests/isis-snmp/test_isis_snmp.dot
new file mode 100644
index 0000000000..6d8c893712
--- /dev/null
+++ b/tests/topotests/isis-snmp/test_isis_snmp.dot
@@ -0,0 +1,114 @@
+## Color coding:
+#########################
+## Main FRR: #f08080 red
+## Switches: #d0e0d0 gray
+## RIP: #19e3d9 Cyan
+## RIPng: #fcb314 dark yellow
+## OSPFv2: #32b835 Green
+## OSPFv3: #19e3d9 Cyan
+## ISIS IPv4 #fcb314 dark yellow
+## ISIS IPv6 #9a81ec purple
+## BGP IPv4 #eee3d3 beige
+## BGP IPv6 #fdff00 yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+ label="Test Topology - LDP-VPLS 1";
+
+ # Routers
+ ce3 [
+ shape=doubleoctagon
+ label="ce3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r1 [
+ shape=doubleoctagon,
+ label="r1",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r2 [
+ shape=doubleoctagon
+ label="r2",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r3 [
+ shape=doubleoctagon
+ label="r3",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+ r4 [
+ shape=doubleoctagon
+ label="r4",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+ r5 [
+ shape=doubleoctagon
+ label="r5",
+ fillcolor="#f08080",
+ style=filled,
+ ];
+
+
+
+ # Switches
+ s1 [
+ shape=oval,
+ label="s1\n14.0.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s2 [
+ shape=oval,
+ label="s2\n25.0.0.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s3 [
+ shape=oval,
+ label="s3\n172.16.1.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s4 [
+ shape=oval,
+ label="s4\n45.0.0.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s5 [
+ shape=oval,
+ label="s5\n13.0.0.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+ s6 [
+ shape=oval,
+ label="s6\n23.0.0.0/24",
+ fillcolor="#d0e0d0",
+ style=filled,
+ ];
+
+ # Connections
+ ce3 -- s3 [label="eth0\n.3"];
+
+ r1 -- s1 [label="eth1\n.1"];
+ r1 -- s5 [label="eth2\n.1"];
+
+ r2 -- s2 [label="eth1\n.2"];
+ r2 -- s6 [label="eth2\n.2"];
+
+ r3 -- s5 [label="eth1\n.3"];
+ r3 -- s6 [label="eth2\n.3"];
+
+ r4 -- s1 [label="eth1\n.4"];
+ r4 -- s4 [label="eth2\n.4"];
+
+ r5 -- s2 [label="eth1\n.5"];
+ r5 -- s4 [label="eth2\n.5"];
+}
diff --git a/tests/topotests/isis-snmp/test_isis_snmp.py b/tests/topotests/isis-snmp/test_isis_snmp.py
new file mode 100755
index 0000000000..1bcd0eefc6
--- /dev/null
+++ b/tests/topotests/isis-snmp/test_isis_snmp.py
@@ -0,0 +1,369 @@
+#!/usr/bin/env python
+
+#
+# test_isis_snmp.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2020 by Volta Networks
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_isis_snmp.py:
+
+ +---------+ 45.0.0.0/24 +---------+
+ | | rt4-eth1 | |
+ | RT4 +----------------+ RT5 |
+ | | rt5-eth1| |
+ +---------+ +---------+
+ rt4-eth0| |rt5-eth0
+ | |
+ 14.0.0.0/24| |25.0.0.0/24
+ | |
+ rt1-eth0| |rt2-eth0
+ +---------+ +---------+
+ | | | |
+ | RT1 | | RT2 |
+ | 1.1.1.1 | | 2.2.2.2 |
+ | | | |
+ +---------+ +---------+
+ rt1-eth1| |rt2-eth1
+ | |
+ | |
+ 13.0.0.0/24| +---------+ |23.0.0.0/24
+ | | | |
+ | | RT3 | |
+ +--------+ 3.3.3.3 +-------+
+ rt3-eth1| |rt3-eth2
+ +---------+
+ |rt3-eth0
+ |
+ |
+ ce3-eth0 (172.16.1.3/24)|
+ +---------+
+ | |
+ | CE3 |
+ | |
+ +---------+
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+from time import sleep
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from lib.snmptest import SnmpTester
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+ "Test topology builder"
+
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ #
+ # Define FRR Routers
+ #
+ for router in ["ce3", "r1", "r2", "r3", "r4", "r5"]:
+ tgen.add_router(router)
+
+ #
+ # Define connections
+ #
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r4"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r5"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["ce3"])
+ switch.add_link(tgen.gears["r3"])
+
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["r4"])
+ switch.add_link(tgen.gears["r5"])
+
+ switch = tgen.add_switch("s5")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r3"])
+
+ switch = tgen.add_switch("s6")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+
+ # skip tests is SNMP not installed
+ if not os.path.isfile("/usr/sbin/snmpd"):
+ error_msg = "SNMP not installed - skipping"
+ pytest.skip(error_msg)
+
+ # This function initiates the topology build with Topogen...
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ # ... and here it calls Mininet initialization functions.
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ # For all registered routers, load the zebra configuration file
+ for rname, router in router_list.iteritems():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ # Don't start the following in the CE nodes
+ if router.name[0] == "r":
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)),
+ "-M snmp",
+ )
+ router.load_config(
+ TopoRouter.RD_LDP, os.path.join(CWD, "{}/ldpd.conf".format(rname)),
+ )
+ router.load_config(
+ TopoRouter.RD_SNMP, os.path.join(CWD, "{}/snmpd.conf".format(rname)),
+ "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap",
+ )
+
+ # After loading the configurations, this function loads configured daemons.
+ tgen.start_router()
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+def router_compare_json_output(rname, command, reference):
+ "Compare router JSON output"
+
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+
+ tgen = get_topogen()
+ filename = "{}/{}/{}".format(CWD, rname, reference)
+ expected = json.loads(open(filename).read())
+
+ # Run test function until we get an result. Wait at most 80 seconds.
+ test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
+ _, diff = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
+ assert diff is None, assertmsg
+
+def generate_oid(numoids, index1, index2):
+ if numoids == 1:
+ oid = "{}".format(index1)
+ else:
+ oid = "{}.{}".format(index1, index2)
+ return oid
+
+
+def test_isis_convergence():
+ logger.info("Test: check ISIS adjacencies")
+ tgen = get_topogen()
+
+ for rname in ["r1", "r2", "r3", "r4", "r5"]:
+ router_compare_json_output(
+ rname,
+ "show yang operational-data /frr-interface:lib isisd",
+ "show_yang_interface_isis_adjacencies.ref")
+
+def test_r1_scalar_snmp():
+ "Wait for protocol convergence"
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.net.get("r1")
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ assert r1_snmp.test_oid('isisSysVersion', "one(1)")
+ assert r1_snmp.test_oid('isisSysLevelType', "level1and2(3)")
+ assert r1_snmp.test_oid('isisSysID',"00 00 00 00 00 01")
+ assert r1_snmp.test_oid('isisSysMaxPathSplits',"32")
+ assert r1_snmp.test_oid('isisSysMaxLSPGenInt',"900 seconds")
+ assert r1_snmp.test_oid('isisSysAdminState',"on(1)")
+ assert r1_snmp.test_oid('isisSysMaxAge',"1200 seconds")
+ assert r1_snmp.test_oid('isisSysProtSupported',"07 5 6 7")
+
+ r2 = tgen.net.get("r2")
+ r2_snmp = SnmpTester(r2, "2.2.2.2", "public", "2c")
+
+ assert r2_snmp.test_oid('isisSysVersion', "one(1)")
+ assert r2_snmp.test_oid('isisSysLevelType', "level1and2(3)")
+ assert r2_snmp.test_oid('isisSysID',"00 00 00 00 00 02")
+ assert r2_snmp.test_oid('isisSysMaxPathSplits',"32")
+ assert r2_snmp.test_oid('isisSysMaxLSPGenInt',"900 seconds")
+ assert r2_snmp.test_oid('isisSysAdminState',"on(1)")
+ assert r2_snmp.test_oid('isisSysMaxAge',"1200 seconds")
+ assert r2_snmp.test_oid('isisSysProtSupported',"07 5 6 7")
+
+
+circtable_test = {
+ "isisCircAdminState": ["on(1)", "on(1)", "on(1)"],
+ "isisCircExistState": ["active(1)", "active(1)", "active(1)"],
+ "isisCircType": ["broadcast(1)", "ptToPt(2)", "staticIn(3)"],
+ "isisCircExtDomain": ["false(2)", "false(2)", "false(2)"],
+ "isisCircLevelType": ["level1(1)", "level1(1)", "level1and2(3)"],
+ "isisCircPassiveCircuit": ["false(2)", "false(2)", "true(1)"],
+ "isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)", "inactive(1)"],
+ "isisCircSmallHellos": ["false(2)", "false(2)", "false(2)"],
+ "isisCirc3WayEnabled": ["false(2)", "false(2)", "false(2)"],
+ }
+
+def test_r1_isisCircTable():
+ tgen = get_topogen()
+
+ r1 = tgen.net.get("r1")
+ r1r = tgen.gears["r1"]
+
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ oids = []
+ oids.append(generate_oid(1,1,0))
+ oids.append(generate_oid(1,2,0))
+ oids.append(generate_oid(1,3,0))
+
+ # check items
+ for item in circtable_test.keys():
+ assertmsg = "{} should be {} oids {} full dict {}:".format(
+ item, circtable_test[item], oids, r1_snmp.walk(item)
+ )
+ assert r1_snmp.test_oid_walk(item, circtable_test[item], oids), assertmsg
+
+circleveltable_test = {
+ "isisCircLevelMetric": ["10", "10", "10", "10"],
+ "isisCircLevelWideMetric": ["10", "10", "0", "0"],
+ "isisCircLevelISPriority": ["64", "64", "64", "64"],
+ "isisCircLevelHelloMultiplier": ["10", "10", "10", "10"],
+ "isisCircLevelHelloTimer": ["3000 milliseconds", "3000 milliseconds", "3000 milliseconds", "3000 milliseconds"],
+ "isisCircLevelMinLSPRetransInt": ["1 seconds", "1 seconds", "0 seconds", "0 seconds"],
+ }
+
+def test_r1_isislevelCircTable():
+ tgen = get_topogen()
+
+ r1 = tgen.net.get("r1")
+ r1r = tgen.gears["r1"]
+
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ oids = []
+ oids.append(generate_oid(2,1,"area"))
+ oids.append(generate_oid(2,2,"area"))
+ oids.append(generate_oid(2,3,"area"))
+ oids.append(generate_oid(2,3,"domain"))
+
+ # check items
+ for item in circleveltable_test.keys():
+ assertmsg = "{} should be {} oids {} full dict {}:".format(
+ item, circleveltable_test[item], oids, r1_snmp.walk(item)
+ )
+ assert r1_snmp.test_oid_walk(item, circleveltable_test[item], oids), assertmsg
+
+
+adjtable_test = {
+ "isisISAdjState": ["up(3)", "up(3)"],
+ "isisISAdj3WayState": ["down(2)", "up(0)"],
+ "isisISAdjNeighSysType": ["l1IntermediateSystem(1)", "l1IntermediateSystem(1)"],
+ "isisISAdjNeighSysID": ["00 00 00 00 00 04", "00 00 00 00 00 03"],
+ "isisISAdjUsage": ["0", "level1(1)"],
+ "isisISAdjNeighPriority": ["64", "0"],
+}
+
+adjtable_down_test = {
+ "isisISAdjState": ["up(3)"],
+ "isisISAdj3WayState": ["down(2)"],
+ "isisISAdjNeighSysType": ["l1IntermediateSystem(1)"],
+ "isisISAdjNeighSysID": ["00 00 00 00 00 04"],
+ "isisISAdjUsage": ["0"],
+ "isisISAdjNeighPriority": ["64"],
+}
+
+def test_r1_isisAdjTable():
+ "check ISIS Adjacency Table"
+ tgen = get_topogen()
+ r1 = tgen.net.get("r1")
+ r1_cmd = tgen.gears["r1"]
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ oids = []
+ oids.append(generate_oid(2,1,1))
+ oids.append(generate_oid(2,2,1))
+
+ oids_down = []
+ oids_down.append(generate_oid(2,1,1))
+
+ # check items
+ for item in adjtable_test.keys():
+ assertmsg = "{} should be {} oids {} full dict {}:".format(
+ item, adjtable_test[item], oids, r1_snmp.walk(item)
+ )
+ assert r1_snmp.test_oid_walk(item, adjtable_test[item], oids), assertmsg
+
+
+ # shutdown interface and one adjacency should be removed
+ "check ISIS adjacency is removed when interface is shutdown"
+ r1_cmd.vtysh_cmd("conf t\ninterface r1-eth1\nshutdown")
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ for item in adjtable_down_test.keys():
+ assertmsg = "{} should be {} oids {} full dict {}:".format(
+ item, adjtable_down_test[item], oids_down, r1_snmp.walk(item)
+ )
+ assert r1_snmp.test_oid_walk(item, adjtable_down_test[item], oids_down), assertmsg
+
+ # no shutdown interface and adjacency should be restored
+ r1_cmd.vtysh_cmd("conf t\ninterface r1-eth1\nno shutdown")
+
+
+# Memory leak test template
+# disabling memory leak
+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/isis-sr-te-topo1/test_isis_sr_te_topo1.py b/tests/topotests/isis-sr-te-topo1/test_isis_sr_te_topo1.py
index bfd2f92a28..6bbb570267 100755
--- a/tests/topotests/isis-sr-te-topo1/test_isis_sr_te_topo1.py
+++ b/tests/topotests/isis-sr-te-topo1/test_isis_sr_te_topo1.py
@@ -85,7 +85,7 @@ from functools import partial
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
-sys.path.append(os.path.join(CWD, '../'))
+sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
# Import topogen and topotest helpers
@@ -96,8 +96,12 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd, pytest.mark.isisd, pytest.mark.pathd]
+
+
class TemplateTopo(Topo):
"Test topology builder"
+
def build(self, *_args, **_opts):
"Build function"
tgen = get_topogen(self)
@@ -105,50 +109,50 @@ class TemplateTopo(Topo):
#
# Define FRR Routers
#
- for router in ['rt1', 'rt2', 'rt3', 'rt4', 'rt5', 'rt6', 'dst']:
+ for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6", "dst"]:
tgen.add_router(router)
#
# Define connections
#
- switch = tgen.add_switch('s1')
- switch.add_link(tgen.gears['rt1'], nodeif="eth-sw1")
- switch.add_link(tgen.gears['rt2'], nodeif="eth-sw1")
- switch.add_link(tgen.gears['rt3'], nodeif="eth-sw1")
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["rt1"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1")
- switch = tgen.add_switch('s2')
- switch.add_link(tgen.gears['rt2'], nodeif="eth-rt4-1")
- switch.add_link(tgen.gears['rt4'], nodeif="eth-rt2-1")
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-1")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-1")
- switch = tgen.add_switch('s3')
- switch.add_link(tgen.gears['rt2'], nodeif="eth-rt4-2")
- switch.add_link(tgen.gears['rt4'], nodeif="eth-rt2-2")
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-2")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-2")
- switch = tgen.add_switch('s4')
- switch.add_link(tgen.gears['rt3'], nodeif="eth-rt5-1")
- switch.add_link(tgen.gears['rt5'], nodeif="eth-rt3-1")
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-1")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-1")
- switch = tgen.add_switch('s5')
- switch.add_link(tgen.gears['rt3'], nodeif="eth-rt5-2")
- switch.add_link(tgen.gears['rt5'], nodeif="eth-rt3-2")
+ switch = tgen.add_switch("s5")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-2")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-2")
- switch = tgen.add_switch('s6')
- switch.add_link(tgen.gears['rt4'], nodeif="eth-rt5")
- switch.add_link(tgen.gears['rt5'], nodeif="eth-rt4")
+ switch = tgen.add_switch("s6")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
- switch = tgen.add_switch('s7')
- switch.add_link(tgen.gears['rt4'], nodeif="eth-rt6")
- switch.add_link(tgen.gears['rt6'], nodeif="eth-rt4")
+ switch = tgen.add_switch("s7")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt4")
- switch = tgen.add_switch('s8')
- switch.add_link(tgen.gears['rt5'], nodeif="eth-rt6")
- switch.add_link(tgen.gears['rt6'], nodeif="eth-rt5")
+ switch = tgen.add_switch("s8")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
+
+ switch = tgen.add_switch("s9")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-dst")
+ switch.add_link(tgen.gears["dst"], nodeif="eth-rt6")
- switch = tgen.add_switch('s9')
- switch.add_link(tgen.gears['rt6'], nodeif="eth-dst")
- switch.add_link(tgen.gears['dst'], nodeif="eth-rt6")
-@pytest.mark.isis
def setup_module(mod):
"Sets up the pytest environment"
@@ -165,24 +169,21 @@ def setup_module(mod):
# For all registered routers, load the zebra configuration file
for rname, router in router_list.iteritems():
router.load_config(
- TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname))
+ 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))
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
)
router.load_config(
- TopoRouter.RD_PATH,
- os.path.join(CWD, '{}/pathd.conf'.format(rname))
+ 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))
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
)
tgen.start_router()
+
def teardown_module(mod):
"Teardown the pytest environment"
tgen = get_topogen()
@@ -190,6 +191,7 @@ def teardown_module(mod):
# This function tears down the whole topology.
tgen.stop_topology()
+
def setup_testcase(msg):
logger.info(msg)
tgen = get_topogen()
@@ -200,9 +202,11 @@ def setup_testcase(msg):
return tgen
+
def print_cmd_result(rname, command):
print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False))
+
def compare_json_test(router, command, reference, exact):
output = router.vtysh_cmd(command, isjson=True)
result = topotest.json_cmp(output, reference)
@@ -210,9 +214,10 @@ def compare_json_test(router, command, reference, exact):
# Note: topotest.json_cmp() just checks on inclusion of keys.
# For exact matching also compare the other way around.
if not result and exact:
- return topotest.json_cmp(reference, output)
+ return topotest.json_cmp(reference, output)
else:
- return result
+ return result
+
def cmp_json_output(rname, command, reference, exact=False):
"Compare router JSON output"
@@ -220,78 +225,136 @@ def cmp_json_output(rname, command, reference, exact=False):
logger.info('Comparing router "%s" "%s" output', rname, command)
tgen = get_topogen()
- filename = '{}/{}/{}'.format(CWD, rname, reference)
+ filename = "{}/{}/{}".format(CWD, rname, reference)
expected = json.loads(open(filename).read())
# Run test function until we get an result. Wait at most 60 seconds.
- test_func = partial(compare_json_test,
- tgen.gears[rname], command, expected, exact)
+ test_func = partial(compare_json_test, tgen.gears[rname], command, expected, exact)
_, 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
+
def cmp_json_output_exact(rname, command, reference):
return cmp_json_output(rname, command, reference, True)
-def add_candidate_path(rname, endpoint, pref, name, segment_list='default'):
- get_topogen().net[rname].cmd(''' \
+
+def add_candidate_path(rname, endpoint, pref, name, segment_list="default"):
+ get_topogen().net[rname].cmd(
+ """ \
vtysh -c "conf t" \
-c "segment-routing" \
-c "traffic-eng" \
- -c "policy color 1 endpoint ''' + endpoint + '''" \
- -c "candidate-path preference ''' + str(pref) + ''' name ''' + name + ''' explicit segment-list ''' + segment_list + '''"''')
+ -c "policy color 1 endpoint """
+ + endpoint
+ + """" \
+ -c "candidate-path preference """
+ + str(pref)
+ + """ name """
+ + name
+ + """ explicit segment-list """
+ + segment_list
+ + '''"'''
+ )
+
def delete_candidate_path(rname, endpoint, pref):
- get_topogen().net[rname].cmd(''' \
+ get_topogen().net[rname].cmd(
+ """ \
vtysh -c "conf t" \
-c "segment-routing" \
-c "traffic-eng" \
- -c "policy color 1 endpoint ''' + endpoint + '''" \
- -c "no candidate-path preference ''' + str(pref) + '''"''')
+ -c "policy color 1 endpoint """
+ + endpoint
+ + """" \
+ -c "no candidate-path preference """
+ + str(pref)
+ + '''"'''
+ )
+
def add_segment(rname, name, index, label):
- get_topogen().net[rname].cmd(''' \
+ get_topogen().net[rname].cmd(
+ """ \
vtysh -c "conf t" \
-c "segment-routing" \
-c "traffic-eng" \
- -c "segment-list ''' + name + '''" \
- -c "index ''' + str(index) + ''' mpls label ''' + str(label) + '''"''')
+ -c "segment-list """
+ + name
+ + """" \
+ -c "index """
+ + str(index)
+ + """ mpls label """
+ + str(label)
+ + '''"'''
+ )
+
def delete_segment(rname, name, index):
- get_topogen().net[rname].cmd(''' \
+ get_topogen().net[rname].cmd(
+ """ \
vtysh -c "conf t" \
-c "segment-routing" \
-c "traffic-eng" \
- -c "segment-list ''' + name + '''" \
- -c "no index ''' + str(index) + '''"''')
+ -c "segment-list """
+ + name
+ + """" \
+ -c "no index """
+ + str(index)
+ + '''"'''
+ )
+
def create_sr_policy(rname, endpoint, bsid):
- get_topogen().net[rname].cmd(''' \
+ get_topogen().net[rname].cmd(
+ """ \
vtysh -c "conf t" \
-c "segment-routing" \
-c "traffic-eng" \
- -c "policy color 1 endpoint ''' + endpoint + '''" \
+ -c "policy color 1 endpoint """
+ + endpoint
+ + """" \
-c "name default" \
- -c "binding-sid ''' + str(bsid) + '''"''')
+ -c "binding-sid """
+ + str(bsid)
+ + '''"'''
+ )
+
def delete_sr_policy(rname, endpoint):
- get_topogen().net[rname].cmd(''' \
+ get_topogen().net[rname].cmd(
+ """ \
vtysh -c "conf t" \
-c "segment-routing" \
-c "traffic-eng" \
- -c "no policy color 1 endpoint ''' + endpoint + '''"''')
+ -c "no policy color 1 endpoint """
+ + endpoint
+ + '''"'''
+ )
+
def create_prefix_sid(rname, prefix, sid):
- get_topogen().net[rname].cmd(''' \
+ get_topogen().net[rname].cmd(
+ """ \
vtysh -c "conf t" \
-c "router isis 1" \
- -c "segment-routing prefix ''' + prefix + " index " + str(sid) + '''"''')
+ -c "segment-routing prefix """
+ + prefix
+ + " index "
+ + str(sid)
+ + '''"'''
+ )
+
def delete_prefix_sid(rname, prefix):
- get_topogen().net[rname].cmd(''' \
+ get_topogen().net[rname].cmd(
+ ''' \
vtysh -c "conf t" \
-c "router isis 1" \
- -c "no segment-routing prefix "''' + prefix)
+ -c "no segment-routing prefix "'''
+ + prefix
+ )
+
#
# Step 1
@@ -301,37 +364,42 @@ def delete_prefix_sid(rname, prefix):
def test_srte_init_step1():
setup_testcase("Test (step 1): wait for IS-IS convergence / label distribution")
- for rname in ['rt1', 'rt6']:
- cmp_json_output(rname,
- "show mpls table json",
- "step1/show_mpls_table_without_candidate.ref")
+ for rname in ["rt1", "rt6"]:
+ cmp_json_output(
+ rname, "show mpls table json", "step1/show_mpls_table_without_candidate.ref"
+ )
+
def test_srte_add_candidate_check_mpls_table_step1():
setup_testcase("Test (step 1): check MPLS table regarding the added Candidate Path")
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- add_candidate_path(rname, endpoint, 100, 'default')
- cmp_json_output(rname,
- "show mpls table json",
- "step1/show_mpls_table_with_candidate.ref")
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ add_candidate_path(rname, endpoint, 100, "default")
+ cmp_json_output(
+ rname, "show mpls table json", "step1/show_mpls_table_with_candidate.ref"
+ )
delete_candidate_path(rname, endpoint, 100)
+
def test_srte_reinstall_sr_policy_check_mpls_table_step1():
- setup_testcase("Test (step 1): check MPLS table after the SR Policy was removed and reinstalled")
+ setup_testcase(
+ "Test (step 1): check MPLS table after the SR Policy was removed and reinstalled"
+ )
- for rname, endpoint, bsid in [('rt1', '6.6.6.6', 1111), ('rt6', '1.1.1.1', 6666)]:
- add_candidate_path(rname, endpoint, 100, 'default')
+ for rname, endpoint, bsid in [("rt1", "6.6.6.6", 1111), ("rt6", "1.1.1.1", 6666)]:
+ add_candidate_path(rname, endpoint, 100, "default")
delete_sr_policy(rname, endpoint)
- cmp_json_output(rname,
- "show mpls table json",
- "step1/show_mpls_table_without_candidate.ref")
+ cmp_json_output(
+ rname, "show mpls table json", "step1/show_mpls_table_without_candidate.ref"
+ )
create_sr_policy(rname, endpoint, bsid)
- add_candidate_path(rname, endpoint, 100, 'default')
- cmp_json_output(rname,
- "show mpls table json",
- "step1/show_mpls_table_with_candidate.ref")
+ add_candidate_path(rname, endpoint, 100, "default")
+ cmp_json_output(
+ rname, "show mpls table json", "step1/show_mpls_table_with_candidate.ref"
+ )
delete_candidate_path(rname, endpoint, 100)
+
#
# Step 2
#
@@ -340,28 +408,41 @@ def test_srte_reinstall_sr_policy_check_mpls_table_step1():
def test_srte_bare_policy_step2():
setup_testcase("Test (step 2): bare SR Policy should not be operational")
- for rname in ['rt1', 'rt6']:
- cmp_json_output_exact(rname,
- "show yang operational-data /frr-pathd:pathd pathd",
- "step2/show_operational_data.ref")
+ for rname in ["rt1", "rt6"]:
+ cmp_json_output_exact(
+ rname,
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step2/show_operational_data.ref",
+ )
+
def test_srte_add_candidate_check_operational_data_step2():
- setup_testcase("Test (step 2): add single Candidate Path, SR Policy should be operational")
+ setup_testcase(
+ "Test (step 2): add single Candidate Path, SR Policy should be operational"
+ )
+
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ add_candidate_path(rname, endpoint, 100, "default")
+ cmp_json_output(
+ rname,
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step2/show_operational_data_with_candidate.ref",
+ )
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- add_candidate_path(rname, endpoint, 100, 'default')
- cmp_json_output(rname,
- "show yang operational-data /frr-pathd:pathd pathd",
- "step2/show_operational_data_with_candidate.ref")
def test_srte_config_remove_candidate_check_operational_data_step2():
- setup_testcase("Test (step 2): remove single Candidate Path, SR Policy should not be operational anymore")
+ setup_testcase(
+ "Test (step 2): remove single Candidate Path, SR Policy should not be operational anymore"
+ )
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
delete_candidate_path(rname, endpoint, 100)
- cmp_json_output_exact(rname,
- "show yang operational-data /frr-pathd:pathd pathd",
- "step2/show_operational_data.ref")
+ cmp_json_output_exact(
+ rname,
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step2/show_operational_data.ref",
+ )
+
#
# Step 3
@@ -371,53 +452,62 @@ def test_srte_config_remove_candidate_check_operational_data_step2():
def test_srte_add_two_candidates_step3():
setup_testcase("Test (step 3): second Candidate Path has higher Priority")
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- for pref, cand_name in [('100', 'first'), ('200', 'second')]:
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ for pref, cand_name in [("100", "first"), ("200", "second")]:
add_candidate_path(rname, endpoint, pref, cand_name)
- cmp_json_output(rname,
- "show yang operational-data /frr-pathd:pathd pathd",
- "step3/show_operational_data_with_two_candidates.ref")
+ cmp_json_output(
+ rname,
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step3/show_operational_data_with_two_candidates.ref",
+ )
# cleanup
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- for pref in ['100', '200']:
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ for pref in ["100", "200"]:
delete_candidate_path(rname, endpoint, pref)
+
def test_srte_add_two_candidates_with_reverse_priority_step3():
setup_testcase("Test (step 3): second Candidate Path has lower Priority")
# Use reversed priorities here
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- for pref, cand_name in [('200', 'first'), ('100', 'second')]:
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ for pref, cand_name in [("200", "first"), ("100", "second")]:
add_candidate_path(rname, endpoint, pref, cand_name)
- cmp_json_output(rname,
- "show yang operational-data /frr-pathd:pathd pathd",
- "step3/show_operational_data_with_two_candidates.ref")
+ cmp_json_output(
+ rname,
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step3/show_operational_data_with_two_candidates.ref",
+ )
# cleanup
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- for pref in ['100', '200']:
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ for pref in ["100", "200"]:
delete_candidate_path(rname, endpoint, pref)
+
def test_srte_remove_best_candidate_step3():
setup_testcase("Test (step 3): delete the Candidate Path with higher priority")
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- for pref, cand_name in [('100', 'first'), ('200', 'second')]:
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ for pref, cand_name in [("100", "first"), ("200", "second")]:
add_candidate_path(rname, endpoint, pref, cand_name)
# Delete candidate with higher priority
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
delete_candidate_path(rname, endpoint, 200)
# Candidate with lower priority should get active now
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- cmp_json_output(rname,
- "show yang operational-data /frr-pathd:pathd pathd",
- "step3/show_operational_data_with_single_candidate.ref")
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ cmp_json_output(
+ rname,
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step3/show_operational_data_with_single_candidate.ref",
+ )
# cleanup
delete_candidate_path(rname, endpoint, 100)
+
#
# Step 4
#
@@ -426,38 +516,38 @@ def test_srte_remove_best_candidate_step3():
def test_srte_change_segment_list_check_mpls_table_step4():
setup_testcase("Test (step 4): check MPLS table for changed Segment List")
- for rname, endpoint in [('rt1', '6.6.6.6'), ('rt6', '1.1.1.1')]:
- add_candidate_path(rname, endpoint, 100, 'default')
- # now change the segment list name
- add_candidate_path(rname, endpoint, 100, 'default', 'test')
- cmp_json_output(rname,
- "show mpls table json",
- "step4/show_mpls_table.ref")
+ for rname, endpoint in [("rt1", "6.6.6.6"), ("rt6", "1.1.1.1")]:
+ add_candidate_path(rname, endpoint, 100, "default")
+ # now change the segment list name
+ add_candidate_path(rname, endpoint, 100, "default", "test")
+ cmp_json_output(rname, "show mpls table json", "step4/show_mpls_table.ref")
delete_candidate_path(rname, endpoint, 100)
+
def test_srte_segment_list_add_segment_check_mpls_table_step4():
- setup_testcase("Test (step 4): check MPLS table for added (then changed and finally deleted) segment")
+ setup_testcase(
+ "Test (step 4): check MPLS table for added (then changed and finally deleted) segment"
+ )
- add_candidate_path('rt1', '6.6.6.6', 100, 'default', 'test')
+ add_candidate_path("rt1", "6.6.6.6", 100, "default", "test")
# first add a new segment
- add_segment('rt1', 'test', 25, 16050)
- cmp_json_output('rt1',
- "show mpls table json",
- "step4/show_mpls_table_add_segment.ref")
+ add_segment("rt1", "test", 25, 16050)
+ cmp_json_output(
+ "rt1", "show mpls table json", "step4/show_mpls_table_add_segment.ref"
+ )
# ... then change it ...
- add_segment('rt1', 'test', 25, 16030)
- cmp_json_output('rt1',
- "show mpls table json",
- "step4/show_mpls_table_change_segment.ref")
+ add_segment("rt1", "test", 25, 16030)
+ cmp_json_output(
+ "rt1", "show mpls table json", "step4/show_mpls_table_change_segment.ref"
+ )
# ... and finally delete it
- delete_segment('rt1', 'test', 25)
- cmp_json_output('rt1',
- "show mpls table json",
- "step4/show_mpls_table.ref")
- delete_candidate_path('rt1', '6.6.6.6', 100)
+ delete_segment("rt1", "test", 25)
+ cmp_json_output("rt1", "show mpls table json", "step4/show_mpls_table.ref")
+ delete_candidate_path("rt1", "6.6.6.6", 100)
+
#
# Step 5
@@ -465,68 +555,81 @@ def test_srte_segment_list_add_segment_check_mpls_table_step4():
# Checking the nexthop using a single SR Policy and a Candidate Path with configured route-map
#
def test_srte_route_map_with_sr_policy_check_nextop_step5():
- setup_testcase("Test (step 5): recursive nexthop learned through BGP neighbour should be aligned with SR Policy from route-map")
+ setup_testcase(
+ "Test (step 5): recursive nexthop learned through BGP neighbour should be aligned with SR Policy from route-map"
+ )
# (re-)build the SR Policy two times to ensure that reinstalling still works
- for i in [1,2]:
- cmp_json_output('rt1',
- "show ip route bgp json",
- "step5/show_ip_route_bgp_inactive_srte.ref")
+ for i in [1, 2]:
+ cmp_json_output(
+ "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
+ )
- delete_sr_policy('rt1', '6.6.6.6')
- cmp_json_output('rt1',
- "show ip route bgp json",
- "step5/show_ip_route_bgp_inactive_srte.ref")
+ delete_sr_policy("rt1", "6.6.6.6")
+ cmp_json_output(
+ "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
+ )
- create_sr_policy('rt1', '6.6.6.6', 1111)
- cmp_json_output('rt1',
- "show ip route bgp json",
- "step5/show_ip_route_bgp_inactive_srte.ref")
+ create_sr_policy("rt1", "6.6.6.6", 1111)
+ cmp_json_output(
+ "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
+ )
+
+ add_candidate_path("rt1", "6.6.6.6", 100, "default")
+ cmp_json_output(
+ "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+ )
- add_candidate_path('rt1', '6.6.6.6', 100, 'default')
- cmp_json_output('rt1',
- "show ip route bgp json",
- "step5/show_ip_route_bgp_active_srte.ref")
+ delete_candidate_path("rt1", "6.6.6.6", 100)
- delete_candidate_path('rt1', '6.6.6.6', 100)
def test_srte_route_map_with_sr_policy_reinstall_prefix_sid_check_nextop_step5():
- setup_testcase("Test (step 5): remove and re-install prefix SID on fist path element and check SR Policy activity")
+ setup_testcase(
+ "Test (step 5): remove and re-install prefix SID on fist path element and check SR Policy activity"
+ )
# first add a candidate path so the SR Policy is active
- add_candidate_path('rt1', '6.6.6.6', 100, 'default')
- cmp_json_output('rt1',
- "show yang operational-data /frr-pathd:pathd pathd",
- "step5/show_operational_data_active.ref")
+ add_candidate_path("rt1", "6.6.6.6", 100, "default")
+ cmp_json_output(
+ "rt1",
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step5/show_operational_data_active.ref",
+ )
# delete prefix SID from first element of the configured path and check
# if the SR Policy is inactive since the label can't be resolved anymore
- delete_prefix_sid('rt5', "5.5.5.5/32")
- cmp_json_output('rt1',
- "show yang operational-data /frr-pathd:pathd pathd",
- "step5/show_operational_data_inactive.ref")
- cmp_json_output('rt1',
- "show ip route bgp json",
- "step5/show_ip_route_bgp_inactive_srte.ref")
+ delete_prefix_sid("rt5", "5.5.5.5/32")
+ cmp_json_output(
+ "rt1",
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step5/show_operational_data_inactive.ref",
+ )
+ cmp_json_output(
+ "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_inactive_srte.ref"
+ )
# re-create the prefix SID and check if the SR Policy is active
- create_prefix_sid('rt5', "5.5.5.5/32", 50)
- cmp_json_output('rt1',
- "show yang operational-data /frr-pathd:pathd pathd",
- "step5/show_operational_data_active.ref")
- cmp_json_output('rt1',
- "show ip route bgp json",
- "step5/show_ip_route_bgp_active_srte.ref")
+ create_prefix_sid("rt5", "5.5.5.5/32", 50)
+ cmp_json_output(
+ "rt1",
+ "show yang operational-data /frr-pathd:pathd pathd",
+ "step5/show_operational_data_active.ref",
+ )
+ cmp_json_output(
+ "rt1", "show ip route bgp json", "step5/show_ip_route_bgp_active_srte.ref"
+ )
+
# Memory leak test template
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
if not tgen.is_memleak_enabled():
- pytest.skip('Memory leak test/report is disabled')
+ pytest.skip("Memory leak test/report is disabled")
tgen.report_memory_leaks()
-if __name__ == '__main__':
+
+if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py b/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py
index 63be3f78aa..148a89474e 100644
--- a/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py
+++ b/tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py
@@ -84,6 +84,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.isisd]
+
class TemplateTopo(Topo):
"Test topology builder"
@@ -134,7 +136,7 @@ class TemplateTopo(Topo):
switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
diff --git a/tests/topotests/isis-tilfa-topo1/test_isis_tilfa_topo1.py b/tests/topotests/isis-tilfa-topo1/test_isis_tilfa_topo1.py
index 83751fabcd..00cb623999 100755
--- a/tests/topotests/isis-tilfa-topo1/test_isis_tilfa_topo1.py
+++ b/tests/topotests/isis-tilfa-topo1/test_isis_tilfa_topo1.py
@@ -85,6 +85,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.isisd]
+
# Global multi-dimensional dictionary containing all expected outputs
outputs = {}
@@ -177,7 +179,7 @@ class TemplateTopo(Topo):
f_in.close()
f_out.close()
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
diff --git a/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py b/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
index a79c8a268b..6ab78c385e 100644
--- a/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
+++ b/tests/topotests/isis-topo1-vrf/test_isis_topo1_vrf.py
@@ -43,6 +43,8 @@ from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.isisd]
+
class ISISTopo1(Topo):
"Simple two layer ISIS vrf topology"
@@ -82,7 +84,7 @@ class ISISTopo1(Topo):
sw.add_link(tgen.gears["r4"])
sw.add_link(tgen.gears["r5"])
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(ISISTopo1, mod.__name__)
@@ -138,15 +140,6 @@ def setup_module(mod):
# After loading the configurations, this function loads configured daemons.
tgen.start_router()
- has_version_20 = False
- for router in tgen.routers().values():
- if router.has_version("<", "4"):
- has_version_20 = True
-
- if has_version_20:
- logger.info("Skipping ISIS vrf tests for FRR 2.0")
- tgen.set_error("ISIS has convergence problems with IPv6")
-
def teardown_module(mod):
"Teardown the pytest environment"
@@ -195,17 +188,6 @@ def test_isis_route_installation():
actual = router.vtysh_cmd(
"show ip route vrf {0}-cust1 json".format(rname), isjson=True
)
- # Older FRR versions don't list interfaces in some ISIS routes
- if router.has_version("<", "3.1"):
- for network, routes in expected.items():
- for route in routes:
- if route["protocol"] != "isis":
- continue
-
- for nexthop in route["nexthops"]:
- nexthop.pop("interfaceIndex", None)
- nexthop.pop("interfaceName", None)
-
assertmsg = "Router '{}' routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
@@ -229,13 +211,6 @@ def test_isis_linux_route_installation():
filename = "{0}/{1}/{1}_route_linux.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
actual = topotest.ip4_vrf_route(router)
-
- # Older FRR versions install routes using different proto
- if router.has_version("<", "3.1"):
- for network, netoptions in expected.items():
- if "proto" in netoptions and netoptions["proto"] == "187":
- netoptions["proto"] = "zebra"
-
assertmsg = "Router '{}' OS routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
@@ -256,17 +231,6 @@ def test_isis_route6_installation():
"show ipv6 route vrf {}-cust1 json".format(rname), isjson=True
)
- # Older FRR versions don't list interfaces in some ISIS routes
- if router.has_version("<", "3.1"):
- for network, routes in expected.items():
- for route in routes:
- if route["protocol"] != "isis":
- continue
-
- for nexthop in route["nexthops"]:
- nexthop.pop("interfaceIndex", None)
- nexthop.pop("interfaceName", None)
-
assertmsg = "Router '{}' routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
@@ -290,13 +254,6 @@ def test_isis_linux_route6_installation():
filename = "{0}/{1}/{1}_route6_linux.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
actual = topotest.ip6_vrf_route(router)
-
- # Older FRR versions install routes using different proto
- if router.has_version("<", "3.1"):
- for network, netoptions in expected.items():
- if "proto" in netoptions and netoptions["proto"] == "187":
- netoptions["proto"] = "zebra"
-
assertmsg = "Router '{}' OS routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
diff --git a/tests/topotests/isis-topo1/test_isis_topo1.py b/tests/topotests/isis-topo1/test_isis_topo1.py
index 25116d9452..e7618c7bce 100644
--- a/tests/topotests/isis-topo1/test_isis_topo1.py
+++ b/tests/topotests/isis-topo1/test_isis_topo1.py
@@ -45,6 +45,8 @@ from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.isisd]
+
class ISISTopo1(Topo):
"Simple two layer ISIS topology"
@@ -84,7 +86,7 @@ class ISISTopo1(Topo):
sw.add_link(tgen.gears["r4"])
sw.add_link(tgen.gears["r5"])
-@pytest.mark.isis
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(ISISTopo1, mod.__name__)
@@ -102,15 +104,6 @@ def setup_module(mod):
# After loading the configurations, this function loads configured daemons.
tgen.start_router()
- has_version_20 = False
- for router in tgen.routers().values():
- if router.has_version("<", "3"):
- has_version_20 = True
-
- if has_version_20:
- logger.info("Skipping ISIS tests for FRR 2.0")
- tgen.set_error("ISIS has convergence problems with IPv6")
-
def teardown_module(mod):
"Teardown the pytest environment"
@@ -162,18 +155,6 @@ def test_isis_route_installation():
filename = "{0}/{1}/{1}_route.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
actual = router.vtysh_cmd("show ip route json", isjson=True)
-
- # Older FRR versions don't list interfaces in some ISIS routes
- if router.has_version("<", "3.1"):
- for network, routes in expected.items():
- for route in routes:
- if route["protocol"] != "isis":
- continue
-
- for nexthop in route["nexthops"]:
- nexthop.pop("interfaceIndex", None)
- nexthop.pop("interfaceName", None)
-
assertmsg = "Router '{}' routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
@@ -192,13 +173,6 @@ def test_isis_linux_route_installation():
filename = "{0}/{1}/{1}_route_linux.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
actual = topotest.ip4_route(router)
-
- # Older FRR versions install routes using different proto
- if router.has_version("<", "3.1"):
- for network, netoptions in expected.items():
- if "proto" in netoptions and netoptions["proto"] == "187":
- netoptions["proto"] = "zebra"
-
assertmsg = "Router '{}' OS routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
@@ -217,21 +191,6 @@ def test_isis_route6_installation():
filename = "{0}/{1}/{1}_route6.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
actual = router.vtysh_cmd("show ipv6 route json", isjson=True)
-
- # Older FRR versions don't list interfaces in some ISIS routes
- if router.has_version("<", "3.1"):
- for network, routes in expected.items():
- for route in routes:
- # Older versions display different metrics for IPv6 routes
- route.pop("metric", None)
-
- if route["protocol"] != "isis":
- continue
-
- for nexthop in route["nexthops"]:
- nexthop.pop("interfaceIndex", None)
- nexthop.pop("interfaceName", None)
-
assertmsg = "Router '{}' routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
@@ -250,13 +209,6 @@ def test_isis_linux_route6_installation():
filename = "{0}/{1}/{1}_route6_linux.json".format(CWD, rname)
expected = json.loads(open(filename, "r").read())
actual = topotest.ip6_route(router)
-
- # Older FRR versions install routes using different proto
- if router.has_version("<", "3.1"):
- for network, netoptions in expected.items():
- if "proto" in netoptions and netoptions["proto"] == "187":
- netoptions["proto"] = "zebra"
-
assertmsg = "Router '{}' OS routes mismatch".format(rname)
assert topotest.json_cmp(actual, expected) is None, assertmsg
diff --git a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py
index 3b3ed3383c..9aa4024598 100644
--- a/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py
+++ b/tests/topotests/ldp-oc-acl-topo1/test_ldp_oc_acl_topo1.py
@@ -78,6 +78,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.ldpd, pytest.mark.ospfd]
+
class TemplateTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py
index ead991b183..aef22c395d 100644
--- a/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py
+++ b/tests/topotests/ldp-oc-topo1/test_ldp_oc_topo1.py
@@ -78,6 +78,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.ldpd, pytest.mark.ospfd]
+
class TemplateTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/ldp-snmp/ce1/zebra.conf b/tests/topotests/ldp-snmp/ce1/zebra.conf
new file mode 100644
index 0000000000..6f165e2724
--- /dev/null
+++ b/tests/topotests/ldp-snmp/ce1/zebra.conf
@@ -0,0 +1,12 @@
+log file zebra.log
+!
+hostname ce1
+!
+interface ce1-eth0
+ ip address 172.16.1.1/24
+ no link-detect
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ldp-snmp/ce2/zebra.conf b/tests/topotests/ldp-snmp/ce2/zebra.conf
new file mode 100644
index 0000000000..ac02d0f9a4
--- /dev/null
+++ b/tests/topotests/ldp-snmp/ce2/zebra.conf
@@ -0,0 +1,12 @@
+log file zebra.log
+!
+hostname ce2
+!
+interface ce2-eth0
+ ip address 172.16.1.2/24
+ no link-detect
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ldp-snmp/ce3/zebra.conf b/tests/topotests/ldp-snmp/ce3/zebra.conf
new file mode 100644
index 0000000000..c6a5824d15
--- /dev/null
+++ b/tests/topotests/ldp-snmp/ce3/zebra.conf
@@ -0,0 +1,12 @@
+log file zebra.log
+!
+hostname ce3
+!
+interface ce3-eth0
+ ip address 172.16.1.3/24
+ no link-detect
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ldp-snmp/r1/isisd.conf b/tests/topotests/ldp-snmp/r1/isisd.conf
new file mode 100644
index 0000000000..da2970d94e
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/isisd.conf
@@ -0,0 +1,27 @@
+hostname r1
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+debug isis ldp-sync
+!
+router isis 1
+ lsp-gen-interval 2
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0001.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+ mpls ldp-sync
+!
+interface r1-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
+interface r1-eth2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
diff --git a/tests/topotests/ldp-snmp/r1/ldpd.conf b/tests/topotests/ldp-snmp/r1/ldpd.conf
new file mode 100644
index 0000000000..01fc039b09
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/ldpd.conf
@@ -0,0 +1,35 @@
+hostname r1
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 1.1.1.1
+ !
+ address-family ipv4
+ discovery transport-address 1.1.1.1
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r1-eth1
+ !
+ interface r1-eth2
+ !
+ !
+!
+l2vpn CUST_A type vpls
+ member interface r1-eth0
+ !
+ member pseudowire r1-mpw0
+ neighbor lsr-id 2.2.2.2
+ pw-id 100
+ !
+!
+line vty
+!
+agentx
+!
diff --git a/tests/topotests/ldp-snmp/r1/show_ip_route.ref b/tests/topotests/ldp-snmp/r1/show_ip_route.ref
new file mode 100644
index 0000000000..b1a55ba103
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_ip_route.ref
@@ -0,0 +1,134 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.3",
+ "afi":"ipv4",
+ "interfaceName":"r1-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_isis_interface_detail.ref b/tests/topotests/ldp-snmp/r1/show_isis_interface_detail.ref
new file mode 100644
index 0000000000..d8fb27af8c
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_isis_interface_detail.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r1-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ],
+ "r1-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..f77d65ebc1
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r1_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r1-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "16777214"
+ }
+ ],
+ "r1-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r2_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r2_eth1_shutdown.ref
new file mode 100644
index 0000000000..f77d65ebc1
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_isis_interface_detail_r2_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r1-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "16777214"
+ }
+ ],
+ "r1-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync.ref b/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync.ref
new file mode 100644
index 0000000000..b699e8c145
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync.ref
@@ -0,0 +1,13 @@
+{
+ "r1-eth1":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync achieved"
+ },
+ "r1-eth2":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync achieved"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..c28cd4cc7d
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r1_eth1_shutdown.ref
@@ -0,0 +1,11 @@
+{
+ "r1-eth1":{
+ "Interface":true
+ },
+ "r1-eth2":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync achieved"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r2_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r2_eth1_shutdown.ref
new file mode 100644
index 0000000000..c63bbea77f
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_isis_ldp_sync_r2_eth1_shutdown.ref
@@ -0,0 +1,13 @@
+{
+ "r1-eth1":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync not achieved"
+ },
+ "r1-eth2":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync achieved"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_l2vpn_binding.ref b/tests/topotests/ldp-snmp/r1/show_l2vpn_binding.ref
new file mode 100644
index 0000000000..b3de7e2c66
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_l2vpn_binding.ref
@@ -0,0 +1,16 @@
+{
+ "2.2.2.2: 100":{
+ "destination":"2.2.2.2",
+ "vcId":100,
+ "localLabel":16,
+ "localControlWord":1,
+ "localVcType":"Ethernet",
+ "localGroupID":0,
+ "localIfMtu":1500,
+ "remoteLabel":16,
+ "remoteControlWord":1,
+ "remoteVcType":"Ethernet",
+ "remoteGroupID":0,
+ "remoteIfMtu":1500
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_l2vpn_vc.ref b/tests/topotests/ldp-snmp/r1/show_l2vpn_vc.ref
new file mode 100644
index 0000000000..29e9df1089
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_l2vpn_vc.ref
@@ -0,0 +1,8 @@
+{
+ "r1-mpw0":{
+ "peerId":"2.2.2.2",
+ "vcId":100,
+ "VpnName":"CUST_A",
+ "status":"up"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_ldp_binding.ref b/tests/topotests/ldp-snmp/r1/show_ldp_binding.ref
new file mode 100644
index 0000000000..b3a12ec53f
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_ldp_binding.ref
@@ -0,0 +1,44 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"2.2.2.2",
+ "localLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"3.3.3.3",
+ "localLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"3.3.3.3",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"2.2.2.2",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"3.3.3.3",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_ldp_discovery.ref b/tests/topotests/ldp-snmp/r1/show_ldp_discovery.ref
new file mode 100644
index 0000000000..9301e60c67
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_ldp_discovery.ref
@@ -0,0 +1,25 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "type":"link",
+ "interface":"r1-eth1",
+ "helloHoldtime":15
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "type":"targeted",
+ "peer":"2.2.2.2",
+ "helloHoldtime":45
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "type":"link",
+ "interface":"r1-eth2",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_ldp_igp_sync.ref b/tests/topotests/ldp-snmp/r1/show_ldp_igp_sync.ref
new file mode 100644
index 0000000000..54d015fef9
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_ldp_igp_sync.ref
@@ -0,0 +1,16 @@
+{
+ "r1-eth1":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"2.2.2.2"
+ },
+ "r1-eth2":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"3.3.3.3"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_ldp_igp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r1/show_ldp_igp_sync_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..2232069f68
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_ldp_igp_sync_r1_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "r1-eth1":{
+ "state":"labelExchangeNotComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":""
+ },
+ "r1-eth2":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"3.3.3.3"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_ldp_neighbor.ref b/tests/topotests/ldp-snmp/r1/show_ldp_neighbor.ref
new file mode 100644
index 0000000000..40d8ebeb90
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_ldp_neighbor.ref
@@ -0,0 +1,16 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "state":"OPERATIONAL",
+ "transportAddress":"2.2.2.2"
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "state":"OPERATIONAL",
+ "transportAddress":"3.3.3.3"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/ldp-snmp/r1/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..6138d03672
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,42 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r1-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "neighbor-extended-circuit-id": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r1-eth2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "neighbor-extended-circuit-id": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r1/snmpd.conf b/tests/topotests/ldp-snmp/r1/snmpd.conf
new file mode 100644
index 0000000000..b37911da36
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/snmpd.conf
@@ -0,0 +1,15 @@
+agentAddress udp:1.1.1.1:161
+
+com2sec public 1.1.1.1 public
+
+group public_group v1 public
+group public_group v2c public
+
+access public_group "" any noauth prefix all all none
+
+view all included .1
+
+iquerySecName frr
+rouser frr
+
+master agentx
diff --git a/tests/topotests/ldp-snmp/r1/zebra.conf b/tests/topotests/ldp-snmp/r1/zebra.conf
new file mode 100644
index 0000000000..ea047355ad
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r1/zebra.conf
@@ -0,0 +1,29 @@
+log file zebra.log
+!
+hostname r1
+!
+debug zebra kernel
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra nht
+debug zebra pseudowires
+debug zebra mpls
+!
+interface lo
+ ip address 1.1.1.1/32
+!
+interface r1-eth0
+ description to s1
+!
+interface r1-eth1
+ description to s4
+ ip address 10.0.1.1/24
+!
+interface r1-eth2
+ description to s5
+ ip address 10.0.2.1/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ldp-snmp/r2/isisd.conf b/tests/topotests/ldp-snmp/r2/isisd.conf
new file mode 100644
index 0000000000..b29a2b93ee
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/isisd.conf
@@ -0,0 +1,28 @@
+hostname r2
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+debug isis ldp-sync
+!
+router isis 1
+ lsp-gen-interval 2
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0002.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+ mpls ldp-sync
+!
+interface r2-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
+interface r2-eth2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+ no isis mpls ldp-sync
+!
diff --git a/tests/topotests/ldp-snmp/r2/ldpd.conf b/tests/topotests/ldp-snmp/r2/ldpd.conf
new file mode 100644
index 0000000000..c93e1a6ac5
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/ldpd.conf
@@ -0,0 +1,35 @@
+hostname r2
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 2.2.2.2
+ !
+ address-family ipv4
+ discovery transport-address 2.2.2.2
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r2-eth1
+ !
+ interface r2-eth2
+ !
+ !
+!
+l2vpn CUST_A type vpls
+ member interface r2-eth0
+ !
+ member pseudowire r2-mpw0
+ neighbor lsr-id 1.1.1.1
+ pw-id 100
+ !
+!
+line vty
+!
+!agentx
+!
diff --git a/tests/topotests/ldp-sync-isis-topo1/r2/ospfd.conf b/tests/topotests/ldp-snmp/r2/ospfd.conf
index f93f6aed56..f93f6aed56 100644
--- a/tests/topotests/ldp-sync-isis-topo1/r2/ospfd.conf
+++ b/tests/topotests/ldp-snmp/r2/ospfd.conf
diff --git a/tests/topotests/ldp-snmp/r2/show_ip_route.ref b/tests/topotests/ldp-snmp/r2/show_ip_route.ref
new file mode 100644
index 0000000000..04f141aba4
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_ip_route.ref
@@ -0,0 +1,134 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.3",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r2-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.3",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.3.3",
+ "afi":"ipv4",
+ "interfaceName":"r2-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r2-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_isis_interface_detail.ref b/tests/topotests/ldp-snmp/r2/show_isis_interface_detail.ref
new file mode 100644
index 0000000000..844aa9402a
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_isis_interface_detail.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r2-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ],
+ "r2-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..821ec70ba5
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r1_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r2-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "16777214"
+ }
+ ],
+ "r2-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r2_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r2_eth1_shutdown.ref
new file mode 100644
index 0000000000..821ec70ba5
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_isis_interface_detail_r2_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r2-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "16777214"
+ }
+ ],
+ "r2-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync.ref b/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync.ref
new file mode 100644
index 0000000000..433d89bd16
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync.ref
@@ -0,0 +1,13 @@
+{
+ "r2-eth1":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync achieved"
+ },
+ "r2-eth2":{
+ "ldpIgpSyncEnabled":false,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync not required"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..2f3eae47c8
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r1_eth1_shutdown.ref
@@ -0,0 +1,13 @@
+{
+ "r2-eth1":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync not achieved"
+ },
+ "r2-eth2":{
+ "ldpIgpSyncEnabled":false,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync not required"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r2_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r2_eth1_shutdown.ref
new file mode 100644
index 0000000000..c3d97a3c73
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_isis_ldp_sync_r2_eth1_shutdown.ref
@@ -0,0 +1,11 @@
+{
+ "r2-eth1":{
+ "Interface":true
+ },
+ "r2-eth2":{
+ "ldpIgpSyncEnabled":false,
+ "holdDownTimeInSec":0,
+ "ldpIgpSyncState":"Sync not required"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_l2vpn_binding.ref b/tests/topotests/ldp-snmp/r2/show_l2vpn_binding.ref
new file mode 100644
index 0000000000..42c5a1cbd9
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_l2vpn_binding.ref
@@ -0,0 +1,16 @@
+{
+ "1.1.1.1: 100":{
+ "destination":"1.1.1.1",
+ "vcId":100,
+ "localLabel":16,
+ "localControlWord":1,
+ "localVcType":"Ethernet",
+ "localGroupID":0,
+ "localIfMtu":1500,
+ "remoteLabel":16,
+ "remoteControlWord":1,
+ "remoteVcType":"Ethernet",
+ "remoteGroupID":0,
+ "remoteIfMtu":1500
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_l2vpn_vc.ref b/tests/topotests/ldp-snmp/r2/show_l2vpn_vc.ref
new file mode 100644
index 0000000000..942ed23a1e
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_l2vpn_vc.ref
@@ -0,0 +1,8 @@
+{
+ "r2-mpw0":{
+ "peerId":"1.1.1.1",
+ "vcId":100,
+ "VpnName":"CUST_A",
+ "status":"up"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_ldp_binding.ref b/tests/topotests/ldp-snmp/r2/show_ldp_binding.ref
new file mode 100644
index 0000000000..c641fb47e6
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_ldp_binding.ref
@@ -0,0 +1,44 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"1.1.1.1",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"3.3.3.3",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"1.1.1.1",
+ "localLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"3.3.3.3",
+ "localLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"1.1.1.1",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"3.3.3.3",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_ldp_discovery.ref b/tests/topotests/ldp-snmp/r2/show_ldp_discovery.ref
new file mode 100644
index 0000000000..26801acade
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_ldp_discovery.ref
@@ -0,0 +1,25 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "type":"link",
+ "interface":"r2-eth1",
+ "helloHoldtime":15
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "type":"targeted",
+ "peer":"1.1.1.1",
+ "helloHoldtime":45
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "type":"link",
+ "interface":"r2-eth2",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync.ref b/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync.ref
new file mode 100644
index 0000000000..f2b24d7d62
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync.ref
@@ -0,0 +1,16 @@
+{
+ "r2-eth1":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"1.1.1.1"
+ },
+ "r2-eth2":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"3.3.3.3"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..b5508dd35c
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r1_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "r2-eth1":{
+ "state":"labelExchangeNotComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":""
+ },
+ "r2-eth2":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"3.3.3.3"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r2_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r2_eth1_shutdown.ref
new file mode 100644
index 0000000000..f2b24d7d62
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_ldp_igp_sync_r2_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "r2-eth1":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"1.1.1.1"
+ },
+ "r2-eth2":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"3.3.3.3"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_ldp_neighbor.ref b/tests/topotests/ldp-snmp/r2/show_ldp_neighbor.ref
new file mode 100644
index 0000000000..eed35289ea
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_ldp_neighbor.ref
@@ -0,0 +1,16 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "state":"OPERATIONAL",
+ "transportAddress":"1.1.1.1"
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"3.3.3.3",
+ "state":"OPERATIONAL",
+ "transportAddress":"3.3.3.3"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r2/show_yang_interface_isis_adjacencies.ref b/tests/topotests/ldp-snmp/r2/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..4dd6ddd76b
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,42 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r2-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0001",
+ "neighbor-extended-circuit-id": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r2-eth2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0003",
+ "neighbor-extended-circuit-id": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r2/snmpd.conf b/tests/topotests/ldp-snmp/r2/snmpd.conf
new file mode 100644
index 0000000000..0f779b8b91
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/snmpd.conf
@@ -0,0 +1,15 @@
+agentAddress udp:2.2.2.2:161
+
+com2sec public 2.2.2.2 public
+
+group public_group v1 public
+group public_group v2c public
+
+access public_group "" any noauth prefix all all none
+
+view all included .1
+
+iquerySecName frr
+rouser frr
+
+master agentx
diff --git a/tests/topotests/ldp-snmp/r2/zebra.conf b/tests/topotests/ldp-snmp/r2/zebra.conf
new file mode 100644
index 0000000000..c244442876
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r2/zebra.conf
@@ -0,0 +1,28 @@
+log file zebra.log
+!
+hostname r2
+!
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
+debug zebra nht
+debug zebra pseudowires
+!
+interface lo
+ ip address 2.2.2.2/32
+!
+interface r2-eth0
+ description to s2
+!
+interface r2-eth1
+ description to s4
+ ip address 10.0.1.2/24
+!
+interface r2-eth2
+ description to s6
+ ip address 10.0.3.2/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ldp-snmp/r3/isisd.conf b/tests/topotests/ldp-snmp/r3/isisd.conf
new file mode 100644
index 0000000000..4c8499f23d
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/isisd.conf
@@ -0,0 +1,29 @@
+hostname r3
+log file isisd.log
+debug isis adj-packets
+debug isis events
+debug isis update-packets
+debug isis ldp-sync
+!
+router isis 1
+ lsp-gen-interval 2
+ net 10.0000.0000.0000.0000.0000.0000.0000.0000.0003.00
+ metric-style wide
+ redistribute ipv4 connected level-1
+ redistribute ipv6 connected level-1
+ mpls ldp-sync
+ mpls ldp-sync holddown 50
+!
+interface r3-eth1
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+ no isis mpls ldp-sync
+!
+interface r3-eth2
+ ip router isis 1
+ ipv6 router isis 1
+ isis network point-to-point
+ isis circuit-type level-1
+!
diff --git a/tests/topotests/ldp-snmp/r3/ldpd.conf b/tests/topotests/ldp-snmp/r3/ldpd.conf
new file mode 100644
index 0000000000..b7eeb258f1
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/ldpd.conf
@@ -0,0 +1,27 @@
+hostname r3
+log file ldpd.log
+!
+debug mpls ldp zebra
+debug mpls ldp event
+debug mpls ldp errors
+debug mpls ldp sync
+!
+mpls ldp
+ router-id 3.3.3.3
+ !
+ address-family ipv4
+ discovery transport-address 3.3.3.3
+ label local allocate host-routes
+ !
+ ttl-security disable
+ !
+ interface r3-eth1
+ !
+ interface r3-eth2
+ !
+ !
+!
+line vty
+!
+!agentx
+!
diff --git a/tests/topotests/ldp-snmp/r3/show_ip_route.ref b/tests/topotests/ldp-snmp/r3/show_ip_route.ref
new file mode 100644
index 0000000000..22504046ed
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_ip_route.ref
@@ -0,0 +1,134 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"lo",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.2.1",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth1"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r3-eth1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":10,
+ "nexthops":[
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"r3-eth2"
+ }
+ ]
+ },
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"connected",
+ "selected":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"r3-eth2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_isis_interface_detail.ref b/tests/topotests/ldp-snmp/r3/show_isis_interface_detail.ref
new file mode 100644
index 0000000000..e323f61f25
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_isis_interface_detail.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r3-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ],
+ "r3-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..e323f61f25
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r1_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r3-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ],
+ "r3-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r2_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r2_eth1_shutdown.ref
new file mode 100644
index 0000000000..e323f61f25
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_isis_interface_detail_r2_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "1": {
+ "r3-eth1": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ],
+ "r3-eth2": [
+ {
+ "level": "Level-1",
+ "metric": "10"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync.ref b/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync.ref
new file mode 100644
index 0000000000..9cb70a4758
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync.ref
@@ -0,0 +1,13 @@
+{
+ "r3-eth1":{
+ "ldpIgpSyncEnabled":false,
+ "holdDownTimeInSec":50,
+ "ldpIgpSyncState":"Sync not required"
+ },
+ "r3-eth2":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":50,
+ "ldpIgpSyncState":"Sync achieved"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..9cb70a4758
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref
@@ -0,0 +1,13 @@
+{
+ "r3-eth1":{
+ "ldpIgpSyncEnabled":false,
+ "holdDownTimeInSec":50,
+ "ldpIgpSyncState":"Sync not required"
+ },
+ "r3-eth2":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":50,
+ "ldpIgpSyncState":"Sync achieved"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref
new file mode 100644
index 0000000000..9cb70a4758
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref
@@ -0,0 +1,13 @@
+{
+ "r3-eth1":{
+ "ldpIgpSyncEnabled":false,
+ "holdDownTimeInSec":50,
+ "ldpIgpSyncState":"Sync not required"
+ },
+ "r3-eth2":{
+ "ldpIgpSyncEnabled":true,
+ "holdDownTimeInSec":50,
+ "ldpIgpSyncState":"Sync achieved"
+ }
+
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_l2vpn_binding.ref b/tests/topotests/ldp-snmp/r3/show_l2vpn_binding.ref
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_l2vpn_binding.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_l2vpn_vc.ref b/tests/topotests/ldp-snmp/r3/show_l2vpn_vc.ref
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_l2vpn_vc.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_ldp_binding.ref b/tests/topotests/ldp-snmp/r3/show_ldp_binding.ref
new file mode 100644
index 0000000000..e54bd6e755
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_ldp_binding.ref
@@ -0,0 +1,44 @@
+{
+ "bindings":[
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"1.1.1.1",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"1.1.1.1/32",
+ "neighborId":"2.2.2.2",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"1.1.1.1",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"2.2.2.2/32",
+ "neighborId":"2.2.2.2",
+ "remoteLabel":"imp-null",
+ "inUse":1
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"1.1.1.1",
+ "localLabel":"imp-null",
+ "inUse":0
+ },
+ {
+ "addressFamily":"ipv4",
+ "prefix":"3.3.3.3/32",
+ "neighborId":"2.2.2.2",
+ "localLabel":"imp-null",
+ "inUse":0
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_ldp_discovery.ref b/tests/topotests/ldp-snmp/r3/show_ldp_discovery.ref
new file mode 100644
index 0000000000..42fa98d4da
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_ldp_discovery.ref
@@ -0,0 +1,18 @@
+{
+ "adjacencies":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "type":"link",
+ "interface":"r3-eth1",
+ "helloHoldtime":15
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "type":"link",
+ "interface":"r3-eth2",
+ "helloHoldtime":15
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_ldp_igp_sync.ref b/tests/topotests/ldp-snmp/r3/show_ldp_igp_sync.ref
new file mode 100644
index 0000000000..73261830c9
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_ldp_igp_sync.ref
@@ -0,0 +1,16 @@
+{
+ "r3-eth1":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"1.1.1.1"
+ },
+ "r3-eth2":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"2.2.2.2"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_ldp_igp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp-snmp/r3/show_ldp_igp_sync_r1_eth1_shutdown.ref
new file mode 100644
index 0000000000..73261830c9
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_ldp_igp_sync_r1_eth1_shutdown.ref
@@ -0,0 +1,16 @@
+{
+ "r3-eth1":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"1.1.1.1"
+ },
+ "r3-eth2":{
+ "state":"labelExchangeComplete",
+ "waitTime":10,
+ "waitTimeRemaining":0,
+ "timerRunning":false,
+ "peerLdpId":"2.2.2.2"
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_ldp_neighbor.ref b/tests/topotests/ldp-snmp/r3/show_ldp_neighbor.ref
new file mode 100644
index 0000000000..5c482da697
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_ldp_neighbor.ref
@@ -0,0 +1,16 @@
+{
+ "neighbors":[
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"1.1.1.1",
+ "state":"OPERATIONAL",
+ "transportAddress":"1.1.1.1"
+ },
+ {
+ "addressFamily":"ipv4",
+ "neighborId":"2.2.2.2",
+ "state":"OPERATIONAL",
+ "transportAddress":"2.2.2.2"
+ }
+ ]
+}
diff --git a/tests/topotests/ldp-snmp/r3/show_yang_interface_isis_adjacencies.ref b/tests/topotests/ldp-snmp/r3/show_yang_interface_isis_adjacencies.ref
new file mode 100644
index 0000000000..0922192361
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/show_yang_interface_isis_adjacencies.ref
@@ -0,0 +1,42 @@
+{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r3-eth1",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0001",
+ "neighbor-extended-circuit-id": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ },
+ {
+ "name": "r3-eth2",
+ "vrf": "default",
+ "state": {
+ "frr-isisd:isis": {
+ "adjacencies": {
+ "adjacency": [
+ {
+ "neighbor-sys-type": "level-1",
+ "neighbor-sysid": "0000.0000.0002",
+ "neighbor-extended-circuit-id": 0,
+ "state": "up"
+ }
+ ]
+ }
+ }
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ldp-snmp/r3/zebra.conf b/tests/topotests/ldp-snmp/r3/zebra.conf
new file mode 100644
index 0000000000..b1919bd296
--- /dev/null
+++ b/tests/topotests/ldp-snmp/r3/zebra.conf
@@ -0,0 +1,32 @@
+log file zebra.log
+!
+hostname r3
+!
+debug zebra rib detailed
+debug zebra dplane detailed
+debug zebra kernel
+debug zebra nht
+debug zebra pseudowires
+!
+interface lo
+ ip address 3.3.3.3/32
+!
+interface r3-eth0
+ description to s3
+!
+interface r3-eth1
+ description to s5
+ ip address 10.0.2.3/24
+!
+interface r3-eth2
+ description to s6
+ ip address 10.0.3.3/24
+!
+!!interface r3-eth3
+!! description to s4
+!! ip address 10.0.1.3/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py b/tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py
new file mode 100644
index 0000000000..c8760f457a
--- /dev/null
+++ b/tests/topotests/ldp-snmp/test_ldp_snmp_topo1.py
@@ -0,0 +1,373 @@
+#!/usr/bin/env python
+
+#
+# test_ldp_isis_topo1.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2020 by Volta Networks
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ldp_vpls_topo1.py:
+
+ +---------+ +---------+
+ | | | |
+ | CE1 | | CE2 |
+ | | | |
+ +---------+ +---------+
+ce1-eth0 (172.16.1.1/24)| |ce2-eth0 (172.16.1.2/24)
+ | |
+ | |
+ rt1-eth0| |rt2-eth0
+ +---------+ 10.0.1.0/24 +---------+
+ | |rt1-eth1 | |
+ | RT1 +----------------+ RT2 |
+ | 1.1.1.1 | rt2-eth1| 2.2.2.2 |
+ | | | |
+ +---------+ +---------+
+ rt1-eth2| |rt2-eth2
+ | |
+ | |
+ 10.0.2.0/24| +---------+ |10.0.3.0/24
+ | | | |
+ | | RT3 | |
+ +--------+ 3.3.3.3 +-------+
+ rt3-eth2| |rt3-eth1
+ +---------+
+ |rt3-eth0
+ |
+ |
+ ce3-eth0 (172.16.1.3/24)|
+ +---------+
+ | |
+ | CE3 |
+ | |
+ +---------+
+"""
+
+import os
+import re
+import sys
+import pytest
+import json
+from time import sleep
+from functools import partial
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from lib.snmptest import SnmpTester
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+ "Test topology builder"
+
+ def build(self, *_args, **_opts):
+ "Build function"
+ tgen = get_topogen(self)
+
+ #
+ # Define FRR Routers
+ #
+ for router in ["ce1", "ce2", "ce3", "r1", "r2", "r3"]:
+ tgen.add_router(router)
+
+ #
+ # Define connections
+ #
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["ce1"])
+ switch.add_link(tgen.gears["r1"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["ce2"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["ce3"])
+ switch.add_link(tgen.gears["r3"])
+
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s5")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r3"])
+
+ switch = tgen.add_switch("s6")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(TemplateTopo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ # For all registered routers, load the zebra configuration file
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ # Don't start isisd and ldpd in the CE nodes
+ if router.name[0] == "r":
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_LDP, os.path.join(CWD, "{}/ldpd.conf".format(rname)),
+ "-M snmp"
+ )
+ router.load_config(
+ TopoRouter.RD_SNMP, os.path.join(CWD, "{}/snmpd.conf".format(rname)),
+ "-Le -Ivacm_conf,usmConf,iquery -V -DAgentX,trap"
+ )
+
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ # This function tears down the whole topology.
+ tgen.stop_topology()
+
+
+def router_compare_json_output(rname, command, reference):
+ "Compare router JSON output"
+
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+
+ tgen = get_topogen()
+ filename = "{}/{}/{}".format(CWD, rname, reference)
+ expected = json.loads(open(filename).read())
+
+ # Run test function until we get an result.
+ test_func = partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
+ _, diff = topotest.run_and_expect(test_func, None, count=320, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
+ assert diff is None, assertmsg
+
+
+def test_isis_convergence():
+ logger.info("Test: check ISIS adjacencies")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["r1", "r2", "r3"]:
+ router_compare_json_output(
+ rname,
+ "show yang operational-data /frr-interface:lib isisd",
+ "show_yang_interface_isis_adjacencies.ref",
+ )
+
+
+def test_rib():
+ logger.info("Test: verify RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ # TODO: disabling this check to avoid 'snmpd not running' errors
+ #if tgen.routers_have_failure():
+ # pytest.skip(tgen.errors)
+
+ for rname in ["r1", "r2", "r3"]:
+ router_compare_json_output(rname, "show ip route json", "show_ip_route.ref")
+
+
+def test_ldp_adjacencies():
+ logger.info("Test: verify LDP adjacencies")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ # TODO: disabling this check to avoid 'snmpd not running' errors
+ #if tgen.routers_have_failure():
+ # pytest.skip(tgen.errors)
+
+ for rname in ["r1", "r2", "r3"]:
+ router_compare_json_output(
+ rname, "show mpls ldp discovery json", "show_ldp_discovery.ref"
+ )
+
+
+def test_ldp_neighbors():
+ logger.info("Test: verify LDP neighbors")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ #if tgen.routers_have_failure():
+ # pytest.skip(tgen.errors)
+
+ for rname in ["r1", "r2", "r3"]:
+ router_compare_json_output(
+ rname, "show mpls ldp neighbor json", "show_ldp_neighbor.ref"
+ )
+
+
+def test_r1_ldp_lsr_objects():
+ "Test mplsLdpLsrObjects objects"
+ tgen = get_topogen()
+
+ r1 = tgen.net.get("r1")
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ assert r1_snmp.test_oid('mplsLdpLsrId', "01 01 01 01")
+ assert r1_snmp.test_oid('mplsLdpLsrLoopDetectionCapable', 'none(1)')
+
+
+def test_r1_ldp_entity_table():
+ "Test mplsLdpEntityTable"
+ tgen = get_topogen()
+
+ r1 = tgen.net.get("r1")
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityLdpId', ['1.1.1.1:0'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityIndex', ['1'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityProtocolVersion', ['1'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityAdminStatus', ['enable(1)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityOperStatus', ['enabled(2)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityTcpPort', ['646'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityUdpDscPort', ['646'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityMaxPduLength', ['4096 octets'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityKeepAliveHoldTimer', ['180 seconds'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityHelloHoldTimer', ['0 seconds'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityInitSessionThreshold', ['0'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityLabelDistMethod', ['downstreamUnsolicited(2)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityLabelRetentionMode', ['liberal(2)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityPathVectorLimit', ['0'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityHopCountLimit', ['0'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityTransportAddrKind', ['loopback(2)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityTargetPeer', ['true(1)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityTargetPeerAddrType', ['ipv4(1)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityTargetPeerAddr', ['01 01 01 01'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityLabelType', ['generic(1)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityDiscontinuityTime', ['(0) 0:00:00.00'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityStorageType', ['nonVolatile(3)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpEntityRowStatus', ['createAndGo(4)'])
+
+
+def test_r1_ldp_peer_table():
+ "Test mplsLdpPeerTable"
+ tgen = get_topogen()
+
+ r1 = tgen.net.get("r1")
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpPeerLdpId', ['2.2.2.2:0', '3.3.3.3:0'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpPeerLabelDistMethod',
+ ['downstreamUnsolicited(2)', 'downstreamUnsolicited(2)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpPeerPathVectorLimit', ['0', '0'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpPeerTransportAddrType', ['ipv4(1)', 'ipv4(1)'])
+ assert r1_snmp.test_oid_walk(
+ 'mplsLdpPeerTransportAddr', ['02 02 02 02', '03 03 03 03'])
+
+
+def test_r1_ldp_session_table():
+ "Test mplsLdpSessionTable"
+ tgen = get_topogen()
+
+ r1 = tgen.net.get("r1")
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ assert r1_snmp.test_oid_walk('mplsLdpSessionState',
+ ['operational(5)', 'operational(5)'])
+ assert r1_snmp.test_oid_walk('mplsLdpSessionRole',
+ ['passive(3)', 'passive(3)'])
+ assert r1_snmp.test_oid_walk('mplsLdpSessionProtocolVersion',
+ ['1', '1'])
+ assert r1_snmp.test_oid_walk('mplsLdpSessionKeepAliveTime',
+ ['180 seconds', '180 seconds'])
+ assert r1_snmp.test_oid_walk('mplsLdpSessionMaxPduLength',
+ ['4096 octets', '4096 octets'])
+ assert r1_snmp.test_oid_walk('mplsLdpSessionDiscontinuityTime',
+ ['(0) 0:00:00.00', '(0) 0:00:00.00'])
+
+
+def test_r1_ldp_hello_adjacency_table():
+ "Test mplsLdpHelloAdjacencyTable"
+ tgen = get_topogen()
+
+ r1 = tgen.net.get("r1")
+ r1_snmp = SnmpTester(r1, "1.1.1.1", "public", "2c")
+
+ assert r1_snmp.test_oid_walk('mplsLdpHelloAdjacencyIndex',
+ ['1', '2', '1'])
+ assert r1_snmp.test_oid_walk('mplsLdpHelloAdjacencyHoldTime',
+ ['15', '45', '15'])
+ assert r1_snmp.test_oid_walk('mplsLdpHelloAdjacencyType',
+ ['link(1)', 'targeted(2)', 'link(1)'])
+
+
+# Memory leak test template
+# disabling memory leak
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ldp-sync-ospf-topo1/test_ldp_sync_ospf_topo1.py b/tests/topotests/ldp-sync-ospf-topo1/test_ldp_sync_ospf_topo1.py
index 20d7f46d4c..57b45e5fdf 100644
--- a/tests/topotests/ldp-sync-ospf-topo1/test_ldp_sync_ospf_topo1.py
+++ b/tests/topotests/ldp-sync-ospf-topo1/test_ldp_sync_ospf_topo1.py
@@ -79,6 +79,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.ldpd, pytest.mark.ospfd]
+
class TemplateTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/ldp-topo1/test_ldp_topo1.py b/tests/topotests/ldp-topo1/test_ldp_topo1.py
index dfe65f010e..06e7734094 100644
--- a/tests/topotests/ldp-topo1/test_ldp_topo1.py
+++ b/tests/topotests/ldp-topo1/test_ldp_topo1.py
@@ -77,6 +77,8 @@ from lib import topotest
fatal_error = ""
+pytestmark = [pytest.mark.ldpd, pytest.mark.ospfd]
+
#####################################################
##
## Network Topology Definition
@@ -159,7 +161,7 @@ class NetworkTopo(Topo):
##
#####################################################
-@pytest.mark.ldp
+
def setup_module(module):
global topo, net
global fatal_error
diff --git a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
index d659acb470..0ea7aca3eb 100644
--- a/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
+++ b/tests/topotests/ldp-vpls-topo1/test_ldp_vpls_topo1.py
@@ -80,6 +80,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.ldpd, pytest.mark.ospfd]
+
class TemplateTopo(Topo):
"Test topology builder"
@@ -121,8 +123,7 @@ class TemplateTopo(Topo):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r3"])
-@pytest.mark.ldp
-@pytest.mark.ospf
+
def setup_module(mod):
"Sets up the pytest environment"
tgen = Topogen(TemplateTopo, mod.__name__)
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 22602cb460..55b11dab3c 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -2516,8 +2516,9 @@ def verify_best_path_as_per_admin_distance(
@retry(attempts=5, wait=2, return_is_str=True, initial_wait=2)
-def verify_bgp_rib(tgen, addr_type, dut, input_dict, next_hop=None,
-aspath=None, multi_nh=None):
+def verify_bgp_rib(
+ tgen, addr_type, dut, input_dict, next_hop=None, aspath=None, multi_nh=None
+):
"""
This API is to verify whether bgp rib has any
matching route for a nexthop.
@@ -2663,25 +2664,35 @@ aspath=None, multi_nh=None):
if not isinstance(next_hop, list):
next_hop = [next_hop]
list1 = next_hop
- found_hops = [rib_r["ip"] for rib_r in
- rib_routes_json["routes"][
- st_rt][0]["nexthops"]]
+ found_hops = [
+ rib_r["ip"]
+ for rib_r in rib_routes_json["routes"][st_rt][0][
+ "nexthops"
+ ]
+ ]
list2 = found_hops
- missing_list_of_nexthops = \
- set(list2).difference(list1)
- additional_nexthops_in_required_nhs = \
- set(list1).difference(list2)
+ missing_list_of_nexthops = set(list2).difference(list1)
+ additional_nexthops_in_required_nhs = set(
+ list1
+ ).difference(list2)
if list2:
if additional_nexthops_in_required_nhs:
- logger.info("Missing nexthop %s for route"\
- " %s in RIB of router %s\n", \
- additional_nexthops_in_required_nhs, \
- st_rt, dut)
- errormsg=("Nexthop {} is Missing for "\
- "route {} in RIB of router {}\n".format(
+ logger.info(
+ "Missing nexthop %s for route"
+ " %s in RIB of router %s\n",
additional_nexthops_in_required_nhs,
- st_rt, dut))
+ st_rt,
+ dut,
+ )
+ errormsg = (
+ "Nexthop {} is Missing for "
+ "route {} in RIB of router {}\n".format(
+ additional_nexthops_in_required_nhs,
+ st_rt,
+ dut,
+ )
+ )
return errormsg
else:
nh_found = True
@@ -3869,6 +3880,7 @@ def verify_attributes_for_evpn_routes(
return errormsg
if rt == "auto":
+ vni_dict = {}
logger.info(
"[DUT: %s]: Verifying auto-rt value for " "evpn route %s:",
dut,
@@ -3876,8 +3888,6 @@ def verify_attributes_for_evpn_routes(
)
if rt_peer:
- vni_dict = {}
-
rnode = tgen.routers()[rt_peer]
show_bgp_json = run_frr_cmd(
rnode, "show bgp vrf all summary json", isjson=True
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index ce35bdc0fe..9174389bea 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -336,16 +336,15 @@ def start_router_daemons(tgen, router, daemons):
router_list = tgen.routers()
# Start daemons
- result = router_list[router].startDaemons(daemons)
- return result
+ res = router_list[router].startDaemons(daemons)
except Exception as e:
errormsg = traceback.format_exc()
logger.error(errormsg)
- return errormsg
+ res = errormsg
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
- return True
+ return res
def kill_mininet_routers_process(tgen):
@@ -1376,12 +1375,14 @@ def generate_ips(network, no_of_ips):
return ipaddress_list
start_ip = ipaddress.IPv4Address(unicode(start_ip))
step = 2 ** (32 - mask)
- if addr_type == "ipv6":
+ elif addr_type == "ipv6":
if start_ip == "0::0" and mask == 0 and no_of_ips == 1:
ipaddress_list.append("{}/{}".format(start_ip, mask))
return ipaddress_list
start_ip = ipaddress.IPv6Address(unicode(start_ip))
step = 2 ** (128 - mask)
+ else:
+ return []
next_ip = start_ip
count = 0
@@ -2390,14 +2391,7 @@ def create_bgp_community_lists(tgen, input_dict, build=False):
logger.error(errormsg)
return False
- try:
- community_type = int(community_type)
- cmd = "{} {} {} {}".format(cmd, community_type, action, value)
- except ValueError:
-
- cmd = "{} {} {} {} {}".format(
- cmd, community_type, name, action, value
- )
+ cmd = "{} {} {} {} {}".format(cmd, community_type, name, action, value)
if del_action:
cmd = "no {}".format(cmd)
diff --git a/tests/topotests/lib/lutil.py b/tests/topotests/lib/lutil.py
index 0b6a946fda..f8f580632e 100644
--- a/tests/topotests/lib/lutil.py
+++ b/tests/topotests/lib/lutil.py
@@ -25,6 +25,7 @@ import json
import math
import time
from lib.topolog import logger
+from lib.topotest import json_cmp
from mininet.net import Mininet
@@ -194,6 +195,10 @@ Total %-4d %-4d %d\n\
global net
if op != "wait":
self.l_line += 1
+
+ if op == "jsoncmp_pass" or op == "jsoncmp_fail":
+ returnJson = True
+
self.log(
"%s (#%d) %s:%s COMMAND:%s:%s:%s:%s:%s:"
% (
@@ -227,6 +232,33 @@ Total %-4d %-4d %d\n\
)
self.log("COMMAND OUTPUT:%s:" % report)
+ # JSON comparison
+ if op == "jsoncmp_pass" or op == "jsoncmp_fail":
+ try:
+ expect = json.loads(regexp)
+ except:
+ expect = None
+ self.log(
+ "WARNING: JSON load failed -- confirm regex input is in JSON format."
+ )
+ json_diff = json_cmp(js, expect)
+ if json_diff != None:
+ if op == "jsoncmp_fail":
+ success = True
+ else:
+ success = False
+ self.log("JSON DIFF:%s:" % json_diff)
+ ret = success
+ else:
+ if op == "jsoncmp_fail":
+ success = False
+ else:
+ success = True
+ self.result(target, success, result)
+ if js != None:
+ return js
+ return ret
+
# Experiment: can we achieve the same match behavior via DOTALL
# without converting newlines to spaces?
out_nl = out
diff --git a/tests/topotests/lib/ospf.py b/tests/topotests/lib/ospf.py
index 5bc9f14fea..79e4d97448 100644
--- a/tests/topotests/lib/ospf.py
+++ b/tests/topotests/lib/ospf.py
@@ -94,7 +94,9 @@ def create_router_ospf(tgen, topo, input_dict=None, build=False, load_config=Tru
return result
-def __create_ospf_global(tgen, input_dict, router, build=False, load_config=True, ospf="ospf"):
+def __create_ospf_global(
+ tgen, input_dict, router, build=False, load_config=True, ospf="ospf"
+):
"""
Helper API to create ospf global configuration.
diff --git a/tests/topotests/lib/pim.py b/tests/topotests/lib/pim.py
index 294f60bf68..d07b58a774 100644
--- a/tests/topotests/lib/pim.py
+++ b/tests/topotests/lib/pim.py
@@ -1564,26 +1564,30 @@ def verify_pim_interface(tgen, topo, dut, interface=None, interface_ip=None):
logger.info("[DUT: %s]: Verifying PIM interface status:", dut)
rnode = tgen.routers()[dut]
- show_ip_pim_interface_json = rnode.\
- vtysh_cmd("show ip pim interface json", isjson=True)
+ show_ip_pim_interface_json = rnode.vtysh_cmd(
+ "show ip pim interface json", isjson=True
+ )
- logger.info("show_ip_pim_interface_json: \n %s",
- show_ip_pim_interface_json)
+ logger.info("show_ip_pim_interface_json: \n %s", show_ip_pim_interface_json)
if interface_ip:
if interface in show_ip_pim_interface_json:
pim_intf_json = show_ip_pim_interface_json[interface]
if pim_intf_json["address"] != interface_ip:
- errormsg = ("[DUT %s]: PIM interface "
- "ip is not correct "
- "[FAILED]!! Expected : %s, Found : %s"
- %(dut, pim_intf_json["address"],interface_ip))
+ errormsg = (
+ "[DUT %s]: PIM interface "
+ "ip is not correct "
+ "[FAILED]!! Expected : %s, Found : %s"
+ % (dut, pim_intf_json["address"], interface_ip)
+ )
return errormsg
else:
- logger.info("[DUT %s]: PIM interface "
- "ip is correct "
- "[Passed]!! Expected : %s, Found : %s"
- %(dut, pim_intf_json["address"],interface_ip))
+ logger.info(
+ "[DUT %s]: PIM interface "
+ "ip is correct "
+ "[Passed]!! Expected : %s, Found : %s"
+ % (dut, pim_intf_json["address"], interface_ip)
+ )
return True
else:
for destLink, data in topo["routers"][dut]["links"].items():
@@ -1595,24 +1599,36 @@ def verify_pim_interface(tgen, topo, dut, interface=None, interface_ip=None):
pim_intf_ip = data["ipv4"].split("/")[0]
if pim_interface in show_ip_pim_interface_json:
- pim_intf_json = show_ip_pim_interface_json\
- [pim_interface]
+ pim_intf_json = show_ip_pim_interface_json[pim_interface]
# Verifying PIM interface
- if pim_intf_json["address"] != pim_intf_ip and \
- pim_intf_json["state"] != "up":
- errormsg = ("[DUT %s]: PIM interface: %s "
- "PIM interface ip: %s, status check "
- "[FAILED]!! Expected : %s, Found : %s"
- %(dut, pim_interface, pim_intf_ip,
- pim_interface, pim_intf_json["state"]))
+ if (
+ pim_intf_json["address"] != pim_intf_ip
+ and pim_intf_json["state"] != "up"
+ ):
+ errormsg = (
+ "[DUT %s]: PIM interface: %s "
+ "PIM interface ip: %s, status check "
+ "[FAILED]!! Expected : %s, Found : %s"
+ % (
+ dut,
+ pim_interface,
+ pim_intf_ip,
+ pim_interface,
+ pim_intf_json["state"],
+ )
+ )
return errormsg
- logger.info("[DUT %s]: PIM interface: %s, "
- "interface ip: %s, status: %s"
- " [PASSED]!!",
- dut, pim_interface, pim_intf_ip,
- pim_intf_json["state"])
+ logger.info(
+ "[DUT %s]: PIM interface: %s, "
+ "interface ip: %s, status: %s"
+ " [PASSED]!!",
+ dut,
+ pim_interface,
+ pim_intf_ip,
+ pim_intf_json["state"],
+ )
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
return True
@@ -3420,30 +3436,36 @@ def verify_igmp_interface(tgen, topo, dut, igmp_iface, interface_ip):
if router != dut:
continue
- logger.info("[DUT: %s]: Verifying PIM interface status:",
- dut)
+ logger.info("[DUT: %s]: Verifying PIM interface status:", dut)
rnode = tgen.routers()[dut]
- show_ip_igmp_interface_json = \
- run_frr_cmd(rnode, "show ip igmp interface json", isjson=True)
+ show_ip_igmp_interface_json = run_frr_cmd(
+ rnode, "show ip igmp interface json", isjson=True
+ )
- if igmp_iface in show_ip_igmp_interface_json:
+ if igmp_iface in show_ip_igmp_interface_json:
igmp_intf_json = show_ip_igmp_interface_json[igmp_iface]
# Verifying igmp interface
- if igmp_intf_json["address"] != interface_ip:
- errormsg = ("[DUT %s]: igmp interface ip is not correct "
- "[FAILED]!! Expected : %s, Found : %s"
- %(dut, igmp_intf_json["address"], interface_ip))
+ if igmp_intf_json["address"] != interface_ip:
+ errormsg = (
+ "[DUT %s]: igmp interface ip is not correct "
+ "[FAILED]!! Expected : %s, Found : %s"
+ % (dut, igmp_intf_json["address"], interface_ip)
+ )
return errormsg
- logger.info("[DUT %s]: igmp interface: %s, "
- "interface ip: %s"
- " [PASSED]!!",
- dut, igmp_iface, interface_ip)
+ logger.info(
+ "[DUT %s]: igmp interface: %s, " "interface ip: %s" " [PASSED]!!",
+ dut,
+ igmp_iface,
+ interface_ip,
+ )
else:
- errormsg = ("[DUT %s]: igmp interface: %s "
- "igmp interface ip: %s, is not present "
- %(dut, igmp_iface, interface_ip))
+ errormsg = (
+ "[DUT %s]: igmp interface: %s "
+ "igmp interface ip: %s, is not present "
+ % (dut, igmp_iface, interface_ip)
+ )
return errormsg
logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py
index 5112500e0b..e6b140a0e2 100644
--- a/tests/topotests/lib/snmptest.py
+++ b/tests/topotests/lib/snmptest.py
@@ -86,12 +86,11 @@ class SnmpTester(object):
def _get_snmp_oid(snmp_output):
tokens = snmp_output.strip().split()
-# if len(tokens) > 5:
-# return None
-
+ # if len(tokens) > 5:
+ # return None
# third token is the value of the object
- return tokens[0].split('.',1)[1]
+ return tokens[0].split(".", 1)[1]
def _parse_multiline(self, snmp_output):
results = snmp_output.strip().split("\r\n")
@@ -142,7 +141,11 @@ class SnmpTester(object):
print("FAIL: missing oid key {}".format(oid))
return False
if results_dict[oid] != values[index]:
- print("FAIL{} {} |{}| == |{}|".format(oid, index, results_dict[oid], values[index]))
+ print(
+ "FAIL{} {} |{}| == |{}|".format(
+ oid, index, results_dict[oid], values[index]
+ )
+ )
return False
index += 1
return True
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index f958cc11d3..553f2bc6cf 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -1006,7 +1006,7 @@ def diagnose_env_linux():
if not os.path.isdir("/tmp"):
logger.warning("could not find /tmp for logs")
else:
- os.system("mkdir /tmp/topotests")
+ os.system("mkdir -p /tmp/topotests")
# Log diagnostics to file so it can be examined later.
fhandler = logging.FileHandler(filename="/tmp/topotests/diagnostics.txt")
fhandler.setLevel(logging.DEBUG)
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 1e6ef1b2b3..5cc1a6981d 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -1424,7 +1424,7 @@ class Router(Node):
zebra_option = self.daemons_options["zebra"]
self.cmd(
"ASAN_OPTIONS=log_path=zebra.asan {0} {1} --log file:zebra.log --log-level debug -s 90000000 -d > zebra.out 2> zebra.err".format(
- zebra_path, zebra_option, self.logdir, self.name
+ zebra_path, zebra_option
)
)
logger.debug("{}: {} zebra started".format(self, self.routertype))
@@ -1439,7 +1439,7 @@ class Router(Node):
staticd_option = self.daemons_options["staticd"]
self.cmd(
"ASAN_OPTIONS=log_path=staticd.asan {0} {1} --log file:staticd.log --log-level debug -d > staticd.out 2> staticd.err".format(
- staticd_path, staticd_option, self.logdir, self.name
+ staticd_path, staticd_option
)
)
logger.debug("{}: {} staticd started".format(self, self.routertype))
@@ -1723,7 +1723,7 @@ class Router(Node):
interface = ""
ll_per_if_count = 0
for line in ifaces:
- m = re.search("[0-9]+: ([^:@]+)[@if0-9:]+ <", line)
+ m = re.search("[0-9]+: ([^:@]+)[-@a-z0-9:]+ <", line)
if m:
interface = m.group(1)
ll_per_if_count = 0
@@ -1831,8 +1831,8 @@ class LinuxRouter(Router):
class FreeBSDRouter(Router):
"A FreeBSD Router Node with IPv4/IPv6 forwarding enabled."
- def __init__(eslf, name, **params):
- Router.__init__(Self, name, **params)
+ def __init__(self, name, **params):
+ Router.__init__(self, name, **params)
class LegacySwitch(OVSSwitch):
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 c670c82d21..6b7180978e 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
@@ -642,11 +642,13 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
next_hop_rp = topo["routers"]["f1"]["links"]["i1"]["ipv4"].split("/")[0]
next_hop_lhr = topo["routers"]["i1"]["links"]["l1"]["ipv4"].split("/")[0]
+ next_hop_fhr = topo["routers"]["i1"]["links"]["f1"]["ipv4"].split("/")[0]
+ CRP = topo["routers"]["b1"]["bsm"]["bsr_packets"]["packet9"]["candidate_rp"]
input_dict = {
- "f1": {"static_routes": [{"network": BSR1_ADDR, "next_hop": NEXT_HOP1}]},
"i1": {"static_routes": [{"network": BSR1_ADDR, "next_hop": next_hop_rp}]},
"l1": {"static_routes": [{"network": BSR1_ADDR, "next_hop": next_hop_lhr}]},
+ "f1": {"static_routes": [{"network": CRP, "next_hop": next_hop_fhr, "delete": True}]},
}
result = create_static_routes(tgen, input_dict)
@@ -655,7 +657,6 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
# Use scapy to send pre-defined packet from senser to receiver
group = topo["routers"]["b1"]["bsm"]["bsr_packets"]["packet9"]["group"]
- CRP = topo["routers"]["b1"]["bsm"]["bsr_packets"]["packet9"]["candidate_rp"]
step("waiting for BSR to timeout before configuring blackhole route")
clear_bsrp_data(tgen, topo)
@@ -691,7 +692,10 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
step("Verify if b1 chosen as BSR in l1")
result = verify_pim_bsr(tgen, topo, "l1", BSR_IP_1, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "b1 is not chosen as BSR in l1 \n Error: {}".format(
+ tc_name, result
+ ))
state_after = verify_pim_interface_traffic(tgen, state_dict)
assert isinstance(
@@ -706,7 +710,8 @@ def test_BSR_CRP_with_blackhole_address_p1(request):
input_dict = {
"f1": {
"static_routes": [
- {"network": [BSR1_ADDR, CRP], "next_hop": "blackhole", "delete": True}
+ {"network": [BSR1_ADDR, CRP], "next_hop": "blackhole", "delete": True},
+ {"network": BSR1_ADDR, "next_hop": NEXT_HOP1},
]
}
}
@@ -836,7 +841,10 @@ def test_new_router_fwd_p0(request):
# Verify bsr state in l1
step("Verify no BSR in l1 as i1 would not forward the no-forward bsm")
result = verify_pim_bsr(tgen, topo, "l1", bsr_ip, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "BSR data is present after no-forward bsm also \n Error: {}".format(
+ tc_name, result
+ ))
# unconfigure unicast bsm on f1-i1-eth2
step("unconfigure unicast bsm on f1-i1-eth2, will forward with only mcast")
@@ -958,7 +966,10 @@ def test_int_bsm_config_p1(request):
result = verify_ip_mroutes(
tgen, "i1", src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "Mroutes are still present \n Error: {}".format(
+ tc_name, result
+ ))
# unconfigure bsm processing on f1 on f1-i1-eth2
step("unconfigure bsm processing on f1 in f1-i1-eth2, will drop bsm")
@@ -978,14 +989,20 @@ def test_int_bsm_config_p1(request):
# Verify bsr state in i1
step("Verify if b1 is not chosen as BSR in i1")
result = verify_pim_bsr(tgen, topo, "i1", bsr_ip, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "b1 is chosen as BSR in i1 \n Error: {}".format(
+ tc_name, result
+ ))
# check if mroute still not installed because of rp not available
step("check if mroute still not installed because of rp not available")
result = verify_ip_mroutes(
tgen, "i1", src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "mroute installed but rp not available \n Error: {}".format(
+ tc_name, result
+ ))
# configure bsm processing on i1 on f1-i1-eth2
step("configure bsm processing on f1 in f1-i1-eth2, will accept bsm")
@@ -1118,7 +1135,10 @@ def test_static_rp_override_p1(request):
"l1": {
"pim": {
"rp": [
- {"rp_addr": "33.33.33.33", "group_addr_range": ["225.1.1.1/32"],}
+ {
+ "rp_addr": "33.33.33.33",
+ "group_addr_range": ["225.1.1.1/32"],
+ }
]
}
}
@@ -1294,7 +1314,8 @@ def test_bsmp_stress_add_del_restart_p2(request):
assert (
rp_add1 == rp2[group]
), "Testcase {} :Failed \n Error : rp expected {} rp received {}".format(
- tc_name, rp_add1,
+ tc_name,
+ rp_add1,
)
# Verify if that rp is installed
@@ -1443,7 +1464,10 @@ def test_BSM_timeout_p0(request):
tgen, topo, "f1", group, rp_source="BSR", expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "bsr has not aged out in f1 \n Error: {}".format(
+ tc_name, result
+ ))
# Verify RP mapping removed after hold timer expires
group = "225.1.1.1/32"
@@ -1467,14 +1491,20 @@ def test_BSM_timeout_p0(request):
result = verify_join_state_and_timer(
tgen, dut, iif, src_addr, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "join state is up and join timer is running in l1 \n Error: {}".format(
+ tc_name, result
+ ))
# Verify ip mroute is not installed
step("Verify mroute not installed in l1")
result = verify_ip_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "mroute installed in l1 \n Error: {}".format(
+ tc_name, result
+ ))
step("clear BSM database before moving to next case")
clear_bsrp_data(tgen, topo)
@@ -1627,12 +1657,22 @@ def test_iif_join_state_p0(request):
result = verify_ip_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, expected=False
)
- assert result is not True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "mroute installed in l1 \n Error: {}".format(
+ tc_name, result
+ ))
# Add back route for RP to make it reachable
step("Add back route for RP to make it reachable")
input_dict = {
- "l1": {"static_routes": [{"network": rp_ip, "next_hop": next_hop_lhr,}]}
+ "l1": {
+ "static_routes": [
+ {
+ "network": rp_ip,
+ "next_hop": next_hop_lhr,
+ }
+ ]
+ }
}
result = create_static_routes(tgen, input_dict)
assert result is True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
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 459afb5a02..5fc5e52518 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
@@ -454,7 +454,10 @@ def test_starg_mroute_p0(request):
result = verify_ip_mroutes(
tgen, dut, src_addr, GROUP_ADDRESS, iif, oil, wait=20, expected=False
)
- assert result is not True, "Testcase {}:Failed \n Error: {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "mroute installed in l1 \n Error: {}".format(
+ tc_name, result
+ ))
# Send BSM again to configure rp
step("Add back RP by sending BSM from b1")
@@ -695,7 +698,8 @@ def test_RP_priority_p0(request):
assert (
rp_add1 == rp2[group]
), "Testcase {} :Failed \n Error : rp expected {} rp received {}".format(
- tc_name, rp_add1,
+ tc_name,
+ rp_add1,
)
# Verify if that rp is installed
@@ -803,7 +807,10 @@ def test_BSR_election_p0(request):
# Verify bsr state in FHR
step("Verify if b2 is not chosen as bsr in f1")
result = verify_pim_bsr(tgen, topo, "f1", bsr_ip2, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error {}".format(tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "b2 is chosen as bsr in f1 \n Error: {}".format(
+ tc_name, result
+ ))
# Verify if b1 is still chosen as bsr
step("Verify if b1 is still chosen as bsr in f1")
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 ac675c5c2f..e55e30270d 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
@@ -102,7 +102,7 @@ from lib.pim import (
clear_ip_mroute,
clear_ip_pim_interface_traffic,
verify_igmp_config,
- clear_ip_mroute_verify
+ clear_ip_mroute_verify,
)
from lib.topolog import logger
from lib.topojson import build_topo_from_json, build_config_from_json
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 a9d914da57..7e409c2a05 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
@@ -877,7 +877,7 @@ def test_verify_SPT_switchover_when_RPT_and_SPT_path_is_different_p0(request):
data["src_address"],
_IGMP_JOIN_RANGE,
data["iif"],
- data["oil"]
+ data["oil"],
)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
@@ -1122,8 +1122,9 @@ def test_verify_mroute_after_shut_noshut_of_upstream_interface_p1(request):
done_flag = False
for retry in range(1, 11):
- result = verify_upstream_iif(tgen, "l1", "Unknown", source, IGMP_JOIN_RANGE_2,
- expected=False)
+ result = verify_upstream_iif(
+ tgen, "l1", "Unknown", source, IGMP_JOIN_RANGE_2, expected=False
+ )
if result is not True:
done_flag = True
else:
@@ -1515,7 +1516,7 @@ def test_verify_mroute_when_FRR_is_FHR_and_LHR_p0(request):
_IGMP_JOIN_RANGE,
data["iif"],
data["oil"],
- expected=False
+ expected=False,
)
if result is not True:
done_flag = True
@@ -1928,9 +1929,10 @@ def test_verify_oil_iif_for_mroute_after_shut_noshut_source_interface_p1(request
"f1-i8-eth2",
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n mroutes are"
- " still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behavior: {}".format(result))
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 fdceb77fd1..1c22654541 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
@@ -597,9 +597,10 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
input_traffic = {"l1": {"traffic_sent": [intf_l1_i1]}}
result = verify_multicast_traffic(tgen, input_traffic, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- " Traffic is not stopped yet \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " " Traffic is not stopped yet \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -612,9 +613,10 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
result = verify_igmp_groups(
tgen, dut, intf_l1_i1, IGMP_JOIN_RANGE_1, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "IGMP groups are not deleted \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "IGMP groups are not deleted \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -655,9 +657,10 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "mroutes are still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -722,9 +725,10 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
input_traffic = {"f1": {"traffic_sent": [intf_f1_i8]}}
result = verify_multicast_traffic(tgen, input_traffic, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- " Traffic is not stopped yet \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " " Traffic is not stopped yet \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -737,9 +741,10 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
result = verify_igmp_groups(
tgen, dut, intf_f1_i8, IGMP_JOIN_RANGE_1, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "IGMP groups are not deleted \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "IGMP groups are not deleted \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -775,9 +780,10 @@ def test_verify_oil_when_join_prune_sent_scenario_1_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "mroutes are still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -959,9 +965,10 @@ def test_verify_oil_when_join_prune_sent_scenario_2_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "mroutes are still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -1022,9 +1029,10 @@ def test_verify_oil_when_join_prune_sent_scenario_2_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "mroutes are still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroutes are still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -1190,9 +1198,10 @@ def test_shut_noshut_source_interface_when_upstream_cleared_from_LHR_p1(request)
result = verify_ip_mroutes(
tgen, "f1", source_i2, IGMP_JOIN_RANGE_1, intf_f1_i2, intf_f1_r2, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n mroutes are"
- " still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n mroutes are" " still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behavior: {}".format(result))
@@ -1630,7 +1639,14 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
input_dict_2 = {
"l1": {
"igmp": {
- "interfaces": {intf_l1_i1: {"igmp": {"version": "2", "delete": True,}}}
+ "interfaces": {
+ intf_l1_i1: {
+ "igmp": {
+ "version": "2",
+ "delete": True,
+ }
+ }
+ }
}
}
}
@@ -1642,9 +1658,10 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
dut = "l1"
interface = topo["routers"]["l1"]["links"]["i1"]["interface"]
result = verify_igmp_groups(tgen, dut, interface, IGMP_JOIN_RANGE_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n Groups are not"
- " present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Groups are not" " present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -1712,7 +1729,14 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
input_dict_2 = {
"l1": {
"igmp": {
- "interfaces": {intf_l1_i1: {"igmp": {"version": "2", "delete": True,}}}
+ "interfaces": {
+ intf_l1_i1: {
+ "igmp": {
+ "version": "2",
+ "delete": True,
+ }
+ }
+ }
}
}
}
@@ -1725,9 +1749,10 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
dut = "l1"
interface = topo["routers"]["l1"]["links"]["i1"]["interface"]
result = verify_igmp_groups(tgen, dut, interface, IGMP_JOIN_RANGE_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n Groups are not"
- " present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Groups are not" " present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -1811,7 +1836,14 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
input_dict_2 = {
"l1": {
"igmp": {
- "interfaces": {intf_l1_i1: {"igmp": {"version": "2", "delete": True,}}}
+ "interfaces": {
+ intf_l1_i1: {
+ "igmp": {
+ "version": "2",
+ "delete": True,
+ }
+ }
+ }
}
}
}
@@ -1831,9 +1863,10 @@ def test_verify_remove_add_igmp_config_to_receiver_interface_p0(request):
result = verify_ip_mroutes(
tgen, dut, source, IGMP_JOIN_RANGE_1, iif, oil, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n routes are still"
- " present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n routes are still" " present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -1995,7 +2028,14 @@ def test_verify_remove_add_igmp_commands_when_pim_configured_p0(request):
input_dict_2 = {
"l1": {
"igmp": {
- "interfaces": {intf_l1_i1: {"igmp": {"version": "2", "delete": True,}}}
+ "interfaces": {
+ intf_l1_i1: {
+ "igmp": {
+ "version": "2",
+ "delete": True,
+ }
+ }
+ }
}
}
}
@@ -2009,9 +2049,10 @@ def test_verify_remove_add_igmp_commands_when_pim_configured_p0(request):
)
result = verify_igmp_config(tgen, input_dict_1, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "IGMP interface is not removed \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "IGMP interface is not removed \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -2914,9 +2955,10 @@ def test_mroute_after_removing_RP_sending_IGMP_prune_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "mroute still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroute still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -3259,9 +3301,10 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "mroute still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "mroute still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -3287,9 +3330,10 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "upstream still present \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "upstream still present \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -3311,9 +3355,10 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "RP iif is not updated \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -3442,9 +3487,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "upstream is still present after shut the link from "
+ "FHR to RP from RP node \n Error: {}".format(
tc_name, result
- )
+ ))
step(" No shut the link from FHR to RP from RP node")
@@ -3459,9 +3506,10 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "RP iif is not updated \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -3590,9 +3638,11 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "upstream is still present after shut the link from "
+ "FHR to RP from FHR node \n Error: {}".format(
tc_name, result
- )
+ ))
step(" No shut the link from FHR to RP from FHR node")
@@ -3606,9 +3656,10 @@ def test_prune_sent_to_LHR_and_FHR_when_PIMnbr_down_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "RP iif is not updated \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n " "RP iif is not updated \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -3873,7 +3924,12 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
"l1": {
"igmp": {
"interfaces": {
- "l1-i1-eth1": {"igmp": {"version": "2", "delete": True,}}
+ "l1-i1-eth1": {
+ "igmp": {
+ "version": "2",
+ "delete": True,
+ }
+ }
}
}
}
@@ -4107,9 +4163,10 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n"
- "mroutes are cleared \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n" "mroutes are cleared \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -4181,9 +4238,10 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n"
- " mroutes are cleared \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -4248,9 +4306,10 @@ def test_verify_multicast_traffic_when_LHR_connected_to_RP_p1(request):
result = verify_ip_mroutes(
tgen, dut, src_address, _IGMP_JOIN_RANGE, iif, oil, expected=False
)
- assert result is not True, (
- "Testcase {} : Failed \n"
- " mroutes are cleared \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -4459,9 +4518,10 @@ def test_verify_multicast_traffic_when_FHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n"
- " mroutes are cleared \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -4524,9 +4584,10 @@ def test_verify_multicast_traffic_when_FHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n"
- " mroutes are cleared \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
@@ -4595,9 +4656,10 @@ def test_verify_multicast_traffic_when_FHR_connected_to_RP_p1(request):
data["oil"],
expected=False,
)
- assert result is not True, (
- "Testcase {} : Failed \n"
- " mroutes are cleared \n Error: {}".format(tc_name, result)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n" " mroutes are cleared \n Error: {}".format(
+ tc_name, result
)
logger.info("Expected Behaviour: {}".format(result))
diff --git a/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py b/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py
index e8579e2a1e..68b7849c2b 100755
--- a/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py
+++ b/tests/topotests/multicast-pim-sm-topo3/test_multicast_pim_sm_topo4.py
@@ -490,9 +490,10 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "mroutes(S,G) are present after delete of static routes on c1 \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_upstream_iif(
tgen,
@@ -502,9 +503,10 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "upstream is present after delete of static routes on c1 \n Error: {}".format(
tc_name, result
- )
+ ))
for data in input_dict_starg:
result = verify_ip_mroutes(
@@ -516,9 +518,10 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "mroutes(*,G) are present after delete of static routes on c1 \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_upstream_iif(
tgen,
@@ -528,9 +531,10 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "upstream is present after delete of static routes on c1 \n Error: {}".format(
tc_name, result
- )
+ ))
step("Configure default routes on c2")
@@ -553,9 +557,10 @@ def test_mroute_when_RP_reachable_default_route_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "RP info is unknown after removing static route from c2 \n Error: {}".format(
tc_name, result
- )
+ ))
step("Verify (s,g) populated after adding default route ")
@@ -782,9 +787,10 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
data["oil"],
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "mroutes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_upstream_iif(
tgen,
@@ -794,9 +800,10 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
IGMP_JOIN_RANGE_1,
expected=False,
)
- assert result is not True, "Testcase {} : Failed Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "upstream is still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Configure default routes on all the nodes")
@@ -833,9 +840,10 @@ def test_mroute_with_RP_default_route_all_nodes_p2(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_1, "Unknown", rp_address, SOURCE, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "RP info is unknown after removing static route from c2 \n Error: {}".format(
tc_name, result
- )
+ ))
step("Verify (s,g) populated after adding default route ")
@@ -1009,7 +1017,11 @@ def test_PIM_hello_tx_rx_p1(request):
intf_c1_l1 = topo["routers"]["c1"]["links"]["l1"]["interface"]
step("verify before stats on C1")
- state_dict = {"c1": {intf_c1_l1: ["helloTx", "helloRx"],}}
+ state_dict = {
+ "c1": {
+ intf_c1_l1: ["helloTx", "helloRx"],
+ }
+ }
c1_state_before = verify_pim_interface_traffic(tgen, state_dict)
assert isinstance(
@@ -1040,7 +1052,11 @@ def test_PIM_hello_tx_rx_p1(request):
), "Testcase{} : Failed Error: {}" "stats incremented".format(tc_name, result)
step("verify before stats on l1")
- l1_state_dict = {"l1": {intf_l1_c1: ["helloTx", "helloRx"],}}
+ l1_state_dict = {
+ "l1": {
+ intf_l1_c1: ["helloTx", "helloRx"],
+ }
+ }
l1_state_before = verify_pim_interface_traffic(tgen, l1_state_dict)
assert isinstance(
@@ -1077,7 +1093,11 @@ def test_PIM_hello_tx_rx_p1(request):
l1_state_after = {}
step("verify before stats on C1")
- state_dict = {"c1": {intf_c1_l1: ["helloTx", "helloRx"],}}
+ state_dict = {
+ "c1": {
+ intf_c1_l1: ["helloTx", "helloRx"],
+ }
+ }
c1_state_before = verify_pim_interface_traffic(tgen, state_dict)
assert isinstance(
diff --git a/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py b/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py
index 8dfdd50527..1317ec67b4 100755
--- a/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py
+++ b/tests/topotests/multicast-pim-static-rp-topo1/test_multicast_pim_static_rp.py
@@ -281,6 +281,7 @@ def teardown_module():
#
#####################################################
+
def config_to_send_igmp_join_and_traffic(tgen, tc_name):
"""
API to do pre-configuration to send IGMP join and multicast
@@ -422,9 +423,10 @@ def test_add_delete_static_RP_p0(request):
dut = "r1"
interface = "r1-r0-eth0"
result = verify_igmp_groups(tgen, dut, interface, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: igmp group present without any IGMP join \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify show ip pim interface traffic without any IGMP join")
state_dict = {"r1": {"r1-r2-eth1": ["pruneTx"]}}
@@ -490,23 +492,26 @@ def test_add_delete_static_RP_p0(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: RP info present \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify upstream IIF interface")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: upstream IIF interface present \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify upstream join state and join timer")
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: upstream join state is up and join timer is running \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
@@ -516,9 +521,10 @@ def test_add_delete_static_RP_p0(request):
step("r1: Verify ip mroutes")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: mroutes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify show ip pim interface traffic without any IGMP join")
state_after = verify_pim_interface_traffic(tgen, state_dict)
@@ -675,9 +681,10 @@ def test_SPT_RPT_path_same_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S, G) upstream join state is up and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r2-eth1"
@@ -804,15 +811,17 @@ def test_not_reachable_static_RP_p0(request):
"using show ip pim state"
)
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "OIL is not same and IIF is not cleared on R1 \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: upstream IIF should be unknown , verify using show ip pim" "upstream")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: upstream IIF is not unknown \n Error: {}".format(
tc_name, result
- )
+ ))
step(
"r1: join state should not be joined and join timer should stop,"
@@ -821,9 +830,10 @@ def test_not_reachable_static_RP_p0(request):
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: join state is joined and timer is not stopped \n Error: {}".format(
tc_name, result
- )
+ ))
step(
"r1: (*,G) prune is sent towards the RP interface, verify using"
@@ -840,9 +850,10 @@ def test_not_reachable_static_RP_p0(request):
step("r1: (*, G) cleared from mroute table using show ip mroute")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: (*, G) are not cleared from mroute table \n Error: {}".format(
tc_name, result
- )
+ ))
logger.info("Expected behavior: {}".format(result))
# Uncomment next line for debugging
@@ -909,9 +920,10 @@ def test_add_RP_after_join_received_p1(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: rp-info is present \n Error: {}".format(
tc_name, result
- )
+ ))
step("joinTx value before join sent")
state_dict = {"r1": {"r1-r2-eth1": ["joinTx"]}}
@@ -932,36 +944,45 @@ def test_add_RP_after_join_received_p1(request):
step("r1: Verify upstream IIF interface")
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: upstream IFF interface is present \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify upstream join state and join timer")
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: upstream join state is joined and timer is running \n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: PIM state is up\n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Verify ip mroutes")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: mroutes are still present\n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Configure static RP")
input_dict = {
"r1": {
"pim": {
- "rp": [{"rp_addr": "1.0.2.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
}
}
@@ -1074,29 +1095,33 @@ def test_reachable_static_RP_after_join_p0(request):
step("r1 : Verify upstream IIF interface")
iif = "r1-r2-eth1"
result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: upstream IIF interface is present\n Error: {}".format(
tc_name, result
- )
+ ))
step("r1 : Verify upstream join state and join timer")
result = verify_join_state_and_timer(
tgen, dut, iif, STAR, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: upstream join state is joined and timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r1 : Verify PIM state")
result = verify_pim_state(tgen, dut, iif, oif, GROUP_ADDRESS, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: PIM state is up\n Error: {}".format(
tc_name, result
- )
+ ))
step("r1 : Verify ip mroutes")
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: mroutes are still present\n Error: {}".format(
tc_name, result
- )
+ ))
step("r1: Make RP reachable")
intf = "r1-r2-eth1"
@@ -1147,32 +1172,32 @@ def test_reachable_static_RP_after_join_p0(request):
def test_send_join_on_higher_preffered_rp_p1(request):
"""
- TC_11_P1 : Verify PIM join send towards the higher preferred RP
- TC_12_P1 : Verify PIM prune send towards the lower preferred RP
- TC_13_P1 : Verify RPF interface is updated in mroute (kernel) when higher
- preferred overlapping RP configured
- TC_14_P1 : Verify IIF and OIL in "show ip pim state" updated properly when
- higher preferred overlapping RP configured
- TC_15_P1 : Verify upstream interfaces(IIF) and join state are updated when
- higher preferred overlapping RP is configured
- TC_16_P1 : Verify join is send to lower preferred RP, when higher
- preferred RP gets deleted
- TC_17_P1 : Verify prune is send to higher preferred RP when higher
- preferred RP gets deleted
- TC_18_P1 : Verify RPF interface updated in mroute when higher preferred RP
- gets deleted
- TC_19_P1 : Verify IIF and OIL in "show ip pim state" updated when higher
- preferred overlapping RP is deleted
- TC_20_P1 : Verfiy PIM upstream IIF updated when higher preferred
- overlapping RP deleted
-
- Topology used:
- _______r2
- |
- iperf |
- r0-----r1
- |
- |_______r4
+ TC_11_P1 : Verify PIM join send towards the higher preferred RP
+ TC_12_P1 : Verify PIM prune send towards the lower preferred RP
+ TC_13_P1 : Verify RPF interface is updated in mroute (kernel) when higher
+ preferred overlapping RP configured
+ TC_14_P1 : Verify IIF and OIL in "show ip pim state" updated properly when
+ higher preferred overlapping RP configured
+ TC_15_P1 : Verify upstream interfaces(IIF) and join state are updated when
+ higher preferred overlapping RP is configured
+ TC_16_P1 : Verify join is send to lower preferred RP, when higher
+ preferred RP gets deleted
+ TC_17_P1 : Verify prune is send to higher preferred RP when higher
+ preferred RP gets deleted
+ TC_18_P1 : Verify RPF interface updated in mroute when higher preferred RP
+ gets deleted
+ TC_19_P1 : Verify IIF and OIL in "show ip pim state" updated when higher
+ preferred overlapping RP is deleted
+ TC_20_P1 : Verfiy PIM upstream IIF updated when higher preferred
+ overlapping RP deleted
+
+ Topology used:
+ _______r2
+ |
+ iperf |
+ r0-----r1
+ |
+ |_______r4
"""
tgen = get_topogen()
@@ -1241,7 +1266,12 @@ def test_send_join_on_higher_preffered_rp_p1(request):
input_dict = {
"r4": {
"pim": {
- "rp": [{"rp_addr": "1.0.4.17", "group_addr_range": ["225.1.1.1/32"],}]
+ "rp": [
+ {
+ "rp_addr": "1.0.4.17",
+ "group_addr_range": ["225.1.1.1/32"],
+ }
+ ]
}
}
}
@@ -1332,9 +1362,10 @@ def test_send_join_on_higher_preffered_rp_p1(request):
result = verify_pim_rp_info(
tgen, topo, dut, GROUP_RANGE, oif, rp_address_2, SOURCE, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: rp-info is present for group 225.1.1.1 \n Error: {}".format(
tc_name, result
- )
+ ))
step(
"r1 : Verify RPF interface updated in mroute when higher preferred"
@@ -1483,22 +1514,42 @@ def test_RP_configured_as_LHR_1_p1(request):
input_dict = {
"r1": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r2": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r3": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r4": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
}
@@ -1568,9 +1619,11 @@ def test_RP_configured_as_LHR_1_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S, G) upstream join state is joined and join"
+ " timer is running \n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -1677,22 +1730,42 @@ def test_RP_configured_as_LHR_2_p1(request):
input_dict = {
"r1": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r2": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r3": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r4": {
"pim": {
- "rp": [{"rp_addr": "1.0.1.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
}
@@ -1755,9 +1828,10 @@ def test_RP_configured_as_LHR_2_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -1863,22 +1937,42 @@ def test_RP_configured_as_FHR_1_p1(request):
input_dict = {
"r1": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r2": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r3": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r4": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
}
@@ -1942,9 +2036,10 @@ def test_RP_configured_as_FHR_1_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2050,22 +2145,42 @@ def test_RP_configured_as_FHR_2_p2(request):
input_dict = {
"r1": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r2": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r3": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
"r4": {
"pim": {
- "rp": [{"rp_addr": "1.0.3.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
},
}
@@ -2130,9 +2245,10 @@ def test_RP_configured_as_FHR_2_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2256,9 +2372,10 @@ def test_SPT_RPT_path_different_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2277,9 +2394,10 @@ def test_SPT_RPT_path_different_p1(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -2505,9 +2623,10 @@ def test_restart_pimd_process_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2672,9 +2791,10 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2693,9 +2813,10 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -2733,7 +2854,12 @@ def test_multiple_groups_same_RP_address_p2(request):
input_dict = {
"r1": {
"pim": {
- "rp": [{"rp_addr": "1.0.2.17", "group_addr_range": GROUP_RANGE_ALL,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
}
}
}
@@ -2806,9 +2932,10 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -2825,9 +2952,10 @@ def test_multiple_groups_same_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -2893,12 +3021,22 @@ def test_multiple_groups_different_RP_address_p2(request):
input_dict = {
"r2": {
"pim": {
- "rp": [{"rp_addr": "1.0.2.17", "group_addr_range": GROUP_RANGE_LIST_1,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_LIST_1,
+ }
+ ]
}
},
"r4": {
"pim": {
- "rp": [{"rp_addr": "1.0.4.17", "group_addr_range": GROUP_RANGE_LIST_2,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.4.17",
+ "group_addr_range": GROUP_RANGE_LIST_2,
+ }
+ ]
}
},
}
@@ -2994,9 +3132,10 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -3015,9 +3154,10 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -3084,9 +3224,10 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r4: Verify (S, G) ip mroutes")
oif = "none"
@@ -3148,12 +3289,22 @@ def test_multiple_groups_different_RP_address_p2(request):
input_dict = {
"r2": {
"pim": {
- "rp": [{"rp_addr": "1.0.2.17", "group_addr_range": GROUP_RANGE_LIST_1,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_LIST_1,
+ }
+ ]
}
},
"r4": {
"pim": {
- "rp": [{"rp_addr": "1.0.4.17", "group_addr_range": GROUP_RANGE_LIST_2,}]
+ "rp": [
+ {
+ "rp_addr": "1.0.4.17",
+ "group_addr_range": GROUP_RANGE_LIST_2,
+ }
+ ]
}
},
}
@@ -3248,9 +3399,10 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (S, G) ip mroutes")
oif = "none"
@@ -3269,9 +3421,10 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -3338,9 +3491,10 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r4: Verify (S, G) ip mroutes")
oif = "none"
@@ -3359,9 +3513,10 @@ def test_multiple_groups_different_RP_address_p2(request):
result = verify_join_state_and_timer(
tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (S, G) ip mroutes")
oif = "r3-r1-eth0"
@@ -3488,27 +3643,30 @@ def test_shutdown_primary_path_p1(request):
iif = "r1-r3-eth2"
oif = "r1-r0-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (*, G) ip mroutes")
dut = "r2"
iif = "lo"
oif = "r2-r3-eth1"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: Verify (*, G) ip mroutes")
dut = "r3"
iif = "r3-r2-eth1"
oif = "r3-r1-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
tc_name, result
- )
+ ))
step("r3: No shutdown the link from R1 to R3 from R3 node")
dut = "r3"
@@ -3668,18 +3826,20 @@ def test_delete_RP_shut_noshut_upstream_interface_p1(request):
iif = "r1-r2-eth1"
oif = "r1-r0-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (*, G) ip mroutes cleared")
dut = "r2"
iif = "lo"
oif = "r2-r1-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -3789,18 +3949,20 @@ def test_delete_RP_shut_noshut_RP_interface_p1(request):
iif = "r1-r2-eth1"
oif = "r1-r0-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
tc_name, result
- )
+ ))
step("r2: Verify (*, G) ip mroutes cleared")
dut = "r2"
iif = "lo"
oif = "r2-r1-eth0"
result = verify_ip_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r2: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
diff --git a/tests/topotests/ospf-sr-topo1/__init__.py b/tests/topotests/ospf-sr-topo1/__init__.py
index e69de29bb2..e69de29bb2 100755..100644
--- a/tests/topotests/ospf-sr-topo1/__init__.py
+++ b/tests/topotests/ospf-sr-topo1/__init__.py
diff --git a/tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json
deleted file mode 100644
index 952a26ed10..0000000000
--- a/tests/topotests/ospf-sr-topo1/r1/ospf_srdb.json
+++ /dev/null
@@ -1,161 +0,0 @@
-{
- "srdbID":"10.0.255.1",
- "srNodes":[
- {
- "routerID":"10.0.255.2",
- "srgbSize":8000,
- "srgbLabel":16000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "extendedPrefix":[
- {
- "prefix":"10.0.255.2\/32",
- "sid":200,
- "inputLabel":20200,
- "prefixRoute":[
- {
- "outputLabel":3,
- "interface":"r1-eth0",
- "nexthop":"10.0.0.2"
- },
- {
- "outputLabel":3,
- "interface":"r1-eth1",
- "nexthop":"10.0.1.2"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.4",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":12,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.4\/32",
- "sid":400,
- "inputLabel":20400,
- "prefixRoute":[
- {
- "outputLabel":16400,
- "interface":"r1-eth0",
- "nexthop":"10.0.0.2"
- },
- {
- "outputLabel":16400,
- "interface":"r1-eth1",
- "nexthop":"10.0.1.2"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.3",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":8,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.3\/32",
- "sid":300,
- "inputLabel":20300,
- "prefixRoute":[
- {
- "outputLabel":16300,
- "interface":"r1-eth0",
- "nexthop":"10.0.0.2"
- },
- {
- "outputLabel":16300,
- "interface":"r1-eth1",
- "nexthop":"10.0.1.2"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.1",
- "srgbSize":10000,
- "srgbLabel":20000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":16,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.1\/32",
- "sid":100,
- "inputLabel":0,
- "prefixRoute":[
- {
- "outputLabel":0,
- "interface":"lo",
- "nexthop":"10.0.255.1"
- }
- ]
- }
- ],
- "extendedLink":[
- {
- "prefix":"10.0.0.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r1-eth0",
- "nexthop":"10.0.0.2"
- },
- {
- "prefix":"10.0.0.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r1-eth0",
- "nexthop":"10.0.0.2"
- },
- {
- "prefix":"10.0.1.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r1-eth1",
- "nexthop":"10.0.1.2"
- },
- {
- "prefix":"10.0.1.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r1-eth1",
- "nexthop":"10.0.1.2"
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ospf-sr-topo1/r1/ospfd.conf b/tests/topotests/ospf-sr-topo1/r1/ospfd.conf
deleted file mode 100644
index 0773153a76..0000000000
--- a/tests/topotests/ospf-sr-topo1/r1/ospfd.conf
+++ /dev/null
@@ -1,27 +0,0 @@
-debug ospf sr
-!
-interface lo
- ip ospf area 0.0.0.0
-!
-interface r1-eth0
- ip ospf network point-to-point
- ip ospf hello-interval 2
- ip ospf dead-interval 10
- ip ospf area 0.0.0.0
-!
-interface r1-eth1
- ip ospf network point-to-point
- ip ospf hello-interval 2
- ip ospf dead-interval 10
- ip ospf area 0.0.0.0
-!
-router ospf
- ospf router-id 10.0.255.1
- capability opaque
- router-info area 0.0.0.0
- segment-routing on
- segment-routing node-msd 16
- segment-routing global-block 20000 29999
- segment-routing prefix 10.0.255.1/32 index 100 explicit-null
-!
-
diff --git a/tests/topotests/ospf-sr-topo1/r1/zebra.conf b/tests/topotests/ospf-sr-topo1/r1/zebra.conf
deleted file mode 100644
index faf71db25c..0000000000
--- a/tests/topotests/ospf-sr-topo1/r1/zebra.conf
+++ /dev/null
@@ -1,12 +0,0 @@
-!
-interface lo
- ip address 10.0.255.1/32
-!
-interface r1-eth0
- ip address 10.0.0.1/24
-!
-interface r1-eth1
- ip address 10.0.1.1/24
-!
-ip forwarding
-!
diff --git a/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json
deleted file mode 100644
index 6c87596acb..0000000000
--- a/tests/topotests/ospf-sr-topo1/r1/zebra_mpls.json
+++ /dev/null
@@ -1,115 +0,0 @@
-[
- {
- "inLabel":20200,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.2"
- },
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "distance":150,
- "installed":true,
- "nexthop":"10.0.0.2"
- }
- ]
- },
- {
- "inLabel":20300,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":16300,
- "outLabelStack":[
- 16300
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.2"
- }
- ]
- },
- {
- "inLabel":20400,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":16400,
- "outLabelStack":[
- 16400
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.2"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "distance":150,
- "installed":true,
- "nexthop":"10.0.0.2"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "distance":150,
- "installed":true,
- "nexthop":"10.0.0.2"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.2"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.2"
- }
- ]
- }
-]
diff --git a/tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json
deleted file mode 100644
index 1de780d84e..0000000000
--- a/tests/topotests/ospf-sr-topo1/r2/ospf_srdb.json
+++ /dev/null
@@ -1,183 +0,0 @@
-{
- "srdbID":"10.0.255.2",
- "srNodes":[
- {
- "routerID":"10.0.255.2",
- "srgbSize":8000,
- "srgbLabel":16000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "extendedPrefix":[
- {
- "prefix":"10.0.255.2\/32",
- "sid":200,
- "inputLabel":0,
- "prefixRoute":[
- {
- "outputLabel":0,
- "interface":"lo",
- "nexthop":"10.0.255.2"
- }
- ]
- }
- ],
- "extendedLink":[
- {
- "prefix":"10.0.4.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth3",
- "nexthop":"10.0.4.1"
- },
- {
- "prefix":"10.0.4.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth3",
- "nexthop":"10.0.4.1"
- },
- {
- "prefix":"10.0.0.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth0",
- "nexthop":"10.0.0.1"
- },
- {
- "prefix":"10.0.0.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth0",
- "nexthop":"10.0.0.1"
- },
- {
- "prefix":"10.0.1.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth1",
- "nexthop":"10.0.1.1"
- },
- {
- "prefix":"10.0.1.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth1",
- "nexthop":"10.0.1.1"
- },
- {
- "prefix":"10.0.3.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth2",
- "nexthop":"10.0.3.1"
- },
- {
- "prefix":"10.0.3.2\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r2-eth2",
- "nexthop":"10.0.3.1"
- }
- ]
- },
- {
- "routerID":"10.0.255.4",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":12,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.4\/32",
- "sid":400,
- "inputLabel":16400,
- "prefixRoute":[
- {
- "outputLabel":10400,
- "interface":"r2-eth3",
- "nexthop":"10.0.4.1"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.3",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":8,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.3\/32",
- "sid":300,
- "inputLabel":16300,
- "prefixRoute":[
- {
- "outputLabel":3,
- "interface":"r2-eth2",
- "nexthop":"10.0.3.1"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.1",
- "srgbSize":10000,
- "srgbLabel":20000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":16,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.1\/32",
- "sid":100,
- "inputLabel":16100,
- "prefixRoute":[
- {
- "outputLabel":0,
- "interface":"r2-eth0",
- "nexthop":"10.0.0.1"
- },
- {
- "outputLabel":0,
- "interface":"r2-eth1",
- "nexthop":"10.0.1.1"
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ospf-sr-topo1/r2/ospfd.conf b/tests/topotests/ospf-sr-topo1/r2/ospfd.conf
deleted file mode 100644
index 92dc2f7cd1..0000000000
--- a/tests/topotests/ospf-sr-topo1/r2/ospfd.conf
+++ /dev/null
@@ -1,36 +0,0 @@
-!
-debug ospf sr
-!
-interface lo
- ip ospf area 0.0.0.0
-!
-interface r2-eth0
- ip ospf network point-to-point
- ip ospf hello-interval 2
- ip ospf dead-interval 10
- ip ospf area 0.0.0.0
-!
-interface r2-eth1
- ip ospf network point-to-point
- ip ospf hello-interval 2
- ip ospf dead-interval 10
- ip ospf area 0.0.0.0
-!
-interface r2-eth2
- ip ospf area 0.0.0.0
- ip ospf hello-interval 2
- ip ospf dead-interval 10
-!
-interface r2-eth3
- ip ospf network point-to-point
- ip ospf hello-interval 2
- ip ospf dead-interval 10
- ip ospf area 0.0.0.0
-!
-router ospf
- ospf router-id 10.0.255.2
- capability opaque
- router-info area 0.0.0.0
- segment-routing on
- segment-routing prefix 10.0.255.2/32 index 200
-!
diff --git a/tests/topotests/ospf-sr-topo1/r2/zebra.conf b/tests/topotests/ospf-sr-topo1/r2/zebra.conf
deleted file mode 100644
index ba1d833f50..0000000000
--- a/tests/topotests/ospf-sr-topo1/r2/zebra.conf
+++ /dev/null
@@ -1,18 +0,0 @@
-!
-interface lo
- ip address 10.0.255.2/32
-!
-interface r2-eth0
- ip address 10.0.0.2/24
-!
-interface r2-eth1
- ip address 10.0.1.2/24
-!
-interface r2-eth2
- ip address 10.0.3.2/24
-!
-interface r2-eth3
- ip address 10.0.4.2/24
-!
-ip forwarding
-!
diff --git a/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json
deleted file mode 100644
index a885e88fc5..0000000000
--- a/tests/topotests/ospf-sr-topo1/r2/zebra_mpls.json
+++ /dev/null
@@ -1,179 +0,0 @@
-[
- {
- "inLabel":16100,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":0,
- "outLabelStack":[
- 0
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.1"
- },
- {
- "type":"SR (OSPF)",
- "outLabel":0,
- "distance":150,
- "installed":true,
- "nexthop":"10.0.0.1"
- }
- ]
- },
- {
- "inLabel":16300,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.3.1"
- }
- ]
- },
- {
- "inLabel":16400,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":10400,
- "outLabelStack":[
- 10400
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.0.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.0.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.1.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "distance":150,
- "installed":true,
- "nexthop":"10.0.3.1"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "distance":150,
- "installed":true,
- "nexthop":"10.0.3.1"
- }
- ]
- }
-]
diff --git a/tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json
deleted file mode 100644
index e7371ff593..0000000000
--- a/tests/topotests/ospf-sr-topo1/r3/ospf_srdb.json
+++ /dev/null
@@ -1,130 +0,0 @@
-{
- "srdbID":"10.0.255.3",
- "srNodes":[
- {
- "routerID":"10.0.255.2",
- "srgbSize":8000,
- "srgbLabel":16000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "extendedPrefix":[
- {
- "prefix":"10.0.255.2\/32",
- "sid":200,
- "inputLabel":10200,
- "prefixRoute":[
- {
- "outputLabel":3,
- "interface":"r3-eth0",
- "nexthop":"10.0.3.2"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.4",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":12,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.4\/32",
- "sid":400,
- "inputLabel":10400,
- "prefixRoute":[
- {
- "outputLabel":16400,
- "interface":"r3-eth0",
- "nexthop":"10.0.3.2"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.3",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":8,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.3\/32",
- "sid":300,
- "inputLabel":0,
- "prefixRoute":[
- {
- "outputLabel":0,
- "interface":"lo",
- "nexthop":"10.0.255.3"
- }
- ]
- }
- ],
- "extendedLink":[
- {
- "prefix":"10.0.3.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r3-eth0",
- "nexthop":"10.0.3.2"
- },
- {
- "prefix":"10.0.3.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r3-eth0",
- "nexthop":"10.0.3.2"
- }
- ]
- },
- {
- "routerID":"10.0.255.1",
- "srgbSize":10000,
- "srgbLabel":20000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":16,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.1\/32",
- "sid":100,
- "inputLabel":10100,
- "prefixRoute":[
- {
- "outputLabel":16100,
- "interface":"r3-eth0",
- "nexthop":"10.0.3.2"
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ospf-sr-topo1/r3/ospfd.conf b/tests/topotests/ospf-sr-topo1/r3/ospfd.conf
deleted file mode 100644
index e2766f202d..0000000000
--- a/tests/topotests/ospf-sr-topo1/r3/ospfd.conf
+++ /dev/null
@@ -1,22 +0,0 @@
-!
-interface lo
- ip ospf area 0.0.0.0
- ip ospf hello-interval 2
- ip ospf dead-interval 10
-!
-interface r3-eth0
- ip ospf area 0.0.0.0
- ip ospf hello-interval 2
- ip ospf dead-interval 10
-!
-!
-router ospf
- ospf router-id 10.0.255.3
- capability opaque
- router-info area 0.0.0.0
- segment-routing on
- segment-routing local-block 5000 5999
- segment-routing global-block 10000 19999
- segment-routing node-msd 8
- segment-routing prefix 10.0.255.3/32 index 300
-!
diff --git a/tests/topotests/ospf-sr-topo1/r3/zebra.conf b/tests/topotests/ospf-sr-topo1/r3/zebra.conf
deleted file mode 100644
index ef16a8ca13..0000000000
--- a/tests/topotests/ospf-sr-topo1/r3/zebra.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-interface lo
- ip address 10.0.255.3/32
-!
-interface r3-eth0
- ip address 10.0.3.1/24
-!
-ip forwarding
-!
diff --git a/tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json b/tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json
deleted file mode 100644
index a241b32607..0000000000
--- a/tests/topotests/ospf-sr-topo1/r4/ospf_srdb.json
+++ /dev/null
@@ -1,130 +0,0 @@
-{
- "srdbID":"10.0.255.4",
- "srNodes":[
- {
- "routerID":"10.0.255.2",
- "srgbSize":8000,
- "srgbLabel":16000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "extendedPrefix":[
- {
- "prefix":"10.0.255.2\/32",
- "sid":200,
- "inputLabel":10200,
- "prefixRoute":[
- {
- "outputLabel":3,
- "interface":"r4-eth0",
- "nexthop":"10.0.4.2"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.4",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":12,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.4\/32",
- "sid":400,
- "inputLabel":10400,
- "prefixRoute":[
- {
- "outputLabel":3,
- "interface":"lo",
- "nexthop":"10.0.255.4"
- }
- ]
- }
- ],
- "extendedLink":[
- {
- "prefix":"10.0.4.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r4-eth0",
- "nexthop":"10.0.4.2"
- },
- {
- "prefix":"10.0.4.1\/32",
- "sid":"*",
- "inputLabel":"*",
- "outputLabel":3,
- "interface":"r4-eth0",
- "nexthop":"10.0.4.2"
- }
- ]
- },
- {
- "routerID":"10.0.255.3",
- "srgbSize":10000,
- "srgbLabel":10000,
- "srlbSize":1000,
- "srlbLabel":5000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":8,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.3\/32",
- "sid":300,
- "inputLabel":10300,
- "prefixRoute":[
- {
- "outputLabel":16300,
- "interface":"r4-eth0",
- "nexthop":"10.0.4.2"
- }
- ]
- }
- ]
- },
- {
- "routerID":"10.0.255.1",
- "srgbSize":10000,
- "srgbLabel":20000,
- "srlbSize":1000,
- "srlbLabel":15000,
- "algorithms":[
- {
- "0":"SPF"
- }
- ],
- "nodeMsd":16,
- "extendedPrefix":[
- {
- "prefix":"10.0.255.1\/32",
- "sid":100,
- "inputLabel":10100,
- "prefixRoute":[
- {
- "outputLabel":16100,
- "interface":"r4-eth0",
- "nexthop":"10.0.4.2"
- }
- ]
- }
- ]
- }
- ]
-}
diff --git a/tests/topotests/ospf-sr-topo1/r4/ospfd.conf b/tests/topotests/ospf-sr-topo1/r4/ospfd.conf
deleted file mode 100644
index e80880af88..0000000000
--- a/tests/topotests/ospf-sr-topo1/r4/ospfd.conf
+++ /dev/null
@@ -1,23 +0,0 @@
-!
-interface lo
- ip ospf area 0.0.0.0
- ip ospf hello-interval 2
- ip ospf dead-interval 10
-!
-interface r4-eth0
- ip ospf network point-to-point
- ip ospf hello-interval 2
- ip ospf dead-interval 10
- ip ospf area 0.0.0.0
-!
-!
-router ospf
- ospf router-id 10.0.255.4
- capability opaque
- router-info area 0.0.0.0
- segment-routing on
- segment-routing local-block 5000 5999
- segment-routing global-block 10000 19999
- segment-routing node-msd 12
- segment-routing prefix 10.0.255.4/32 index 400 no-php-flag
-!
diff --git a/tests/topotests/ospf-sr-topo1/r4/zebra.conf b/tests/topotests/ospf-sr-topo1/r4/zebra.conf
deleted file mode 100644
index 428f6f4156..0000000000
--- a/tests/topotests/ospf-sr-topo1/r4/zebra.conf
+++ /dev/null
@@ -1,9 +0,0 @@
-!
-interface lo
- ip address 10.0.255.4/32
-!
-interface r4-eth0
- ip address 10.0.4.1/24
-!
-ip forwarding
-!
diff --git a/tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json
deleted file mode 100644
index b5758f29a0..0000000000
--- a/tests/topotests/ospf-sr-topo1/r4/zebra_mpls.json
+++ /dev/null
@@ -1,97 +0,0 @@
-[
- {
- "inLabel":10100,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":16100,
- "outLabelStack":[
- 16100
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.2"
- }
- ]
- },
- {
- "inLabel":10200,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.2"
- }
- ]
- },
- {
- "inLabel":10300,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":16300,
- "outLabelStack":[
- 16300
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.2"
- }
- ]
- },
- {
- "inLabel":10400,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.2"
- }
- ]
- },
- {
- "inLabel":"*",
- "installed":true,
- "nexthops":[
- {
- "type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
- "installed":true,
- "nexthop":"10.0.4.2"
- }
- ]
- }
-]
diff --git a/tests/topotests/ospf-sr-topo1/rt1/ospfd.conf b/tests/topotests/ospf-sr-topo1/rt1/ospfd.conf
new file mode 100644
index 0000000000..94dba7c061
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/ospfd.conf
@@ -0,0 +1,29 @@
+password 1
+hostname rt1
+log file ospfd.log
+!
+debug ospf sr
+debug ospf te
+debug ospf event
+debug ospf lsa
+debug ospf zebra
+!
+interface lo
+!
+interface eth-sw1
+ ip ospf network broadcast
+!
+router ospf
+ ospf router-id 1.1.1.1
+ network 1.1.1.1/32 area 0.0.0.0
+ network 10.0.0.0/16 area 0.0.0.0
+ capability opaque
+ mpls-te on
+ mpls-te router-address 1.1.1.1
+ router-info area 0.0.0.0
+ passive-interface lo
+ segment-routing on
+ segment-routing global-block 16000 23999
+ segment-routing node-msd 8
+ segment-routing prefix 1.1.1.1/32 index 10
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step1/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step1/show_ip_route.ref
new file mode 100644
index 0000000000..374184e60a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step1/show_ip_route.ref
@@ -0,0 +1,289 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step1/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step1/show_mpls_table.ref
new file mode 100644
index 0000000000..de906c270d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step1/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step10/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step10/show_ip_route.ref
new file mode 100644
index 0000000000..37f73629fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step10/show_ip_route.ref
@@ -0,0 +1,282 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step10/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step10/show_mpls_table.ref
new file mode 100644
index 0000000000..2006392564
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step10/show_mpls_table.ref
@@ -0,0 +1,79 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step2/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step2/show_ip_route.ref
new file mode 100644
index 0000000000..37f73629fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step2/show_ip_route.ref
@@ -0,0 +1,282 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step2/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step2/show_mpls_table.ref
new file mode 100644
index 0000000000..de906c270d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step2/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step3/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step3/show_ip_route.ref
new file mode 100644
index 0000000000..f6ead5cb91
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step3/show_ip_route.ref
@@ -0,0 +1,249 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step3/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step3/show_mpls_table.ref
new file mode 100644
index 0000000000..96e05913ed
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step3/show_mpls_table.ref
@@ -0,0 +1,50 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step4/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step4/show_ip_route.ref
new file mode 100644
index 0000000000..37f73629fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step4/show_ip_route.ref
@@ -0,0 +1,282 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step4/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step4/show_mpls_table.ref
new file mode 100644
index 0000000000..de906c270d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step4/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step5/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step5/show_ip_route.ref
new file mode 100644
index 0000000000..f2b8924b85
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step5/show_ip_route.ref
@@ -0,0 +1,276 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step5/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step5/show_mpls_table.ref
new file mode 100644
index 0000000000..96e05913ed
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step5/show_mpls_table.ref
@@ -0,0 +1,50 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step6/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step6/show_ip_route.ref
new file mode 100644
index 0000000000..37f73629fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step6/show_ip_route.ref
@@ -0,0 +1,282 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step6/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step6/show_mpls_table.ref
new file mode 100644
index 0000000000..de906c270d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step6/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step7/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step7/show_ip_route.ref
new file mode 100644
index 0000000000..37f73629fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step7/show_ip_route.ref
@@ -0,0 +1,282 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step7/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step7/show_mpls_table.ref
new file mode 100644
index 0000000000..de906c270d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step7/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step8/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step8/show_ip_route.ref
new file mode 100644
index 0000000000..37f73629fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step8/show_ip_route.ref
@@ -0,0 +1,282 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step8/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step8/show_mpls_table.ref
new file mode 100644
index 0000000000..de906c270d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step8/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step9/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt1/step9/show_ip_route.ref
new file mode 100644
index 0000000000..37f73629fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step9/show_ip_route.ref
@@ -0,0 +1,282 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/step9/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt1/step9/show_mpls_table.ref
new file mode 100644
index 0000000000..2006392564
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/step9/show_mpls_table.ref
@@ -0,0 +1,79 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17060,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt1/zebra.conf b/tests/topotests/ospf-sr-topo1/rt1/zebra.conf
new file mode 100644
index 0000000000..7d3139a80e
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt1/zebra.conf
@@ -0,0 +1,18 @@
+log file zebra.log
+!
+hostname rt1
+!
+debug zebra kernel
+debug zebra packet
+debug zebra mpls
+!
+interface lo
+ ip address 1.1.1.1/32
+!
+interface eth-sw1
+ ip address 10.0.1.1/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt2/ospfd.conf b/tests/topotests/ospf-sr-topo1/rt2/ospfd.conf
new file mode 100644
index 0000000000..b47e788062
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/ospfd.conf
@@ -0,0 +1,35 @@
+password 1
+hostname rt2
+log file ospfd.log
+!
+debug ospf sr
+debug ospf te
+debug ospf event
+debug ospf lsa
+debug ospf zebra
+!
+interface lo
+!
+interface eth-sw1
+ ip ospf network broadcast
+!
+interface eth-rt4-1
+ ip ospf network point-to-point
+!
+interface eth-rt4-2
+ ip ospf network point-to-point
+!
+router ospf
+ ospf router-id 2.2.2.2
+ network 2.2.2.2/32 area 0.0.0.0
+ network 10.0.0.0/16 area 0.0.0.0
+ capability opaque
+ mpls-te on
+ mpls-te router-address 2.2.2.2
+ router-info area 0.0.0.0
+ passive-interface lo
+ segment-routing on
+ segment-routing global-block 16000 23999
+ segment-routing node-msd 8
+ segment-routing prefix 2.2.2.2/32 index 20 no-php-flag
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step1/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step1/show_ip_route.ref
new file mode 100644
index 0000000000..3dde042b51
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step1/show_ip_route.ref
@@ -0,0 +1,330 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step1/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step1/show_mpls_table.ref
new file mode 100644
index 0000000000..eba7c403d3
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step1/show_mpls_table.ref
@@ -0,0 +1,97 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step10/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step10/show_ip_route.ref
new file mode 100644
index 0000000000..9a06059df2
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step10/show_ip_route.ref
@@ -0,0 +1,254 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step10/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step10/show_mpls_table.ref
new file mode 100644
index 0000000000..be44a7521d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step10/show_mpls_table.ref
@@ -0,0 +1,73 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step2/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step2/show_ip_route.ref
new file mode 100644
index 0000000000..384aac032d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step2/show_ip_route.ref
@@ -0,0 +1,303 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step2/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step2/show_mpls_table.ref
new file mode 100644
index 0000000000..5088aa2f7a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step2/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step3/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step3/show_ip_route.ref
new file mode 100644
index 0000000000..879cd1e0c5
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step3/show_ip_route.ref
@@ -0,0 +1,256 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step3/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step3/show_mpls_table.ref
new file mode 100644
index 0000000000..6333e7f7f9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step3/show_mpls_table.ref
@@ -0,0 +1,67 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step4/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step4/show_ip_route.ref
new file mode 100644
index 0000000000..384aac032d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step4/show_ip_route.ref
@@ -0,0 +1,303 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step4/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step4/show_mpls_table.ref
new file mode 100644
index 0000000000..5088aa2f7a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step4/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step5/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step5/show_ip_route.ref
new file mode 100644
index 0000000000..07edd42dc8
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step5/show_ip_route.ref
@@ -0,0 +1,297 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step5/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step5/show_mpls_table.ref
new file mode 100644
index 0000000000..6333e7f7f9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step5/show_mpls_table.ref
@@ -0,0 +1,67 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step6/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step6/show_ip_route.ref
new file mode 100644
index 0000000000..384aac032d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step6/show_ip_route.ref
@@ -0,0 +1,303 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step6/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step6/show_mpls_table.ref
new file mode 100644
index 0000000000..5088aa2f7a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step6/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step7/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step7/show_ip_route.ref
new file mode 100644
index 0000000000..274931bef7
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step7/show_ip_route.ref
@@ -0,0 +1,300 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step7/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step7/show_mpls_table.ref
new file mode 100644
index 0000000000..cd23725a80
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step7/show_mpls_table.ref
@@ -0,0 +1,73 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step8/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step8/show_ip_route.ref
new file mode 100644
index 0000000000..384aac032d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step8/show_ip_route.ref
@@ -0,0 +1,303 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step8/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step8/show_mpls_table.ref
new file mode 100644
index 0000000000..5088aa2f7a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step8/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step9/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt2/step9/show_ip_route.ref
new file mode 100644
index 0000000000..c71515f3ff
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step9/show_ip_route.ref
@@ -0,0 +1,303 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 17050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/step9/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt2/step9/show_mpls_table.ref
new file mode 100644
index 0000000000..2f06641f7f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/step9/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17050,
+ "installed":true,
+ "nexthop":"10.0.1.3"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt2/zebra.conf b/tests/topotests/ospf-sr-topo1/rt2/zebra.conf
new file mode 100644
index 0000000000..c4ed4276d9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt2/zebra.conf
@@ -0,0 +1,24 @@
+log file zebra.log
+!
+hostname rt2
+!
+debug zebra kernel
+debug zebra packet
+debug zebra mpls
+!
+interface lo
+ ip address 2.2.2.2/32
+!
+interface eth-sw1
+ ip address 10.0.1.2/24
+!
+interface eth-rt4-1
+ ip address 10.0.2.2/24
+!
+interface eth-rt4-2
+ ip address 10.0.3.2/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt3/ospfd.conf b/tests/topotests/ospf-sr-topo1/rt3/ospfd.conf
new file mode 100644
index 0000000000..238d82ff97
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/ospfd.conf
@@ -0,0 +1,35 @@
+password 1
+hostname rt3
+log file ospfd.log
+!
+debug ospf sr
+debug ospf te
+debug ospf event
+debug ospf lsa
+debug ospf zebra
+!
+interface lo
+!
+interface eth-sw1
+ ip ospf network broadcast
+!
+interface eth-rt5-1
+ ip ospf network point-to-point
+!
+interface eth-rt5-2
+ ip ospf network point-to-point
+!
+router ospf
+ ospf router-id 3.3.3.3
+ network 3.3.3.3/32 area 0.0.0.0
+ network 10.0.0.0/16 area 0.0.0.0
+ capability opaque
+ mpls-te on
+ mpls-te router-address 3.3.3.3
+ router-info area 0.0.0.0
+ passive-interface lo
+ segment-routing on
+ segment-routing global-block 17000 24999
+ segment-routing node-msd 8
+ segment-routing prefix 3.3.3.3/32 index 30 no-php-flag
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step1/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step1/show_ip_route.ref
new file mode 100644
index 0000000000..4b1500ef97
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step1/show_ip_route.ref
@@ -0,0 +1,330 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step1/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step1/show_mpls_table.ref
new file mode 100644
index 0000000000..39cc3e8ffd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step1/show_mpls_table.ref
@@ -0,0 +1,97 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step10/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step10/show_ip_route.ref
new file mode 100644
index 0000000000..14a2ac1e8a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step10/show_ip_route.ref
@@ -0,0 +1,310 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step10/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step10/show_mpls_table.ref
new file mode 100644
index 0000000000..a0f7c790a0
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step10/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step2/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step2/show_ip_route.ref
new file mode 100644
index 0000000000..63c6a1845f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step2/show_ip_route.ref
@@ -0,0 +1,310 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step2/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step2/show_mpls_table.ref
new file mode 100644
index 0000000000..1ab2242b7e
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step2/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step3/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step3/show_ip_route.ref
new file mode 100644
index 0000000000..0894c51cf2
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step3/show_ip_route.ref
@@ -0,0 +1,263 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step3/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step3/show_mpls_table.ref
new file mode 100644
index 0000000000..4dcaedeca1
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step3/show_mpls_table.ref
@@ -0,0 +1,67 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step4/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step4/show_ip_route.ref
new file mode 100644
index 0000000000..63c6a1845f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step4/show_ip_route.ref
@@ -0,0 +1,310 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step4/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step4/show_mpls_table.ref
new file mode 100644
index 0000000000..1ab2242b7e
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step4/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step5/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step5/show_ip_route.ref
new file mode 100644
index 0000000000..3e74ff039c
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step5/show_ip_route.ref
@@ -0,0 +1,304 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step5/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step5/show_mpls_table.ref
new file mode 100644
index 0000000000..4dcaedeca1
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step5/show_mpls_table.ref
@@ -0,0 +1,67 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step6/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step6/show_ip_route.ref
new file mode 100644
index 0000000000..63c6a1845f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step6/show_ip_route.ref
@@ -0,0 +1,310 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step6/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step6/show_mpls_table.ref
new file mode 100644
index 0000000000..1ab2242b7e
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step6/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step7/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step7/show_ip_route.ref
new file mode 100644
index 0000000000..41544d4296
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step7/show_ip_route.ref
@@ -0,0 +1,307 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step7/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step7/show_mpls_table.ref
new file mode 100644
index 0000000000..bf055bad78
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step7/show_mpls_table.ref
@@ -0,0 +1,73 @@
+{
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step8/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step8/show_ip_route.ref
new file mode 100644
index 0000000000..63c6a1845f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step8/show_ip_route.ref
@@ -0,0 +1,310 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step8/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step8/show_mpls_table.ref
new file mode 100644
index 0000000000..1ab2242b7e
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step8/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step9/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt3/step9/show_ip_route.ref
new file mode 100644
index 0000000000..14a2ac1e8a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step9/show_ip_route.ref
@@ -0,0 +1,310 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/step9/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt3/step9/show_mpls_table.ref
new file mode 100644
index 0000000000..a0f7c790a0
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/step9/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "17010":{
+ "inLabel":17010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.1.1"
+ }
+ ]
+ },
+ "17020":{
+ "inLabel":17020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17030":{
+ "inLabel":17030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "17040":{
+ "inLabel":17040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2"
+ }
+ ]
+ },
+ "17050":{
+ "inLabel":17050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ },
+ "17060":{
+ "inLabel":17060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt3/zebra.conf b/tests/topotests/ospf-sr-topo1/rt3/zebra.conf
new file mode 100644
index 0000000000..89a781fe3c
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt3/zebra.conf
@@ -0,0 +1,24 @@
+log file zebra.log
+!
+hostname rt3
+!
+debug zebra kernel
+debug zebra packet
+debug zebra mpls
+!
+interface lo
+ ip address 3.3.3.3/32
+!
+interface eth-sw1
+ ip address 10.0.1.3/24
+!
+interface eth-rt5-1
+ ip address 10.0.4.3/24
+!
+interface eth-rt5-2
+ ip address 10.0.5.3/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt4/ospfd.conf b/tests/topotests/ospf-sr-topo1/rt4/ospfd.conf
new file mode 100644
index 0000000000..b12e0729ad
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/ospfd.conf
@@ -0,0 +1,38 @@
+password 1
+hostname rt4
+log file ospfd.log
+!
+debug ospf sr
+debug ospf te
+debug ospf event
+debug ospf lsa
+debug ospf zebra
+!
+interface lo
+!
+interface eth-rt2-1
+ ip ospf network point-to-point
+!
+interface eth-rt2-2
+ ip ospf network point-to-point
+!
+interface eth-rt5
+ ip ospf network point-to-point
+!
+interface eth-rt6
+ ip ospf network point-to-point
+!
+router ospf
+ ospf router-id 4.4.4.4
+ network 4.4.4.4/32 area 0.0.0.0
+ network 10.0.0.0/16 area 0.0.0.0
+ capability opaque
+ mpls-te on
+ mpls-te router-address 4.4.4.4
+ router-info area 0.0.0.0
+ passive-interface lo
+ segment-routing on
+ segment-routing global-block 16000 23999
+ segment-routing node-msd 8
+ segment-routing prefix 4.4.4.4/32 index 40 no-php-flag
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step1/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step1/show_ip_route.ref
new file mode 100644
index 0000000000..4a2d3aa10f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step1/show_ip_route.ref
@@ -0,0 +1,311 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step1/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step1/show_mpls_table.ref
new file mode 100644
index 0000000000..3246d22842
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step1/show_mpls_table.ref
@@ -0,0 +1,97 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.6.5"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.6.5"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step10/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step10/show_ip_route.ref
new file mode 100644
index 0000000000..db4cf5b3f5
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step10/show_ip_route.ref
@@ -0,0 +1,278 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json b/tests/topotests/ospf-sr-topo1/rt4/step10/show_mpls_table.ref
index 1b98ff4756..58cf526a83 100644
--- a/tests/topotests/ospf-sr-topo1/r3/zebra_mpls.json
+++ b/tests/topotests/ospf-sr-topo1/rt4/step10/show_mpls_table.ref
@@ -1,82 +1,73 @@
-[
- {
- "inLabel":10100,
+{
+ "16010":{
+ "inLabel":16010,
"installed":true,
"nexthops":[
{
"type":"SR (OSPF)",
- "outLabel":16100,
- "outLabelStack":[
- 16100
- ],
- "distance":150,
+ "outLabel":16010,
"installed":true,
"nexthop":"10.0.3.2"
}
]
},
- {
- "inLabel":10200,
+ "16020":{
+ "inLabel":16020,
"installed":true,
"nexthops":[
{
"type":"SR (OSPF)",
- "outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
+ "outLabel":16020,
"installed":true,
"nexthop":"10.0.3.2"
}
]
},
- {
- "inLabel":10400,
+ "16030":{
+ "inLabel":16030,
"installed":true,
"nexthops":[
{
"type":"SR (OSPF)",
- "outLabel":16400,
- "outLabelStack":[
- 16400
- ],
- "distance":150,
+ "outLabel":16030,
"installed":true,
"nexthop":"10.0.3.2"
}
]
},
- {
- "inLabel":"*",
+ "16040":{
+ "inLabel":16040,
"installed":true,
"nexthops":[
{
"type":"SR (OSPF)",
"outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18050,
"installed":true,
- "nexthop":"10.0.3.2"
+ "nexthop":"10.0.7.6"
}
]
},
- {
- "inLabel":"*",
+ "16060":{
+ "inLabel":16060,
"installed":true,
"nexthops":[
{
"type":"SR (OSPF)",
"outLabel":3,
- "outLabelStack":[
- 3
- ],
- "distance":150,
"installed":true,
- "nexthop":"10.0.3.2"
+ "nexthop":"10.0.7.6"
}
]
}
-]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step2/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step2/show_ip_route.ref
new file mode 100644
index 0000000000..c44b3eef30
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step2/show_ip_route.ref
@@ -0,0 +1,324 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step2/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step2/show_mpls_table.ref
new file mode 100644
index 0000000000..05f9f28cbd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step2/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step3/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step3/show_ip_route.ref
new file mode 100644
index 0000000000..a078dd2daf
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step3/show_ip_route.ref
@@ -0,0 +1,296 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":40,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step3/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step3/show_mpls_table.ref
new file mode 100644
index 0000000000..f5515636d2
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step3/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step4/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step4/show_ip_route.ref
new file mode 100644
index 0000000000..b63812ab1d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step4/show_ip_route.ref
@@ -0,0 +1,324 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step4/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step4/show_mpls_table.ref
new file mode 100644
index 0000000000..f2e56c2e19
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step4/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18050,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step5/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step5/show_ip_route.ref
new file mode 100644
index 0000000000..3157ae1ea1
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step5/show_ip_route.ref
@@ -0,0 +1,318 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step5/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step5/show_mpls_table.ref
new file mode 100644
index 0000000000..8213840652
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step5/show_mpls_table.ref
@@ -0,0 +1,67 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step6/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step6/show_ip_route.ref
new file mode 100644
index 0000000000..b63812ab1d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step6/show_ip_route.ref
@@ -0,0 +1,324 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step6/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step6/show_mpls_table.ref
new file mode 100644
index 0000000000..f2e56c2e19
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step6/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18050,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step7/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step7/show_ip_route.ref
new file mode 100644
index 0000000000..775d8c4034
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step7/show_ip_route.ref
@@ -0,0 +1,318 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step7/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step7/show_mpls_table.ref
new file mode 100644
index 0000000000..8a5fdef806
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step7/show_mpls_table.ref
@@ -0,0 +1,73 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18050,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step8/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step8/show_ip_route.ref
new file mode 100644
index 0000000000..b63812ab1d
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step8/show_ip_route.ref
@@ -0,0 +1,324 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step8/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step8/show_mpls_table.ref
new file mode 100644
index 0000000000..f2e56c2e19
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step8/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18050,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step9/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt4/step9/show_ip_route.ref
new file mode 100644
index 0000000000..48e306d393
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step9/show_ip_route.ref
@@ -0,0 +1,324 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/step9/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt4/step9/show_mpls_table.ref
new file mode 100644
index 0000000000..275abab715
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/step9/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18050,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt4/zebra.conf b/tests/topotests/ospf-sr-topo1/rt4/zebra.conf
new file mode 100644
index 0000000000..13c621eb31
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt4/zebra.conf
@@ -0,0 +1,27 @@
+log file zebra.log
+!
+hostname rt4
+!
+debug zebra kernel
+debug zebra packet
+debug zebra mpls
+!
+interface lo
+ ip address 4.4.4.4/32
+!
+interface eth-rt2-1
+ ip address 10.0.2.4/24
+!
+interface eth-rt2-2
+ ip address 10.0.3.4/24
+!
+interface eth-rt5
+ ip address 10.0.6.4/24
+!
+interface eth-rt6
+ ip address 10.0.7.4/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt5/ospfd.conf b/tests/topotests/ospf-sr-topo1/rt5/ospfd.conf
new file mode 100644
index 0000000000..4e7b24c03a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/ospfd.conf
@@ -0,0 +1,38 @@
+password 1
+hostname rt5
+log file ospfd.log
+!
+debug ospf sr
+debug ospf te
+debug ospf event
+debug ospf lsa
+debug ospf zebra
+!
+interface lo
+!
+interface eth-rt3-1
+ ip ospf network point-to-point
+!
+interface eth-rt3-2
+ ip ospf network point-to-point
+!
+interface eth-rt4
+ ip ospf network point-to-point
+!
+interface eth-rt6
+ ip ospf network point-to-point
+!
+router ospf
+ ospf router-id 5.5.5.5
+ network 5.5.5.5/32 area 0.0.0.0
+ network 10.0.0.0/16 area 0.0.0.0
+ capability opaque
+ mpls-te on
+ mpls-te router-address 5.5.5.5
+ router-info area 0.0.0.0
+ passive-interface lo
+ segment-routing on
+ segment-routing global-block 16000 23999
+ segment-routing node-msd 8
+ segment-routing prefix 5.5.5.5/32 index 50 no-php-flag
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step1/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step1/show_ip_route.ref
new file mode 100644
index 0000000000..0a43788a18
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step1/show_ip_route.ref
@@ -0,0 +1,311 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step1/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step1/show_mpls_table.ref
new file mode 100644
index 0000000000..e8c46085be
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step1/show_mpls_table.ref
@@ -0,0 +1,97 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.6.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step10/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step10/show_ip_route.ref
new file mode 100644
index 0000000000..2bad2eb7bf
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step10/show_ip_route.ref
@@ -0,0 +1,300 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step10/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step10/show_mpls_table.ref
new file mode 100644
index 0000000000..c5ed18d76f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step10/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18040,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step2/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step2/show_ip_route.ref
new file mode 100644
index 0000000000..3572ec713f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step2/show_ip_route.ref
@@ -0,0 +1,307 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step2/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step2/show_mpls_table.ref
new file mode 100644
index 0000000000..d9cadeb513
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step2/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step3/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step3/show_ip_route.ref
new file mode 100644
index 0000000000..2f7b0cc242
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step3/show_ip_route.ref
@@ -0,0 +1,272 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step3/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step3/show_mpls_table.ref
new file mode 100644
index 0000000000..7c78d2ce53
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step3/show_mpls_table.ref
@@ -0,0 +1,85 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17040,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17040,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step4/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step4/show_ip_route.ref
new file mode 100644
index 0000000000..1a12715086
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step4/show_ip_route.ref
@@ -0,0 +1,307 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step4/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step4/show_mpls_table.ref
new file mode 100644
index 0000000000..42e476e9d1
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step4/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18040,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step5/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step5/show_ip_route.ref
new file mode 100644
index 0000000000..e50fa10ccb
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step5/show_ip_route.ref
@@ -0,0 +1,286 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step5/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step5/show_mpls_table.ref
new file mode 100644
index 0000000000..bb95379228
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step5/show_mpls_table.ref
@@ -0,0 +1,67 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step6/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step6/show_ip_route.ref
new file mode 100644
index 0000000000..1a12715086
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step6/show_ip_route.ref
@@ -0,0 +1,307 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step6/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step6/show_mpls_table.ref
new file mode 100644
index 0000000000..42e476e9d1
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step6/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18040,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step7/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step7/show_ip_route.ref
new file mode 100644
index 0000000000..15a024d18b
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step7/show_ip_route.ref
@@ -0,0 +1,286 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step7/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step7/show_mpls_table.ref
new file mode 100644
index 0000000000..cff0d25e25
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step7/show_mpls_table.ref
@@ -0,0 +1,73 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18040,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step8/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step8/show_ip_route.ref
new file mode 100644
index 0000000000..1a12715086
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step8/show_ip_route.ref
@@ -0,0 +1,307 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 0
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step8/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step8/show_mpls_table.ref
new file mode 100644
index 0000000000..42e476e9d1
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step8/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18040,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":0,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step9/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt5/step9/show_ip_route.ref
new file mode 100644
index 0000000000..d9ddad2462
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step9/show_ip_route.ref
@@ -0,0 +1,292 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 17030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 18040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/step9/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt5/step9/show_mpls_table.ref
new file mode 100644
index 0000000000..c5ed18d76f
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/step9/show_mpls_table.ref
@@ -0,0 +1,91 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17010,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17020,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.5.3"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":17030,
+ "installed":true,
+ "nexthop":"10.0.4.3"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":18040,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt5/zebra.conf b/tests/topotests/ospf-sr-topo1/rt5/zebra.conf
new file mode 100644
index 0000000000..ca2d6df665
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt5/zebra.conf
@@ -0,0 +1,27 @@
+log file zebra.log
+!
+hostname rt5
+!
+debug zebra kernel
+debug zebra packet
+debug zebra mpls
+!
+interface lo
+ ip address 5.5.5.5/32
+!
+interface eth-rt3-1
+ ip address 10.0.4.5/24
+!
+interface eth-rt3-2
+ ip address 10.0.5.5/24
+!
+interface eth-rt4
+ ip address 10.0.6.5/24
+!
+interface eth-rt6
+ ip address 10.0.8.5/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt6/ospfd.conf b/tests/topotests/ospf-sr-topo1/rt6/ospfd.conf
new file mode 100644
index 0000000000..c6d07d169e
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/ospfd.conf
@@ -0,0 +1,32 @@
+password 1
+hostname rt6
+log file ospfd.log
+!
+debug ospf sr
+debug ospf te
+debug ospf event
+debug ospf lsa
+debug ospf zebra
+!
+interface lo
+!
+interface eth-rt4
+ ip ospf network point-to-point
+!
+interface eth-rt5
+ ip ospf network point-to-point
+!
+router ospf
+ ospf router-id 6.6.6.6
+ network 6.6.6.6/32 area 0.0.0.0
+ network 10.0.0.0/16 area 0.0.0.0
+ capability opaque
+ mpls-te on
+ mpls-te router-address 6.6.6.6
+ router-info area 0.0.0.0
+ passive-interface lo
+ segment-routing on
+ segment-routing global-block 16000 23999
+ segment-routing node-msd 8
+ segment-routing prefix 6.6.6.6/32 index 60 explicit-null
+!
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step1/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step1/show_ip_route.ref
new file mode 100644
index 0000000000..9f05ec7688
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step1/show_ip_route.ref
@@ -0,0 +1,291 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step1/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step1/show_mpls_table.ref
new file mode 100644
index 0000000000..baa2314454
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step1/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step10/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step10/show_ip_route.ref
new file mode 100644
index 0000000000..6abb3805a2
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step10/show_ip_route.ref
@@ -0,0 +1,284 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step10/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step10/show_mpls_table.ref
new file mode 100644
index 0000000000..09ecec29d9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step10/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "18010":{
+ "inLabel":18010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18020":{
+ "inLabel":18020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18030":{
+ "inLabel":18030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "18040":{
+ "inLabel":18040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18050":{
+ "inLabel":18050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step2/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step2/show_ip_route.ref
new file mode 100644
index 0000000000..80b3c426d4
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step2/show_ip_route.ref
@@ -0,0 +1,284 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step2/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step2/show_mpls_table.ref
new file mode 100644
index 0000000000..baa2314454
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step2/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step3/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step3/show_ip_route.ref
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step3/show_ip_route.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step3/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step3/show_mpls_table.ref
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step3/show_mpls_table.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step4/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step4/show_ip_route.ref
new file mode 100644
index 0000000000..80b3c426d4
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step4/show_ip_route.ref
@@ -0,0 +1,284 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step4/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step4/show_mpls_table.ref
new file mode 100644
index 0000000000..09ecec29d9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step4/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "18010":{
+ "inLabel":18010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18020":{
+ "inLabel":18020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18030":{
+ "inLabel":18030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "18040":{
+ "inLabel":18040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18050":{
+ "inLabel":18050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step5/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step5/show_ip_route.ref
new file mode 100644
index 0000000000..0e4b3eba12
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step5/show_ip_route.ref
@@ -0,0 +1,266 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step5/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step5/show_mpls_table.ref
new file mode 100644
index 0000000000..2c63c08510
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step5/show_mpls_table.ref
@@ -0,0 +1,2 @@
+{
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step6/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step6/show_ip_route.ref
new file mode 100644
index 0000000000..80b3c426d4
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step6/show_ip_route.ref
@@ -0,0 +1,284 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step6/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step6/show_mpls_table.ref
new file mode 100644
index 0000000000..09ecec29d9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step6/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "18010":{
+ "inLabel":18010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18020":{
+ "inLabel":18020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18030":{
+ "inLabel":18030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "18040":{
+ "inLabel":18040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18050":{
+ "inLabel":18050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step7/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step7/show_ip_route.ref
new file mode 100644
index 0000000000..aa2329a04a
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step7/show_ip_route.ref
@@ -0,0 +1,278 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step7/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step7/show_mpls_table.ref
new file mode 100644
index 0000000000..800b1ae2fd
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step7/show_mpls_table.ref
@@ -0,0 +1,50 @@
+{
+ "18020":{
+ "inLabel":18020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18030":{
+ "inLabel":18030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "18040":{
+ "inLabel":18040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18050":{
+ "inLabel":18050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step8/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step8/show_ip_route.ref
new file mode 100644
index 0000000000..80b3c426d4
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step8/show_ip_route.ref
@@ -0,0 +1,284 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step8/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step8/show_mpls_table.ref
new file mode 100644
index 0000000000..09ecec29d9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step8/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "18010":{
+ "inLabel":18010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18020":{
+ "inLabel":18020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18030":{
+ "inLabel":18030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "18040":{
+ "inLabel":18040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18050":{
+ "inLabel":18050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step9/show_ip_route.ref b/tests/topotests/ospf-sr-topo1/rt6/step9/show_ip_route.ref
new file mode 100644
index 0000000000..80b3c426d4
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step9/show_ip_route.ref
@@ -0,0 +1,284 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":10,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ },
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"ospf",
+ "selected":true,
+ "destSelected":true,
+ "distance":110,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"ospf",
+ "distance":110,
+ "metric":10,
+ "nexthops":[
+ {
+ "directlyConnected":true,
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/step9/show_mpls_table.ref b/tests/topotests/ospf-sr-topo1/rt6/step9/show_mpls_table.ref
new file mode 100644
index 0000000000..09ecec29d9
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/step9/show_mpls_table.ref
@@ -0,0 +1,68 @@
+{
+ "18010":{
+ "inLabel":18010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ },
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18020":{
+ "inLabel":18020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18030":{
+ "inLabel":18030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ },
+ "18040":{
+ "inLabel":18040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.7.4"
+ }
+ ]
+ },
+ "18050":{
+ "inLabel":18050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (OSPF)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.8.5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/ospf-sr-topo1/rt6/zebra.conf b/tests/topotests/ospf-sr-topo1/rt6/zebra.conf
new file mode 100644
index 0000000000..4b739d0bca
--- /dev/null
+++ b/tests/topotests/ospf-sr-topo1/rt6/zebra.conf
@@ -0,0 +1,21 @@
+log file zebra.log
+!
+hostname rt6
+!
+debug zebra kernel
+debug zebra packet
+debug zebra mpls
+!
+interface lo
+ ip address 6.6.6.6/32
+!
+interface eth-rt4
+ ip address 10.0.7.6/24
+!
+interface eth-rt5
+ ip address 10.0.8.6/24
+!
+ip forwarding
+!
+line vty
+!
diff --git a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.dot b/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.dot
deleted file mode 100644
index d293669209..0000000000
--- a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.dot
+++ /dev/null
@@ -1,78 +0,0 @@
-## Color coding:
-#########################
-## Main FRR: #f08080 red
-## Switches: #d0e0d0 gray
-## RIP: #19e3d9 Cyan
-## RIPng: #fcb314 dark yellow
-## OSPFv2: #32b835 Green
-## OSPFv3: #19e3d9 Cyan
-## ISIS IPv4 #fcb314 dark yellow
-## ISIS IPv6 #9a81ec purple
-## BGP IPv4 #eee3d3 beige
-## BGP IPv6 #fdff00 yellow
-##### Colors (see http://www.color-hex.com/)
-
-graph ospf_topo1 {
- label="ospf SR topo1";
-
- # Routers
- r1 [
- label="r1\nrtr-id 10.0.255.1/32",
- shape=doubleoctagon,
- fillcolor="#f08080",
- style=filled,
- ];
- r2 [
- label="r2\nrtr-id 10.0.255.2/32",
- shape=doubleoctagon,
- fillcolor="#f08080",
- style=filled,
- ];
- r3 [
- label="r3\nrtr-id 10.0.255.3/32",
- shape=doubleoctagon,
- fillcolor="#f08080",
- style=filled,
- ];
- r4 [
- label="r4\nrtr-id 10.0.255.4/32",
- shape=doubleoctagon,
- fillcolor="#f08080",
- style=filled,
- ];
-
- # Switches
- s1 [
- label="s2\n10.0.1.0/24",
- shape=oval,
- fillcolor="#d0e0d0",
- style=filled,
- ];
- s2 [
- label="s1\n10.0.3.0/24",
- shape=oval,
- fillcolor="#d0e0d0",
- style=filled,
- ];
- s3 [
- label="s2\n10.0.4.0/24",
- shape=oval,
- fillcolor="#d0e0d0",
- style=filled,
- ];
-
- # Connections
- subgraph cluster0 {
- label="area 0"
-
- r1 -- s1 [label="eth0\n.1"];
-
- r2 -- s1 [label="eth0\n.2"];
- r2 -- s2 [label="eth1\n.2"];
- r2 -- s3 [label="eth2\n.2"];
-
- r3 -- s2 [label="eth0\n.1"];
-
- r4 -- s3 [label="eth0\n.1"];
- }
-}
diff --git a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.jpg b/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.jpg
deleted file mode 100644
index 636f9b320c..0000000000
--- a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.jpg
+++ /dev/null
Binary files differ
diff --git a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py b/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py
index 53322f432f..57b93c3fd5 100644
--- a/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py
+++ b/tests/topotests/ospf-sr-topo1/test_ospf_sr_topo1.py
@@ -4,7 +4,7 @@
# test_ospf_sr_topo1.py
# Part of NetDEF Topology Tests
#
-# Copyright (c) 2017 by
+# Copyright (c) 2020 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
# Permission to use, copy, modify, and/or distribute this software
@@ -23,13 +23,52 @@
#
"""
-test_ospf_sr_topo1.py: Test the FRR OSPF routing daemon with Segment Routing.
+test_ospf_sr_topo1.py:
+
+ +---------+
+ | |
+ | RT1 |
+ | 1.1.1.1 |
+ | |
+ +---------+
+ |eth-sw1
+ |
+ |
+ |
+ +---------+ | +---------+
+ | | | | |
+ | RT2 |eth-sw1 | eth-sw1| RT3 |
+ | 2.2.2.2 +----------+----------+ 3.3.3.3 |
+ | | 10.0.1.0/24 | |
+ +---------+ +---------+
+ eth-rt4-1| |eth-rt4-2 eth-rt5-1| |eth-rt5-2
+ | | | |
+ 10.0.2.0/24| |10.0.3.0/24 10.0.4.0/24| |10.0.5.0/24
+ | | | |
+ eth-rt2-1| |eth-rt2-2 eth-rt3-1| |eth-rt3-2
+ +---------+ +---------+
+ | | | |
+ | RT4 | 10.0.6.0/24 | RT5 |
+ | 4.4.4.4 +---------------------+ 5.5.5.5 |
+ | |eth-rt5 eth-rt4| |
+ +---------+ +---------+
+ eth-rt6| |eth-rt6
+ | |
+ 10.0.7.0/24| |10.0.8.0/24
+ | +---------+ |
+ | | | |
+ | | RT6 | |
+ +----------+ 6.6.6.6 +-----------+
+ eth-rt4| |eth-rt5
+ +---------+
"""
import os
-import re
import sys
+import pytest
import json
+import re
+from time import sleep
from functools import partial
# Save the Current Working Directory to find configuration files.
@@ -37,62 +76,74 @@ CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
-# Required to instantiate the topology builder class.
-from mininet.topo import Topo
-
# Import topogen and topotest helpers
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-# and Finally pytest
-import pytest
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+pytestmark = [pytest.mark.ospfd]
-class OspfSrTopo(Topo):
+class TemplateTopo(Topo):
"Test topology builder"
- def build(self):
+ def build(self, *_args, **_opts):
"Build function"
tgen = get_topogen(self)
- # Check for mpls
- if tgen.hasmpls is not True:
- tgen.set_error("MPLS not available, tests will be skipped")
+ #
+ # Define FRR Routers
+ #
+ for router in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ tgen.add_router(router)
- # Create 4 routers
- for routern in range(1, 5):
- tgen.add_router("r{}".format(routern))
-
- # Interconect router 1 and 2 with 2 links
+ #
+ # Define connections
+ #
switch = tgen.add_switch("s1")
- switch.add_link(tgen.gears["r1"])
- switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["rt1"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-sw1")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-sw1")
+
switch = tgen.add_switch("s2")
- switch.add_link(tgen.gears["r1"])
- switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-1")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-1")
- # Interconect router 3 and 2
switch = tgen.add_switch("s3")
- switch.add_link(tgen.gears["r3"])
- switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["rt2"], nodeif="eth-rt4-2")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt2-2")
- # Interconect router 4 and 2
switch = tgen.add_switch("s4")
- switch.add_link(tgen.gears["r4"])
- switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-1")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-1")
+ switch = tgen.add_switch("s5")
+ switch.add_link(tgen.gears["rt3"], nodeif="eth-rt5-2")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt3-2")
-def setup_module(mod):
- "Sets up the pytest environment"
+ switch = tgen.add_switch("s6")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt5")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt4")
+
+ switch = tgen.add_switch("s7")
+ switch.add_link(tgen.gears["rt4"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt4")
- logger.info("\n\n---- Starting OSPF Segment Routing tests ----\n")
+ switch = tgen.add_switch("s8")
+ switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
+ switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
- tgen = Topogen(OspfSrTopo, mod.__name__)
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(TemplateTopo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
+ # For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
@@ -101,101 +152,536 @@ def setup_module(mod):
TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
)
- # Initialize all routers.
tgen.start_router()
def teardown_module(mod):
"Teardown the pytest environment"
-
tgen = get_topogen()
+
+ # This function tears down the whole topology.
tgen.stop_topology()
- logger.info("\n\n---- OSPF Segment Routing tests End ----\n")
+
+def print_cmd_result(rname, command):
+ print(get_topogen().gears[rname].vtysh_cmd(command, isjson=False))
+
+
+def router_compare_json_output(rname, command, reference):
+ "Compare router JSON output"
+
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+
+ tgen = get_topogen()
+ filename = "{}/{}/{}".format(CWD, rname, reference)
+ expected = json.loads(open(filename).read())
+
+ # Run test function until we get an result. Wait at most 60 seconds.
+ test_func = 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
+
+
+#
+# Step 1
+#
+# Test initial network convergence
+#
+def test_rib_step1():
+ logger.info("Test (step 1): verify RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step1/show_ip_route.ref"
+ )
+
+
+def test_mpls_lib_step1():
+ logger.info("Test (step 1): verify MPLS LIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step1/show_mpls_table.ref"
+ )
+
+
+#
+# Step 2
+#
+# Action(s):
+# -Disable OSPF on the eth-rt5 interface on rt4
+#
+# Expected changes:
+# -rt4 should uninstall the Adj-SIDs pointing to rt5
+# -rt5 should uninstall the Adj-SIDs pointing to rt4
+# -rt2 should reinstall rt5's Prefix-SIDs (2 nexthops deleted)
+# -rt3 should reinstall rt4's Prefix-SIDs (2 nexthops deleted)
+# -rt4 should reinstall rt3's Prefix-SIDs (1 nexthop deleted)
+# -rt4 should reinstall rt5's Prefix-SIDs (1 nexthop changed)
+# -rt5 should reinstall rt2's Prefix-SIDs (1 nexthop deleted)
+# -rt5 should reinstall rt4's Prefix-SIDs (1 nexthop changed)
+#
+def test_rib_ipv4_step2():
+ logger.info("Test (step 2): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Disabling OSPF on the eth-rt5 interface on rt4")
+ tgen.net["rt4"].cmd(
+ 'vtysh -c "conf t" -c "interface eth-rt5" -c "no ip ospf network point-to-point"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step2/show_ip_route.ref"
+ )
+
+
+def test_mpls_lib_step2():
+ logger.info("Test (step 2): verify MPLS LIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step2/show_mpls_table.ref"
+ )
+
+
+#
+# Step 3
+#
+# Action(s):
+# -Shut down the eth-rt4 interface on rt6
+# -Shut down the eth-rt5 interface on rt6
+#
+# Expected changes:
+# -All routers should uninstall rt6's Prefix-SIDs
+# -rt4 and rt5 should uninstall the Adj-SIDs pointing to rt6
+# -rt4 should reconverge rt5's Prefix-SIDs through rt2 using ECMP
+# -rt5 should reconverge rt4's Prefix-SIDs through rt3 using ECMP
+# -rt6 should uninstall all its IS-IS routes, Prefix-SIDs and Adj-SIDs
+#
+def test_rib_ipv4_step3():
+ logger.info("Test (step 3): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Shutting down the eth-rt4 interface on rt6")
+ tgen.net["rt6"].cmd('vtysh -c "conf t" -c "interface eth-rt4" -c "shutdown"')
+ logger.info("Shutting down the eth-rt5 interface on rt6")
+ tgen.net["rt6"].cmd('vtysh -c "conf t" -c "interface eth-rt5" -c "shutdown"')
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step3/show_ip_route.ref"
+ )
+
+
+def test_mpls_lib_step3():
+ logger.info("Test (step 3): verify MPLS LIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step3/show_mpls_table.ref"
+ )
+
+
+#
+# Step 4
+#
+# Action(s):
+# -Bring up the eth-rt4 interface on rt6
+# -Bring up the eth-rt5 interface on rt6
+# -Change rt6's SRGB
+#
+# Expected changes:
+# -All routers should install rt6's Prefix-SIDs
+# -rt4 and rt5 should install Adj-SIDs for rt6
+# -rt4 should reconverge rt5's Prefix-SIDs through rt6 using the new SRGB
+# -rt5 should reconverge rt4's Prefix-SIDs through rt6 using the new SRGB
+# -rt6 should reinstall all IS-IS routes and Prefix-SIDs from the network, and Adj-SIDs for rt4 and rt5
+#
+def test_rib_ipv4_step4():
+ logger.info("Test (step 4): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Bringing up the eth-rt4 interface on rt6")
+ tgen.net["rt6"].cmd('vtysh -c "conf t" -c "interface eth-rt4" -c "no shutdown"')
+ logger.info("Bringing up the eth-rt5 interface on rt6")
+ tgen.net["rt6"].cmd('vtysh -c "conf t" -c "interface eth-rt5" -c "no shutdown"')
+ logger.info("Changing rt6's SRGB")
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing global-block 18000 25999"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step4/show_ip_route.ref"
+ )
+
+
+def test_mpls_lib_step4():
+ logger.info("Test (step 4): verify MPLS LIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step4/show_mpls_table.ref"
+ )
+
+
+#
+# Step 5
+#
+# Action(s):
+# -Disable SR on rt6
+#
+# Expected changes:
+# -All routers should uninstall rt6's Prefix-SIDs
+# -rt4 should uninstall rt5's Prefix-SIDs since the nexthop router hasn't SR enabled anymore
+# -rt5 should uninstall rt4's Prefix-SIDs since the nexthop router hasn't SR enabled anymore
+# -rt6 should uninstall all Prefix-SIDs from the network, and the Adj-SIDs for rt4 and rt5
+#
+def test_rib_ipv4_step5():
+ logger.info("Test (step 5): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Disabling SR on rt6")
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "no segment-routing on"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step5/show_ip_route.ref"
+ )
+
+
+def test_mpls_lib_step5():
+ logger.info("Test (step 5): verify MPLS LIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step5/show_mpls_table.ref"
+ )
+
+
+#
+# Step 6
+#
+# Action(s):
+# -Enable SR on rt6
+#
+# Expected changes:
+# -All routers should install rt6's Prefix-SIDs
+# -rt4 should install rt5's Prefix-SIDs through rt6
+# -rt5 should install rt4's Prefix-SIDs through rt6
+# -rt6 should install all Prefix-SIDs from the network, and Adj-SIDs for rt4 and rt5
+#
+def test_rib_ipv4_step6():
+ logger.info("Test (step 6): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Enabling SR on rt6")
+ tgen.net["rt6"].cmd('vtysh -c "conf t" -c "router ospf" -c "segment-routing on"')
+
+ # FIXME: This is currently necessary because the CLI is not yet yang based.
+ logger.info("Re-do rt6's SR config")
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing global-block 18000 25999"'
+ )
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing node-msd 8"'
+ )
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 6.6.6.6/32 index 60 explicit-null"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step6/show_ip_route.ref"
+ )
+
+
+def test_mpls_lib_step6():
+ logger.info("Test (step 6): verify MPLS LIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step6/show_mpls_table.ref"
+ )
+
+
+#
+# Step 7
+#
+# Action(s):
+# -Delete rt1's Prefix-SIDs
+#
+# Expected changes:
+# -All routers should uninstall rt1's Prefix-SIDs
+#
+def test_rib_ipv4_step7():
+ logger.info("Test (step 7): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Deleting rt1's Prefix-SIDs")
+ tgen.net["rt1"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "no segment-routing prefix 1.1.1.1/32 index 10"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step7/show_ip_route.ref"
+ )
-def test_ospf_sr():
- "Test OSPF daemon Segment Routing"
+def test_mpls_lib_step7():
+ logger.info("Test (step 7): verify MPLS LIB")
tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- logger.info("--- test OSPF Segment Routing Data Base ---")
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step7/show_mpls_table.ref"
+ )
- for rnum in range(1, 5):
- router = "r{}".format(rnum)
- logger.info('\tRouter "%s"', router)
+#
+# Step 8
+#
+# Action(s):
+# -Re-add rt1's Prefix-SIDs
+#
+# Expected changes:
+# -All routers should install rt1's Prefix-SIDs
+#
+def test_rib_ipv4_step8():
+ logger.info("Test (step 8): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
- # Load expected results from the command
- reffile = os.path.join(CWD, "{}/ospf_srdb.json".format(router))
- expected = json.loads(open(reffile).read())
+ logger.info("Re-adding rt1's Prefix-SIDs")
+ tgen.net["rt1"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 1.1.1.1/32 index 10"'
+ )
- # Run test function until we get an result. Wait at most 60 seconds.
- rt = tgen.gears[router]
- test_func = partial(
- topotest.router_json_cmp,
- rt,
- "show ip ospf database segment-routing json",
- expected,
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step8/show_ip_route.ref"
)
- rv, diff = topotest.run_and_expect(test_func, None, count=25, wait=3)
- assert rv, "OSPF did not start Segment Routing on {}:\n{}".format(router, diff)
-def test_ospf_kernel_route():
- "Test OSPF Segment Routing MPLS route installation"
+def test_mpls_lib_step8():
+ logger.info("Test (step 8): verify MPLS LIB")
tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- logger.info("--- test OSPF Segment Routing MPLS tables ---")
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step8/show_mpls_table.ref"
+ )
- def show_mpls_table_json_cmp(rt, expected):
- """
- Reformat MPLS table output to use a list of labels instead of dict.
- Original:
- {
- "X": {
- inLabel: "X",
- # ...
- }
- }
+#
+# Step 9
+#
+# Action(s):
+# -Change rt1's Prefix-SIDs to use the no-php option
+# -Change rt6's Prefix-SIDs to stop using the explicit-null option
+#
+# Expected changes:
+# -rt2 and rt3 should reinstall rt1's Prefix-SIDs accordingly
+# -rt4 and rt5 should reinstall rt6's Prefix-SIDs accordingly
+#
+def test_rib_ipv4_step9():
+ logger.info("Test (step 9): verify IPv4 RIB")
+ tgen = get_topogen()
- List format:
- [
- {
- inLabel: "X",
- }
- ]
- """
- out = rt.vtysh_cmd("show mpls table json", isjson=True)
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
- outlist = []
- for key in out.keys():
- outlist.append(out[key])
+ logger.info("Changing rt1's Prefix-SIDs to use the no-php option")
+ tgen.net["rt1"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 1.1.1.1/32 index 10 no-php-flag"'
+ )
- return topotest.json_cmp(outlist, expected)
+ logger.info("Change rt6's Prefix-SIDs to stop using the explicit-null option")
+ tgen.net["rt6"].cmd(
+ 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 6.6.6.6/32 index 60"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step9/show_ip_route.ref"
+ )
- for rnum in range(1, 5):
- router = "r{}".format(rnum)
- logger.info('\tRouter "%s"', router)
+def test_mpls_lib_step9():
+ logger.info("Test (step 9): verify MPLS LIB")
+ tgen = get_topogen()
- # Load expected results from the command
- reffile = os.path.join(CWD, "{}/zebra_mpls.json".format(router))
- expected = json.loads(open(reffile).read())
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
- # Run test function until we get an result. Wait at most 60 seconds.
- rt = tgen.gears[router]
- test_func = partial(show_mpls_table_json_cmp, rt, expected)
- rv, diff = topotest.run_and_expect(test_func, None, count=25, wait=3)
- assert rv, "OSPF did not properly instal MPLS table on {}:\n{}".format(
- router, diff
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step9/show_mpls_table.ref"
)
+#
+# Step 10
+#
+# Action(s):
+# -Remove the IPv4 address from rt4's eth-rt2-1 interface
+#
+# Expected changes:
+# -rt2 should uninstall the IPv4 Adj-SIDs attached to the eth-rt4-1 interface
+# -rt2 should reinstall all IPv4 Prefix-SIDs whose nexthop router is rt4 (ECMP shouldn't be used anymore)
+# -rt4 should reinstall all IPv4 Prefix-SIDs whose nexthop router is rt2 (ECMP shouldn't be used anymore)
+#
+def test_rib_ipv4_step10():
+ logger.info("Test (step 10): verify IPv4 RIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Removing the IPv4 address from rt4's eth-rt2-1 interface")
+ tgen.net["rt4"].cmd(
+ 'vtysh -c "conf t" -c "interface eth-rt2-1" -c "no ip address 10.0.2.4/24"'
+ )
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show ip route ospf json", "step10/show_ip_route.ref"
+ )
+
+
+def test_mpls_lib_step10():
+ logger.info("Test (step 10): verify MPLS LIB")
+ tgen = get_topogen()
+
+ # Skip if previous fatal error condition is raised
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ router_compare_json_output(
+ rname, "show mpls table json", "step10/show_mpls_table.ref"
+ )
+
+
+# FIXME: These tests don't work yet, this should be fixed with the
+# switchover to a yang based CLI.
+#
+# Step 11
+#
+# Action(s):
+# -Enter invalid SR configuration
+#
+# Expected changes:
+# -All commands should be rejected
+#
+#def test_ospf_invalid_config_step11():
+# logger.info("Test (step 11): check if invalid configuration is rejected")
+# tgen = get_topogen()
+#
+# # Skip if previous fatal error condition is raised
+# if tgen.routers_have_failure():
+# pytest.skip(tgen.errors)
+#
+# logger.info("Entering invalid Segment Routing configuration...")
+# ret = tgen.net["rt1"].cmd(
+# 'vtysh -c "conf t" -c "router ospf" -c "segment-routing prefix 1.1.1.1/32 index 10000"'
+# )
+# assert (
+# re.search("Configuration failed", ret) is not None
+# ), "Invalid SR configuration wasn't rejected"
+# ret = tgen.net["rt1"].cmd(
+# 'vtysh -c "conf t" -c "router ospf" -c "segment-routing global-block 16000 14999"'
+# )
+# assert (
+# re.search("Configuration failed", ret) is not None
+# ), "Invalid SR configuration wasn't rejected"
+# ret = tgen.net["rt1"].cmd(
+# 'vtysh -c "conf t" -c "router ospf" -c "segment-routing global-block 16000 16001"'
+# )
+# assert (
+# re.search("Configuration failed", ret) is not None
+# ), "Invalid SR configuration wasn't rejected"
+
+
+# Memory leak test template
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/ospf-tilfa-topo1/test_ospf_tilfa_topo1.py b/tests/topotests/ospf-tilfa-topo1/test_ospf_tilfa_topo1.py
index eb3ad5d995..489690471c 100644
--- a/tests/topotests/ospf-tilfa-topo1/test_ospf_tilfa_topo1.py
+++ b/tests/topotests/ospf-tilfa-topo1/test_ospf_tilfa_topo1.py
@@ -166,6 +166,7 @@ def test_ospf_initial_convergence_step1():
"step1/show_ip_route_initial.ref",
)
+
def test_ospf_link_protection_step2():
logger.info("Test (step 2): check OSPF link protection")
tgen = get_topogen()
@@ -175,9 +176,7 @@ def test_ospf_link_protection_step2():
pytest.skip(tgen.errors)
# enable TI-LFA link protection on all interfaces
- tgen.net["rt1"].cmd(
- 'vtysh -c "conf t" -c "router ospf" -c "fast-reroute ti-lfa"'
- )
+ tgen.net["rt1"].cmd('vtysh -c "conf t" -c "router ospf" -c "fast-reroute ti-lfa"')
router_compare_json_output(
"rt1",
@@ -197,6 +196,7 @@ def test_ospf_link_protection_step2():
"step2/show_ip_route_initial.ref",
)
+
def test_ospf_node_protection_step3():
logger.info("Test (step 3): check OSPF node protection")
tgen = get_topogen()
@@ -228,6 +228,7 @@ def test_ospf_node_protection_step3():
"step3/show_ip_route_initial.ref",
)
+
# Memory leak test template
def test_memory_leak():
"Run the memory leak test and report results."
@@ -237,6 +238,7 @@ def test_memory_leak():
tgen.report_memory_leaks()
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py b/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py
index 2421b312d2..e2cb7bff03 100644
--- a/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py
+++ b/tests/topotests/ospf-topo1-vrf/test_ospf_topo1_vrf.py
@@ -45,6 +45,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.ospfd]
+
class OSPFTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/ospf-topo1/test_ospf_topo1.py b/tests/topotests/ospf-topo1/test_ospf_topo1.py
index 24806dd8fc..5bb6c2c818 100644
--- a/tests/topotests/ospf-topo1/test_ospf_topo1.py
+++ b/tests/topotests/ospf-topo1/test_ospf_topo1.py
@@ -45,6 +45,8 @@ from lib.topolog import logger
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.ospfd]
+
class OSPFTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
index c3efb6ff22..6ae886b76e 100644
--- a/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
+++ b/tests/topotests/ospf6-topo1/test_ospf6_topo1.py
@@ -384,15 +384,14 @@ def test_linux_ipv6_kernel_routingTable():
% (i, diff)
)
else:
- logger.error(
- "r{} failed - no nhid ref file: {}".format(i, refTableFile)
- )
+ logger.error("r{} failed - no nhid ref file: {}".format(i, refTableFile))
assert False, (
"Linux Kernel IPv6 Routing Table verification failed for router r%s\n"
% (i)
)
+
def test_shutdown_check_stderr():
tgen = get_topogen()
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py b/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py
index 37b7528490..cebe55b39c 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_chaos.py
@@ -49,28 +49,32 @@ from lib.common_config import (
shutdown_bringup_interface,
topo_daemons,
verify_rib,
- stop_router, start_router,
+ stop_router,
+ start_router,
create_static_routes,
start_router_daemons,
- kill_router_daemons
+ kill_router_daemons,
)
-from lib.ospf import (
- verify_ospf_neighbor, verify_ospf_rib,
- create_router_ospf)
+from lib.ospf import verify_ospf_neighbor, verify_ospf_rib, create_router_ospf
from lib.topolog import logger
from lib.topojson import build_topo_from_json, build_config_from_json
from ipaddress import IPv4Address
-
+pytestmark = [pytest.mark.ospfd, pytest.mark.staticd]
# Global variables
topo = None
NETWORK = {
- "ipv4": ["11.0.20.1/32", "11.0.20.2/32", "11.0.20.3/32", "11.0.20.4/32",
- "11.0.20.5/32"]
+ "ipv4": [
+ "11.0.20.1/32",
+ "11.0.20.2/32",
+ "11.0.20.3/32",
+ "11.0.20.4/32",
+ "11.0.20.5/32",
+ ]
}
"""
Topology:
@@ -102,6 +106,7 @@ try:
except IOError:
assert False, "Could not read file {}".format(jsonFile)
+
class CreateTopo(Topo):
"""
Test topology builder.
@@ -190,78 +195,71 @@ def test_ospf_chaos_tc31_p1(request):
step(
"Create static routes(10.0.20.1/32) in R1 and redistribute "
- "to OSPF using route map.")
+ "to OSPF using route map."
+ )
# Create Static routes
input_dict = {
"r0": {
"static_routes": [
{
- "network": NETWORK['ipv4'][0],
+ "network": NETWORK["ipv4"][0],
"no_of_ip": 5,
- "next_hop": 'Null0',
+ "next_hop": "Null0",
}
]
}
}
result = create_static_routes(tgen, input_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)
- ospf_red_r0 = {
- "r0": {
- "ospf": {
- "redistribute": [{
- "redist_type": "static"
- }]
- }
- }
- }
+ ospf_red_r0 = {"r0": {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
result = create_router_ospf(tgen, topo, ospf_red_r0)
- 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 OSPF neighbors after base config is done.")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step("Verify that route is advertised to R1.")
- dut = 'r1'
- protocol = 'ospf'
- nh = topo['routers']['r0']['links']['r1']['ipv4'].split('/')[0]
+ dut = "r1"
+ protocol = "ospf"
+ nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Kill OSPFd daemon on R0.")
kill_router_daemons(tgen, "r0", ["ospfd"])
step("Verify OSPF neighbors are down after killing ospfd in R0")
- dut = 'r0'
+ dut = "r0"
# Api call verify whether OSPF is converged
- ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut,
- expected=False)
- assert ospf_covergence is not True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut, expected=False)
+ assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step("Verify that route advertised to R1 are deleted from RIB and FIB.")
- dut = 'r1'
- protocol = 'ospf'
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
+ tc_name, result
+ ))
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol,
expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
+ tc_name, result
+ ))
step("Bring up OSPFd daemon on R0.")
start_router_daemons(tgen, "r0", ["ospfd"])
@@ -269,33 +267,32 @@ def test_ospf_chaos_tc31_p1(request):
step("Verify OSPF neighbors are up after bringing back ospfd in R0")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step(
"All the neighbours are up and routes are installed before the"
- " restart. Verify OSPF route table and ip route table.")
- dut = 'r1'
- protocol = 'ospf'
+ " restart. Verify OSPF route table and ip route table."
+ )
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Kill OSPFd daemon on R1.")
kill_router_daemons(tgen, "r1", ["ospfd"])
step("Verify OSPF neighbors are down after killing ospfd in R1")
- dut = 'r1'
+ dut = "r1"
# Api call verify whether OSPF is converged
- ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut,
- expected=False)
- assert ospf_covergence is not True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ ospf_covergence = verify_ospf_neighbor(tgen, topo, dut=dut, expected=False)
+ assert ospf_covergence is not True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step("Bring up OSPFd daemon on R1.")
start_router_daemons(tgen, "r1", ["ospfd"])
@@ -303,23 +300,22 @@ def test_ospf_chaos_tc31_p1(request):
step("Verify OSPF neighbors are up after bringing back ospfd in R1")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step(
"All the neighbours are up and routes are installed before the"
- " restart. Verify OSPF route table and ip route table.")
+ " restart. Verify OSPF route table and ip route table."
+ )
- dut = 'r1'
- protocol = 'ospf'
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
write_test_footer(tc_name)
@@ -335,104 +331,91 @@ def test_ospf_chaos_tc32_p1(request):
step(
"Create static routes(10.0.20.1/32) in R1 and redistribute "
- "to OSPF using route map.")
+ "to OSPF using route map."
+ )
# Create Static routes
input_dict = {
"r0": {
"static_routes": [
{
- "network": NETWORK['ipv4'][0],
+ "network": NETWORK["ipv4"][0],
"no_of_ip": 5,
- "next_hop": 'Null0',
+ "next_hop": "Null0",
}
]
}
}
result = create_static_routes(tgen, input_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)
- ospf_red_r0 = {
- "r0": {
- "ospf": {
- "redistribute": [{
- "redist_type": "static"
- }]
- }
- }
- }
+ ospf_red_r0 = {"r0": {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
result = create_router_ospf(tgen, topo, ospf_red_r0)
- 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 OSPF neighbors after base config is done.")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step("Verify that route is advertised to R1.")
- dut = 'r1'
- protocol = 'ospf'
+ dut = "r1"
+ protocol = "ospf"
- nh = topo['routers']['r0']['links']['r1']['ipv4'].split('/')[0]
+ nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Restart frr on R0")
- stop_router(tgen, 'r0')
- start_router(tgen, 'r0')
+ stop_router(tgen, "r0")
+ start_router(tgen, "r0")
step("Verify OSPF neighbors are up after restarting R0")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step(
"All the neighbours are up and routes are installed before the"
- " restart. Verify OSPF route table and ip route table.")
- dut = 'r1'
- protocol = 'ospf'
+ " restart. Verify OSPF route table and ip route table."
+ )
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Restart frr on R1")
- stop_router(tgen, 'r1')
- start_router(tgen, 'r1')
+ stop_router(tgen, "r1")
+ start_router(tgen, "r1")
step("Verify OSPF neighbors are up after restarting R1")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step(
"All the neighbours are up and routes are installed before the"
- " restart. Verify OSPF route table and ip route table.")
- dut = 'r1'
- protocol = 'ospf'
+ " restart. Verify OSPF route table and ip route table."
+ )
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
write_test_footer(tc_name)
@@ -453,70 +436,63 @@ def test_ospf_chaos_tc34_p1(request):
step(
"Create static routes(10.0.20.1/32) in R1 and redistribute "
- "to OSPF using route map.")
+ "to OSPF using route map."
+ )
# Create Static routes
input_dict = {
"r0": {
"static_routes": [
{
- "network": NETWORK['ipv4'][0],
+ "network": NETWORK["ipv4"][0],
"no_of_ip": 5,
- "next_hop": 'Null0',
+ "next_hop": "Null0",
}
]
}
}
result = create_static_routes(tgen, input_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)
- ospf_red_r0 = {
- "r0": {
- "ospf": {
- "redistribute": [{
- "redist_type": "static"
- }]
- }
- }
- }
+ ospf_red_r0 = {"r0": {"ospf": {"redistribute": [{"redist_type": "static"}]}}}
result = create_router_ospf(tgen, topo, ospf_red_r0)
- 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 OSPF neighbors after base config is done.")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step("Verify that route is advertised to R1.")
- dut = 'r1'
- protocol = 'ospf'
- nh = topo['routers']['r0']['links']['r1']['ipv4'].split('/')[0]
+ dut = "r1"
+ protocol = "ospf"
+ nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Kill staticd daemon on R0.")
kill_router_daemons(tgen, "r0", ["staticd"])
step("Verify that route advertised to R1 are deleted from RIB and FIB.")
- dut = 'r1'
- protocol = 'ospf'
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
+ tc_name, result
+ ))
result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol,
expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
+ tc_name, result
+ ))
step("Bring up staticd daemon on R0.")
start_router_daemons(tgen, "r0", ["staticd"])
@@ -524,22 +500,21 @@ def test_ospf_chaos_tc34_p1(request):
step("Verify OSPF neighbors are up after bringing back ospfd in R0")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step(
"All the neighbours are up and routes are installed before the"
- " restart. Verify OSPF route table and ip route table.")
- dut = 'r1'
- protocol = 'ospf'
+ " restart. Verify OSPF route table and ip route table."
+ )
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Kill staticd daemon on R1.")
kill_router_daemons(tgen, "r1", ["staticd"])
@@ -550,23 +525,22 @@ def test_ospf_chaos_tc34_p1(request):
step("Verify OSPF neighbors are up after bringing back ospfd in R1")
# Api call verify whether OSPF is converged
ospf_covergence = verify_ospf_neighbor(tgen, topo)
- assert ospf_covergence is True, ("setup_module :Failed \n Error:"
- " {}".format(ospf_covergence))
+ assert ospf_covergence is True, "setup_module :Failed \n Error:" " {}".format(
+ ospf_covergence
+ )
step(
"All the neighbours are up and routes are installed before the"
- " restart. Verify OSPF route table and ip route table.")
+ " restart. Verify OSPF route table and ip route table."
+ )
- dut = 'r1'
- protocol = 'ospf'
+ dut = "r1"
+ protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh)
- 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, "ipv4", dut, input_dict, protocol=protocol,
- next_hop=nh)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ result = verify_rib(tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
write_test_footer(tc_name)
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
index 441368e8fa..adf82a5e85 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp.py
@@ -259,17 +259,19 @@ def test_ospf_ecmp_tc16_p0(request):
shutdown_bringup_interface(tgen, dut, intf, False)
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
protocol = "ospf"
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, next_hop=nh, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
for intfr in range(1, 7):
intf = topo["routers"]["r1"]["links"]["r0-link{}".format(intfr)]["interface"]
@@ -324,9 +326,10 @@ def test_ospf_ecmp_tc16_p0(request):
result = verify_ospf_rib(
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
protocol = "ospf"
result = verify_rib(
@@ -339,9 +342,10 @@ def test_ospf_ecmp_tc16_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Re configure the static route in R0.")
dut = "r0"
@@ -428,9 +432,10 @@ def test_ospf_ecmp_tc17_p0(request):
result = verify_ospf_rib(
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
protocol = "ospf"
result = verify_rib(
@@ -443,9 +448,10 @@ def test_ospf_ecmp_tc17_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Reconfigure the static route in R0.Change ECMP value to 2.")
dut = "r0"
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
index 2da1dcd21a..c5230d6614 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_ecmp_lan.py
@@ -307,9 +307,10 @@ def test_ospf_lan_ecmp_tc18_p0(request):
result = verify_ospf_rib(
tgen, dut, input_dict, next_hop=nh, attempts=5, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
protocol = "ospf"
result = verify_rib(
@@ -322,9 +323,10 @@ def test_ospf_lan_ecmp_tc18_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
index dac32090bc..2fbb27f4fc 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_lan.py
@@ -397,9 +397,10 @@ def test_ospf_lan_tc1_p0(request):
shutdown_bringup_interface(tgen, dut, intf, False)
result = verify_ospf_neighbor(tgen, topo, dut, lan=True, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r0: OSPF neighbors-hip is up \n Error: {}".format(
tc_name, result
- )
+ ))
step("No Shut interface on R0")
dut = "r0"
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py b/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py
index c90275ecb0..be18ba5a78 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_p2mp.py
@@ -146,7 +146,6 @@ def setup_module(mod):
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
logger.info("Running setup_module() done")
@@ -397,10 +396,7 @@ def test_ospf_p2mp_tc1_p0(request):
"links": {
"r3": {
"interface": topo["routers"]["r0"]["links"]["r3"]["interface"],
- "ospf": {
- "area": "0.0.0.0",
- "networkType":"POINTOMULTIPOINT"
- },
+ "ospf": {"area": "0.0.0.0", "networkType": "POINTOMULTIPOINT"},
}
}
}
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
index ceadb3975b..b99ce6cfb8 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_routemaps.py
@@ -332,16 +332,18 @@ def test_ospf_routemaps_functionality_tc19_p0(request):
}
}
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are present in fib \n Error: {}".format(
tc_name, result
- )
+ ))
step("Delete and reconfigure prefix list.")
# Create ip prefix list
@@ -381,16 +383,18 @@ def test_ospf_routemaps_functionality_tc19_p0(request):
}
}
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
pfx_list = {
"r0": {
@@ -434,16 +438,18 @@ def test_ospf_routemaps_functionality_tc19_p0(request):
}
}
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
@@ -490,16 +496,18 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, attempts=2, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, attempts=2, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step(
"configure the route map with the same name that is used "
@@ -515,16 +523,18 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
# Create route map
routemaps = {"r0": {"route_maps": {"rmap_ipv4": [{"action": "deny"}]}}}
@@ -535,16 +545,18 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
step("Delete the route map.")
# Create route map
@@ -561,16 +573,18 @@ def test_ospf_routemaps_functionality_tc20_p0(request):
dut = "r1"
protocol = "ospf"
result = verify_ospf_rib(tgen, dut, input_dict, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present \n Error: {}".format(
tc_name, result
- )
+ ))
result = verify_rib(
tgen, "ipv4", dut, input_dict, protocol=protocol, expected=False
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: routes are still present \n Error: {}".format(
tc_name, result
- )
+ ))
write_test_footer(tc_name)
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 5aa2779aee..fb6b28ce5b 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
@@ -247,9 +247,11 @@ def test_ospf_redistribution_tc5_p0(request):
if result is not True:
break
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present after deleting ip address of newly "
+ "configured interface of R0 \n Error: {}".format(
tc_name, result
- )
+ ))
protocol = "ospf"
result = verify_rib(
@@ -262,9 +264,11 @@ def test_ospf_redistribution_tc5_p0(request):
attempts=5,
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present in fib after deleting ip address of newly "
+ "configured interface of R0 \n Error: {}".format(
tc_name, result
- )
+ ))
step("Add back the deleted ip address on newly configured interface of R0")
topo1 = {
@@ -366,9 +370,11 @@ def test_ospf_redistribution_tc6_p0(request):
result = verify_ospf_rib(tgen, dut, input_dict, next_hop=nh, expected=False)
if result is not True:
break
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present after deleting ip address of newly "
+ "configured loopback of R0 \n Error: {}".format(
tc_name, result
- )
+ ))
protocol = "ospf"
result = verify_rib(
@@ -380,9 +386,11 @@ def test_ospf_redistribution_tc6_p0(request):
next_hop=nh,
expected=False,
)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ assert result is not True, ("Testcase {} : Failed \n "
+ "r1: OSPF routes are present in fib after deleting ip address of newly "
+ "configured loopback of R0 \n Error: {}".format(
tc_name, result
- )
+ ))
step("Add back the deleted ip address on newly configured interface of R0")
topo1 = {
diff --git a/tests/topotests/pbr-topo1/test_pbr_topo1.py b/tests/topotests/pbr-topo1/test_pbr_topo1.py
index 5161d5eec7..1a024063b8 100644
--- a/tests/topotests/pbr-topo1/test_pbr_topo1.py
+++ b/tests/topotests/pbr-topo1/test_pbr_topo1.py
@@ -49,6 +49,8 @@ from lib.common_config import shutdown_bringup_interface
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.pbrd]
+
#####################################################
##
## Network Topology Definition
@@ -80,7 +82,7 @@ class NetworkTopo(Topo):
##
#####################################################
-@pytest.mark.pbr
+
def setup_module(module):
"Setup topology"
tgen = Topogen(NetworkTopo, module.__name__)
diff --git a/tests/topotests/pim-basic/test_pim.py b/tests/topotests/pim-basic/test_pim.py
index 224b82f1fb..4debbeb851 100644
--- a/tests/topotests/pim-basic/test_pim.py
+++ b/tests/topotests/pim-basic/test_pim.py
@@ -43,6 +43,8 @@ from lib.topolog import logger
from mininet.topo import Topo
+pytestmark = [pytest.mark.pimd]
+
class PIMTopo(Topo):
def build(self, *_args, **_opts):
diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini
index 0c45a09445..562e754f21 100644
--- a/tests/topotests/pytest.ini
+++ b/tests/topotests/pytest.ini
@@ -24,6 +24,7 @@ markers =
sharpd: Tests that run against SHARPD
staticd: Tests that run against STATICD
vrrpd: Tests that run against VRRPD
+ snmp: Tests that run against snmp changes
[topogen]
# Default configuration values
diff --git a/tests/topotests/rip-topo1/test_rip_topo1.py b/tests/topotests/rip-topo1/test_rip_topo1.py
index edad1ff65d..78672ac871 100644
--- a/tests/topotests/rip-topo1/test_rip_topo1.py
+++ b/tests/topotests/rip-topo1/test_rip_topo1.py
@@ -47,6 +47,7 @@ from lib import topotest
fatal_error = ""
+pytestmark = [pytest.mark.ripd]
#####################################################
##
@@ -104,7 +105,7 @@ class NetworkTopo(Topo):
##
#####################################################
-@pytest.mark.rip
+
def setup_module(module):
global topo, net
diff --git a/tests/topotests/ripng-topo1/test_ripng_topo1.py b/tests/topotests/ripng-topo1/test_ripng_topo1.py
index 47b63e5b26..4a5a59cd75 100644
--- a/tests/topotests/ripng-topo1/test_ripng_topo1.py
+++ b/tests/topotests/ripng-topo1/test_ripng_topo1.py
@@ -48,6 +48,7 @@ from lib import topotest
fatal_error = ""
+pytestmark = [pytest.mark.ripd]
#####################################################
##
@@ -104,7 +105,7 @@ class NetworkTopo(Topo):
##
#####################################################
-@pytest.mark.rip
+
def setup_module(module):
global topo, net
diff --git a/tests/topotests/simple-snmp-test/test_simple_snmp.py b/tests/topotests/simple-snmp-test/test_simple_snmp.py
index 88ff01bf0a..5647e2b663 100755
--- a/tests/topotests/simple-snmp-test/test_simple_snmp.py
+++ b/tests/topotests/simple-snmp-test/test_simple_snmp.py
@@ -46,6 +46,8 @@ from lib.snmptest import SnmpTester
# Required to instantiate the topology builder class.
from mininet.topo import Topo
+pytestmark = [pytest.mark.bgpd, pytest.mark.isisd, pytest.mark.snmp]
+
class TemplateTopo(Topo):
"Test topology builder"
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py
index a33257de65..a4cc8e8e7a 100644
--- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py
+++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo1_ebgp.py
@@ -35,6 +35,7 @@ import time
import os
import pytest
import platform
+
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -44,6 +45,7 @@ sys.path.append(os.path.join(CWD, "../lib/"))
from mininet.topo import Topo
from lib.topogen import Topogen, get_topogen
from lib.topotest import version_cmp
+
# Import topoJson from lib, to create topology and initial configuration
from lib.common_config import (
start_topology,
@@ -63,6 +65,8 @@ from lib.topolog import logger
from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
from lib.topojson import build_topo_from_json, build_config_from_json
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/static_routes_topo1_ebgp.json".format(CWD)
try:
@@ -119,9 +123,11 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, topo)
- if version_cmp(platform.release(), '4.19') < 0:
- error_msg = ('These tests will not run. (have kernel "{}", '
- 'requires kernel >= 4.19)'.format(platform.release()))
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ 'These tests will not run. (have kernel "{}", '
+ "requires kernel >= 4.19)".format(platform.release())
+ )
pytest.skip(error_msg)
# Checking BGP convergence
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py
index 93320df327..6649915dec 100644
--- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py
+++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo2_ebgp.py
@@ -73,6 +73,8 @@ from lib.topolog import logger
from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
from lib.topojson import build_topo_from_json, build_config_from_json
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/static_routes_topo2_ebgp.json".format(CWD)
try:
@@ -161,9 +163,11 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, topo)
- if version_cmp(platform.release(), '4.19') < 0:
- error_msg = ('These tests will not run. (have kernel "{}", '
- 'requires kernel >= 4.19)'.format(platform.release()))
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ 'These tests will not run. (have kernel "{}", '
+ "requires kernel >= 4.19)".format(platform.release())
+ )
pytest.skip(error_msg)
# Checking BGP convergence
@@ -852,12 +856,12 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ebgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
-
write_test_footer(tc_name)
@@ -1127,9 +1131,10 @@ def test_static_route_8nh_diff_AD_ebgp_ecmp_p1_tc8_ebgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
write_test_footer(tc_name)
@@ -1337,7 +1342,15 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ebgp(request):
" value and all the nexthop populated in RIB and FIB again"
)
for addr_type in ADDR_TYPES:
- input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+ input_dict_4 = {
+ "r2": {
+ "static_routes": [
+ {
+ "network": PREFIX1[addr_type],
+ }
+ ]
+ }
+ }
nh = NEXT_HOP_IP["nh1"][addr_type]
result = verify_rib(
tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
@@ -1466,9 +1479,10 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ebgp(request):
protocol=protocol,
fib=True,
)
- assert result is True, (
- "Testcase {} : Failed \nError: Route "
- " is missing in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \nError: Route " " is missing in RIB".format(
+ tc_name
)
write_test_footer(tc_name)
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py
index 255bb073b4..175a1123d7 100644
--- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py
+++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo3_ebgp.py
@@ -68,6 +68,8 @@ from lib.topolog import logger
from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
from lib.topojson import build_topo_from_json, build_config_from_json
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/static_routes_topo3_ebgp.json".format(CWD)
try:
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 75657a8895..dc4e29ebde 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
@@ -86,6 +86,8 @@ 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]
+
class CreateTopo(Topo):
"""
@@ -125,9 +127,11 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, topo)
- if version_cmp(platform.release(), '4.19') < 0:
- error_msg = ('These tests will not run. (have kernel "{}", '
- 'requires kernel >= 4.19)'.format(platform.release()))
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ 'These tests will not run. (have kernel "{}", '
+ "requires kernel >= 4.19)".format(platform.release())
+ )
pytest.skip(error_msg)
# Checking BGP convergence
@@ -945,9 +949,10 @@ def static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
result4 = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert result4 is not True, "Testcase {} : Failed \n" "Error: {}".format(
+ assert result4 is not True, ("Testcase {} : Failed \n"
+ "routes are still present \n Error: {}".format(
tc_name, result4
- )
+ ))
step("vm4 should be present in FRR1")
dut = "r1"
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py
index 130f4fd9aa..8c2fdfca13 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo1_ibgp.py
@@ -66,6 +66,8 @@ from lib.topolog import logger
from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
from lib.topojson import build_topo_from_json, build_config_from_json
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/static_routes_topo1_ibgp.json".format(CWD)
try:
@@ -123,9 +125,11 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, topo)
- if version_cmp(platform.release(), '4.19') < 0:
- error_msg = ('These tests will not run. (have kernel "{}", '
- 'requires kernel >= 4.19)'.format(platform.release()))
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ 'These tests will not run. (have kernel "{}", '
+ "requires kernel >= 4.19)".format(platform.release())
+ )
pytest.skip(error_msg)
# Checking BGP convergence
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py
index 0a757c9f28..644ddc02d4 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo2_ibgp.py
@@ -75,6 +75,8 @@ from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
from lib.topojson import build_topo_from_json, build_config_from_json
from lib.topotest import version_cmp
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/static_routes_topo2_ibgp.json".format(CWD)
try:
@@ -163,9 +165,11 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, topo)
- if version_cmp(platform.release(), '4.19') < 0:
- error_msg = ('These tests will not run. (have kernel "{}", '
- 'requires kernel >= 4.19)'.format(platform.release()))
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ 'These tests will not run. (have kernel "{}", '
+ "requires kernel >= 4.19)".format(platform.release())
+ )
pytest.skip(error_msg)
# Checking BGP convergence
@@ -882,9 +886,10 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
step("BGP neighbor remove and add")
@@ -905,9 +910,10 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
dut = "r3"
@@ -915,9 +921,10 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc6_ibgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
step("Remove the redistribute static knob")
@@ -1272,9 +1279,10 @@ def test_static_route_8nh_diff_AD_ibgp_ecmp_p1_tc7_ibgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
step("BGP neighbor remove and add")
@@ -1295,9 +1303,10 @@ def test_static_route_8nh_diff_AD_ibgp_ecmp_p1_tc7_ibgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
dut = "r3"
@@ -1305,9 +1314,10 @@ def test_static_route_8nh_diff_AD_ibgp_ecmp_p1_tc7_ibgp(request):
for addr_type in ADDR_TYPES:
input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type]}]}}
result = verify_rib(tgen, addr_type, dut, input_dict_4, protocol=protocol)
- assert result is True, (
- "Testcase {} : Failed \n"
- "Error: Routes are still present in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n" "Error: Routes are still present in RIB".format(
+ tc_name
)
step("Remove the redistribute static knob")
@@ -1555,7 +1565,15 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ibgp(request):
" value and all the nexthop populated in RIB and FIB again"
)
for addr_type in ADDR_TYPES:
- input_dict_4 = {"r2": {"static_routes": [{"network": PREFIX1[addr_type],}]}}
+ input_dict_4 = {
+ "r2": {
+ "static_routes": [
+ {
+ "network": PREFIX1[addr_type],
+ }
+ ]
+ }
+ }
nh = NEXT_HOP_IP["nh1"][addr_type]
result = verify_rib(
tgen, addr_type, dut, input_dict_4, next_hop=nh, protocol=protocol, fib=True
@@ -1684,9 +1702,10 @@ def test_static_route_8nh_diff_AD_bgp_ecmp_p1_tc10_ibgp(request):
protocol=protocol,
fib=True,
)
- assert result is True, (
- "Testcase {} : Failed \nError: Route "
- " is missing in RIB".format(tc_name)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \nError: Route " " is missing in RIB".format(
+ tc_name
)
step("Remove the redistribute static knob")
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py
index 924fb3a598..8f9d88a442 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo3_ibgp.py
@@ -69,6 +69,8 @@ from lib.topolog import logger
from lib.bgp import verify_bgp_convergence, create_router_bgp, verify_bgp_rib
from lib.topojson import build_topo_from_json, build_config_from_json
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/static_routes_topo3_ibgp.json".format(CWD)
try:
@@ -147,9 +149,11 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, topo)
- if version_cmp(platform.release(), '4.19') < 0:
- error_msg = ('These tests will not run. (have kernel "{}", '
- 'requires kernel >= 4.19)'.format(platform.release()))
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ 'These tests will not run. (have kernel "{}", '
+ "requires kernel >= 4.19)".format(platform.release())
+ )
pytest.skip(error_msg)
# Checking BGP convergence
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 fdbfad25b3..14db729195 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
@@ -69,6 +69,7 @@ from lib.bgp import (
)
from lib.topojson import build_topo_from_json, build_config_from_json
from lib.topotest import version_cmp
+
# Reading the data from JSON File for topology creation
jsonFile = "{}/static_routes_topo4_ibgp.json".format(CWD)
try:
@@ -83,6 +84,8 @@ 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]
+
class CreateTopo(Topo):
"""
@@ -122,9 +125,11 @@ def setup_module(mod):
# Creating configuration from JSON
build_config_from_json(tgen, topo)
- if version_cmp(platform.release(), '4.19') < 0:
- error_msg = ('These tests will not run. (have kernel "{}", '
- 'requires kernel >= 4.19)'.format(platform.release()))
+ if version_cmp(platform.release(), "4.19") < 0:
+ error_msg = (
+ 'These tests will not run. (have kernel "{}", '
+ "requires kernel >= 4.19)".format(platform.release())
+ )
pytest.skip(error_msg)
# Checking BGP convergence
@@ -942,9 +947,10 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
result4 = verify_rib(
tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
)
- assert result4 is not True, "Testcase {} : Failed \n" "Error: {}".format(
+ assert result4 is not True, ("Testcase {} : Failed \n"
+ "routes are still present \n Error: {}".format(
tc_name, result4
- )
+ ))
step("vm4 should be present in FRR1")
dut = "r1"
diff --git a/tests/topotests/zebra_rib/test_zebra_rib.py b/tests/topotests/zebra_rib/test_zebra_rib.py
index daf8f7be20..9fcf7b6820 100644
--- a/tests/topotests/zebra_rib/test_zebra_rib.py
+++ b/tests/topotests/zebra_rib/test_zebra_rib.py
@@ -76,9 +76,11 @@ def setup_module(mod):
router_list = tgen.routers()
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_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname)))
+ TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
+ )
# Initialize all routers.
tgen.start_router()
@@ -159,6 +161,7 @@ def test_zebra_kernel_override():
_, result = topotest.run_and_expect(test_func, None, count=2, wait=0.5)
assert result is None, '"r1" JSON output mismatches'
+
def test_route_map_usage():
"Test that FRR only reruns over routes associated with the routemap"
logger.info("Test that FRR runs on selected re's on route-map changes")
@@ -174,7 +177,9 @@ def test_route_map_usage():
r1.vtysh_cmd("conf\nroute-map static permit 10\nset src 192.168.215.1")
r1.vtysh_cmd("conf\naccess-list 5 seq 5 permit 10.0.0.44/32")
r1.vtysh_cmd("conf\naccess-list 10 seq 5 permit 10.0.1.0/24")
- r1.vtysh_cmd("conf\nroute-map sharp permit 10\nmatch ip address 10\nset src 192.168.214.1")
+ r1.vtysh_cmd(
+ "conf\nroute-map sharp permit 10\nmatch ip address 10\nset src 192.168.214.1"
+ )
r1.vtysh_cmd("conf\nroute-map sharp permit 20\nset src 192.168.213.1")
r1.vtysh_cmd("conf\nip protocol static route-map static")
r1.vtysh_cmd("conf\nip protocol sharp route-map sharp")
@@ -186,47 +191,57 @@ def test_route_map_usage():
static_rmapfile = "%s/r1/static_rmap.ref" % (thisDir)
expected = open(static_rmapfile).read().rstrip()
- expected = ('\n'.join(expected.splitlines()) + '\n').rstrip()
+ expected = ("\n".join(expected.splitlines()) + "\n").rstrip()
actual = r1.vtysh_cmd("show route-map static")
- actual = ('\n'.join(actual.splitlines()) + '\n').rstrip()
- logger.info("Does the show route-map static command run the correct number of times")
+ actual = ("\n".join(actual.splitlines()) + "\n").rstrip()
+ logger.info(
+ "Does the show route-map static command run the correct number of times"
+ )
- diff = topotest.get_textdiff(actual, expected,
- title1 = "Actual Route-map output",
- title2 = "Expected Route-map output")
+ diff = topotest.get_textdiff(
+ actual,
+ expected,
+ title1="Actual Route-map output",
+ title2="Expected Route-map output",
+ )
if diff:
logger.info("Actual:")
logger.info(actual)
logger.info("Expected:")
logger.info(expected)
srun = r1.vtysh_cmd("show run")
- srun = ('\n'.join(srun.splitlines()) + '\n').rstrip()
+ srun = ("\n".join(srun.splitlines()) + "\n").rstrip()
logger.info("Show run")
logger.info(srun)
assert 0, "r1 static route processing:\n"
sharp_rmapfile = "%s/r1/sharp_rmap.ref" % (thisDir)
expected = open(sharp_rmapfile).read().rstrip()
- expected = ('\n'.join(expected.splitlines()) + '\n').rstrip()
+ expected = ("\n".join(expected.splitlines()) + "\n").rstrip()
actual = r1.vtysh_cmd("show route-map sharp")
- actual = ('\n'.join(actual.splitlines()) + '\n').rstrip()
+ actual = ("\n".join(actual.splitlines()) + "\n").rstrip()
logger.info("Does the show route-map sharp command run the correct number of times")
- diff = topotest.get_textdiff(actual, expected,
- title1 = "Actual Route-map output",
- title2 = "Expected Route-map output")
+ diff = topotest.get_textdiff(
+ actual,
+ expected,
+ title1="Actual Route-map output",
+ title2="Expected Route-map output",
+ )
if diff:
logger.info("Actual:")
logger.info(actual)
logger.info("Expected:")
logger.info(expected)
srun = r1.vtysh_cmd("show run")
- srun = ('\n'.join(srun.splitlines()) + '\n').rstrip()
+ srun = ("\n".join(srun.splitlines()) + "\n").rstrip()
logger.info("Show run:")
logger.info(srun)
assert 0, "r1 sharp route-map processing:\n"
- logger.info("Add a extension to the static route-map to see the static route go away")
+ logger.info(
+ "Add a extension to the static route-map to see the static route go away"
+ )
r1.vtysh_cmd("conf\nroute-map sharp deny 5\nmatch ip address 5")
sleep(2)
# we are only checking the kernel here as that this will give us the implied
@@ -236,9 +251,9 @@ def test_route_map_usage():
logger.info("Test that the routes installed are correct")
sharp_ipfile = "%s/r1/iproute.ref" % (thisDir)
expected = open(sharp_ipfile).read().rstrip()
- expected = ('\n'.join(expected.splitlines()) + '\n').rstrip()
+ expected = ("\n".join(expected.splitlines()) + "\n").rstrip()
actual = r1.run("ip route show")
- actual = ('\n'.join(actual.splitlines()) + '\n').rstrip()
+ actual = ("\n".join(actual.splitlines()) + "\n").rstrip()
actual = re.sub(r" nhid [0-9][0-9]", "", actual)
actual = re.sub(r" proto sharp", " proto XXXX", actual)
actual = re.sub(r" proto static", " proto XXXX", actual)
@@ -250,9 +265,9 @@ def test_route_map_usage():
actual = re.sub(r" proto XXXX ", " proto XXXX ", actual)
actual = re.sub(r" metric", " metric", actual)
actual = re.sub(r" link ", " link ", actual)
- diff = topotest.get_textdiff(actual, expected,
- title1 = "Actual ip route show",
- title2 = "Expected ip route show")
+ diff = topotest.get_textdiff(
+ actual, expected, title1="Actual ip route show", title2="Expected ip route show"
+ )
if diff:
logger.info("Actual:")
@@ -260,11 +275,12 @@ def test_route_map_usage():
logger.info("Expected:")
logger.info(expected)
srun = r1.vtysh_cmd("show run")
- srun = ('\n'.join(srun.splitlines()) + '\n').rstrip()
+ srun = ("\n".join(srun.splitlines()) + "\n").rstrip()
logger.info("Show run:")
logger.info(srun)
assert 0, "r1 ip route show is not correct:"
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index b98c001e7d..1461e0f296 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -97,7 +97,7 @@ class Vtysh(object):
args = ["-c", command]
return self._call(args, stdin, stdout, stderr)
- def __call__(self, command):
+ def __call__(self, command, stdouts=None):
"""
Call a CLI command (e.g. "show running-config")
@@ -107,6 +107,8 @@ class Vtysh(object):
proc = self._call_cmd(command, stdout=subprocess.PIPE)
stdout, stderr = proc.communicate()
if proc.wait() != 0:
+ if stdouts is not None:
+ stdouts.append(stdout.decode('UTF-8'))
raise VtyshException(
'vtysh returned status %d for command "%s"' % (proc.returncode, command)
)
@@ -2006,9 +2008,10 @@ if __name__ == "__main__":
# frr(config-if)# no ip ospf authentication
# frr(config-if)#
+ stdouts = []
while True:
try:
- vtysh(["configure"] + cmd)
+ vtysh(["configure"] + cmd, stdouts)
except VtyshException:
@@ -2024,6 +2027,10 @@ if __name__ == "__main__":
'"%s" we failed to remove this command',
" -- ".join(original_cmd),
)
+ # Log first error msg for original_cmd
+ if stdouts:
+ log.error(stdouts[0])
+ reload_ok = False
break
new_last_arg = last_arg[0:-1]
diff --git a/tools/nhrpd-event-handler.sh b/tools/nhrpd-event-handler.sh
new file mode 100755
index 0000000000..5dce43fe84
--- /dev/null
+++ b/tools/nhrpd-event-handler.sh
@@ -0,0 +1,216 @@
+#!/bin/bash
+
+# Author: Joe Maimon
+# Released to public domain
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; see the file COPYING; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+#
+
+PROGNAME=`basename $0`
+VERSION="0.0.6"
+#api fields
+EV_ID="eventid"
+EV_TYPE="type"
+EV_OTYPE="old_type"
+EV_NUMNHS="num_nhs"
+EV_INT="interface"
+EV_LADDR="local_address"
+EV_VCINIT="vc_initiated"
+EV_LNBMA="local_nbma"
+EV_LCERT="local_cert"
+EV_RADDR="remote_addr"
+EV_RNBMA="remote_nbma"
+EV_RCERT="remote_cert"
+
+usage()
+{
+ echo "Usage: $PROGNAME [-s nhrp-sock] [-d] [-i interface-name] [-t table] [-e execute-cmd] [-u user] [-g group] [-r] [-l logfile]"
+ echo ""
+ echo "-s nhrp-sock file"
+ echo "-i interface-name to execute on, may be repeated multiple times"
+ echo "-t tableid to execute on for immdiate preceeding interface"
+ echo "-e execute command for immmediate preceeding interface"
+ echo " The command will be passed the following arguments $EV_ID $EV_TYPE $EV_INT $EV_LNMBA $EV_RADDR $EV_RNBMA int_table"
+ echo "-u user to own the sock"
+ echo "-g group to own the sock"
+ echo "-r send rejection (testing)"
+ echo "-l logfile to record conversation with nhrpd"
+ echo "-d daemonize"
+
+ exit 1
+}
+
+declare -A EXECARR
+declare -A TABLEARR
+declare -Ag NHRPEVENT
+SOCK="/var/run/frr/nhrp.sock"
+USER="frr"
+GROUP="frr"
+DAEMON=0
+j=0
+RESULT="accept"
+
+while getopts rds:i:u:g:l:t:e: opt; do
+ case "$opt" in
+ d)
+ DAEMON=1
+ ;;
+ s)
+ SOCK="$OPTARG"
+ ;;
+ i)
+ INTARR[((j++))]="$OPTARG"
+ ;;
+ e)
+ if [[ "$j" == "0" ]] || [[ "${INTARR[((j-1))]}" == "" ]]; then
+ echo "execute argument must follow interface argument"
+ usage
+ fi
+ EXECARR["${INTARR[((j-1))]}"]="$OPTARG"
+ ;;
+ t)
+ if [[ "$j" == "0" ]] || [[ "${INTARR[((j-1))]}" == "" ]]; then
+ echo "execute argument must follow interface argument"
+ usage
+ fi
+ TABLEARR["${INTARR[((j-1))]}"]="$OPTARG"
+ ;;
+ u)
+ USER="$OPTARG"
+ ;;
+ g)
+ GROUP="$OPTARG"
+ ;;
+ r)
+ RESULT="reject"
+ ;;
+ l)
+ EVLOGFILE="${OPTARG}"
+ ;;
+ esac;
+done
+
+if [[ "$EVLOGFILE" != "" ]]; then
+ if [[ ! -w "${EVLOGFILE}" ]]; then
+ touch "$EVLOGFILE" || ( echo "Cannot write to logfile $EVLOGFILE" ; usage )
+ fi
+ echo -e "PROG: $0 Startup\nPROG: Arguments $*" >> $EVLOGFILE
+fi
+
+
+function mainloop()
+{
+
+if [[ "$EVLOGFILE" != "" ]]; then
+ echo -e "PROG: `date -R`\nPROG: Starting mainloop" >> $EVLOGFILE
+fi
+
+coproc socat - UNIX-LISTEN:$SOCK,unlink-early,setuid-early=$USER,unlink-close=0 || exit 1
+test -S $SOCK && chown $USER:$GROUP $SOCK
+
+OLDIFS="$IFS"
+
+TABLE="table "
+
+while read -r S; do
+ if [[ "$EVLOGFILE" != "" ]]; then
+ echo "IN: $S" >> $EVLOGFILE
+ fi
+ if [[ "$S" == "" ]]; then
+ if [[ "${NHRPEVENT[$EV_ID]}" != "" ]]; then
+ OUTMSG="eventid=${NHRPEVENT[$EV_ID]}\nresult=$RESULT\n"
+ echo -e "$OUTMSG" >&"${COPROC[1]}"
+ if [[ "$EVLOGFILE" != "" ]]; then
+ echo -e "OUT:\n${OUTMSG}" >> $EVLOGFILE;
+ fi
+ fi
+
+
+ for((i=0;i<${#INTARR[@]};i++)); do
+ if [[ "${NHRPEVENT[$EV_INT]}" == "" ]]; then break; fi
+ if [[ "${INTARR[$i]}" != "${NHRPEVENT[$EV_INT]}" ]]; then continue; fi
+ EVINT="${NHRPEVENT[$EV_INT]}"
+ if [[ "${NHRPEVENT[$EV_RADDR]}" == "" ]]; then break; fi
+ if [[ "${NHRPEVENT[$EV_RNBMA]}" == "" ]]; then break; fi
+ if [[ "${NHRPEVENT[$EV_TYPE]}" != "dynamic" ]]; then break; fi
+
+ INTEXEC=${EXECARR["$EVINT"]}
+ INTABLE=${TABLEARR["$EVINT"]}
+
+ unset CMD
+ unset CMDEND
+ CMDADD="ip neigh add "
+ CMDREPL="ip neigh replace"
+ CMDBEG="$CMDADD"
+ if [[ "$INTEXEC" != "" ]]; then
+ CMD="$INTEXEC ${NHRPEVENT[$EV_ID]:-nil}"
+ CMD="$CMD ${NHRPEVENT[$EV_TYPE]:-nil}"
+ CMD="$CMD ${NHRPEVENT[$EV_INT]:-nil}"
+ CMD="$CMD ${NHRPEVENT[$EV_LNBMA]:-nil}"
+ CMD="$CMD ${NHRPEVENT[$EV_RADDR]:-nil}"
+ CMD="$CMD ${NHRPEVENT[$EV_RNBMA]:-nil}"
+ CMD="$CMD ${INTABLE:-nil}"
+ unset CMDBEG
+ else
+ CMDTAB="${INTABLE:+${TABLE}${INTABLE}}"
+ CMDEND="$CMDEND ${NHRPEVENT[$EV_RADDR]} dev $EVINT lladdr ${NHRPEVENT[$EV_RNBMA]} nud noarp"
+ CMD="$CMDEND"
+ fi
+ unset CMDTAB
+ for ((k=0;k<2;k++)); do
+ for ((l=0;l<2;l++)); do
+ if [[ "$EVLOGFILE" != "" ]]; then
+ echo "PROG: Executing $CMD" >> $EVLOGFILE
+ CMDOUT=`$CMDBEG $CMD $CMDTAB 2>&1`
+ CMDRET="$?"
+ if [[ "$CMDOUT" != "" ]]; then
+ echo "PROG: Execution output: $CMDOUT" >> $EVLOGFILE
+ fi
+ else
+ $CMDBEG $CMD $CMDTAB
+ fi
+ if [[ "$CMDTAB" == "" ]] || [[ "$INTEXEC" != "" ]]; then break; fi
+ done
+ if [[ "$INTEXEC" != "" ]] || [[ "$CMDRET" == "0" ]]; then
+ break
+ fi
+ CMDBEG="$CMDREPL"
+ done
+ break
+ done
+
+ unset NHRPEVENT
+ declare -Ag NHRPEVENT
+ continue
+ continue;
+ fi
+ IFS="${IFS}="
+ SA=($S)
+ IFS="$OLDIFS"
+ eval NHRPEVENT[${SA[0]}]="\"${SA[1]}\""
+
+done <&"${COPROC[0]}"
+
+if [[ "$COPROC_PID" != "" ]]; then kill "$COPROC_PID"; fi
+
+}
+
+while true; do
+ mainloop $*
+ if [[ "$DAEMON" == "0" ]]; then
+ break;
+ fi
+ sleep 10
+done
diff --git a/vtysh/extract.pl.in b/vtysh/extract.pl.in
index 53067c43f4..81c9770e55 100755
--- a/vtysh/extract.pl.in
+++ b/vtysh/extract.pl.in
@@ -107,7 +107,7 @@ sub scan_file {
$protocol = "VTYSH_ALL";
}
elsif ($file =~ /lib\/agentx\.c$/) {
- $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA";
+ $protocol = "VTYSH_ISISD|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA";
}
elsif ($file =~ /lib\/nexthop_group\.c$/) {
$protocol = "VTYSH_NH_GROUP";
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index e026a28628..6e809a0713 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -2693,7 +2693,7 @@ static int show_per_daemon(struct vty *vty, struct cmd_token **argv, int argc,
char *line = do_prepend(vty, argv, argc);
for (i = 0; i < array_size(vtysh_client); i++)
- if (vtysh_client[i].fd >= 0) {
+ if (vtysh_client[i].fd >= 0 || vtysh_client[i].next) {
vty_out(vty, headline, vtysh_client[i].name);
ret = vtysh_client_execute(&vtysh_client[i], line);
vty_out(vty, "\n");
@@ -2851,6 +2851,24 @@ DEFUN (vtysh_show_error_code,
}
/* Northbound. */
+DEFUN (show_config_running,
+ show_config_running_cmd,
+ "show configuration running\
+ [<json|xml> [translate WORD]]\
+ [with-defaults]" DAEMONS_LIST,
+ SHOW_STR
+ "Configuration information\n"
+ "Running configuration\n"
+ "Change output format to JSON\n"
+ "Change output format to XML\n"
+ "Translate output\n"
+ "YANG module translator\n"
+ "Show default values\n"
+ DAEMONS_STR)
+{
+ return show_one_daemon(vty, argv, argc - 1, argv[argc - 1]->text);
+}
+
DEFUN (show_yang_operational_data,
show_yang_operational_data_cmd,
"show yang operational-data XPATH\
@@ -4564,6 +4582,7 @@ void vtysh_init_vty(void)
install_element(CONFIG_NODE, &vtysh_debug_memstats_cmd);
/* northbound */
+ install_element(ENABLE_NODE, &show_config_running_cmd);
install_element(ENABLE_NODE, &show_yang_operational_data_cmd);
install_element(ENABLE_NODE, &debug_nb_cmd);
install_element(CONFIG_NODE, &debug_nb_cmd);
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index 441320b193..5f4d564507 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -316,7 +316,7 @@ static pid_t run_background(char *shell_cmd)
/* Use separate process group so child processes can be killed
* easily. */
if (setpgid(0, 0) < 0)
- zlog_warn("warning: setpgid(0,0) failed: %s",
+ zlog_warn("setpgid(0,0) failed: %s",
safe_strerror(errno));
{
char shell[] = "sh";
@@ -356,7 +356,7 @@ static int restart_kill(struct thread *t_kill)
time_elapsed(&delay, &restart->time);
zlog_warn(
- "Warning: %s %s child process %d still running after %ld seconds, sending signal %d",
+ "%s %s child process %d still running after %ld seconds, sending signal %d",
restart->what, restart->name, (int)restart->pid,
(long)delay.tv_sec, (restart->kills ? SIGKILL : SIGTERM));
kill(-restart->pid, (restart->kills ? SIGKILL : SIGTERM));
@@ -423,7 +423,7 @@ static void sigchild(void)
what = "background";
}
if (WIFSTOPPED(status))
- zlog_warn("warning: %s %s process %d is stopped", what, name,
+ zlog_warn("%s %s process %d is stopped", what, name,
(int)child);
else if (WIFSIGNALED(status))
zlog_warn("%s %s process %d terminated due to signal %d", what,
diff --git a/yang/frr-bfdd.yang b/yang/frr-bfdd.yang
index 5b434162d0..0f090a1b72 100644
--- a/yang/frr-bfdd.yang
+++ b/yang/frr-bfdd.yang
@@ -185,7 +185,7 @@ module frr-bfdd {
leaf administrative-down {
type boolean;
- default true;
+ default false;
description "Disables or enables the session administratively";
}
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 8757ab6b8b..7c820c9611 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -60,6 +60,11 @@ module frr-isisd {
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.";
+ revision 2021-02-15 {
+ description
+ "Group SRGB and SRLB in a container so that they can be displayed
+ and configured together";
+ }
revision 2020-04-06 {
description
"Group LSP timers in a container so that they can be displayed and
@@ -1491,38 +1496,42 @@ module frr-isisd {
description
"Enables segment-routing protocol extensions.";
}
- container srgb {
- description
- "Global blocks to be advertised.";
- must "./upper-bound > ./lower-bound";
- leaf lower-bound {
- type uint32;
- default "16000";
- description
- "Lower value in the label range.";
- }
- leaf upper-bound {
- type uint32;
- default "23999";
- description
- "Upper value in the label range.";
- }
- }
- container srlb {
+ container label-blocks {
description
- "Local blocks to be advertised.";
- must "./upper-bound > ./lower-bound";
- leaf lower-bound {
- type uint32;
- default "15000";
- description
- "Lower value in the label range.";
+ "Local and global label blocks.";
+ container srgb {
+ description
+ "Global blocks to be advertised.";
+ must "./upper-bound > ./lower-bound";
+ leaf lower-bound {
+ type uint32;
+ default "16000";
+ description
+ "Lower value in the label range.";
+ }
+ leaf upper-bound {
+ type uint32;
+ default "23999";
+ description
+ "Upper value in the label range.";
+ }
}
- leaf upper-bound {
- type uint32;
- default "15999";
- description
- "Upper value in the label range.";
+ container srlb {
+ description
+ "Local blocks to be advertised.";
+ must "./upper-bound > ./lower-bound";
+ leaf lower-bound {
+ type uint32;
+ default "15000";
+ description
+ "Lower value in the label range.";
+ }
+ leaf upper-bound {
+ type uint32;
+ default "15999";
+ description
+ "Upper value in the label range.";
+ }
}
}
container msd {
diff --git a/zebra/connected.c b/zebra/connected.c
index c885c533e6..dd8fab5e4e 100644
--- a/zebra/connected.c
+++ b/zebra/connected.c
@@ -321,11 +321,11 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
if (IPV4_ADDR_SAME(addr, dest))
flog_warn(
EC_ZEBRA_IFACE_SAME_LOCAL_AS_PEER,
- "warning: interface %s has same local and peer address %pI4, routing protocols may malfunction",
+ "interface %s has same local and peer address %pI4, routing protocols may malfunction",
ifp->name, addr);
} else {
zlog_debug(
- "warning: %s called for interface %s with peer flag set, but no peer address supplied",
+ "%s called for interface %s with peer flag set, but no peer address supplied",
__func__, ifp->name);
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
}
@@ -335,7 +335,7 @@ void connected_add_ipv4(struct interface *ifp, int flags, struct in_addr *addr,
if (!dest && (prefixlen == IPV4_MAX_PREFIXLEN)
&& if_is_pointopoint(ifp))
zlog_debug(
- "warning: PtP interface %s with addr %pI4/%d needs a peer address",
+ "PtP interface %s with addr %pI4/%d needs a peer address",
ifp->name, addr, prefixlen);
/* Label of this address. */
@@ -503,7 +503,7 @@ void connected_add_ipv6(struct interface *ifp, int flags, struct in6_addr *addr,
} else {
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_PEER)) {
zlog_debug(
- "warning: %s called for interface %s with peer flag set, but no peer address supplied",
+ "%s called for interface %s with peer flag set, but no peer address supplied",
__func__, ifp->name);
UNSET_FLAG(ifc->flags, ZEBRA_IFA_PEER);
}
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 00471b9645..98bde4b3c0 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -561,6 +561,8 @@ static void netlink_interface_update_l2info(struct interface *ifp,
netlink_extract_vlan_info(link_data, &vlan_info);
zebra_l2_vlanif_update(ifp, &vlan_info);
+ zebra_evpn_acc_bd_svi_set(ifp->info, NULL,
+ !!if_is_operative(ifp));
} else if (IS_ZEBRA_IF_VXLAN(ifp)) {
struct zebra_l2info_vxlan vxlan_info;
@@ -717,6 +719,21 @@ static void netlink_proc_dplane_if_protodown(struct zebra_if *zif,
}
}
+static uint8_t netlink_parse_lacp_bypass(struct rtattr **linkinfo)
+{
+ uint8_t bypass = 0;
+ struct rtattr *mbrinfo[IFLA_BOND_SLAVE_MAX + 1];
+
+ memset(mbrinfo, 0, sizeof(mbrinfo));
+ parse_rtattr_nested(mbrinfo, IFLA_BOND_SLAVE_MAX,
+ linkinfo[IFLA_INFO_SLAVE_DATA]);
+ if (mbrinfo[IFLA_BOND_SLAVE_AD_RX_BYPASS])
+ bypass = *(uint8_t *)RTA_DATA(
+ mbrinfo[IFLA_BOND_SLAVE_AD_RX_BYPASS]);
+
+ return bypass;
+}
+
/*
* Called from interface_lookup_netlink(). This function is only used
* during bootstrap.
@@ -741,6 +758,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifindex_t bond_ifindex = IFINDEX_INTERNAL;
struct zebra_if *zif;
ns_id_t link_nsid = ns_id;
+ uint8_t bypass = 0;
zns = zebra_ns_lookup(ns_id);
ifi = NLMSG_DATA(h);
@@ -814,6 +832,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
} else if (slave_kind && (strcmp(slave_kind, "bond") == 0)) {
zif_slave_type = ZEBRA_IF_SLAVE_BOND;
bond_ifindex = *(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ bypass = netlink_parse_lacp_bypass(linkinfo);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
@@ -880,7 +899,7 @@ static int netlink_interface(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp))
zebra_l2if_update_bridge_slave(ifp, bridge_ifindex, ns_id);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
- zebra_l2if_update_bond_slave(ifp, bond_ifindex);
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex, !!bypass);
if (tb[IFLA_PROTO_DOWN]) {
uint8_t protodown;
@@ -1320,6 +1339,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
struct zebra_if *zif;
ns_id_t link_nsid = ns_id;
ifindex_t master_infindex = IFINDEX_INTERNAL;
+ uint8_t bypass = 0;
zns = zebra_ns_lookup(ns_id);
ifi = NLMSG_DATA(h);
@@ -1421,6 +1441,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
zif_slave_type = ZEBRA_IF_SLAVE_BOND;
master_infindex = bond_ifindex =
*(ifindex_t *)RTA_DATA(tb[IFLA_MASTER]);
+ bypass = netlink_parse_lacp_bypass(linkinfo);
} else
zif_slave_type = ZEBRA_IF_SLAVE_OTHER;
}
@@ -1482,7 +1503,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
bridge_ifindex,
ns_id);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
- zebra_l2if_update_bond_slave(ifp, bond_ifindex);
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex,
+ !!bypass);
if (tb[IFLA_PROTO_DOWN]) {
uint8_t protodown;
@@ -1595,7 +1617,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
bridge_ifindex,
ns_id);
else if (IS_ZEBRA_IF_BOND_SLAVE(ifp) || was_bond_slave)
- zebra_l2if_update_bond_slave(ifp, bond_ifindex);
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex,
+ !!bypass);
if (tb[IFLA_PROTO_DOWN]) {
uint8_t protodown;
@@ -1631,6 +1654,8 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_IF_BOND(ifp))
zebra_l2if_update_bond(ifp, false);
+ if (IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ zebra_l2if_update_bond_slave(ifp, bond_ifindex, false);
/* Special handling for bridge or VxLAN interfaces. */
if (IS_ZEBRA_IF_BRIDGE(ifp))
zebra_l2_bridge_del(ifp);
diff --git a/zebra/interface.c b/zebra/interface.c
index fc34a6fb9e..6373b4b200 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -241,6 +241,7 @@ static int if_zebra_delete_hook(struct interface *ifp)
#endif /* HAVE_RTADV */
zebra_evpn_if_cleanup(zebra_if);
+ zebra_evpn_mac_ifp_del(ifp);
if_nhg_dependents_release(ifp);
zebra_if_nhg_dependents_free(zebra_if);
@@ -826,6 +827,7 @@ void if_delete_update(struct interface *ifp)
memset(&zif->brslave_info, 0,
sizeof(struct zebra_l2info_brslave));
zebra_evpn_if_cleanup(zif);
+ zebra_evpn_mac_ifp_del(ifp);
}
if (!ifp->configured) {
@@ -1183,6 +1185,11 @@ void zebra_if_update_all_links(void)
zif->link?zif->link->name:"unk",
zif->link_ifindex);
}
+
+ /* Update VLAN<=>SVI map */
+ if (IS_ZEBRA_IF_VLAN(ifp))
+ zebra_evpn_acc_bd_svi_set(zif, NULL,
+ !!if_is_operative(ifp));
}
}
@@ -1599,6 +1606,9 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
}
}
+ if (zebra_if->flags & ZIF_FLAG_LACP_BYPASS)
+ vty_out(vty, " LACP bypass: on\n");
+
zebra_evpn_if_es_print(vty, zebra_if);
vty_out(vty, " protodown: %s %s\n",
(zebra_if->flags & ZIF_FLAG_PROTODOWN) ? "on" : "off",
diff --git a/zebra/interface.h b/zebra/interface.h
index 8dcb477f10..64569742b4 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -286,6 +286,9 @@ struct zebra_es_if_info {
esi_t esi;
uint16_t df_pref;
+ uint8_t flags;
+#define ZIF_CFG_ES_FLAG_BYPASS (1 << 0)
+
struct zebra_evpn_es *es; /* local ES */
};
@@ -297,7 +300,13 @@ enum zebra_if_flags {
ZIF_FLAG_EVPN_MH_UPLINK_OPER_UP = (1 << 1),
/* Dataplane protodown-on */
- ZIF_FLAG_PROTODOWN = (1 << 2)
+ ZIF_FLAG_PROTODOWN = (1 << 2),
+
+ /* LACP bypass state is set by the dataplane on a bond member
+ * and inherited by the bond (if one or more bond members are in
+ * a bypass state the bond is placed in a bypass state)
+ */
+ ZIF_FLAG_LACP_BYPASS = (1 << 3)
};
/* `zebra' daemon local interface structure. */
@@ -386,6 +395,9 @@ struct zebra_if {
*/
enum protodown_reasons protodown_rc;
+ /* list of zebra_mac entries using this interface as destination */
+ struct list *mac_list;
+
/* Link fields - for sub-interfaces. */
ifindex_t link_ifindex;
struct interface *link;
diff --git a/zebra/irdp_interface.c b/zebra/irdp_interface.c
index 2ab5fd3a4c..5352c6214d 100644
--- a/zebra/irdp_interface.c
+++ b/zebra/irdp_interface.c
@@ -93,10 +93,10 @@ static int irdp_if_delete(struct interface *ifp)
return 0;
}
-static const char *inet_2a(uint32_t a, char *b)
+static const char *inet_2a(uint32_t a, char *b, size_t b_len)
{
- sprintf(b, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF, (a >> 16) & 0xFF,
- (a >> 24) & 0xFF);
+ snprintf(b, b_len, "%u.%u.%u.%u", (a)&0xFF, (a >> 8) & 0xFF,
+ (a >> 16) & 0xFF, (a >> 24) & 0xFF);
return b;
}
@@ -140,7 +140,8 @@ static int if_group(struct interface *ifp, int sock, uint32_t group,
flog_err_sys(EC_LIB_SOCKET, "IRDP: %s can't setsockopt %s: %s",
add_leave == IP_ADD_MEMBERSHIP ? "join group"
: "leave group",
- inet_2a(group, b1), safe_strerror(errno));
+ inet_2a(group, b1, sizeof(b1)),
+ safe_strerror(errno));
return ret;
}
@@ -162,7 +163,8 @@ static int if_add_group(struct interface *ifp)
if (irdp->flags & IF_DEBUG_MISC)
zlog_debug("IRDP: Adding group %s for %s",
- inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name);
+ inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1, sizeof(b1)),
+ ifp->name);
return 0;
}
@@ -183,7 +185,8 @@ static int if_drop_group(struct interface *ifp)
if (irdp->flags & IF_DEBUG_MISC)
zlog_debug("IRDP: Leaving group %s for %s",
- inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1), ifp->name);
+ inet_2a(htonl(INADDR_ALLRTRS_GROUP), b1, sizeof(b1)),
+ ifp->name);
return 0;
}
@@ -383,7 +386,8 @@ int irdp_config_write(struct vty *vty, struct interface *ifp)
for (ALL_LIST_ELEMENTS_RO(irdp->AdvPrefList, node, adv))
vty_out(vty, " ip irdp address %s preference %d\n",
- inet_2a(adv->ip.s_addr, b1), adv->pref);
+ inet_2a(adv->ip.s_addr, b1, sizeof(b1)),
+ adv->pref);
vty_out(vty, " ip irdp holdtime %d\n", irdp->Lifetime);
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index c77a357e9f..aa19b18089 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -1350,6 +1350,14 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_BR_PORT_UPDATE:
return FRR_NETLINK_SUCCESS;
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
+ return FRR_NETLINK_ERROR;
+
case DPLANE_OP_NONE:
return FRR_NETLINK_ERROR;
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index b0f124ed55..ac60d09ecc 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -542,7 +542,7 @@ void zebra_interface_address_add_update(struct interface *ifp,
if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_REAL))
flog_warn(
EC_ZEBRA_ADVERTISING_UNUSABLE_ADDR,
- "WARNING: advertising address to clients that is not yet usable.");
+ "advertising address to clients that is not yet usable.");
zebra_vxlan_add_del_gw_macip(ifp, ifc->address, 1);
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 602805be3c..fdeef2c88c 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1132,8 +1132,8 @@ static int build_label_stack(struct mpls_label_stack *nh_label,
if (IS_ZEBRA_DEBUG_KERNEL) {
if (!num_labels)
- sprintf(label_buf, "label %u",
- nh_label->label[i]);
+ snprintf(label_buf, label_buf_size, "label %u",
+ nh_label->label[i]);
else {
snprintf(label_buf1, sizeof(label_buf1), "/%u",
nh_label->label[i]);
@@ -1767,6 +1767,33 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
nl_attr_nest_end(&req->n, nest);
}
+ /*
+ * Always install blackhole routes without using nexthops, because of
+ * the following kernel problems:
+ * 1. Kernel nexthops don't suport unreachable/prohibit route types.
+ * 2. Blackhole kernel nexthops are deleted when loopback is down.
+ */
+ nexthop = dplane_ctx_get_ng(ctx)->nexthop;
+ if (nexthop) {
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ nexthop = nexthop->resolved;
+
+ if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
+ switch (nexthop->bh_type) {
+ case BLACKHOLE_ADMINPROHIB:
+ req->r.rtm_type = RTN_PROHIBIT;
+ break;
+ case BLACKHOLE_REJECT:
+ req->r.rtm_type = RTN_UNREACHABLE;
+ break;
+ default:
+ req->r.rtm_type = RTN_BLACKHOLE;
+ break;
+ }
+ return NLMSG_ALIGN(req->n.nlmsg_len);
+ }
+ }
+
if ((!fpm && kernel_nexthops_supported()
&& (!proto_nexthops_only()
|| is_proto_nhg(dplane_ctx_get_nhe_id(ctx), 0)))
@@ -1820,27 +1847,6 @@ ssize_t netlink_route_multipath_msg_encode(int cmd,
if (nexthop_num == 1) {
nexthop_num = 0;
for (ALL_NEXTHOPS_PTR(dplane_ctx_get_ng(ctx), nexthop)) {
- /*
- * So we want to cover 2 types of blackhole
- * routes here:
- * 1) A normal blackhole route( ala from a static
- * install.
- * 2) A recursively resolved blackhole route
- */
- if (nexthop->type == NEXTHOP_TYPE_BLACKHOLE) {
- switch (nexthop->bh_type) {
- case BLACKHOLE_ADMINPROHIB:
- req->r.rtm_type = RTN_PROHIBIT;
- break;
- case BLACKHOLE_REJECT:
- req->r.rtm_type = RTN_UNREACHABLE;
- break;
- default:
- req->r.rtm_type = RTN_BLACKHOLE;
- break;
- }
- return NLMSG_ALIGN(req->n.nlmsg_len);
- }
if (CHECK_FLAG(nexthop->flags,
NEXTHOP_FLAG_RECURSIVE)) {
@@ -2833,7 +2839,6 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
vlanid_t vid = 0;
struct in_addr vtep_ip;
int vid_present = 0, dst_present = 0;
- char buf[ETHER_ADDR_STRLEN];
char vid_buf[20];
char dst_buf[30];
bool sticky;
@@ -2912,11 +2917,10 @@ static int netlink_macfdb_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
}
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %s%s nhg %d",
+ zlog_debug("Rx %s AF_BRIDGE IF %u%s st 0x%x fl 0x%x MAC %pEA%s nhg %d",
nl_msg_type_to_str(h->nlmsg_type),
ndm->ndm_ifindex, vid_present ? vid_buf : "",
- ndm->ndm_state, ndm->ndm_flags,
- prefix_mac2str(&mac, buf, sizeof(buf)),
+ ndm->ndm_state, ndm->ndm_flags, &mac,
dst_present ? dst_buf : "", nhg_id);
/* The interface should exist. */
@@ -3117,7 +3121,6 @@ static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
char buf[256];
} req;
struct zebra_if *br_zif;
- char buf[ETHER_ADDR_STRLEN];
memset(&req, 0, sizeof(req));
req.n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ndmsg));
@@ -3136,11 +3139,10 @@ static int netlink_request_specific_mac_in_bridge(struct zebra_ns *zns,
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "%s: Tx family %s IF %s(%u) vrf %s(%u) MAC %s vid %u",
+ "%s: Tx family %s IF %s(%u) vrf %s(%u) MAC %pEA vid %u",
__func__, nl_family_to_str(req.ndm.ndm_family),
br_if->name, br_if->ifindex,
- vrf_id_to_name(br_if->vrf_id), br_if->vrf_id,
- prefix_mac2str(mac, buf, sizeof(buf)), vid);
+ vrf_id_to_name(br_if->vrf_id), br_if->vrf_id, mac, vid);
return netlink_request(&zns->netlink_cmd, &req);
}
@@ -3225,8 +3227,6 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
SET_IPADDR_V4(&vtep_ip);
if (IS_ZEBRA_DEBUG_KERNEL) {
- char ipbuf[PREFIX_STRLEN];
- char buf[ETHER_ADDR_STRLEN];
char vid_buf[20];
const struct ethaddr *mac = dplane_ctx_mac_get_addr(ctx);
@@ -3237,12 +3237,11 @@ ssize_t netlink_macfdb_update_ctx(struct zebra_dplane_ctx *ctx, void *data,
vid_buf[0] = '\0';
zlog_debug(
- "Tx %s family %s IF %s(%u)%s %sMAC %s dst %s nhg %u%s%s%s%s%s",
+ "Tx %s family %s IF %s(%u)%s %sMAC %pEA dst %pIA nhg %u%s%s%s%s%s",
nl_msg_type_to_str(cmd), nl_family_to_str(AF_BRIDGE),
dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx),
vid_buf, dplane_ctx_mac_is_sticky(ctx) ? "sticky " : "",
- prefix_mac2str(mac, buf, sizeof(buf)),
- ipaddr2str(&vtep_ip, ipbuf, sizeof(ipbuf)), nhg_id,
+ mac, &vtep_ip, nhg_id,
(update_flags & DPLANE_MAC_REMOTE) ? " rem" : "",
(update_flags & DPLANE_MAC_WAS_STATIC) ? " clr_sync"
: "",
@@ -3303,7 +3302,6 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
struct ipaddr ip;
struct vrf *vrf;
char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
int mac_present = 0;
bool is_ext;
bool is_router;
@@ -3409,11 +3407,11 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "Rx %s family %s IF %s(%u) vrf %s(%u) IP %s MAC %s state 0x%x flags 0x%x ext_flags 0x%x",
+ "Rx %s family %s IF %s(%u) vrf %s(%u) IP %pIA MAC %s state 0x%x flags 0x%x ext_flags 0x%x",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
- ipaddr2str(&ip, buf2, sizeof(buf2)),
+ &ip,
mac_present
? prefix_mac2str(&mac, buf, sizeof(buf))
: "",
@@ -3445,11 +3443,11 @@ static int netlink_ipneigh_change(struct nlmsghdr *h, int len, ns_id_t ns_id)
}
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("Rx %s family %s IF %s(%u) vrf %s(%u) IP %s",
+ zlog_debug("Rx %s family %s IF %s(%u) vrf %s(%u) IP %pIA",
nl_msg_type_to_str(h->nlmsg_type),
nl_family_to_str(ndm->ndm_family), ifp->name,
ndm->ndm_ifindex, VRF_LOGNAME(vrf), ifp->vrf_id,
- ipaddr2str(&ip, buf2, sizeof(buf2)));
+ &ip);
/* Process the delete - it may result in re-adding the neighbor if it is
* a valid "remote" neighbor.
@@ -3576,14 +3574,11 @@ static int netlink_request_specific_neigh_in_vlan(struct zebra_ns *zns,
nl_attr_put(&req.n, sizeof(req), NDA_DST, &ip->ip.addr, ipa_len);
- if (IS_ZEBRA_DEBUG_KERNEL) {
- char buf[INET6_ADDRSTRLEN];
-
- zlog_debug("%s: Tx %s family %s IF %u IP %s flags 0x%x",
+ if (IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s: Tx %s family %s IF %u IP %pIA flags 0x%x",
__func__, nl_msg_type_to_str(type),
- nl_family_to_str(req.ndm.ndm_family), ifindex,
- ipaddr2str(ip, buf, sizeof(buf)), req.n.nlmsg_flags);
- }
+ nl_family_to_str(req.ndm.ndm_family), ifindex, ip,
+ req.n.nlmsg_flags);
return netlink_request(&zns->netlink_cmd, &req);
}
@@ -3594,7 +3589,6 @@ int netlink_neigh_read_specific_ip(struct ipaddr *ip,
int ret = 0;
struct zebra_ns *zns;
struct zebra_vrf *zvrf = zebra_vrf_lookup_by_id(vlan_if->vrf_id);
- char buf[INET6_ADDRSTRLEN];
struct zebra_dplane_info dp_info;
zns = zvrf->zns;
@@ -3602,9 +3596,8 @@ int netlink_neigh_read_specific_ip(struct ipaddr *ip,
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
if (IS_ZEBRA_DEBUG_KERNEL)
- zlog_debug("%s: neigh request IF %s(%u) IP %s vrf %s(%u)",
- __func__, vlan_if->name, vlan_if->ifindex,
- ipaddr2str(ip, buf, sizeof(buf)),
+ zlog_debug("%s: neigh request IF %s(%u) IP %pIA vrf %s(%u)",
+ __func__, vlan_if->name, vlan_if->ifindex, ip,
vrf_id_to_name(vlan_if->vrf_id), vlan_if->vrf_id);
ret = netlink_request_specific_neigh_in_vlan(zns, RTM_GETNEIGH, ip,
@@ -3695,27 +3688,13 @@ static ssize_t netlink_neigh_update_ctx(const struct zebra_dplane_ctx *ctx,
/* local neigh */
if (update_flags & DPLANE_NEIGH_SET_STATIC)
ext_flags |= NTF_E_MH_PEER_SYNC;
-
- /* the ndm_state set for local entries can be REACHABLE or
- * STALE. if the dataplane has already establish reachability
- * (in the meantime) FRR must not over-write it with STALE.
- * this accidental race/over-write is avoided by using the
- * WEAK_OVERRIDE_STATE
- */
- ext_flags |= NTF_E_WEAK_OVERRIDE_STATE;
}
- if (IS_ZEBRA_DEBUG_KERNEL) {
- char buf[INET6_ADDRSTRLEN];
- char buf2[ETHER_ADDR_STRLEN];
-
+ if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
- "Tx %s family %s IF %s(%u) Neigh %s MAC %s flags 0x%x state 0x%x %sext_flags 0x%x",
+ "Tx %s family %s IF %s(%u) Neigh %pIA MAC %pEA flags 0x%x state 0x%x %sext_flags 0x%x",
nl_msg_type_to_str(cmd), nl_family_to_str(family),
dplane_ctx_get_ifname(ctx), dplane_ctx_get_ifindex(ctx),
- ipaddr2str(ip, buf, sizeof(buf)),
- mac ? prefix_mac2str(mac, buf2, sizeof(buf2)) : "null",
- flags, state, ext ? "ext " : "", ext_flags);
- }
+ ip, mac, flags, state, ext ? "ext " : "", ext_flags);
return netlink_neigh_update_msg_encode(
ctx, cmd, mac, ip, true, family, RTN_UNICAST, flags, state,
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 46171df848..9f5adfa409 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -866,18 +866,24 @@ void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
zserv_send_message(client, s);
}
-void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
- enum zapi_ipset_notify_owner note)
+void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
+ uint16_t note)
{
struct listnode *node;
struct zserv *client;
struct stream *s;
+ struct zebra_pbr_iptable ipt;
+ uint16_t cmd = ZEBRA_IPTABLE_NOTIFY_OWNER;
+
+ if (!dplane_ctx_get_pbr_iptable(ctx, &ipt))
+ return;
if (IS_ZEBRA_DEBUG_PACKET)
- zlog_debug("%s: Notifying %u", __func__, ipset->unique);
+ zlog_debug("%s: Notifying %s id %u note %u", __func__,
+ zserv_command_string(cmd), ipt.unique, note);
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
- if (ipset->sock == client->sock)
+ if (ipt.sock == client->sock)
break;
}
@@ -886,27 +892,32 @@ void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, ZEBRA_IPSET_NOTIFY_OWNER, VRF_DEFAULT);
+ zclient_create_header(s, cmd, VRF_DEFAULT);
stream_put(s, &note, sizeof(note));
- stream_putl(s, ipset->unique);
- stream_put(s, ipset->ipset_name, ZEBRA_IPSET_NAME_SIZE);
+ stream_putl(s, ipt.unique);
+ stream_put(s, ipt.ipset_name, ZEBRA_IPSET_NAME_SIZE);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
}
-void zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset,
- enum zapi_ipset_entry_notify_owner note)
+void zsend_ipset_notify_owner(const struct zebra_dplane_ctx *ctx, uint16_t note)
{
struct listnode *node;
struct zserv *client;
struct stream *s;
+ struct zebra_pbr_ipset ipset;
+ uint16_t cmd = ZEBRA_IPSET_NOTIFY_OWNER;
+
+ if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
+ return;
if (IS_ZEBRA_DEBUG_PACKET)
- zlog_debug("%s: Notifying %u", __func__, ipset->unique);
+ zlog_debug("%s: Notifying %s id %u note %u", __func__,
+ zserv_command_string(cmd), ipset.unique, note);
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
- if (ipset->sock == client->sock)
+ if (ipset.sock == client->sock)
break;
}
@@ -915,27 +926,36 @@ void zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset,
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, ZEBRA_IPSET_ENTRY_NOTIFY_OWNER, VRF_DEFAULT);
+ zclient_create_header(s, cmd, VRF_DEFAULT);
stream_put(s, &note, sizeof(note));
- stream_putl(s, ipset->unique);
- stream_put(s, ipset->backpointer->ipset_name, ZEBRA_IPSET_NAME_SIZE);
+ stream_putl(s, ipset.unique);
+ stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
}
-void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
- enum zapi_iptable_notify_owner note)
+void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
+ uint16_t note)
{
struct listnode *node;
struct zserv *client;
struct stream *s;
+ struct zebra_pbr_ipset_entry ipent;
+ struct zebra_pbr_ipset ipset;
+ uint16_t cmd = ZEBRA_IPSET_ENTRY_NOTIFY_OWNER;
+
+ if (!dplane_ctx_get_pbr_ipset_entry(ctx, &ipent))
+ return;
+ if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
+ return;
if (IS_ZEBRA_DEBUG_PACKET)
- zlog_debug("%s: Notifying %u", __func__, iptable->unique);
+ zlog_debug("%s: Notifying %s id %u note %u", __func__,
+ zserv_command_string(cmd), ipent.unique, note);
for (ALL_LIST_ELEMENTS_RO(zrouter.client_list, node, client)) {
- if (iptable->sock == client->sock)
+ if (ipent.sock == client->sock)
break;
}
@@ -944,9 +964,10 @@ void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
s = stream_new(ZEBRA_MAX_PACKET_SIZ);
- zclient_create_header(s, ZEBRA_IPTABLE_NOTIFY_OWNER, VRF_DEFAULT);
+ zclient_create_header(s, cmd, VRF_DEFAULT);
stream_put(s, &note, sizeof(note));
- stream_putl(s, iptable->unique);
+ stream_putl(s, ipent.unique);
+ stream_put(s, ipset.ipset_name, ZEBRA_IPSET_NAME_SIZE);
stream_putw_at(s, 0, stream_get_endp(s));
zserv_send_message(client, s);
diff --git a/zebra/zapi_msg.h b/zebra/zapi_msg.h
index c03278669a..023b9f74a8 100644
--- a/zebra/zapi_msg.h
+++ b/zebra/zapi_msg.h
@@ -84,13 +84,13 @@ extern int zsend_route_notify_owner_ctx(const struct zebra_dplane_ctx *ctx,
extern void zsend_rule_notify_owner(const struct zebra_dplane_ctx *ctx,
enum zapi_rule_notify_owner note);
-extern void zsend_ipset_notify_owner(struct zebra_pbr_ipset *ipset,
- enum zapi_ipset_notify_owner note);
-extern void
-zsend_ipset_entry_notify_owner(struct zebra_pbr_ipset_entry *ipset,
- enum zapi_ipset_entry_notify_owner note);
-extern void zsend_iptable_notify_owner(struct zebra_pbr_iptable *iptable,
- enum zapi_iptable_notify_owner note);
+
+extern void zsend_iptable_notify_owner(const struct zebra_dplane_ctx *ctx,
+ uint16_t note);
+extern void zsend_ipset_notify_owner(const struct zebra_dplane_ctx *ctx,
+ uint16_t note);
+extern void zsend_ipset_entry_notify_owner(const struct zebra_dplane_ctx *ctx,
+ uint16_t note);
extern bool zserv_nexthop_num_warn(const char *caller, const struct prefix *p,
const unsigned int nexthop_num);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index db2b9e002e..4e63d08aca 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -42,6 +42,7 @@
DEFINE_MTYPE_STATIC(ZEBRA, DP_CTX, "Zebra DPlane Ctx")
DEFINE_MTYPE_STATIC(ZEBRA, DP_INTF, "Zebra DPlane Intf")
DEFINE_MTYPE_STATIC(ZEBRA, DP_PROV, "Zebra DPlane Provider")
+DEFINE_MTYPE_STATIC(ZEBRA, DP_NETFILTER, "Zebra Netfilter Internal Object")
#ifndef AOK
# define AOK 0
@@ -307,6 +308,12 @@ struct zebra_dplane_ctx {
struct dplane_mac_info macinfo;
struct dplane_neigh_info neigh;
struct dplane_rule_info rule;
+ struct zebra_pbr_iptable iptable;
+ struct zebra_pbr_ipset ipset;
+ union {
+ struct zebra_pbr_ipset_entry entry;
+ struct zebra_pbr_ipset_info info;
+ } ipset_entry;
} u;
/* Namespace info, used especially for netlink kernel communication */
@@ -438,6 +445,14 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_update_yields;
+ _Atomic uint32_t dg_iptable_in;
+ _Atomic uint32_t dg_iptable_errors;
+
+ _Atomic uint32_t dg_ipset_in;
+ _Atomic uint32_t dg_ipset_errors;
+ _Atomic uint32_t dg_ipset_entry_in;
+ _Atomic uint32_t dg_ipset_entry_errors;
+
/* Dataplane pthread */
struct frr_pthread *dg_pthread;
@@ -656,7 +671,29 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_NEIGH_DISCOVER:
case DPLANE_OP_BR_PORT_UPDATE:
case DPLANE_OP_NONE:
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ break;
+
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
break;
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ if (ctx->u.iptable.interface_name_list) {
+ struct listnode *node, *nnode;
+ char *ifname;
+
+ for (ALL_LIST_ELEMENTS(
+ ctx->u.iptable.interface_name_list, node,
+ nnode, ifname)) {
+ LISTNODE_DETACH(
+ ctx->u.iptable.interface_name_list,
+ node);
+ XFREE(MTYPE_DP_NETFILTER, ifname);
+ }
+ list_delete(&ctx->u.iptable.interface_name_list);
+ }
}
}
@@ -895,6 +932,25 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_NEIGH_DISCOVER:
ret = "NEIGH_DISCOVER";
break;
+
+ case DPLANE_OP_IPTABLE_ADD:
+ ret = "IPTABLE_ADD";
+ break;
+ case DPLANE_OP_IPTABLE_DELETE:
+ ret = "IPTABLE_DELETE";
+ break;
+ case DPLANE_OP_IPSET_ADD:
+ ret = "IPSET_ADD";
+ break;
+ case DPLANE_OP_IPSET_DELETE:
+ ret = "IPSET_DELETE";
+ break;
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ ret = "IPSET_ENTRY_ADD";
+ break;
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
+ ret = "IPSET_ENTRY_DELETE";
+ break;
}
return ret;
@@ -1843,6 +1899,46 @@ dplane_ctx_get_br_port_backup_nhg_id(const struct zebra_dplane_ctx *ctx)
return ctx->u.br_port.backup_nhg_id;
}
+/* Accessors for PBR iptable information */
+bool
+dplane_ctx_get_pbr_iptable(const struct zebra_dplane_ctx *ctx,
+ struct zebra_pbr_iptable *table)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ memcpy(table, &ctx->u.iptable, sizeof(struct zebra_pbr_iptable));
+ return true;
+}
+
+bool dplane_ctx_get_pbr_ipset(const struct zebra_dplane_ctx *ctx,
+ struct zebra_pbr_ipset *ipset)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ if (!ipset)
+ return false;
+ if (ctx->zd_op == DPLANE_OP_IPSET_ENTRY_ADD ||
+ ctx->zd_op == DPLANE_OP_IPSET_ENTRY_DELETE) {
+ memset(ipset, 0, sizeof(struct zebra_pbr_ipset));
+ ipset->type = ctx->u.ipset_entry.info.type;
+ memcpy(&ipset->ipset_name, &ctx->u.ipset_entry.info.ipset_name,
+ ZEBRA_IPSET_NAME_SIZE);
+ } else
+ memcpy(ipset, &ctx->u.ipset, sizeof(struct zebra_pbr_ipset));
+ return true;
+}
+
+bool dplane_ctx_get_pbr_ipset_entry(const struct zebra_dplane_ctx *ctx,
+ struct zebra_pbr_ipset_entry *entry)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ if (!entry)
+ return false;
+ memcpy(entry, &ctx->u.ipset_entry.entry, sizeof(struct zebra_pbr_ipset_entry));
+ return true;
+}
+
/*
* End of dplane context accessors
*/
@@ -2398,6 +2494,126 @@ static int dplane_ctx_rule_init(struct zebra_dplane_ctx *ctx,
return AOK;
}
+/**
+ * dplane_ctx_iptable_init() - Initialize a context block for a PBR iptable
+ * update.
+ *
+ * @ctx: Dataplane context to init
+ * @op: Operation being performed
+ * @new_rule: PBR iptable
+ *
+ * Return: Result status
+ */
+static int dplane_ctx_iptable_init(struct zebra_dplane_ctx *ctx,
+ enum dplane_op_e op,
+ struct zebra_pbr_iptable *iptable)
+{
+ char *ifname;
+ struct listnode *node;
+
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ zlog_debug(
+ "init dplane ctx %s: Unique %u Fwmark %u Family %s Action %s",
+ dplane_op2str(op), iptable->unique, iptable->fwmark,
+ family2str(iptable->family),
+ iptable->action == ZEBRA_IPTABLES_DROP ? "Drop"
+ : "Forward");
+ }
+
+ ctx->zd_op = op;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+ dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false);
+ ctx->zd_is_update = false;
+
+ ctx->zd_vrf_id = iptable->vrf_id;
+ memcpy(&ctx->u.iptable, iptable, sizeof(struct zebra_pbr_iptable));
+ ctx->u.iptable.interface_name_list = NULL;
+ if (iptable->nb_interface > 0) {
+ ctx->u.iptable.interface_name_list = list_new();
+ for (ALL_LIST_ELEMENTS_RO(iptable->interface_name_list, node,
+ ifname)) {
+ listnode_add(ctx->u.iptable.interface_name_list,
+ XSTRDUP(MTYPE_DP_NETFILTER, ifname));
+ }
+ }
+ return AOK;
+}
+
+/**
+ * dplane_ctx_ipset_init() - Initialize a context block for a PBR ipset update.
+ *
+ * @ctx: Dataplane context to init
+ * @op: Operation being performed
+ * @new_rule: PBR ipset
+ *
+ * Return: Result status
+ */
+static int dplane_ctx_ipset_init(struct zebra_dplane_ctx *ctx,
+ enum dplane_op_e op,
+ struct zebra_pbr_ipset *ipset)
+{
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ zlog_debug("init dplane ctx %s: %s Unique %u Family %s Type %s",
+ dplane_op2str(op), ipset->ipset_name, ipset->unique,
+ family2str(ipset->family),
+ zebra_pbr_ipset_type2str(ipset->type));
+ }
+
+ ctx->zd_op = op;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+ dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false);
+ ctx->zd_is_update = false;
+
+ ctx->zd_vrf_id = ipset->vrf_id;
+
+ memcpy(&ctx->u.ipset, ipset, sizeof(struct zebra_pbr_ipset));
+ return AOK;
+}
+
+/**
+ * dplane_ctx_ipset_entry_init() - Initialize a context block for a PBR ipset
+ * update.
+ *
+ * @ctx: Dataplane context to init
+ * @op: Operation being performed
+ * @new_rule: PBR ipset
+ *
+ * Return: Result status
+ */
+static int
+dplane_ctx_ipset_entry_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
+ struct zebra_pbr_ipset_entry *ipset_entry)
+{
+ struct zebra_pbr_ipset *ipset;
+
+ ipset = ipset_entry->backpointer;
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+ zlog_debug("init dplane ctx %s: %s Unique %u filter %u",
+ dplane_op2str(op), ipset->ipset_name,
+ ipset_entry->unique, ipset_entry->filter_bm);
+ }
+
+ ctx->zd_op = op;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+ dplane_ctx_ns_init(ctx, zebra_ns_lookup(NS_DEFAULT), false);
+ ctx->zd_is_update = false;
+
+ ctx->zd_vrf_id = ipset->vrf_id;
+
+ memcpy(&ctx->u.ipset_entry.entry, ipset_entry,
+ sizeof(struct zebra_pbr_ipset_entry));
+ ctx->u.ipset_entry.entry.backpointer = NULL;
+ ctx->u.ipset_entry.info.type = ipset->type;
+ memcpy(&ctx->u.ipset_entry.info.ipset_name, &ipset->ipset_name,
+ ZEBRA_IPSET_NAME_SIZE);
+
+ return AOK;
+}
+
+
/*
* Enqueue a new update,
* and ensure an event is active for the dataplane pthread.
@@ -3251,6 +3467,24 @@ enum zebra_dplane_result dplane_local_mac_add(const struct interface *ifp,
}
/*
+ * Enqueue local mac del
+ */
+enum zebra_dplane_result
+dplane_local_mac_del(const struct interface *ifp,
+ const struct interface *bridge_ifp, vlanid_t vid,
+ const struct ethaddr *mac)
+{
+ enum zebra_dplane_result result;
+ struct in_addr vtep_ip;
+
+ vtep_ip.s_addr = 0;
+
+ /* Use common helper api */
+ result = mac_update_common(DPLANE_OP_MAC_DELETE, ifp, bridge_ifp, vid,
+ mac, vtep_ip, false, 0, 0);
+ return result;
+}
+/*
* Public api to init an empty context - either newly-allocated or
* reset/cleared - for a MAC update.
*/
@@ -3305,15 +3539,9 @@ mac_update_common(enum dplane_op_e op,
int ret;
struct zebra_dplane_ctx *ctx = NULL;
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
-
- zlog_debug("init mac ctx %s: mac %s, ifp %s, vtep %s",
- dplane_op2str(op),
- prefix_mac2str(mac, buf1, sizeof(buf1)),
- ifp->name,
- inet_ntop(AF_INET, &vtep_ip, buf2, sizeof(buf2)));
- }
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("init mac ctx %s: mac %pEA, ifp %s, vtep %pI4",
+ dplane_op2str(op), mac, ifp->name, &vtep_ip);
ctx = dplane_ctx_alloc();
ctx->zd_op = op;
@@ -3491,14 +3719,9 @@ neigh_update_internal(enum dplane_op_e op,
struct zebra_dplane_ctx *ctx = NULL;
struct zebra_ns *zns;
- if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
- char buf1[ETHER_ADDR_STRLEN], buf2[PREFIX_STRLEN];
-
- zlog_debug("init neigh ctx %s: ifp %s, mac %s, ip %s",
- dplane_op2str(op), ifp->name,
- prefix_mac2str(mac, buf1, sizeof(buf1)),
- ipaddr2str(ip, buf2, sizeof(buf2)));
- }
+ if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
+ zlog_debug("init neigh ctx %s: ifp %s, mac %pEA, ip %pIA",
+ dplane_op2str(op), ifp->name, mac, ip);
ctx = dplane_ctx_alloc();
@@ -3590,6 +3813,139 @@ enum zebra_dplane_result dplane_pbr_rule_update(struct zebra_pbr_rule *old_rule,
{
return rule_update_internal(DPLANE_OP_RULE_UPDATE, new_rule, old_rule);
}
+/*
+ * Common helper api for iptable updates
+ */
+static enum zebra_dplane_result
+iptable_update_internal(enum dplane_op_e op, struct zebra_pbr_iptable *iptable)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ struct zebra_dplane_ctx *ctx;
+ int ret;
+
+ ctx = dplane_ctx_alloc();
+
+ ret = dplane_ctx_iptable_init(ctx, op, iptable);
+ if (ret != AOK)
+ goto done;
+
+ ret = dplane_update_enqueue(ctx);
+
+done:
+ atomic_fetch_add_explicit(&zdplane_info.dg_iptable_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ atomic_fetch_add_explicit(&zdplane_info.dg_iptable_errors, 1,
+ memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
+enum zebra_dplane_result
+dplane_pbr_iptable_add(struct zebra_pbr_iptable *iptable)
+{
+ return iptable_update_internal(DPLANE_OP_IPTABLE_ADD, iptable);
+}
+
+enum zebra_dplane_result
+dplane_pbr_iptable_delete(struct zebra_pbr_iptable *iptable)
+{
+ return iptable_update_internal(DPLANE_OP_IPTABLE_DELETE, iptable);
+}
+
+/*
+ * Common helper api for ipset updates
+ */
+static enum zebra_dplane_result
+ipset_update_internal(enum dplane_op_e op, struct zebra_pbr_ipset *ipset)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ struct zebra_dplane_ctx *ctx;
+ int ret;
+
+ ctx = dplane_ctx_alloc();
+
+ ret = dplane_ctx_ipset_init(ctx, op, ipset);
+ if (ret != AOK)
+ goto done;
+
+ ret = dplane_update_enqueue(ctx);
+
+done:
+ atomic_fetch_add_explicit(&zdplane_info.dg_ipset_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ atomic_fetch_add_explicit(&zdplane_info.dg_ipset_errors, 1,
+ memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
+enum zebra_dplane_result dplane_pbr_ipset_add(struct zebra_pbr_ipset *ipset)
+{
+ return ipset_update_internal(DPLANE_OP_IPSET_ADD, ipset);
+}
+
+enum zebra_dplane_result dplane_pbr_ipset_delete(struct zebra_pbr_ipset *ipset)
+{
+ return ipset_update_internal(DPLANE_OP_IPSET_DELETE, ipset);
+}
+
+/*
+ * Common helper api for ipset updates
+ */
+static enum zebra_dplane_result
+ipset_entry_update_internal(enum dplane_op_e op,
+ struct zebra_pbr_ipset_entry *ipset_entry)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ struct zebra_dplane_ctx *ctx;
+ int ret;
+
+ ctx = dplane_ctx_alloc();
+
+ ret = dplane_ctx_ipset_entry_init(ctx, op, ipset_entry);
+ if (ret != AOK)
+ goto done;
+
+ ret = dplane_update_enqueue(ctx);
+
+done:
+ atomic_fetch_add_explicit(&zdplane_info.dg_ipset_entry_in, 1,
+ memory_order_relaxed);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ atomic_fetch_add_explicit(&zdplane_info.dg_ipset_entry_errors,
+ 1, memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_add(struct zebra_pbr_ipset_entry *ipset)
+{
+ return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_ADD, ipset);
+}
+
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset)
+{
+ return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_DELETE, ipset);
+}
/*
* Handler for 'show dplane'
@@ -3675,6 +4031,24 @@ int dplane_show_helper(struct vty *vty, bool detailed)
vty_out(vty, "Bridge port updates: %" PRIu64 "\n", incoming);
vty_out(vty, "Bridge port errors: %" PRIu64 "\n", errs);
+ incoming = atomic_load_explicit(&zdplane_info.dg_iptable_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_iptable_errors,
+ memory_order_relaxed);
+ vty_out(vty, "IPtable updates: %" PRIu64 "\n", incoming);
+ vty_out(vty, "IPtable errors: %" PRIu64 "\n", errs);
+ incoming = atomic_load_explicit(&zdplane_info.dg_ipset_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_ipset_errors,
+ memory_order_relaxed);
+ vty_out(vty, "IPset updates: %" PRIu64 "\n", incoming);
+ vty_out(vty, "IPset errors: %" PRIu64 "\n", errs);
+ incoming = atomic_load_explicit(&zdplane_info.dg_ipset_entry_in,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_ipset_entry_errors,
+ memory_order_relaxed);
+ vty_out(vty, "IPset entry updates: %" PRIu64 "\n", incoming);
+ vty_out(vty, "IPset entry errors: %" PRIu64 "\n", errs);
return CMD_SUCCESS;
}
@@ -4085,6 +4459,33 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_NONE:
break;
+
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE: {
+ struct zebra_pbr_iptable ipt;
+
+ if (dplane_ctx_get_pbr_iptable(ctx, &ipt))
+ zlog_debug("Dplane iptable update op %s, unique(%u), ctx %p",
+ dplane_op2str(dplane_ctx_get_op(ctx)), ipt.unique, ctx);
+ } break;
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE: {
+ struct zebra_pbr_ipset ipset;
+
+ if (dplane_ctx_get_pbr_ipset(ctx, &ipset))
+ zlog_debug("Dplane ipset update op %s, unique(%u), ctx %p",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ ipset.unique, ctx);
+ } break;
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE: {
+ struct zebra_pbr_ipset_entry ipent;
+
+ if (dplane_ctx_get_pbr_ipset_entry(ctx, &ipent))
+ zlog_debug("Dplane ipset entry update op %s, unique(%u), ctx %p",
+ dplane_op2str(dplane_ctx_get_op(ctx)),
+ ipent.unique, ctx);
+ } break;
}
}
@@ -4181,6 +4582,29 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
1, memory_order_relaxed);
break;
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(
+ &zdplane_info.dg_iptable_errors, 1,
+ memory_order_relaxed);
+ break;
+
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(&zdplane_info.dg_ipset_errors,
+ 1, memory_order_relaxed);
+ break;
+
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(
+ &zdplane_info.dg_ipset_entry_errors, 1,
+ memory_order_relaxed);
+ break;
+
/* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
@@ -4197,6 +4621,28 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
}
}
+static void kernel_dplane_process_iptable(struct zebra_dplane_provider *prov,
+ struct zebra_dplane_ctx *ctx)
+{
+ zebra_pbr_process_iptable(ctx);
+ dplane_provider_enqueue_out_ctx(prov, ctx);
+}
+
+static void kernel_dplane_process_ipset(struct zebra_dplane_provider *prov,
+ struct zebra_dplane_ctx *ctx)
+{
+ zebra_pbr_process_ipset(ctx);
+ dplane_provider_enqueue_out_ctx(prov, ctx);
+}
+
+static void
+kernel_dplane_process_ipset_entry(struct zebra_dplane_provider *prov,
+ struct zebra_dplane_ctx *ctx)
+{
+ zebra_pbr_process_ipset_entry(ctx);
+ dplane_provider_enqueue_out_ctx(prov, ctx);
+}
+
/*
* Kernel provider callback
*/
@@ -4218,11 +4664,21 @@ static int kernel_dplane_process_func(struct zebra_dplane_provider *prov)
ctx = dplane_provider_dequeue_in_ctx(prov);
if (ctx == NULL)
break;
-
if (IS_ZEBRA_DEBUG_DPLANE_DETAIL)
kernel_dplane_log_detail(ctx);
- TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
+ if ((dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_ADD
+ || dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_DELETE))
+ kernel_dplane_process_iptable(prov, ctx);
+ else if ((dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ADD
+ || dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_DELETE))
+ kernel_dplane_process_ipset(prov, ctx);
+ else if ((dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ENTRY_ADD
+ || dplane_ctx_get_op(ctx)
+ == DPLANE_OP_IPSET_ENTRY_DELETE))
+ kernel_dplane_process_ipset_entry(prov, ctx);
+ else
+ TAILQ_INSERT_TAIL(&work_list, ctx, zd_q_entries);
}
kernel_update_multi(&work_list);
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 595d3fe562..4913ca251f 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -155,6 +155,16 @@ enum dplane_op_e {
/* bridge port update */
DPLANE_OP_BR_PORT_UPDATE,
+
+ /* Policy based routing iptable update */
+ DPLANE_OP_IPTABLE_ADD,
+ DPLANE_OP_IPTABLE_DELETE,
+
+ /* Policy based routing ipset update */
+ DPLANE_OP_IPSET_ADD,
+ DPLANE_OP_IPSET_DELETE,
+ DPLANE_OP_IPSET_ENTRY_ADD,
+ DPLANE_OP_IPSET_ENTRY_DELETE,
};
/*
@@ -475,7 +485,19 @@ const struct prefix *
dplane_ctx_rule_get_dst_ip(const struct zebra_dplane_ctx *ctx);
const struct prefix *
dplane_ctx_rule_get_old_dst_ip(const struct zebra_dplane_ctx *ctx);
-
+/* Accessors for policy based routing iptable information */
+struct zebra_pbr_iptable;
+bool
+dplane_ctx_get_pbr_iptable(const struct zebra_dplane_ctx *ctx,
+ struct zebra_pbr_iptable *table);
+struct zebra_pbr_ipset;
+bool
+dplane_ctx_get_pbr_ipset(const struct zebra_dplane_ctx *ctx,
+ struct zebra_pbr_ipset *ipset);
+struct zebra_pbr_ipset_entry;
+bool
+dplane_ctx_get_pbr_ipset_entry(const struct zebra_dplane_ctx *ctx,
+ struct zebra_pbr_ipset_entry *entry);
/* Accessors for bridge port information */
uint32_t dplane_ctx_get_br_port_flags(const struct zebra_dplane_ctx *ctx);
uint32_t
@@ -582,6 +604,11 @@ enum zebra_dplane_result dplane_local_mac_add(const struct interface *ifp,
uint32_t set_static,
uint32_t set_inactive);
+enum zebra_dplane_result
+dplane_local_mac_del(const struct interface *ifp,
+ const struct interface *bridge_ifp, vlanid_t vid,
+ const struct ethaddr *mac);
+
enum zebra_dplane_result dplane_rem_mac_del(const struct interface *ifp,
const struct interface *bridge_ifp,
vlanid_t vid,
@@ -643,6 +670,23 @@ enum zebra_dplane_result dplane_pbr_rule_delete(struct zebra_pbr_rule *rule);
enum zebra_dplane_result
dplane_pbr_rule_update(struct zebra_pbr_rule *old_rule,
struct zebra_pbr_rule *new_rule);
+/* iptable */
+enum zebra_dplane_result
+dplane_pbr_iptable_add(struct zebra_pbr_iptable *iptable);
+enum zebra_dplane_result
+dplane_pbr_iptable_delete(struct zebra_pbr_iptable *iptable);
+
+/* ipset */
+struct zebra_pbr_ipset;
+enum zebra_dplane_result dplane_pbr_ipset_add(struct zebra_pbr_ipset *ipset);
+enum zebra_dplane_result dplane_pbr_ipset_delete(struct zebra_pbr_ipset *ipset);
+
+/* ipset entry */
+struct zebra_pbr_ipset_entry;
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_add(struct zebra_pbr_ipset_entry *ipset);
+enum zebra_dplane_result
+dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset);
/* Encode route information into data plane context. */
int dplane_ctx_route_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index b232c664bc..27a5a07e48 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -151,6 +151,9 @@ void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt)
buf, sizeof(buf)));
json_object_string_add(json, "advertiseGatewayMacip",
zevpn->advertise_gw_macip ? "Yes" : "No");
+ json_object_string_add(json, "advertiseSviMacip",
+ zevpn->advertise_svi_macip ? "Yes"
+ : "No");
json_object_int_add(json, "numMacs", num_macs);
json_object_int_add(json, "numArpNd", num_neigh);
}
@@ -194,6 +197,8 @@ void zebra_evpn_print(zebra_evpn_t *zevpn, void **ctxt)
num_neigh);
vty_out(vty, " Advertise-gw-macip: %s\n",
zevpn->advertise_gw_macip ? "Yes" : "No");
+ vty_out(vty, " Advertise-svi-macip: %s\n",
+ zevpn->advertise_svi_macip ? "Yes" : "No");
}
}
@@ -429,7 +434,7 @@ int zebra_evpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
vxl = &zif->l2info.vxl;
if (zebra_evpn_mac_gw_macip_add(ifp, zevpn, ip, &mac, macaddr,
- vxl->access_vlan)
+ vxl->access_vlan, true)
!= 0)
return -1;
@@ -442,8 +447,6 @@ int zebra_evpn_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
int zebra_evpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn,
struct ipaddr *ip)
{
- char buf1[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
zebra_neigh_t *n = NULL;
zebra_mac_t *mac = NULL;
@@ -456,11 +459,8 @@ int zebra_evpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn,
mac = zebra_evpn_mac_lookup(zevpn, &n->emac);
if (!mac) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("MAC %s doesn't exist for neigh %s on VNI %u",
- prefix_mac2str(&n->emac,
- buf1, sizeof(buf1)),
- ipaddr2str(ip, buf2, sizeof(buf2)),
- zevpn->vni);
+ zlog_debug("MAC %pEA doesn't exist for neigh %pIA on VNI %u",
+ &n->emac, ip, zevpn->vni);
return -1;
}
@@ -471,10 +471,9 @@ int zebra_evpn_gw_macip_del(struct interface *ifp, zebra_evpn_t *zevpn,
/* only need to delete the entry from bgp if we sent it before */
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%u:SVI %s(%u) VNI %u, sending GW MAC %s IP %s del to BGP",
+ "%u:SVI %s(%u) VNI %u, sending GW MAC %pEA IP %pIA del to BGP",
ifp->vrf_id, ifp->name, ifp->ifindex, zevpn->vni,
- prefix_mac2str(&(n->emac), buf1, sizeof(buf1)),
- ipaddr2str(ip, buf2, sizeof(buf2)));
+ &n->emac, ip);
/* Remove neighbor from BGP. */
zebra_evpn_neigh_send_del_to_client(zevpn->vni, &n->ip, &n->emac,
@@ -569,7 +568,9 @@ void zebra_evpn_gw_macip_add_for_evpn_hash(struct hash_bucket *bucket,
return;
/* Add primary SVI MAC-IP */
- zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
+ if (advertise_svi_macip_enabled(zevpn)
+ || advertise_gw_macip_enabled(zevpn))
+ zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
if (advertise_gw_macip_enabled(zevpn)) {
/* Add VRR MAC-IP - if any*/
@@ -925,14 +926,20 @@ void zebra_evpn_read_mac_neigh(zebra_evpn_t *zevpn, struct interface *ifp)
macfdb_read_for_bridge(zns, ifp, zif->brslave_info.br_if);
vlan_if = zvni_map_to_svi(vxl->access_vlan, zif->brslave_info.br_if);
if (vlan_if) {
+ /* Add SVI MAC */
+ zebra_evpn_acc_bd_svi_mac_add(vlan_if);
/* Add SVI MAC-IP */
- zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
+ if (advertise_svi_macip_enabled(zevpn)
+ || advertise_gw_macip_enabled(zevpn))
+ zebra_evpn_add_macip_for_intf(vlan_if, zevpn);
/* Add VRR MAC-IP - if any*/
- vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
- if (vrr_if)
- zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
+ if (advertise_gw_macip_enabled(zevpn)) {
+ vrr_if = zebra_get_vrr_intf_for_svi(vlan_if);
+ if (vrr_if)
+ zebra_evpn_add_macip_for_intf(vrr_if, zevpn);
+ }
neigh_read_for_vlan(zns, vlan_if);
}
@@ -1308,7 +1315,6 @@ zebra_evpn_process_sync_macip_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
uint8_t flags, uint32_t seq, esi_t *esi)
{
struct sync_mac_ip_ctx ctx;
- char macbuf[ETHER_ADDR_STRLEN];
char ipbuf[INET6_ADDRSTRLEN];
bool sticky;
bool remote_gw;
@@ -1321,9 +1327,9 @@ zebra_evpn_process_sync_macip_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
|| IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug(
- "Ignore sync-macip vni %u mac %s%s%s%s%s",
+ "Ignore sync-macip vni %u mac %pEA%s%s%s%s",
zevpn->vni,
- prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
+ macaddr,
ipa_len ? " IP " : "",
ipa_len ? ipaddr2str(ipaddr, ipbuf,
sizeof(ipbuf))
@@ -1442,7 +1448,6 @@ void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr,
struct zebra_ns *zns;
struct zebra_l2info_vxlan *vxl;
struct zebra_vrf *zvrf;
- char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
/* Locate EVPN hash entry - expected to exist. */
@@ -1472,9 +1477,8 @@ void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr,
if (n && !mac) {
zlog_warn(
- "Failed to locate MAC %s for neigh %s VNI %u upon remote MACIP DEL",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ipaddr2str(ipaddr, buf1, sizeof(buf1)), vni);
+ "Failed to locate MAC %pEA for neigh %pIA VNI %u upon remote MACIP DEL",
+ macaddr, ipaddr, vni);
return;
}
@@ -1490,8 +1494,8 @@ void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr,
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)
&& CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW)) {
zlog_warn(
- "Ignore remote MACIP DEL VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
- vni, prefix_mac2str(macaddr, buf, sizeof(buf)),
+ "Ignore remote MACIP DEL VNI %u MAC %pEA%s%s as MAC is already configured as gateway MAC",
+ vni, macaddr,
ipa_len ? " IP " : "",
ipa_len ? ipaddr2str(ipaddr, buf1, sizeof(buf1)) : "");
return;
@@ -1512,11 +1516,8 @@ void process_remote_macip_del(vni_t vni, struct ethaddr *macaddr,
&& CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: MAC %s (flags 0x%x) is remote and duplicate, read kernel for local entry",
- __func__,
- prefix_mac2str(macaddr, buf,
- sizeof(buf)),
- mac->flags);
+ "%s: MAC %pEA (flags 0x%x) is remote and duplicate, read kernel for local entry",
+ __func__, macaddr, mac->flags);
macfdb_read_specific_mac(zns, zif->brslave_info.br_if,
macaddr, vxl->access_vlan);
}
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 5227a480fc..b36e8034b7 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -94,6 +94,97 @@ uint32_t num_dup_detected_macs(zebra_evpn_t *zevpn)
return num_macs;
}
+/* Setup mac_list against the access port. This is done when a mac uses
+ * the ifp as destination for the first time
+ */
+static void zebra_evpn_mac_ifp_new(struct zebra_if *zif)
+{
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("MAC list created for ifp %s (%u)", zif->ifp->name,
+ zif->ifp->ifindex);
+
+ zif->mac_list = list_new();
+ listset_app_node_mem(zif->mac_list);
+}
+
+/* Free up the mac_list if any as a part of the interface del/cleanup */
+void zebra_evpn_mac_ifp_del(struct interface *ifp)
+{
+ struct zebra_if *zif = ifp->info;
+
+ if (zif->mac_list) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("MAC list deleted for ifp %s (%u)",
+ zif->ifp->name, zif->ifp->ifindex);
+ list_delete(&zif->mac_list);
+ }
+}
+
+/* Unlink local mac from a destination access port */
+static void zebra_evpn_mac_ifp_unlink(zebra_mac_t *zmac)
+{
+ struct zebra_if *zif;
+ struct interface *ifp = zmac->ifp;
+
+ if (!ifp)
+ return;
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("VNI %d MAC %pEA unlinked from ifp %s (%u)",
+ zmac->zevpn->vni,
+ &zmac->macaddr,
+ ifp->name, ifp->ifindex);
+
+ zif = ifp->info;
+ list_delete_node(zif->mac_list, &zmac->ifp_listnode);
+ zmac->ifp = NULL;
+}
+
+/* Link local mac to destination access port. This is done only if the
+ * local mac is associated with a zero ESI i.e. single attach or lacp-bypass
+ * bridge port member
+ */
+static void zebra_evpn_mac_ifp_link(zebra_mac_t *zmac, struct interface *ifp)
+{
+ struct zebra_if *zif;
+
+ if (!CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
+ return;
+
+ /* already linked to the destination */
+ if (zmac->ifp == ifp)
+ return;
+
+ /* unlink the mac from any old destination */
+ if (zmac->ifp)
+ zebra_evpn_mac_ifp_unlink(zmac);
+
+ if (!ifp)
+ return;
+
+ zif = ifp->info;
+ /* the interface mac_list is created on first mac link attempt */
+ if (!zif->mac_list)
+ zebra_evpn_mac_ifp_new(zif);
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("VNI %d MAC %pEA linked to ifp %s (%u)",
+ zmac->zevpn->vni,
+ &zmac->macaddr,
+ ifp->name, ifp->ifindex);
+
+ zmac->ifp = ifp;
+ listnode_init(&zmac->ifp_listnode, zmac);
+ listnode_add(zif->mac_list, &zmac->ifp_listnode);
+}
+
+/* If the mac is a local mac clear links to destination access port */
+void zebra_evpn_mac_clear_fwd_info(zebra_mac_t *zmac)
+{
+ zebra_evpn_mac_ifp_unlink(zmac);
+ memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
+}
+
/*
* Install remote MAC into the forwarding plane.
*/
@@ -221,8 +312,8 @@ void zebra_evpn_deref_ip2mac(zebra_evpn_t *zevpn, zebra_mac_t *mac)
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
}
- /* If no neighbors, delete the MAC. */
- if (list_isempty(mac->neigh_list))
+ /* If no references, delete the MAC. */
+ if (!zebra_evpn_mac_in_use(mac))
zebra_evpn_mac_del(zevpn, mac);
}
@@ -293,7 +384,6 @@ static int zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t)
zebra_evpn_t *zevpn = NULL;
struct listnode *node = NULL;
zebra_neigh_t *nbr = NULL;
- char buf[ETHER_ADDR_STRLEN];
mac = THREAD_ARG(t);
@@ -314,9 +404,8 @@ static int zebra_evpn_dad_mac_auto_recovery_exp(struct thread *t)
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: duplicate addr mac %s flags %slearn count %u host count %u auto recovery expired",
- __func__,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ "%s: duplicate addr mac %pEA flags %slearn count %u host count %u auto recovery expired",
+ __func__, &mac->macaddr,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)),
mac->dad_count, listcount(mac->neigh_list));
@@ -375,8 +464,6 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
zebra_neigh_t *nbr;
struct listnode *node = NULL;
struct timeval elapsed = {0, 0};
- char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
bool reset_params = false;
if (!(zebra_evpn_do_dup_addr_detect(zvrf) && do_dad))
@@ -391,9 +478,8 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: duplicate addr MAC %s flags %sskip update to client, learn count %u recover time %u",
- __func__,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ "%s: duplicate addr MAC %pEA flags %sskip update to client, learn count %u recover time %u",
+ __func__, &mac->macaddr,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)),
mac->dad_count, zvrf->dad_freeze_time);
@@ -429,9 +515,8 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: duplicate addr MAC %s flags %sdetection time passed, reset learn count %u",
- __func__,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ "%s: duplicate addr MAC %pEA flags %sdetection time passed, reset learn count %u",
+ __func__, &mac->macaddr,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)),
mac->dad_count);
@@ -461,9 +546,8 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
if (mac->dad_count >= zvrf->dad_max_moves) {
flog_warn(EC_ZEBRA_DUP_MAC_DETECTED,
- "VNI %u: MAC %s detected as duplicate during %s VTEP %pI4",
- mac->zevpn->vni,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ "VNI %u: MAC %pEA detected as duplicate during %s VTEP %pI4",
+ mac->zevpn->vni, &mac->macaddr,
is_local ? "local update, last" :
"remote update, from", &vtep_ip);
@@ -486,11 +570,8 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
nbr->dad_dup_detect_time = monotime(NULL);
flog_warn(EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
- "VNI %u: MAC %s IP %s detected as duplicate during %s update, inherit duplicate from MAC",
- mac->zevpn->vni,
- prefix_mac2str(&mac->macaddr,
- buf, sizeof(buf)),
- ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+ "VNI %u: MAC %pEA IP %pIA detected as duplicate during %s update, inherit duplicate from MAC",
+ mac->zevpn->vni, &mac->macaddr, &nbr->ip,
is_local ? "local" : "remote");
}
@@ -501,10 +582,8 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: duplicate addr MAC %s flags %sauto recovery time %u start",
- __func__,
- prefix_mac2str(&mac->macaddr, buf,
- sizeof(buf)),
+ "%s: duplicate addr MAC %pEA flags %sauto recovery time %u start",
+ __func__, &mac->macaddr,
zebra_evpn_zebra_mac_flag_dump(
mac, mac_buf, sizeof(mac_buf)),
zvrf->dad_freeze_time);
@@ -583,6 +662,9 @@ void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
json_object_boolean_true_add(json_mac, "stickyMac");
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
+ json_object_boolean_true_add(json_mac, "sviMac");
+
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
json_object_boolean_true_add(json_mac,
"defaultGateway");
@@ -685,6 +767,9 @@ void zebra_evpn_print_mac(zebra_mac_t *mac, void *ctxt, json_object *json)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
vty_out(vty, " Sticky Mac ");
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
+ vty_out(vty, " SVI-Mac ");
+
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW))
vty_out(vty, " Default-gateway Mac ");
@@ -747,14 +832,10 @@ static char *zebra_evpn_print_mac_flags(zebra_mac_t *mac, char *flags_buf,
size_t flags_buf_sz)
{
snprintf(flags_buf, flags_buf_sz, "%s%s%s%s",
- mac->sync_neigh_cnt ?
- "N" : "",
- (mac->flags & ZEBRA_MAC_ES_PEER_ACTIVE) ?
- "P" : "",
- (mac->flags & ZEBRA_MAC_ES_PEER_PROXY) ?
- "X" : "",
- (mac->flags & ZEBRA_MAC_LOCAL_INACTIVE) ?
- "I" : "");
+ mac->sync_neigh_cnt ? "N" : "",
+ (mac->flags & ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "",
+ (mac->flags & ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "",
+ (mac->flags & ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : "");
return flags_buf;
}
@@ -911,8 +992,6 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
uint32_t seq, int state,
struct zebra_evpn_es *es, uint16_t cmd)
{
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
int ipa_len;
struct zserv *client = NULL;
struct stream *s = NULL;
@@ -957,12 +1036,11 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni, struct ethaddr *macaddr,
char flag_buf[MACIP_BUF_SIZE];
zlog_debug(
- "Send MACIP %s f %s MAC %s IP %s seq %u L2-VNI %u ESI %s to %s",
+ "Send MACIP %s f %s MAC %pEA IP %pIA seq %u L2-VNI %u ESI %s to %s",
(cmd == ZEBRA_MACIP_ADD) ? "Add" : "Del",
zclient_evpn_dump_macip_flags(flags, flag_buf,
sizeof(flag_buf)),
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ipaddr2str(ip, buf2, sizeof(buf2)), seq, vni,
+ macaddr, ip, seq, vni,
es ? es->esi_str : "-",
zebra_route_string(client->proto));
}
@@ -1036,11 +1114,10 @@ zebra_mac_t *zebra_evpn_mac_add(zebra_evpn_t *zevpn, struct ethaddr *macaddr)
mac->uptime = monotime(NULL);
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
- char buf[ETHER_ADDR_STRLEN];
char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %s flags %s", __func__,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ zlog_debug("%s: MAC %pEA flags %s", __func__,
+ &mac->macaddr,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)));
}
@@ -1055,11 +1132,10 @@ int zebra_evpn_mac_del(zebra_evpn_t *zevpn, zebra_mac_t *mac)
zebra_mac_t *tmp_mac;
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
- char buf[ETHER_ADDR_STRLEN];
char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %s flags %s", __func__,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ zlog_debug("%s: MAC %pEA flags %s", __func__,
+ &mac->macaddr,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)));
}
@@ -1075,6 +1151,9 @@ int zebra_evpn_mac_del(zebra_evpn_t *zevpn, zebra_mac_t *mac)
/* force de-ref any ES entry linked to the MAC */
zebra_evpn_es_mac_deref_entry(mac);
+ /* remove links to the destination access port */
+ zebra_evpn_mac_clear_fwd_info(mac);
+
/* Cancel proxy hold timer */
zebra_evpn_mac_stop_hold_timer(mac);
@@ -1105,12 +1184,11 @@ static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx,
else if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_AUTO)
&& !listcount(mac->neigh_list)) {
if (IS_ZEBRA_DEBUG_VXLAN) {
- char buf[ETHER_ADDR_STRLEN];
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: Del MAC %s flags %s", __func__,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ "%s: Del MAC %pEA flags %s", __func__,
+ &mac->macaddr,
zebra_evpn_zebra_mac_flag_dump(
mac, mac_buf, sizeof(mac_buf)));
}
@@ -1375,7 +1453,6 @@ static int zebra_evpn_mac_hold_exp_cb(struct thread *t)
bool new_bgp_ready;
bool old_static;
bool new_static;
- char macbuf[ETHER_ADDR_STRLEN];
mac = THREAD_ARG(t);
/* the purpose of the hold timer is to age out the peer-active
@@ -1394,9 +1471,8 @@ static int zebra_evpn_mac_hold_exp_cb(struct thread *t)
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "sync-mac vni %u mac %s es %s %shold expired",
- mac->zevpn->vni,
- prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
+ "sync-mac vni %u mac %pEA es %s %shold expired",
+ mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)));
@@ -1420,8 +1496,6 @@ static int zebra_evpn_mac_hold_exp_cb(struct thread *t)
static inline void zebra_evpn_mac_start_hold_timer(zebra_mac_t *mac)
{
- char macbuf[ETHER_ADDR_STRLEN];
-
if (mac->hold_timer)
return;
@@ -1429,9 +1503,8 @@ static inline void zebra_evpn_mac_start_hold_timer(zebra_mac_t *mac)
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "sync-mac vni %u mac %s es %s %shold started",
- mac->zevpn->vni,
- prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
+ "sync-mac vni %u mac %pEA es %s %shold started",
+ mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)));
@@ -1442,8 +1515,6 @@ static inline void zebra_evpn_mac_start_hold_timer(zebra_mac_t *mac)
void zebra_evpn_mac_stop_hold_timer(zebra_mac_t *mac)
{
- char macbuf[ETHER_ADDR_STRLEN];
-
if (!mac->hold_timer)
return;
@@ -1451,9 +1522,8 @@ void zebra_evpn_mac_stop_hold_timer(zebra_mac_t *mac)
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "sync-mac vni %u mac %s es %s %shold stopped",
- mac->zevpn->vni,
- prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
+ "sync-mac vni %u mac %pEA es %s %shold stopped",
+ mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)));
@@ -1464,7 +1534,6 @@ void zebra_evpn_mac_stop_hold_timer(zebra_mac_t *mac)
void zebra_evpn_sync_mac_del(zebra_mac_t *mac)
{
- char macbuf[ETHER_ADDR_STRLEN];
bool old_static;
bool new_static;
@@ -1472,9 +1541,8 @@ void zebra_evpn_sync_mac_del(zebra_mac_t *mac)
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "sync-mac del vni %u mac %s es %s seq %d f %s",
- mac->zevpn->vni,
- prefix_mac2str(&mac->macaddr, macbuf, sizeof(macbuf)),
+ "sync-mac del vni %u mac %pEA es %s seq %d f %s",
+ mac->zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)));
@@ -1499,7 +1567,6 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
struct ipaddr *ipaddr,
bool sync)
{
- char macbuf[ETHER_ADDR_STRLEN];
char ipbuf[INET6_ADDRSTRLEN];
uint32_t tmp_seq;
const char *n_type;
@@ -1524,11 +1591,10 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s-macip accept vni %u %s-mac %s%s%s lower seq %u f %s",
+ "%s-macip accept vni %u %s-mac %pEA%s%s lower seq %u f %s",
sync ? "sync" : "rem", zevpn->vni,
n_type,
- prefix_mac2str(&mac->macaddr, macbuf,
- sizeof(macbuf)),
+ &mac->macaddr,
ipa_len ? " IP " : "",
ipa_len ? ipaddr2str(ipaddr, ipbuf,
sizeof(ipbuf))
@@ -1545,10 +1611,9 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(zebra_evpn_t *zevpn,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s-macip ignore vni %u %s-mac %s%s%s as existing has higher seq %u f %s",
+ "%s-macip ignore vni %u %s-mac %pEA%s%s as existing has higher seq %u f %s",
sync ? "sync" : "rem", zevpn->vni, n_type,
- prefix_mac2str(&mac->macaddr, macbuf,
- sizeof(macbuf)),
+ &mac->macaddr,
ipa_len ? " IP " : "",
ipa_len ? ipaddr2str(ipaddr, ipbuf,
sizeof(ipbuf))
@@ -1575,7 +1640,6 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
bool seq_change = false;
bool es_change = false;
uint32_t tmp_seq;
- char macbuf[ETHER_ADDR_STRLEN];
char ipbuf[INET6_ADDRSTRLEN];
bool old_local = false;
bool old_bgp_ready;
@@ -1623,10 +1687,8 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
if (sticky || remote_gw) {
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "Ignore sync-macip vni %u mac %s%s%s%s%s",
- zevpn->vni,
- prefix_mac2str(macaddr, macbuf,
- sizeof(macbuf)),
+ "Ignore sync-macip vni %u mac %pEA%s%s%s%s",
+ zevpn->vni, macaddr,
ipa_len ? " IP " : "",
ipa_len ? ipaddr2str(ipaddr, ipbuf,
sizeof(ipbuf))
@@ -1684,7 +1746,7 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
}
}
mac->rem_seq = 0;
- memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
+ zebra_evpn_mac_clear_fwd_info(mac);
mac->flags = new_flags;
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC && (old_flags != new_flags)) {
@@ -1693,9 +1755,8 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
omac.flags = old_flags;
zlog_debug(
- "sync-mac vni %u mac %s old_f %snew_f %s",
- zevpn->vni,
- prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
+ "sync-mac vni %u mac %pEA old_f %snew_f %s",
+ zevpn->vni, macaddr,
zebra_evpn_zebra_mac_flag_dump(
&omac, omac_buf, sizeof(omac_buf)),
zebra_evpn_zebra_mac_flag_dump(
@@ -1710,6 +1771,7 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
inform_dataplane = true;
ctx->mac_inactive = true;
}
+
/* if peer-flag is being set notify dataplane that the
* entry must not be expired because of local inactivity
*/
@@ -1737,9 +1799,9 @@ zebra_evpn_proc_sync_mac_update(zebra_evpn_t *zevpn, struct ethaddr *macaddr,
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char mac_buf[MAC_BUF_SIZE];
- zlog_debug("sync-mac %s vni %u mac %s es %s seq %d f %s%s%s",
- ctx->mac_created ? "created" : "updated", zevpn->vni,
- prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
+ zlog_debug("sync-mac %s vni %u mac %pEA es %s seq %d f %s%s%s",
+ ctx->mac_created ? "created" : "updated",
+ zevpn->vni, macaddr,
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)),
@@ -1790,20 +1852,25 @@ static bool zebra_evpn_local_mac_update_fwd_info(zebra_mac_t *mac,
bool es_change;
ns_id_t local_ns_id = NS_DEFAULT;
struct zebra_vrf *zvrf;
+ struct zebra_evpn_es *es;
zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
if (zvrf && zvrf->zns)
local_ns_id = zvrf->zns->ns_id;
- memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
+ zebra_evpn_mac_clear_fwd_info(mac);
- es_change = zebra_evpn_es_mac_ref_entry(mac, zif->es_info.es);
+ es = zif->es_info.es;
+ if (es && (es->flags & ZEBRA_EVPNES_BYPASS))
+ es = NULL;
+ es_change = zebra_evpn_es_mac_ref_entry(mac, es);
if (!mac->es) {
/* if es is set fwd_info is not-relevant/taped-out */
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vid;
+ zebra_evpn_mac_ifp_link(mac, ifp);
}
return es_change;
@@ -1898,7 +1965,6 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
struct in_addr vtep_ip, uint8_t flags,
uint32_t seq, esi_t *esi)
{
- char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
bool sticky;
bool remote_gw;
@@ -1908,6 +1974,8 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
esi_t *old_esi;
bool old_static = false;
zebra_mac_t *mac;
+ bool old_es_present;
+ bool new_es_present;
sticky = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_STICKY);
remote_gw = !!CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
@@ -1919,9 +1987,8 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
&& CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_GW)) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Ignore remote MACIP ADD VNI %u MAC %s%s%s as MAC is already configured as gateway MAC",
- zevpn->vni,
- prefix_mac2str(macaddr, buf, sizeof(buf)),
+ "Ignore remote MACIP ADD VNI %u MAC %pEA%s%s as MAC is already configured as gateway MAC",
+ zevpn->vni, macaddr,
ipa_len ? " IP " : "",
ipa_len ? ipaddr2str(ipaddr, buf1, sizeof(buf1))
: "");
@@ -1946,10 +2013,8 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
mac = zebra_evpn_mac_add(zevpn, macaddr);
if (!mac) {
zlog_warn(
- "Failed to add MAC %s VNI %u Remote VTEP %pI4",
- prefix_mac2str(macaddr, buf,
- sizeof(buf)),
- zevpn->vni, &vtep_ip);
+ "Failed to add MAC %pEA VNI %u Remote VTEP %pI4",
+ macaddr, zevpn->vni, &vtep_ip);
return -1;
}
@@ -1971,7 +2036,16 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
zevpn, mac, seq, ipa_len, ipaddr, false))
return -1;
+ old_es_present = !!mac->es;
zebra_evpn_es_mac_ref(mac, esi);
+ new_es_present = !!mac->es;
+ /* XXX - dataplane is curently not able to handle a MAC
+ * replace if the destination changes from L2-NHG to
+ * single VTEP and vice-versa. So delete the old entry
+ * and re-install
+ */
+ if (old_es_present != new_es_present)
+ zebra_evpn_rem_mac_uninstall(zevpn, mac, false);
}
/* Check MAC's curent state is local (this is the case
@@ -1999,10 +2073,8 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "sync-mac->remote vni %u mac %s es %s seq %d f %s",
- zevpn->vni,
- prefix_mac2str(macaddr, buf,
- sizeof(buf)),
+ "sync-mac->remote vni %u mac %pEA es %s seq %d f %s",
+ zevpn->vni, macaddr,
mac->es ? mac->es->esi_str : "-",
mac->loc_seq,
zebra_evpn_zebra_mac_flag_dump(
@@ -2016,8 +2088,8 @@ int process_mac_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
}
/* Set "auto" and "remote" forwarding info. */
+ zebra_evpn_mac_clear_fwd_info(mac);
UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
- memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
SET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
mac->fwd_info.r_vtep_ip = vtep_ip;
@@ -2058,10 +2130,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
struct interface *ifp,
struct ethaddr *macaddr, vlanid_t vid,
bool sticky, bool local_inactive,
- bool dp_static)
+ bool dp_static, zebra_mac_t *mac)
{
- zebra_mac_t *mac;
- char buf[ETHER_ADDR_STRLEN];
bool mac_sticky = false;
bool inform_client = false;
bool upd_neigh = false;
@@ -2077,13 +2147,13 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
assert(ifp);
/* Check if we need to create or update or it is a NO-OP. */
- mac = zebra_evpn_mac_lookup(zevpn, macaddr);
+ if (!mac)
+ mac = zebra_evpn_mac_lookup(zevpn, macaddr);
if (!mac) {
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug(
- "ADD %sMAC %s intf %s(%u) VID %u -> VNI %u%s",
- sticky ? "sticky " : "",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
+ "ADD %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s",
+ sticky ? "sticky " : "", macaddr,
ifp->name, ifp->ifindex, vid, zevpn->vni,
local_inactive ? " local-inactive" : "");
@@ -2091,9 +2161,9 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
if (!mac) {
flog_err(
EC_ZEBRA_MAC_ADD_FAILED,
- "Failed to add MAC %s intf %s(%u) VID %u VNI %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, vid, zevpn->vni);
+ "Failed to add MAC %pEA intf %s(%u) VID %u VNI %u",
+ macaddr, ifp->name, ifp->ifindex, vid,
+ zevpn->vni);
return -1;
}
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
@@ -2106,9 +2176,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "UPD %sMAC %s intf %s(%u) VID %u -> VNI %u %scurFlags %s",
- sticky ? "sticky " : "",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
+ "UPD %sMAC %pEA intf %s(%u) VID %u -> VNI %u %scurFlags %s",
+ sticky ? "sticky " : "", macaddr,
ifp->name, ifp->ifindex, vid, zevpn->vni,
local_inactive ? "local-inactive " : "",
zebra_evpn_zebra_mac_flag_dump(
@@ -2128,6 +2197,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
old_static = zebra_evpn_mac_is_static(mac);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY))
mac_sticky = true;
+ es_change = zebra_evpn_local_mac_update_fwd_info(
+ mac, ifp, vid);
/*
* Update any changes and if changes are relevant to
@@ -2136,16 +2207,14 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
if (mac_sticky == sticky && old_ifp == ifp
&& old_vid == vid
&& old_local_inactive == local_inactive
- && dp_static == old_static) {
+ && dp_static == old_static && !es_change) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- " Add/Update %sMAC %s intf %s(%u) VID %u -> VNI %u%s, "
+ " Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, "
"entry exists and has not changed ",
- sticky ? "sticky " : "",
- prefix_mac2str(macaddr, buf,
- sizeof(buf)),
- ifp->name, ifp->ifindex, vid,
- zevpn->vni,
+ sticky ? "sticky " : "",
+ macaddr, ifp->name,
+ ifp->ifindex, vid, zevpn->vni,
local_inactive
? " local_inactive"
: "");
@@ -2160,15 +2229,17 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
inform_client = true;
}
- es_change = zebra_evpn_local_mac_update_fwd_info(
- mac, ifp, vid);
/* If an es_change is detected we need to advertise
* the route with a sequence that is one
* greater. This is need to indicate a mac-move
* to the ES peers
*/
if (es_change) {
- mac->loc_seq = mac->loc_seq + 1;
+ /* update the sequence number only if the entry
+ * is locally active
+ */
+ if (!local_inactive)
+ mac->loc_seq = mac->loc_seq + 1;
/* force drop the peer/sync info as it is
* simply no longer relevant
*/
@@ -2198,9 +2269,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)) {
flog_warn(
EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
- "MAC %s already learnt as remote sticky MAC behind VTEP %pI4 VNI %u",
- prefix_mac2str(macaddr, buf,
- sizeof(buf)),
+ "MAC %pEA already learnt as remote sticky MAC behind VTEP %pI4 VNI %u",
+ macaddr,
&mac->fwd_info.r_vtep_ip,
zevpn->vni);
return 0;
@@ -2265,9 +2335,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "local mac vni %u mac %s es %s seq %d f %s%s",
- zevpn->vni,
- prefix_mac2str(macaddr, buf, sizeof(buf)),
+ "local mac vni %u mac %pEA es %s seq %d f %s%s",
+ zevpn->vni, macaddr,
mac->es ? mac->es->esi_str : "", mac->loc_seq,
zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
sizeof(mac_buf)),
@@ -2302,32 +2371,30 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
return 0;
}
-int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac)
+int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac,
+ bool clear_static)
{
- char buf[ETHER_ADDR_STRLEN];
bool old_bgp_ready;
bool new_bgp_ready;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("DEL MAC %s VNI %u seq %u flags 0x%x nbr count %u",
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- zevpn->vni, mac->loc_seq, mac->flags,
+ zlog_debug("DEL MAC %pEA VNI %u seq %u flags 0x%x nbr count %u",
+ &mac->macaddr, zevpn->vni, mac->loc_seq, mac->flags,
listcount(mac->neigh_list));
old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
- if (zebra_evpn_mac_is_static(mac)) {
+ if (!clear_static && zebra_evpn_mac_is_static(mac)) {
/* this is a synced entry and can only be removed when the
* es-peers stop advertising it.
*/
- memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
+ zebra_evpn_mac_clear_fwd_info(mac);
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "re-add sync-mac vni %u mac %s es %s seq %d f %s",
- zevpn->vni,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ "re-add sync-mac vni %u mac %pEA es %s seq %d f %s",
+ zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-", mac->loc_seq,
zebra_evpn_zebra_mac_flag_dump(
mac, mac_buf, sizeof(mac_buf)));
@@ -2350,6 +2417,9 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac)
return 0;
}
+ /* flush the peer info */
+ zebra_evpn_mac_clear_sync_info(mac);
+
/* Update all the neigh entries associated with this mac */
zebra_evpn_process_neigh_on_local_mac_del(zevpn, mac);
@@ -2359,6 +2429,9 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac)
zebra_evpn_es_mac_deref_entry(mac);
+ /* remove links to the destination access port */
+ zebra_evpn_mac_clear_fwd_info(mac);
+
/*
* If there are no neigh associated with the mac delete the mac
* else mark it as AUTO for forward reference
@@ -2376,9 +2449,9 @@ int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac)
int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
struct ipaddr *ip, zebra_mac_t **macp,
- struct ethaddr *macaddr, vlanid_t vlan_id)
+ struct ethaddr *macaddr, vlanid_t vlan_id,
+ bool def_gw)
{
- char buf[ETHER_ADDR_STRLEN];
zebra_mac_t *mac;
ns_id_t local_ns_id = NS_DEFAULT;
struct zebra_vrf *zvrf;
@@ -2392,18 +2465,18 @@ int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
mac = zebra_evpn_mac_add(zevpn, macaddr);
if (!mac) {
flog_err(EC_ZEBRA_MAC_ADD_FAILED,
- "Failed to add MAC %s intf %s(%u) VID %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, vlan_id);
+ "Failed to add MAC %pEA intf %s(%u) VID %u",
+ macaddr, ifp->name, ifp->ifindex, vlan_id);
return -1;
}
}
/* Set "local" forwarding info. */
+ zebra_evpn_mac_clear_fwd_info(mac);
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
- SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
- memset(&mac->fwd_info, 0, sizeof(mac->fwd_info));
+ if (def_gw)
+ SET_FLAG(mac->flags, ZEBRA_MAC_DEF_GW);
mac->fwd_info.local.ifindex = ifp->ifindex;
mac->fwd_info.local.ns_id = local_ns_id;
mac->fwd_info.local.vid = vlan_id;
@@ -2412,3 +2485,63 @@ int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
return 0;
}
+
+void zebra_evpn_mac_svi_del(struct interface *ifp, zebra_evpn_t *zevpn)
+{
+ zebra_mac_t *mac;
+ struct ethaddr macaddr;
+ bool old_bgp_ready;
+
+ if (!zebra_evpn_mh_do_adv_svi_mac())
+ return;
+
+ memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
+ mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
+ if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI)) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("SVI %s mac free", ifp->name);
+
+ old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_SVI);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
+ false);
+ zebra_evpn_deref_ip2mac(mac->zevpn, mac);
+ }
+}
+
+void zebra_evpn_mac_svi_add(struct interface *ifp, zebra_evpn_t *zevpn)
+{
+ zebra_mac_t *mac = NULL;
+ struct ethaddr macaddr;
+ struct zebra_if *zif = ifp->info;
+ bool old_bgp_ready;
+ bool new_bgp_ready;
+
+ if (!zebra_evpn_mh_do_adv_svi_mac()
+ || !zebra_evpn_send_to_client_ok(zevpn))
+ return;
+
+ memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
+
+ /* dup check */
+ mac = zebra_evpn_mac_lookup(zevpn, &macaddr);
+ if (mac && CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI))
+ return;
+
+ /* add/update mac */
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("SVI %s mac add", zif->ifp->name);
+
+ old_bgp_ready = (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags))
+ ? true
+ : false;
+
+ mac = NULL;
+ zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
+ if (mac)
+ SET_FLAG(mac->flags, ZEBRA_MAC_SVI);
+
+ new_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
+ new_bgp_ready);
+}
diff --git a/zebra/zebra_evpn_mac.h b/zebra/zebra_evpn_mac.h
index 242097907f..fb162f1a93 100644
--- a/zebra/zebra_evpn_mac.h
+++ b/zebra/zebra_evpn_mac.h
@@ -80,6 +80,8 @@ struct zebra_mac_t_ {
* to advertise it as locally attached but with a "proxy" flag
*/
#define ZEBRA_MAC_LOCAL_INACTIVE 0x800
+/* The MAC entry was created because of advertise_svi_mac */
+#define ZEBRA_MAC_SVI 0x1000
#define ZEBRA_MAC_ALL_LOCAL_FLAGS (ZEBRA_MAC_LOCAL | ZEBRA_MAC_LOCAL_INACTIVE)
#define ZEBRA_MAC_ALL_PEER_FLAGS \
@@ -88,7 +90,9 @@ struct zebra_mac_t_ {
/* back pointer to zevpn */
zebra_evpn_t *zevpn;
- /* Local or remote info. */
+ /* Local or remote info.
+ * Note: fwd_info is only relevant if mac->es is NULL.
+ */
union {
struct {
ifindex_t ifindex;
@@ -104,6 +108,16 @@ struct zebra_mac_t_ {
/* memory used to link the mac to the es */
struct listnode es_listnode;
+ /* access-port/bridge member. only relevant for local macs that
+ * are associated with a zero-ESI,
+ * XXX - this belongs in fwd_info.local; however fwd_info is
+ * being cleared and memset to zero in different ways that can
+ * mess up the links.
+ */
+ struct interface *ifp;
+ /* memory used to link the mac to the ifp */
+ struct listnode ifp_listnode;
+
/* Mobility sequence numbers associated with this entry. */
uint32_t rem_seq;
uint32_t loc_seq;
@@ -201,6 +215,12 @@ static inline void zebra_evpn_mac_clear_sync_info(zebra_mac_t *mac)
zebra_evpn_mac_stop_hold_timer(mac);
}
+static inline bool zebra_evpn_mac_in_use(zebra_mac_t *mac)
+{
+ return !list_isempty(mac->neigh_list)
+ || CHECK_FLAG(mac->flags, ZEBRA_MAC_SVI);
+}
+
struct hash *zebra_mac_db_create(const char *desc);
uint32_t num_valid_macs(zebra_evpn_t *zevi);
uint32_t num_dup_detected_macs(zebra_evpn_t *zevi);
@@ -252,11 +272,17 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf, zebra_evpn_t *zevpn,
struct interface *ifp,
struct ethaddr *macaddr, vlanid_t vid,
bool sticky, bool local_inactive,
- bool dp_static);
-int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac);
+ bool dp_static, zebra_mac_t *mac);
+int zebra_evpn_del_local_mac(zebra_evpn_t *zevpn, zebra_mac_t *mac,
+ bool clear_static);
int zebra_evpn_mac_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
struct ipaddr *ip, zebra_mac_t **macp,
- struct ethaddr *macaddr, vlanid_t vlan_id);
+ struct ethaddr *macaddr, vlanid_t vlan_id,
+ bool def_gw);
+void zebra_evpn_mac_svi_add(struct interface *ifp, zebra_evpn_t *zevpn);
+void zebra_evpn_mac_svi_del(struct interface *ifp, zebra_evpn_t *zevpn);
+void zebra_evpn_mac_ifp_del(struct interface *ifp);
+void zebra_evpn_mac_clear_fwd_info(zebra_mac_t *zmac);
#ifdef __cplusplus
}
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 7e712bf1ee..5a28ee10c6 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -130,12 +130,6 @@ static struct zebra_evpn_es_evi *zebra_evpn_es_evi_new(struct zebra_evpn_es *es,
return es_evi;
}
-/* returns TRUE if the EVPN is ready to be sent to BGP */
-static inline bool zebra_evpn_send_to_client_ok(zebra_evpn_t *zevpn)
-{
- return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
-}
-
/* Evaluate if the es_evi is ready to be sent BGP -
* 1. If it is ready an add is sent to BGP
* 2. If it is not ready a del is sent (if the ES had been previously added
@@ -466,6 +460,9 @@ void zebra_evpn_update_all_es(zebra_evpn_t *zevpn)
{
struct zebra_evpn_es_evi *es_evi;
struct listnode *node;
+ struct interface *vlan_if;
+ struct interface *vxlan_if;
+ struct zebra_if *vxlan_zif;
/* the EVPN is now elgible as a base for EVPN-MH */
if (zebra_evpn_send_to_client_ok(zevpn))
@@ -475,6 +472,20 @@ void zebra_evpn_update_all_es(zebra_evpn_t *zevpn)
for (ALL_LIST_ELEMENTS_RO(zevpn->local_es_evi_list, node, es_evi))
zebra_evpn_es_evi_re_eval_send_to_client(es_evi);
+
+ /* reinstall SVI MAC */
+ vxlan_if = zevpn->vxlan_if;
+ if (vxlan_if) {
+ vxlan_zif = vxlan_if->info;
+ if (if_is_operative(vxlan_if)
+ && vxlan_zif->brslave_info.br_if) {
+ vlan_if = zvni_map_to_svi(
+ vxlan_zif->l2info.vxl.access_vlan,
+ vxlan_zif->brslave_info.br_if);
+ if (vlan_if)
+ zebra_evpn_acc_bd_svi_mac_add(vlan_if);
+ }
+ }
}
/*****************************************************************************/
@@ -524,9 +535,11 @@ static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_find(vlanid_t vid)
/* A new broadcast domain can be created when a VLAN member or VLAN<=>VxLAN_IF
* mapping is added.
*/
-static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_new(vlanid_t vid)
+static struct zebra_evpn_access_bd *
+zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *br_if)
{
struct zebra_evpn_access_bd *acc_bd;
+ struct interface *vlan_if;
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("access vlan %d add", vid);
@@ -544,6 +557,16 @@ static struct zebra_evpn_access_bd *zebra_evpn_acc_vl_new(vlanid_t vid)
return NULL;
}
+ /* check if an svi exists for the vlan */
+ if (br_if) {
+ vlan_if = zvni_map_to_svi(vid, br_if);
+ if (vlan_if) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("vlan %d SVI %s set", vid,
+ vlan_if->name);
+ acc_bd->vlan_zif = vlan_if->info;
+ }
+ }
return acc_bd;
}
@@ -556,6 +579,9 @@ static void zebra_evpn_acc_vl_free(struct zebra_evpn_access_bd *acc_bd)
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
zlog_debug("access vlan %d del", acc_bd->vid);
+ if (acc_bd->vlan_zif && acc_bd->zevpn && acc_bd->zevpn->mac_table)
+ zebra_evpn_mac_svi_del(acc_bd->vlan_zif->ifp, acc_bd->zevpn);
+
/* cleanup resources maintained against the ES */
list_delete(&acc_bd->mbr_zifs);
@@ -584,6 +610,59 @@ static void zebra_evpn_acc_bd_free_on_deref(struct zebra_evpn_access_bd *acc_bd)
zebra_evpn_acc_vl_free(acc_bd);
}
+/* called when a SVI is goes up/down */
+void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
+ struct zebra_if *br_zif, bool is_up)
+{
+ struct zebra_evpn_access_bd *acc_bd;
+ struct zebra_l2info_bridge *br;
+ uint16_t vid;
+ struct zebra_if *tmp_br_zif = br_zif;
+
+ if (!tmp_br_zif) {
+ if (!vlan_zif->link || !vlan_zif->link->info)
+ return;
+
+ tmp_br_zif = vlan_zif->link->info;
+ }
+
+ br = &tmp_br_zif->l2info.br;
+ /* ignore vlan unaware bridges */
+ if (!br->vlan_aware)
+ return;
+
+ vid = vlan_zif->l2info.vl.vid;
+ acc_bd = zebra_evpn_acc_vl_find(vid);
+ if (!acc_bd)
+ return;
+
+ if (is_up) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("vlan %d SVI %s set", vid,
+ vlan_zif->ifp->name);
+
+ acc_bd->vlan_zif = vlan_zif;
+ if (acc_bd->zevpn)
+ zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp,
+ acc_bd->zevpn);
+ } else if (acc_bd->vlan_zif) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("vlan %d SVI clear", vid);
+ acc_bd->vlan_zif = NULL;
+ if (acc_bd->zevpn && acc_bd->zevpn->mac_table)
+ zebra_evpn_mac_svi_del(vlan_zif->ifp, acc_bd->zevpn);
+ }
+}
+
+/* On some events macs are force-flushed. This api can be used to reinstate
+ * the svi-mac after such cleanup-events.
+ */
+void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if)
+{
+ zebra_evpn_acc_bd_svi_set(vlan_if->info, NULL,
+ if_is_operative(vlan_if));
+}
+
/* called when a EVPN-L2VNI is set or cleared against a BD */
static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
zebra_evpn_t *zevpn, zebra_evpn_t *old_zevpn)
@@ -604,6 +683,15 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
else if (old_zevpn)
zebra_evpn_local_es_evi_del(zif->es_info.es, old_zevpn);
}
+
+ if (acc_bd->vlan_zif) {
+ if (zevpn)
+ zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp,
+ acc_bd->zevpn);
+ else if (old_zevpn && old_zevpn->mac_table)
+ zebra_evpn_mac_svi_del(acc_bd->vlan_zif->ifp,
+ old_zevpn);
+ }
}
/* handle VLAN->VxLAN_IF association */
@@ -618,7 +706,8 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, struct zebra_if *vxlan_zif)
acc_bd = zebra_evpn_acc_vl_find(vid);
if (!acc_bd)
- acc_bd = zebra_evpn_acc_vl_new(vid);
+ acc_bd = zebra_evpn_acc_vl_new(vid,
+ vxlan_zif->brslave_info.br_if);
old_vxlan_zif = acc_bd->vxlan_zif;
acc_bd->vxlan_zif = vxlan_zif;
@@ -712,7 +801,7 @@ void zebra_evpn_vl_mbr_ref(uint16_t vid, struct zebra_if *zif)
acc_bd = zebra_evpn_acc_vl_find(vid);
if (!acc_bd)
- acc_bd = zebra_evpn_acc_vl_new(vid);
+ acc_bd = zebra_evpn_acc_vl_new(vid, zif->brslave_info.br_if);
if (listnode_lookup(acc_bd->mbr_zifs, zif))
return;
@@ -756,6 +845,22 @@ void zebra_evpn_vl_mbr_deref(uint16_t vid, struct zebra_if *zif)
zebra_evpn_acc_bd_free_on_deref(acc_bd);
}
+static void zebra_evpn_acc_vl_adv_svi_mac_cb(struct hash_bucket *bucket,
+ void *ctxt)
+{
+ struct zebra_evpn_access_bd *acc_bd = bucket->data;
+
+ if (acc_bd->vlan_zif && acc_bd->zevpn)
+ zebra_evpn_mac_svi_add(acc_bd->vlan_zif->ifp, acc_bd->zevpn);
+}
+
+/* called when advertise SVI MAC is enabled on the switch */
+static void zebra_evpn_acc_vl_adv_svi_mac_all(void)
+{
+ hash_iterate(zmh_info->evpn_vlan_table,
+ zebra_evpn_acc_vl_adv_svi_mac_cb, NULL);
+}
+
static void zebra_evpn_acc_vl_json_fill(struct zebra_evpn_access_bd *acc_bd,
json_object *json, bool detail)
{
@@ -800,6 +905,8 @@ static void zebra_evpn_acc_vl_show_entry_detail(struct vty *vty,
vty_out(vty, " VxLAN Interface: %s\n",
acc_bd->vxlan_zif ?
acc_bd->vxlan_zif->ifp->name : "-");
+ vty_out(vty, " SVI: %s\n",
+ acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-");
vty_out(vty, " L2-VNI: %d\n",
acc_bd->zevpn ? acc_bd->zevpn->vni : 0);
vty_out(vty, " Member Count: %d\n",
@@ -817,12 +924,11 @@ static void zebra_evpn_acc_vl_show_entry(struct vty *vty,
if (json) {
zebra_evpn_acc_vl_json_fill(acc_bd, json, false);
} else {
- vty_out(vty, "%-5u %21s %-8d %u\n",
- acc_bd->vid,
- acc_bd->vxlan_zif ?
- acc_bd->vxlan_zif->ifp->name : "-",
- acc_bd->zevpn ? acc_bd->zevpn->vni : 0,
- listcount(acc_bd->mbr_zifs));
+ vty_out(vty, "%-5u %-15s %-8d %-15s %u\n", acc_bd->vid,
+ acc_bd->vlan_zif ? acc_bd->vlan_zif->ifp->name : "-",
+ acc_bd->zevpn ? acc_bd->zevpn->vni : 0,
+ acc_bd->vxlan_zif ? acc_bd->vxlan_zif->ifp->name : "-",
+ listcount(acc_bd->mbr_zifs));
}
}
@@ -856,8 +962,8 @@ void zebra_evpn_acc_vl_show(struct vty *vty, bool uj)
wctx.detail = false;
if (!uj)
- vty_out(vty, "%-5s %21s %-8s %s\n",
- "VLAN", "VxLAN-IF", "L2-VNI", "# Members");
+ vty_out(vty, "%-5s %-15s %-8s %-15s %s\n", "VLAN", "SVI",
+ "L2-VNI", "VXLAN-IF", "# Members");
hash_iterate(zmh_info->evpn_vlan_table, zebra_evpn_acc_vl_show_hash,
&wctx);
@@ -1442,20 +1548,30 @@ static bool zebra_evpn_es_br_port_dplane_update(struct zebra_evpn_es *es,
return false;
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
- zlog_debug("es %s br-port dplane update by %s", es->esi_str, caller);
+ zlog_debug("es %s br-port dplane update by %s", es->esi_str,
+ caller);
backup_nhg_id = (es->flags & ZEBRA_EVPNES_NHG_ACTIVE) ? es->nhg_id : 0;
memset(&sph_filters, 0, sizeof(sph_filters));
- if (listcount(es->es_vtep_list) > ES_VTEP_MAX_CNT) {
- zlog_warn("es %s vtep count %d exceeds filter cnt %d",
- es->esi_str, listcount(es->es_vtep_list),
- ES_VTEP_MAX_CNT);
+ if (es->flags & ZEBRA_EVPNES_BYPASS) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug(
+ "es %s SPH filter disabled as it is in bypass",
+ es->esi_str);
} else {
- for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node, es_vtep)) {
- if (es_vtep->flags & ZEBRA_EVPNES_VTEP_DEL_IN_PROG)
- continue;
- sph_filters[sph_filter_cnt] = es_vtep->vtep_ip;
- ++sph_filter_cnt;
+ if (listcount(es->es_vtep_list) > ES_VTEP_MAX_CNT) {
+ zlog_warn("es %s vtep count %d exceeds filter cnt %d",
+ es->esi_str, listcount(es->es_vtep_list),
+ ES_VTEP_MAX_CNT);
+ } else {
+ for (ALL_LIST_ELEMENTS_RO(es->es_vtep_list, node,
+ es_vtep)) {
+ if (es_vtep->flags
+ & ZEBRA_EVPNES_VTEP_DEL_IN_PROG)
+ continue;
+ sph_filters[sph_filter_cnt] = es_vtep->vtep_ip;
+ ++sph_filter_cnt;
+ }
}
}
@@ -1503,6 +1619,7 @@ static bool zebra_evpn_es_run_df_election(struct zebra_evpn_es *es,
* is no need to setup the BUM block filter
*/
if (!(es->flags & ZEBRA_EVPNES_LOCAL)
+ || (es->flags & ZEBRA_EVPNES_BYPASS)
|| !zmh_info->es_originator_ip.s_addr)
return zebra_evpn_es_df_change(es, new_non_df, caller,
"not-ready");
@@ -1728,6 +1845,7 @@ static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es)
struct zserv *client;
struct stream *s;
uint8_t oper_up;
+ bool bypass;
client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
/* BGP may not be running. */
@@ -1742,15 +1860,18 @@ static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es)
oper_up = !!(es->flags & ZEBRA_EVPNES_OPER_UP);
stream_putc(s, oper_up);
stream_putw(s, es->df_pref);
+ bypass = !!(es->flags & ZEBRA_EVPNES_BYPASS);
+ stream_putc(s, bypass);
/* Write packet size. */
stream_putw_at(s, 0, stream_get_endp(s));
if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
- zlog_debug("send add local es %s %pI4 active %u df_pref %u to %s",
- es->esi_str, &zmh_info->es_originator_ip,
- oper_up, es->df_pref,
- zebra_route_string(client->proto));
+ zlog_debug(
+ "send add local es %s %pI4 active %u df_pref %u%s to %s",
+ es->esi_str, &zmh_info->es_originator_ip, oper_up,
+ es->df_pref, bypass ? " bypass" : "",
+ zebra_route_string(client->proto));
client->local_es_add_cnt++;
return zserv_send_message(client, s);
@@ -1874,18 +1995,50 @@ static void zebra_evpn_es_setup_evis(struct zebra_evpn_es *es)
}
}
-static void zebra_evpn_es_local_mac_update(struct zebra_evpn_es *es,
- bool force_clear_static)
+static void zebra_evpn_flush_local_mac(zebra_mac_t *mac, struct interface *ifp)
+{
+ struct zebra_if *zif;
+ struct interface *br_ifp;
+ vlanid_t vid;
+
+ zif = ifp->info;
+ br_ifp = zif->brslave_info.br_if;
+ if (!br_ifp)
+ return;
+
+ if (mac->zevpn->vxlan_if) {
+ zif = mac->zevpn->vxlan_if->info;
+ vid = zif->l2info.vxl.access_vlan;
+ } else {
+ vid = 0;
+ }
+
+ /* delete the local mac from the dataplane */
+ dplane_local_mac_del(ifp, br_ifp, vid, &mac->macaddr);
+ /* delete the local mac in zebra */
+ zebra_evpn_del_local_mac(mac->zevpn, mac, true);
+}
+
+static void zebra_evpn_es_flush_local_macs(struct zebra_evpn_es *es,
+ struct interface *ifp, bool add)
{
zebra_mac_t *mac;
struct listnode *node;
+ struct listnode *nnode;
- for (ALL_LIST_ELEMENTS_RO(es->mac_list, node, mac)) {
- if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE)) {
- zebra_evpn_sync_mac_dp_install(
- mac, false /* set_inactive */,
- force_clear_static, __func__);
- }
+ for (ALL_LIST_ELEMENTS(es->mac_list, node, nnode, mac)) {
+ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
+ continue;
+
+ /* If ES is being attached/detached from the access port we
+ * need to clear local activity and peer activity and start
+ * over */
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("VNI %u mac %pEA update; local ES %s %s",
+ mac->zevpn->vni,
+ &mac->macaddr,
+ es->esi_str, add ? "add" : "del");
+ zebra_evpn_flush_local_mac(mac, ifp);
}
}
@@ -1960,6 +2113,20 @@ static void zebra_evpn_mh_advertise_reach_neigh_only(void)
*/
}
+/* On config of first local-ES turn on advertisement of local SVI-MAC */
+static void zebra_evpn_mh_advertise_svi_mac(void)
+{
+ if (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC)
+ return;
+
+ zmh_info->flags |= ZEBRA_EVPN_MH_ADV_SVI_MAC;
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("evpn-mh: advertise SVI MAC");
+
+ /* walk through all SVIs and see if we need to advertise the MAC */
+ zebra_evpn_acc_vl_adv_svi_mac_all();
+}
+
static int zebra_evpn_es_df_delay_exp_cb(struct thread *t)
{
struct zebra_evpn_es *es;
@@ -1974,6 +2141,17 @@ static int zebra_evpn_es_df_delay_exp_cb(struct thread *t)
return 0;
}
+/* currently there is no global config to turn on MH instead we use
+ * the addition of the first local Ethernet Segment as the trigger to
+ * init MH specific processing
+ */
+static void zebra_evpn_mh_on_first_local_es(void)
+{
+ zebra_evpn_mh_dup_addr_detect_off();
+ zebra_evpn_mh_advertise_reach_neigh_only();
+ zebra_evpn_mh_advertise_svi_mac();
+}
+
static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
struct zebra_if *zif)
{
@@ -1984,8 +2162,7 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
zlog_debug("local es %s add; nhg %u if %s", es->esi_str,
es->nhg_id, zif->ifp->name);
- zebra_evpn_mh_dup_addr_detect_off();
- zebra_evpn_mh_advertise_reach_neigh_only();
+ zebra_evpn_mh_on_first_local_es();
es->flags |= ZEBRA_EVPNES_LOCAL;
listnode_init(&es->local_es_listnode, es);
@@ -2004,6 +2181,10 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
if (zif->brslave_info.bridge_ifindex != IFINDEX_INTERNAL)
es->flags |= ZEBRA_EVPNES_BR_PORT;
+ /* inherit the bypass flag from the interface */
+ if (zif->flags & ZIF_FLAG_LACP_BYPASS)
+ es->flags |= ZEBRA_EVPNES_BYPASS;
+
/* setup base-vni if one doesn't already exist; the ES will get sent
* to BGP as a part of that process
*/
@@ -2035,11 +2216,9 @@ static void zebra_evpn_es_local_info_set(struct zebra_evpn_es *es,
*/
zebra_evpn_es_setup_evis(es);
/* if there any local macs referring to the ES as dest we
- * need to set the static reference on them if the MAC is
- * synced from an ES peer
+ * need to clear the contents and start over
*/
- zebra_evpn_es_local_mac_update(es,
- false /* force_clear_static */);
+ zebra_evpn_es_flush_local_macs(es, zif->ifp, true);
/* inherit EVPN protodown flags on the access port */
zebra_evpn_mh_update_protodown_es(es, true /*resync_dplane*/);
@@ -2054,33 +2233,34 @@ static void zebra_evpn_es_local_info_clear(struct zebra_evpn_es **esp)
if (!(es->flags & ZEBRA_EVPNES_LOCAL))
return;
+ zif = es->zif;
+
+ /* if there any local macs referring to the ES as dest we
+ * need to clear the contents and start over
+ */
+ zebra_evpn_es_flush_local_macs(es, zif->ifp, false);
+
es->flags &= ~(ZEBRA_EVPNES_LOCAL | ZEBRA_EVPNES_READY_FOR_BGP);
THREAD_OFF(es->df_delay_timer);
- /* remove the DF filter */
- dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
-
/* clear EVPN protodown flags on the access port */
zebra_evpn_mh_clear_protodown_es(es);
- /* if there any local macs referring to the ES as dest we
- * need to clear the static reference on them
- */
- zebra_evpn_es_local_mac_update(es,
- true /* force_clear_static */);
+ /* remove the DF filter */
+ dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
/* flush the BUM filters and backup NHG */
if (!dplane_updated)
zebra_evpn_es_br_port_dplane_clear(es);
/* clear the es from the parent interface */
- zif = es->zif;
zif->es_info.es = NULL;
es->zif = NULL;
/* clear all local flags associated with the ES */
- es->flags &= ~(ZEBRA_EVPNES_OPER_UP | ZEBRA_EVPNES_BR_PORT);
+ es->flags &= ~(ZEBRA_EVPNES_OPER_UP | ZEBRA_EVPNES_BR_PORT
+ | ZEBRA_EVPNES_BYPASS);
/* remove from the ES list */
list_delete_node(zmh_info->local_es_list, &es->local_es_listnode);
@@ -2493,6 +2673,102 @@ static void zebra_evpn_es_df_pref_update(struct zebra_if *zif, uint16_t df_pref)
zebra_evpn_es_send_add_to_client(es);
}
+/* If bypass mode on an es changed we set all local macs to
+ * inactive and drop the sync info
+ */
+static void zebra_evpn_es_bypass_update_macs(struct zebra_evpn_es *es,
+ struct interface *ifp, bool bypass)
+{
+ zebra_mac_t *mac;
+ struct listnode *node;
+ struct listnode *nnode;
+ struct zebra_if *zif;
+
+ /* Flush all MACs linked to the ES */
+ for (ALL_LIST_ELEMENTS(es->mac_list, node, nnode, mac)) {
+ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
+ continue;
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("VNI %u mac %pEA %s update es %s",
+ mac->zevpn->vni,
+ &mac->macaddr,
+ bypass ? "bypass" : "non-bypass",
+ es->esi_str);
+ zebra_evpn_flush_local_mac(mac, ifp);
+ }
+
+ /* While in bypass-mode locally learnt MACs are linked
+ * to the access port instead of the ES
+ */
+ zif = ifp->info;
+ if (!zif->mac_list)
+ return;
+
+ for (ALL_LIST_ELEMENTS(zif->mac_list, node, nnode, mac)) {
+ if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
+ continue;
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("VNI %u mac %pEA %s update ifp %s",
+ mac->zevpn->vni,
+ &mac->macaddr,
+ bypass ? "bypass" : "non-bypass", ifp->name);
+ zebra_evpn_flush_local_mac(mac, ifp);
+ }
+}
+
+void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
+ struct interface *ifp, bool bypass)
+{
+ bool old_bypass;
+ bool dplane_updated;
+
+ old_bypass = !!(es->flags & ZEBRA_EVPNES_BYPASS);
+ if (old_bypass == bypass)
+ return;
+
+ if (bypass)
+ es->flags |= ZEBRA_EVPNES_BYPASS;
+ else
+ es->flags &= ~ZEBRA_EVPNES_BYPASS;
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
+ zlog_debug("bond %s es %s lacp bypass changed to %s", ifp->name,
+ es->esi_str, bypass ? "on" : "off");
+
+ /* send bypass update to BGP */
+ if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
+ zebra_evpn_es_send_add_to_client(es);
+
+ zebra_evpn_es_bypass_update_macs(es, ifp, bypass);
+
+ /* re-run DF election */
+ dplane_updated = zebra_evpn_es_run_df_election(es, __func__);
+
+ /* disable SPH filter */
+ if (!dplane_updated && (es->flags & ZEBRA_EVPNES_LOCAL)
+ && (listcount(es->es_vtep_list) > ES_VTEP_MAX_CNT))
+ zebra_evpn_es_br_port_dplane_update(es, __func__);
+}
+
+static void zebra_evpn_es_bypass_cfg_update(struct zebra_if *zif, bool bypass)
+{
+ bool old_bypass = !!(zif->es_info.flags & ZIF_CFG_ES_FLAG_BYPASS);
+
+ if (old_bypass == bypass)
+ return;
+
+ if (bypass)
+ zif->es_info.flags |= ZIF_CFG_ES_FLAG_BYPASS;
+ else
+ zif->es_info.flags &= ~ZIF_CFG_ES_FLAG_BYPASS;
+
+
+ if (zif->es_info.es)
+ zebra_evpn_es_bypass_update(zif->es_info.es, zif->ifp, bypass);
+}
+
/* Only certain types of access ports can be setup as an Ethernet Segment */
bool zebra_evpn_is_if_es_capable(struct zebra_if *zif)
@@ -2688,7 +2964,7 @@ static void zebra_evpn_es_json_vtep_fill(struct zebra_evpn_es *es,
static void zebra_evpn_es_show_entry(struct vty *vty, struct zebra_evpn_es *es,
json_object *json_array)
{
- char type_str[4];
+ char type_str[5];
char vtep_str[ES_VTEP_LIST_STR_SZ];
if (json_array) {
@@ -2709,6 +2985,8 @@ static void zebra_evpn_es_show_entry(struct vty *vty, struct zebra_evpn_es *es,
json_array_string_add(json_flags, "remote");
if (es->flags & ZEBRA_EVPNES_NON_DF)
json_array_string_add(json_flags, "nonDF");
+ if (es->flags & ZEBRA_EVPNES_BYPASS)
+ json_array_string_add(json_flags, "bypass");
json_object_object_add(json, "flags", json_flags);
}
@@ -2730,6 +3008,8 @@ static void zebra_evpn_es_show_entry(struct vty *vty, struct zebra_evpn_es *es,
strlcat(type_str, "R", sizeof(type_str));
if (es->flags & ZEBRA_EVPNES_NON_DF)
strlcat(type_str, "N", sizeof(type_str));
+ if (es->flags & ZEBRA_EVPNES_BYPASS)
+ strlcat(type_str, "B", sizeof(type_str));
zebra_evpn_es_vtep_str(vtep_str, es, sizeof(vtep_str));
@@ -2767,6 +3047,8 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
json_array_string_add(json_flags, "remote");
if (es->flags & ZEBRA_EVPNES_NON_DF)
json_array_string_add(json_flags, "nonDF");
+ if (es->flags & ZEBRA_EVPNES_BYPASS)
+ json_array_string_add(json_flags, "bypass");
if (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)
json_array_string_add(json_flags,
"readyForBgp");
@@ -2822,6 +3104,8 @@ static void zebra_evpn_es_show_entry_detail(struct vty *vty,
vty_out(vty, " Ready for BGP: %s\n",
(es->flags & ZEBRA_EVPNES_READY_FOR_BGP) ?
"yes" : "no");
+ if (es->flags & ZEBRA_EVPNES_BYPASS)
+ vty_out(vty, " LACP bypass: on\n");
vty_out(vty, " VNI Count: %d\n", listcount(es->es_evi_list));
vty_out(vty, " MAC Count: %d\n", listcount(es->mac_list));
if (es->flags & ZEBRA_EVPNES_LOCAL)
@@ -2861,7 +3145,7 @@ void zebra_evpn_es_show(struct vty *vty, bool uj)
if (uj) {
json_array = json_object_new_array();
} else {
- vty_out(vty, "Type: L local, R remote, N non-DF\n");
+ vty_out(vty, "Type: B bypass, L local, R remote, N non-DF\n");
vty_out(vty, "%-30s %-4s %-21s %s\n",
"ESI", "Type", "ES-IF", "VTEPs");
}
@@ -2967,12 +3251,35 @@ int zebra_evpn_mh_if_write(struct vty *vty, struct interface *ifp)
#ifndef VTYSH_EXTRACT_PL
#include "zebra/zebra_evpn_mh_clippy.c"
#endif
+/* CLI for setting an ES in bypass mode */
+DEFPY_HIDDEN(zebra_evpn_es_bypass, zebra_evpn_es_bypass_cmd,
+ "[no] evpn mh bypass",
+ NO_STR "EVPN\n" EVPN_MH_VTY_STR "set bypass mode\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct zebra_if *zif;
+
+ zif = ifp->info;
+
+ if (no) {
+ zebra_evpn_es_bypass_cfg_update(zif, false);
+ } else {
+ if (!zebra_evpn_is_if_es_capable(zif)) {
+ vty_out(vty,
+ "%%DF bypass cannot be associated with this interface type\n");
+ return CMD_WARNING;
+ }
+ zebra_evpn_es_bypass_cfg_update(zif, true);
+ }
+ return CMD_SUCCESS;
+}
+
/* CLI for configuring DF preference part for an ES */
DEFPY(zebra_evpn_es_pref, zebra_evpn_es_pref_cmd,
"[no$no] evpn mh es-df-pref [(1-65535)$df_pref]",
NO_STR "EVPN\n" EVPN_MH_VTY_STR
"preference value used for DF election\n"
- "ID\n")
+ "pref\n")
{
VTY_DECLVAR_CONTEXT(interface, ifp);
struct zebra_if *zif;
@@ -3637,6 +3944,7 @@ void zebra_evpn_interface_init(void)
install_element(INTERFACE_NODE, &zebra_evpn_es_id_cmd);
install_element(INTERFACE_NODE, &zebra_evpn_es_sys_mac_cmd);
install_element(INTERFACE_NODE, &zebra_evpn_es_pref_cmd);
+ install_element(INTERFACE_NODE, &zebra_evpn_es_bypass_cmd);
install_element(INTERFACE_NODE, &zebra_evpn_mh_uplink_cmd);
}
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index 81ae740d49..2361a70bff 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -60,6 +60,10 @@ struct zebra_evpn_es {
* filter, SPH filter and backup NHG for fast-failover
*/
#define ZEBRA_EVPNES_BR_PORT (1 << 6)
+/* ES is in bypass mode i.e. must not be advertised. ES-bypass is set
+ * when the associated host bond goes into LACP bypass
+ */
+#define ZEBRA_EVPNES_BYPASS (1 << 7)
/* memory used for adding the es to zmh_info->es_rb_tree */
RB_ENTRY(zebra_evpn_es) rb_node;
@@ -180,6 +184,8 @@ struct zebra_evpn_access_bd {
struct list *mbr_zifs;
/* presence of zevpn activates the EVI on all the ESs in mbr_zifs */
zebra_evpn_t *zevpn;
+ /* SVI associated with the VLAN */
+ struct zebra_if *vlan_zif;
};
/* multihoming information stored in zrouter */
@@ -200,6 +206,10 @@ struct zebra_evpn_mh_info {
* this flag when the first local ES is detected.
*/
#define ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY (1 << 2)
+/* If EVPN MH is enabled we advertise the SVI MAC address to avoid
+ * flooding of ARP replies rxed from the multi-homed host
+ */
+#define ZEBRA_EVPN_MH_ADV_SVI_MAC (1 << 3)
/* RB tree of Ethernet segments (used for EVPN-MH) */
struct zebra_es_rb_head es_rb_tree;
@@ -256,6 +266,12 @@ struct zebra_evpn_mh_info {
enum protodown_reasons protodown_rc;
};
+/* returns TRUE if the EVPN is ready to be sent to BGP */
+static inline bool zebra_evpn_send_to_client_ok(zebra_evpn_t *zevpn)
+{
+ return !!(zevpn->flags & ZEVPN_READY_FOR_BGP);
+}
+
static inline bool zebra_evpn_mac_is_es_local(zebra_mac_t *mac)
{
return mac->es && (mac->es->flags & ZEBRA_EVPNES_LOCAL);
@@ -285,6 +301,10 @@ static inline bool zebra_evpn_mh_do_adv_reachable_neigh_only(void)
return !!(zmh_info->flags & ZEBRA_EVPN_MH_ADV_REACHABLE_NEIGH_ONLY);
}
+static inline bool zebra_evpn_mh_do_adv_svi_mac(void)
+{
+ return zmh_info && (zmh_info->flags & ZEBRA_EVPN_MH_ADV_SVI_MAC);
+}
/*****************************************************************************/
extern esi_t *zero_esi;
@@ -357,5 +377,10 @@ extern bool zebra_evpn_is_es_bond_member(struct interface *ifp);
extern void zebra_evpn_mh_print(struct vty *vty);
extern void zebra_evpn_mh_json(json_object *json);
extern void zebra_evpn_l2_nh_show(struct vty *vty, bool uj);
+extern void zebra_evpn_acc_bd_svi_set(struct zebra_if *vlan_zif,
+ struct zebra_if *br_zif, bool is_up);
+extern void zebra_evpn_acc_bd_svi_mac_add(struct interface *vlan_if);
+extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
+ struct interface *ifp, bool bypass);
#endif /* _ZEBRA_EVPN_MH_H */
diff --git a/zebra/zebra_evpn_neigh.c b/zebra/zebra_evpn_neigh.c
index 1f45b72e3a..0e31617c4f 100644
--- a/zebra/zebra_evpn_neigh.c
+++ b/zebra/zebra_evpn_neigh.c
@@ -209,8 +209,6 @@ static void zebra_evpn_local_neigh_ref_mac(zebra_neigh_t *n,
zebra_mac_t *mac,
bool send_mac_update)
{
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
bool old_static;
bool new_static;
@@ -228,11 +226,8 @@ static void zebra_evpn_local_neigh_ref_mac(zebra_neigh_t *n,
new_static = zebra_evpn_mac_is_static(mac);
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "sync-neigh ref mac vni %u ip %s mac %s ref %d",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf,
- sizeof(macbuf)),
+ "sync-neigh ref mac vni %u ip %pIA mac %pEA ref %d",
+ n->zevpn->vni, &n->ip, &n->emac,
mac->sync_neigh_cnt);
if ((old_static != new_static) && send_mac_update)
/* program the local mac in the kernel */
@@ -248,8 +243,6 @@ static void zebra_evpn_sync_neigh_dp_install(zebra_neigh_t *n,
bool force_clear_static,
const char *caller)
{
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
struct zebra_ns *zns;
struct interface *ifp;
bool set_static;
@@ -260,11 +253,8 @@ static void zebra_evpn_sync_neigh_dp_install(zebra_neigh_t *n,
if (!ifp) {
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "%s: dp-install sync-neigh vni %u ip %s mac %s if %d f 0x%x skipped",
- caller, n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf,
- sizeof(macbuf)),
+ "%s: dp-install sync-neigh vni %u ip %pIA mac %pEA if %d f 0x%x skipped",
+ caller, n->zevpn->vni, &n->ip, &n->emac,
n->ifindex, n->flags);
return;
}
@@ -282,10 +272,8 @@ static void zebra_evpn_sync_neigh_dp_install(zebra_neigh_t *n,
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "%s: dp-install sync-neigh vni %u ip %s mac %s if %s(%d) f 0x%x%s%s%s",
- caller, n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
+ "%s: dp-install sync-neigh vni %u ip %pIA mac %pEA if %s(%d) f 0x%x%s%s%s",
+ caller, n->zevpn->vni, &n->ip, &n->emac,
ifp->name, n->ifindex, n->flags,
set_router ? " router" : "",
set_static ? " static" : "",
@@ -327,9 +315,9 @@ int zebra_evpn_neigh_send_add_to_client(vni_t vni, struct ipaddr *ip,
if (CHECK_FLAG(neigh_flags, ZEBRA_NEIGH_SVI_IP))
SET_FLAG(flags, ZEBRA_MACIP_TYPE_SVI_IP);
- return zebra_evpn_macip_send_msg_to_client(
- vni, macaddr, ip, flags, seq, ZEBRA_NEIGH_ACTIVE,
- zmac ? zmac->es : NULL, ZEBRA_MACIP_ADD);
+ return zebra_evpn_macip_send_msg_to_client(vni, macaddr, ip, flags, seq,
+ ZEBRA_NEIGH_ACTIVE, zmac->es,
+ ZEBRA_MACIP_ADD);
}
/*
@@ -375,8 +363,6 @@ void zebra_evpn_sync_neigh_static_chg(zebra_neigh_t *n, bool old_n_static,
zebra_mac_t *mac = n->mac;
bool old_mac_static;
bool new_mac_static;
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
if (old_n_static == new_n_static)
return;
@@ -411,10 +397,9 @@ void zebra_evpn_sync_neigh_static_chg(zebra_neigh_t *n, bool old_n_static,
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "sync-neigh ref-chg vni %u ip %s mac %s f 0x%x %d%s%s%s%s by %s",
- n->zevpn->vni, ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
- n->flags, mac->sync_neigh_cnt,
+ "sync-neigh ref-chg vni %u ip %pIA mac %pEA f 0x%x %d%s%s%s%s by %s",
+ n->zevpn->vni, &n->ip, &n->emac, n->flags,
+ mac->sync_neigh_cnt,
old_n_static ? " old_n_static" : "",
new_n_static ? " new_n_static" : "",
old_mac_static ? " old_mac_static" : "",
@@ -434,8 +419,6 @@ static int zebra_evpn_neigh_hold_exp_cb(struct thread *t)
bool new_bgp_ready;
bool old_n_static;
bool new_n_static;
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
n = THREAD_ARG(t);
/* the purpose of the hold timer is to age out the peer-active
@@ -451,11 +434,8 @@ static int zebra_evpn_neigh_hold_exp_cb(struct thread *t)
new_n_static = zebra_evpn_neigh_is_static(n);
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
- zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold expired",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
- n->flags);
+ zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x hold expired",
+ n->zevpn->vni, &n->ip, &n->emac, n->flags);
/* re-program the local neigh in the dataplane if the neigh is no
* longer static
@@ -475,18 +455,12 @@ static int zebra_evpn_neigh_hold_exp_cb(struct thread *t)
static inline void zebra_evpn_neigh_start_hold_timer(zebra_neigh_t *n)
{
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
-
if (n->hold_timer)
return;
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
- zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold start",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
- n->flags);
+ zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x hold start",
+ n->zevpn->vni, &n->ip, &n->emac, n->flags);
thread_add_timer(zrouter.master, zebra_evpn_neigh_hold_exp_cb, n,
zmh_info->neigh_hold_time, &n->hold_timer);
}
@@ -496,8 +470,6 @@ static void zebra_evpn_local_neigh_deref_mac(zebra_neigh_t *n,
{
zebra_mac_t *mac = n->mac;
zebra_evpn_t *zevpn = n->zevpn;
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
bool old_static;
bool new_static;
@@ -511,11 +483,8 @@ static void zebra_evpn_local_neigh_deref_mac(zebra_neigh_t *n,
new_static = zebra_evpn_mac_is_static(mac);
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "sync-neigh deref mac vni %u ip %s mac %s ref %d",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf,
- sizeof(macbuf)),
+ "sync-neigh deref mac vni %u ip %pIA mac %pEA ref %d",
+ n->zevpn->vni, &n->ip, &n->emac,
mac->sync_neigh_cnt);
if ((old_static != new_static) && send_mac_update)
/* program the local mac in the kernel */
@@ -532,8 +501,6 @@ bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
struct ethaddr *macaddr, uint32_t seq,
bool sync)
{
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
uint32_t tmp_seq;
const char *n_type;
@@ -555,24 +522,18 @@ bool zebra_evpn_neigh_is_bgp_seq_ok(zebra_evpn_t *zevpn, zebra_neigh_t *n,
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH
|| IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s-macip accept vni %u %s mac %s IP %s lower seq %u f 0x%x",
+ "%s-macip accept vni %u %s mac %pEA IP %pIA lower seq %u f 0x%x",
sync ? "sync" : "remote", zevpn->vni,
- n_type,
- prefix_mac2str(macaddr, macbuf,
- sizeof(macbuf)),
- ipaddr2str(&n->ip, ipbuf,
- sizeof(ipbuf)),
+ n_type, macaddr, &n->ip,
tmp_seq, n->flags);
return true;
}
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH || IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s-macip ignore vni %u %s mac %s IP %s as existing has higher seq %u f 0x%x",
+ "%s-macip ignore vni %u %s mac %pEA IP %pIA as existing has higher seq %u f 0x%x",
sync ? "sync" : "remote", zevpn->vni, n_type,
- prefix_mac2str(macaddr, macbuf, sizeof(macbuf)),
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- tmp_seq, n->flags);
+ macaddr, &n->ip, tmp_seq, n->flags);
return false;
}
@@ -636,15 +597,10 @@ void zebra_evpn_sync_neigh_del(zebra_neigh_t *n)
{
bool old_n_static;
bool new_n_static;
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
- zlog_debug("sync-neigh del vni %u ip %s mac %s f 0x%x",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
- n->flags);
+ zlog_debug("sync-neigh del vni %u ip %pIA mac %pEA f 0x%x",
+ n->zevpn->vni, &n->ip, &n->emac, n->flags);
old_n_static = zebra_evpn_neigh_is_static(n);
UNSET_FLAG(n->flags, ZEBRA_NEIGH_ES_PEER_PROXY);
@@ -676,8 +632,6 @@ zebra_evpn_proc_sync_neigh_update(zebra_evpn_t *zevpn, zebra_neigh_t *n,
bool old_mac_static;
bool new_mac_static;
bool set_dp_inactive = false;
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
bool created;
ifindex_t ifindex = 0;
@@ -778,11 +732,8 @@ zebra_evpn_proc_sync_neigh_update(zebra_evpn_t *zevpn, zebra_neigh_t *n,
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH && (old_flags != n->flags))
zlog_debug(
- "sync-neigh vni %u ip %s mac %s old_f 0x%x new_f 0x%x",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf,
- sizeof(macbuf)),
+ "sync-neigh vni %u ip %pIA mac %pEA old_f 0x%x new_f 0x%x",
+ n->zevpn->vni, &n->ip, &n->emac,
old_flags, n->flags);
new_n_static = zebra_evpn_neigh_is_static(n);
@@ -844,10 +795,9 @@ zebra_evpn_proc_sync_neigh_update(zebra_evpn_t *zevpn, zebra_neigh_t *n,
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "sync-neigh %s vni %u ip %s mac %s if %s(%d) seq %d f 0x%x%s%s",
+ "sync-neigh %s vni %u ip %pIA mac %pEA if %s(%d) seq %d f 0x%x%s%s",
created ? "created" : "updated", n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
+ &n->ip, &n->emac,
ifp ? ifp->name : "", ifindex, n->loc_seq, n->flags,
inform_bgp ? " inform_bgp" : "",
inform_dataplane ? " inform_dp" : "");
@@ -970,14 +920,13 @@ void zebra_evpn_process_neigh_on_local_mac_change(zebra_evpn_t *zevpn,
zebra_neigh_t *n = NULL;
struct listnode *node = NULL;
struct zebra_vrf *zvrf = NULL;
- char buf[ETHER_ADDR_STRLEN];
zvrf = vrf_info_lookup(zevpn->vxlan_if->vrf_id);
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Processing neighbors on local MAC %s %s, VNI %u",
- prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
- seq_change ? "CHANGE" : "ADD", zevpn->vni);
+ zlog_debug("Processing neighbors on local MAC %pEA %s, VNI %u",
+ &zmac->macaddr, seq_change ? "CHANGE" : "ADD",
+ zevpn->vni);
/* Walk all neighbors and mark any inactive local neighbors as
* active and/or update sequence number upon a move, and inform BGP.
@@ -1012,12 +961,10 @@ void zebra_evpn_process_neigh_on_local_mac_del(zebra_evpn_t *zevpn,
{
zebra_neigh_t *n = NULL;
struct listnode *node = NULL;
- char buf[ETHER_ADDR_STRLEN];
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Processing neighbors on local MAC %s DEL, VNI %u",
- prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
- zevpn->vni);
+ zlog_debug("Processing neighbors on local MAC %pEA DEL, VNI %u",
+ &zmac->macaddr, zevpn->vni);
/* Walk all local neighbors and mark as inactive and inform
* BGP, if needed.
@@ -1047,12 +994,10 @@ void zebra_evpn_process_neigh_on_remote_mac_add(zebra_evpn_t *zevpn,
{
zebra_neigh_t *n = NULL;
struct listnode *node = NULL;
- char buf[ETHER_ADDR_STRLEN];
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Processing neighbors on remote MAC %s ADD, VNI %u",
- prefix_mac2str(&zmac->macaddr, buf, sizeof(buf)),
- zevpn->vni);
+ zlog_debug("Processing neighbors on remote MAC %pEA ADD, VNI %u",
+ &zmac->macaddr, zevpn->vni);
/* Walk all local neighbors and mark as inactive and inform
* BGP, if needed.
@@ -1085,15 +1030,11 @@ static inline void zebra_evpn_local_neigh_update_log(
bool old_bgp_ready, bool new_bgp_ready, bool inform_dataplane,
bool inform_bgp, const char *sfx)
{
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
-
if (!IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
return;
- zlog_debug("%s neigh vni %u ip %s mac %s f 0x%x%s%s%s%s%s%s %s", pfx,
- n->zevpn->vni, ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)), n->flags,
+ zlog_debug("%s neigh vni %u ip %pIA mac %pEA f 0x%x%s%s%s%s%s%s %s", pfx,
+ n->zevpn->vni, &n->ip, &n->emac, n->flags,
is_router ? " router" : "",
local_inactive ? " local-inactive" : "",
old_bgp_ready ? " old_bgp_ready" : "",
@@ -1154,8 +1095,6 @@ static int zebra_evpn_dad_ip_auto_recovery_exp(struct thread *t)
struct zebra_vrf *zvrf = NULL;
zebra_neigh_t *nbr = NULL;
zebra_evpn_t *zevpn = NULL;
- char buf1[INET6_ADDRSTRLEN];
- char buf2[ETHER_ADDR_STRLEN];
nbr = THREAD_ARG(t);
@@ -1174,10 +1113,8 @@ static int zebra_evpn_dad_ip_auto_recovery_exp(struct thread *t)
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: duplicate addr MAC %s IP %s flags 0x%x learn count %u vni %u auto recovery expired",
- __func__,
- prefix_mac2str(&nbr->emac, buf2, sizeof(buf2)),
- ipaddr2str(&nbr->ip, buf1, sizeof(buf1)), nbr->flags,
+ "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x learn count %u vni %u auto recovery expired",
+ __func__, &nbr->emac, &nbr->ip, nbr->flags,
nbr->dad_count, zevpn->vni);
UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
@@ -1207,8 +1144,6 @@ zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr,
{
struct timeval elapsed = {0, 0};
- char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
bool reset_params = false;
if (!zebra_evpn_do_dup_addr_detect(zvrf))
@@ -1221,10 +1156,8 @@ zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr,
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE)) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: duplicate addr MAC %s IP %s flags 0x%x skip installing, learn count %u recover time %u",
- __func__,
- prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
- ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+ "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x skip installing, learn count %u recover time %u",
+ __func__, &nbr->emac, &nbr->ip,
nbr->flags, nbr->dad_count,
zvrf->dad_freeze_time);
@@ -1261,10 +1194,8 @@ zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr,
if (reset_params) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: duplicate addr MAC %s IP %s flags 0x%x detection time passed, reset learn count %u",
- __func__,
- prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
- ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+ "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x detection time passed, reset learn count %u",
+ __func__, &nbr->emac, &nbr->ip,
nbr->flags, nbr->dad_count);
/* Reset learn count but do not start detection
* during REMOTE learn event.
@@ -1294,10 +1225,8 @@ zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr,
if (nbr->dad_count >= zvrf->dad_max_moves) {
flog_warn(
EC_ZEBRA_DUP_IP_DETECTED,
- "VNI %u: MAC %s IP %s detected as duplicate during %s VTEP %pI4",
- nbr->zevpn->vni,
- prefix_mac2str(&nbr->emac, buf, sizeof(buf)),
- ipaddr2str(&nbr->ip, buf1, sizeof(buf1)),
+ "VNI %u: MAC %pEA IP %pIA detected as duplicate during %s VTEP %pI4",
+ nbr->zevpn->vni, &nbr->emac, &nbr->ip,
is_local ? "local update, last" : "remote update, from",
&vtep_ip);
@@ -1311,12 +1240,8 @@ zebra_evpn_dup_addr_detect_for_neigh(struct zebra_vrf *zvrf, zebra_neigh_t *nbr,
if (zvrf->dad_freeze && zvrf->dad_freeze_time) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: duplicate addr MAC %s IP %s flags 0x%x auto recovery time %u start",
- __func__,
- prefix_mac2str(&nbr->emac, buf,
- sizeof(buf)),
- ipaddr2str(&nbr->ip, buf1,
- sizeof(buf1)),
+ "%s: duplicate addr MAC %pEA IP %pIA flags 0x%x auto recovery time %u start",
+ __func__, &nbr->emac, &nbr->ip,
nbr->flags, zvrf->dad_freeze_time);
thread_add_timer(zrouter.master,
@@ -1334,8 +1259,6 @@ int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
bool is_router, bool local_inactive,
bool dp_static)
{
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
struct zebra_vrf *zvrf;
zebra_neigh_t *n = NULL;
zebra_mac_t *zmac = NULL, *old_zmac = NULL;
@@ -1357,20 +1280,17 @@ int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
if (!zmac) {
/* create a dummy MAC if the MAC is not already present */
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("AUTO MAC %s created for neigh %s on VNI %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ipaddr2str(ip, buf2, sizeof(buf2)),
- zevpn->vni);
+ zlog_debug("AUTO MAC %pEA created for neigh %pIA on VNI %u",
+ macaddr, ip, zevpn->vni);
zmac = zebra_evpn_mac_add(zevpn, macaddr);
if (!zmac) {
- zlog_debug("Failed to add MAC %s VNI %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
+ zlog_debug("Failed to add MAC %pEA VNI %u", macaddr,
zevpn->vni);
return -1;
}
- memset(&zmac->fwd_info, 0, sizeof(zmac->fwd_info));
+ zebra_evpn_mac_clear_fwd_info(zmac);
memset(&zmac->flags, 0, sizeof(uint32_t));
SET_FLAG(zmac->flags, ZEBRA_MAC_AUTO);
} else {
@@ -1402,10 +1322,9 @@ int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
if (!n) {
flog_err(
EC_ZEBRA_MAC_ADD_FAILED,
- "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
- ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- ifp->name, ifp->ifindex, zevpn->vni);
+ "Failed to add neighbor %pIA MAC %pEA intf %s(%u) -> VNI %u",
+ ip, macaddr, ifp->name, ifp->ifindex,
+ zevpn->vni);
return -1;
}
/* Set "local" forwarding info. */
@@ -1606,9 +1525,8 @@ int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_zmac, zmac, n)) {
flog_warn(
EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
- "VNI %u: MAC %s IP %s detected as duplicate during local update, inherit duplicate from MAC",
- zevpn->vni, prefix_mac2str(macaddr, buf, sizeof(buf)),
- ipaddr2str(&n->ip, buf2, sizeof(buf2)));
+ "VNI %u: MAC %pEA IP %pIA detected as duplicate during local update, inherit duplicate from MAC",
+ zevpn->vni, macaddr, &n->ip);
}
/* For IP Duplicate Address Detection (DAD) is trigger,
@@ -1651,9 +1569,9 @@ int zebra_evpn_local_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
if (upd_mac_seq && zmac->loc_seq != mac_new_seq) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Seq changed for MAC %s VNI %u - old %u new %u",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- zevpn->vni, zmac->loc_seq, mac_new_seq);
+ "Seq changed for MAC %pEA VNI %u - old %u new %u",
+ macaddr, zevpn->vni,
+ zmac->loc_seq, mac_new_seq);
zmac->loc_seq = mac_new_seq;
if (zebra_evpn_mac_send_add_to_client(zevpn->vni, macaddr,
zmac->flags,
@@ -1682,8 +1600,6 @@ int zebra_evpn_remote_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
struct ipaddr *ip, struct ethaddr *macaddr,
uint16_t state)
{
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
zebra_neigh_t *n = NULL;
zebra_mac_t *zmac = NULL;
@@ -1708,10 +1624,8 @@ int zebra_evpn_remote_neigh_update(zebra_evpn_t *zevpn, struct interface *ifp,
zmac = zebra_evpn_mac_lookup(zevpn, macaddr);
if (!zmac || !CHECK_FLAG(zmac->flags, ZEBRA_MAC_REMOTE)) {
zlog_debug(
- "Ignore remote neigh %s (MAC %s) on L2-VNI %u - MAC unknown or local",
- ipaddr2str(&n->ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, buf, sizeof(buf)),
- zevpn->vni);
+ "Ignore remote neigh %pIA (MAC %pEA) on L2-VNI %u - MAC unknown or local",
+ &n->ip, macaddr, zevpn->vni);
return -1;
}
@@ -2140,8 +2054,6 @@ void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
{
zebra_neigh_t *n;
int update_neigh = 0;
- char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
zebra_mac_t *old_mac = NULL;
bool old_static = false;
bool do_dad = false;
@@ -2167,11 +2079,9 @@ void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
mac, 0);
if (!n) {
zlog_warn(
- "Failed to add Neigh %s MAC %s VNI %u Remote VTEP %pI4",
- ipaddr2str(ipaddr, buf1, sizeof(buf1)),
- prefix_mac2str(&mac->macaddr, buf,
- sizeof(buf)),
- zevpn->vni, &vtep_ip);
+ "Failed to add Neigh %pIA MAC %pEA VNI %u Remote VTEP %pI4",
+ ipaddr, &mac->macaddr, zevpn->vni,
+ &vtep_ip);
return;
}
@@ -2192,12 +2102,8 @@ void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
old_static = zebra_evpn_neigh_is_static(n);
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "sync->remote neigh vni %u ip %s mac %s seq %d f0x%x",
- n->zevpn->vni,
- ipaddr2str(&n->ip, buf1,
- sizeof(buf1)),
- prefix_mac2str(&n->emac, buf,
- sizeof(buf)),
+ "sync->remote neigh vni %u ip %pIA mac %pEA seq %d f0x%x",
+ n->zevpn->vni, &n->ip, &n->emac,
seq, n->flags);
zebra_evpn_neigh_clear_sync_info(n);
if (IS_ZEBRA_NEIGH_ACTIVE(n))
@@ -2258,10 +2164,8 @@ void process_neigh_remote_macip_add(zebra_evpn_t *zevpn, struct zebra_vrf *zvrf,
if (zebra_evpn_ip_inherit_dad_from_mac(zvrf, old_mac, mac, n)) {
flog_warn(
EC_ZEBRA_DUP_IP_INHERIT_DETECTED,
- "VNI %u: MAC %s IP %s detected as duplicate during remote update, inherit duplicate from MAC",
- zevpn->vni,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- ipaddr2str(&n->ip, buf1, sizeof(buf1)));
+ "VNI %u: MAC %pEA IP %pIA detected as duplicate during remote update, inherit duplicate from MAC",
+ zevpn->vni, &mac->macaddr, &n->ip);
}
/* Check duplicate address detection for IP */
@@ -2280,8 +2184,6 @@ int zebra_evpn_neigh_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
struct ipaddr *ip, zebra_mac_t *mac)
{
zebra_neigh_t *n;
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
assert(mac);
@@ -2291,9 +2193,8 @@ int zebra_evpn_neigh_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
if (!n) {
flog_err(
EC_ZEBRA_MAC_ADD_FAILED,
- "Failed to add neighbor %s MAC %s intf %s(%u) -> VNI %u",
- ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
+ "Failed to add neighbor %pIA MAC %pEA intf %s(%u) -> VNI %u",
+ ip, &mac->macaddr,
ifp->name, ifp->ifindex, zevpn->vni);
return -1;
}
@@ -2316,10 +2217,9 @@ int zebra_evpn_neigh_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "SVI %s(%u) L2-VNI %u, sending GW MAC %s IP %s add to BGP with flags 0x%x",
+ "SVI %s(%u) L2-VNI %u, sending GW MAC %pEA IP %pIA add to BGP with flags 0x%x",
ifp->name, ifp->ifindex, zevpn->vni,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
+ &mac->macaddr, ip, n->flags);
zebra_evpn_neigh_send_add_to_client(
zevpn->vni, ip, &n->emac, n->mac, n->flags, n->loc_seq);
@@ -2328,10 +2228,9 @@ int zebra_evpn_neigh_gw_macip_add(struct interface *ifp, zebra_evpn_t *zevpn,
SET_FLAG(n->flags, ZEBRA_NEIGH_SVI_IP);
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "SVI %s(%u) L2-VNI %u, sending SVI MAC %s IP %s add to BGP with flags 0x%x",
+ "SVI %s(%u) L2-VNI %u, sending SVI MAC %pEA IP %pIA add to BGP with flags 0x%x",
ifp->name, ifp->ifindex, zevpn->vni,
- prefix_mac2str(&mac->macaddr, buf, sizeof(buf)),
- ipaddr2str(ip, buf2, sizeof(buf2)), n->flags);
+ &mac->macaddr, ip, n->flags);
zebra_evpn_neigh_send_add_to_client(
zevpn->vni, ip, &n->emac, n->mac, n->flags, n->loc_seq);
@@ -2344,8 +2243,6 @@ void zebra_evpn_neigh_remote_uninstall(zebra_evpn_t *zevpn,
struct zebra_vrf *zvrf, zebra_neigh_t *n,
zebra_mac_t *mac, struct ipaddr *ipaddr)
{
- char buf1[INET6_ADDRSTRLEN];
-
if (zvrf->dad_freeze && CHECK_FLAG(n->flags, ZEBRA_NEIGH_DUPLICATE)
&& CHECK_FLAG(n->flags, ZEBRA_NEIGH_REMOTE)
&& (memcmp(n->emac.octet, mac->macaddr.octet, ETH_ALEN) == 0)) {
@@ -2354,10 +2251,9 @@ void zebra_evpn_neigh_remote_uninstall(zebra_evpn_t *zevpn,
vlan_if = zevpn_map_to_svi(zevpn);
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: IP %s (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
- __func__,
- ipaddr2str(ipaddr, buf1, sizeof(buf1)),
- n->flags, vlan_if ? vlan_if->name : "Unknown");
+ "%s: IP %pIA (flags 0x%x intf %s) is remote and duplicate, read kernel for local entry",
+ __func__, ipaddr, n->flags,
+ vlan_if ? vlan_if->name : "Unknown");
if (vlan_if)
neigh_read_specific_ip(ipaddr, vlan_if);
}
@@ -2384,8 +2280,6 @@ int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
zebra_mac_t *zmac;
bool old_bgp_ready;
bool new_bgp_ready;
- char buf[INET6_ADDRSTRLEN];
- char buf2[ETHER_ADDR_STRLEN];
struct zebra_vrf *zvrf;
/* If entry doesn't exist, nothing to do. */
@@ -2397,9 +2291,8 @@ int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
if (!zmac) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Trying to del a neigh %s without a mac %s on VNI %u",
- ipaddr2str(ip, buf, sizeof(buf)),
- prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
+ "Trying to del a neigh %pIA without a mac %pEA on VNI %u",
+ ip, &n->emac,
zevpn->vni);
return 0;
@@ -2419,10 +2312,8 @@ int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
old_bgp_ready = zebra_evpn_neigh_is_ready_for_bgp(n);
if (zebra_evpn_neigh_is_static(n)) {
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
- zlog_debug("re-add sync neigh vni %u ip %s mac %s 0x%x",
- n->zevpn->vni,
- ipaddr2str(&n->ip, buf, sizeof(buf)),
- prefix_mac2str(&n->emac, buf2, sizeof(buf2)),
+ zlog_debug("re-add sync neigh vni %u ip %pIA mac %pEA 0x%x",
+ n->zevpn->vni, &n->ip, &n->emac,
n->flags);
if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_LOCAL_INACTIVE))
@@ -2464,7 +2355,7 @@ int zebra_evpn_neigh_del_ip(zebra_evpn_t *zevpn, struct ipaddr *ip)
/* see if the AUTO mac needs to be deleted */
if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_AUTO)
- && !listcount(zmac->neigh_list))
+ && !zebra_evpn_mac_in_use(zmac))
zebra_evpn_mac_del(zevpn, zmac);
return 0;
diff --git a/zebra/zebra_evpn_neigh.h b/zebra/zebra_evpn_neigh.h
index eac17a09b4..05156c1255 100644
--- a/zebra/zebra_evpn_neigh.h
+++ b/zebra/zebra_evpn_neigh.h
@@ -167,18 +167,12 @@ static inline bool zebra_evpn_neigh_is_ready_for_bgp(zebra_neigh_t *n)
static inline void zebra_evpn_neigh_stop_hold_timer(zebra_neigh_t *n)
{
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
-
if (!n->hold_timer)
return;
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
- zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x hold stop",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf, sizeof(macbuf)),
- n->flags);
+ zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x hold stop",
+ n->zevpn->vni, &n->ip, &n->emac, n->flags);
THREAD_OFF(n->hold_timer);
}
@@ -188,19 +182,13 @@ void zebra_evpn_sync_neigh_static_chg(zebra_neigh_t *n, bool old_n_static,
static inline bool zebra_evpn_neigh_clear_sync_info(zebra_neigh_t *n)
{
- char macbuf[ETHER_ADDR_STRLEN];
- char ipbuf[INET6_ADDRSTRLEN];
bool old_n_static = false;
bool new_n_static = false;
if (n->flags & ZEBRA_NEIGH_ALL_PEER_FLAGS) {
if (IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
- zlog_debug("sync-neigh vni %u ip %s mac %s 0x%x clear",
- n->zevpn->vni,
- ipaddr2str(&n->ip, ipbuf, sizeof(ipbuf)),
- prefix_mac2str(&n->emac, macbuf,
- sizeof(macbuf)),
- n->flags);
+ zlog_debug("sync-neigh vni %u ip %pIA mac %pEA 0x%x clear",
+ n->zevpn->vni, &n->ip, &n->emac, n->flags);
old_n_static = zebra_evpn_neigh_is_static(n);
UNSET_FLAG(n->flags, ZEBRA_NEIGH_ALL_PEER_FLAGS);
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 73534c4332..099ac1434b 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -1555,7 +1555,6 @@ static void zfpm_mac_info_del(struct fpm_mac_info_t *fpm_mac)
static int zfpm_trigger_rmac_update(zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
bool delete, const char *reason)
{
- char buf[ETHER_ADDR_STRLEN];
struct fpm_mac_info_t *fpm_mac, key;
struct interface *vxlan_if, *svi_if;
bool mac_found = false;
@@ -1568,9 +1567,8 @@ static int zfpm_trigger_rmac_update(zebra_mac_t *rmac, zebra_l3vni_t *zl3vni,
return 0;
if (reason) {
- zfpm_debug("triggering update to FPM - Reason: %s - %s",
- reason,
- prefix_mac2str(&rmac->macaddr, buf, sizeof(buf)));
+ zfpm_debug("triggering update to FPM - Reason: %s - %pEA",
+ reason, &rmac->macaddr);
}
vxlan_if = zl3vni_map_to_vxlan_if(zl3vni);
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index f7c5da5dec..cebd576365 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -500,9 +500,8 @@ static void zfpm_log_route_info(struct netlink_route_info *ri,
unsigned int i;
char buf[PREFIX_STRLEN];
- zfpm_debug("%s : %s %s, Proto: %s, Metric: %u", label,
- nl_msg_type_to_str(ri->nlmsg_type),
- prefix2str(ri->prefix, buf, sizeof(buf)),
+ zfpm_debug("%s : %s %pFX, Proto: %s, Metric: %u", label,
+ nl_msg_type_to_str(ri->nlmsg_type), ri->prefix,
nl_rtproto_to_str(ri->rtm_protocol),
ri->metric ? *ri->metric : 0);
@@ -557,7 +556,6 @@ int zfpm_netlink_encode_route(int cmd, rib_dest_t *dest, struct route_entry *re,
int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
size_t in_buf_len)
{
- char buf1[ETHER_ADDR_STRLEN];
size_t buf_offset;
struct macmsg {
@@ -600,11 +598,10 @@ int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
assert(req->hdr.nlmsg_len < in_buf_len);
- zfpm_debug("Tx %s family %s ifindex %u MAC %s DEST %pI4",
+ zfpm_debug("Tx %s family %s ifindex %u MAC %pEA DEST %pI4",
nl_msg_type_to_str(req->hdr.nlmsg_type),
nl_family_to_str(req->ndm.ndm_family), req->ndm.ndm_ifindex,
- prefix_mac2str(&mac->macaddr, buf1, sizeof(buf1)),
- &mac->r_vtep_ip);
+ &mac->macaddr, &mac->r_vtep_ip);
return req->hdr.nlmsg_len;
}
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index c1ad91c8ca..3583c5fbf4 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -110,6 +110,44 @@ void zebra_l2_unmap_slave_from_bridge(struct zebra_l2info_brslave *br_slave)
br_slave->br_if = NULL;
}
+/* If any of the bond members are in bypass state the bond is placed
+ * in bypass state
+ */
+static void zebra_l2_bond_lacp_bypass_eval(struct zebra_if *bond_zif)
+{
+ struct listnode *node;
+ struct zebra_if *bond_mbr;
+ bool old_bypass = !!(bond_zif->flags & ZIF_FLAG_LACP_BYPASS);
+ bool new_bypass = false;
+
+ if (bond_zif->bond_info.mbr_zifs) {
+ for (ALL_LIST_ELEMENTS_RO(bond_zif->bond_info.mbr_zifs, node,
+ bond_mbr)) {
+ if (bond_mbr->flags & ZIF_FLAG_LACP_BYPASS) {
+ new_bypass = true;
+ break;
+ }
+ }
+ }
+
+ if (old_bypass == new_bypass)
+ return;
+
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond %s lacp bypass changed to %s",
+ bond_zif->ifp->name, new_bypass ? "on" : "off");
+
+ if (new_bypass)
+ bond_zif->flags |= ZIF_FLAG_LACP_BYPASS;
+ else
+ bond_zif->flags &= ~ZIF_FLAG_LACP_BYPASS;
+
+ if (bond_zif->es_info.es)
+ zebra_evpn_es_bypass_update(bond_zif->es_info.es, bond_zif->ifp,
+ new_bypass);
+}
+
+/* Returns true if member was newly linked to bond */
void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf_id)
{
struct interface *bond_if;
@@ -138,6 +176,7 @@ void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf_id)
if (zebra_evpn_is_es_bond(bond_if))
zebra_evpn_mh_update_protodown_bond_mbr(
zif, false /*clear*/, __func__);
+ zebra_l2_bond_lacp_bypass_eval(bond_zif);
}
} else {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
@@ -170,6 +209,7 @@ void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif)
__func__);
listnode_delete(bond_zif->bond_info.mbr_zifs, zif);
bond_slave->bond_if = NULL;
+ zebra_l2_bond_lacp_bypass_eval(bond_zif);
}
void zebra_l2if_update_bond(struct interface *ifp, bool add)
@@ -378,14 +418,36 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
}
}
-void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex)
+void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex,
+ bool new_bypass)
{
struct zebra_if *zif;
ifindex_t old_bond_ifindex;
+ bool old_bypass;
+ struct zebra_l2info_bondslave *bond_mbr;
zif = ifp->info;
assert(zif);
+ old_bypass = !!(zif->flags & ZIF_FLAG_LACP_BYPASS);
+ if (old_bypass != new_bypass) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
+ zlog_debug("bond-mbr %s lacp bypass changed to %s",
+ zif->ifp->name, new_bypass ? "on" : "off");
+
+ if (new_bypass)
+ zif->flags |= ZIF_FLAG_LACP_BYPASS;
+ else
+ zif->flags &= ~ZIF_FLAG_LACP_BYPASS;
+
+ bond_mbr = &zif->bondslave_info;
+ if (bond_mbr->bond_if) {
+ struct zebra_if *bond_zif = bond_mbr->bond_if->info;
+
+ zebra_l2_bond_lacp_bypass_eval(bond_zif);
+ }
+ }
+
old_bond_ifindex = zif->bondslave_info.bond_ifindex;
if (old_bond_ifindex == bond_ifindex)
return;
diff --git a/zebra/zebra_l2.h b/zebra/zebra_l2.h
index 4b84eb071e..1834430287 100644
--- a/zebra/zebra_l2.h
+++ b/zebra/zebra_l2.h
@@ -107,7 +107,7 @@ extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
ns_id_t ns_id);
extern void zebra_l2if_update_bond_slave(struct interface *ifp,
- ifindex_t bond_ifindex);
+ ifindex_t bond_ifindex, bool bypass);
extern void zebra_vlan_bitmap_compute(struct interface *ifp,
uint32_t vid_start, uint16_t vid_end);
extern void zebra_vlan_mbr_re_eval(struct interface *ifp,
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index ef9a1f33bb..f3ccf83fbc 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -2767,6 +2767,12 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_NEIGH_DISCOVER:
case DPLANE_OP_BR_PORT_UPDATE:
case DPLANE_OP_NONE:
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
break;
}
diff --git a/zebra/zebra_pbr.c b/zebra/zebra_pbr.c
index 87ab900092..92a7a0ba3a 100644
--- a/zebra/zebra_pbr.c
+++ b/zebra/zebra_pbr.c
@@ -542,6 +542,69 @@ void zebra_pbr_del_rule(struct zebra_pbr_rule *rule)
__func__);
}
+void zebra_pbr_process_iptable(struct zebra_dplane_ctx *ctx)
+{
+ int mode, ret = 0;
+ struct zebra_pbr_iptable ipt;
+
+ if (dplane_ctx_get_op(ctx) == DPLANE_OP_IPTABLE_ADD)
+ mode = 1;
+ else
+ mode = 0;
+
+ if (dplane_ctx_get_pbr_iptable(ctx, &ipt)) {
+ ret = hook_call(zebra_pbr_iptable_update, mode, &ipt);
+ if (ret)
+ dplane_ctx_set_status(ctx,
+ ZEBRA_DPLANE_REQUEST_SUCCESS);
+ }
+ if (!ret)
+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_FAILURE);
+}
+
+void zebra_pbr_process_ipset(struct zebra_dplane_ctx *ctx)
+{
+ int mode, ret = 0;
+ struct zebra_pbr_ipset ipset;
+
+ if (dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ADD)
+ mode = 1;
+ else
+ mode = 0;
+ if (dplane_ctx_get_pbr_ipset(ctx, &ipset)) {
+ ret = hook_call(zebra_pbr_ipset_update, mode, &ipset);
+ if (ret)
+ dplane_ctx_set_status(ctx,
+ ZEBRA_DPLANE_REQUEST_SUCCESS);
+ }
+ if (!ret)
+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_FAILURE);
+}
+
+void zebra_pbr_process_ipset_entry(struct zebra_dplane_ctx *ctx)
+{
+ int mode, ret = 0;
+ struct zebra_pbr_ipset_entry ipset_entry;
+ struct zebra_pbr_ipset ipset;
+
+ if (dplane_ctx_get_op(ctx) == DPLANE_OP_IPSET_ENTRY_ADD)
+ mode = 1;
+ else
+ mode = 0;
+
+ if (!dplane_ctx_get_pbr_ipset_entry(ctx, &ipset_entry))
+ return;
+ if (!dplane_ctx_get_pbr_ipset(ctx, &ipset))
+ return;
+ ipset_entry.backpointer = &ipset;
+
+ ret = hook_call(zebra_pbr_ipset_entry_update, mode, &ipset_entry);
+ if (ret)
+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_SUCCESS);
+ else
+ dplane_ctx_set_status(ctx, ZEBRA_DPLANE_REQUEST_FAILURE);
+}
+
static void zebra_pbr_cleanup_rules(struct hash_bucket *b, void *data)
{
struct zebra_pbr_rule *rule = b->data;
@@ -632,13 +695,8 @@ static void *pbr_ipset_alloc_intern(void *arg)
void zebra_pbr_create_ipset(struct zebra_pbr_ipset *ipset)
{
- int ret;
-
(void)hash_get(zrouter.ipset_hash, ipset, pbr_ipset_alloc_intern);
- ret = hook_call(zebra_pbr_ipset_update, 1, ipset);
- kernel_pbr_ipset_add_del_status(ipset,
- ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
- : ZEBRA_DPLANE_INSTALL_FAILURE);
+ (void)dplane_pbr_ipset_add(ipset);
}
void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset)
@@ -646,7 +704,7 @@ void zebra_pbr_destroy_ipset(struct zebra_pbr_ipset *ipset)
struct zebra_pbr_ipset *lookup;
lookup = hash_lookup(zrouter.ipset_hash, ipset);
- hook_call(zebra_pbr_ipset_update, 0, ipset);
+ (void)dplane_pbr_ipset_delete(ipset);
if (lookup) {
hash_release(zrouter.ipset_hash, lookup);
XFREE(MTYPE_TMP, lookup);
@@ -711,14 +769,9 @@ static void *pbr_ipset_entry_alloc_intern(void *arg)
void zebra_pbr_add_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
{
- int ret;
-
(void)hash_get(zrouter.ipset_entry_hash, ipset,
pbr_ipset_entry_alloc_intern);
- ret = hook_call(zebra_pbr_ipset_entry_update, 1, ipset);
- kernel_pbr_ipset_entry_add_del_status(ipset,
- ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
- : ZEBRA_DPLANE_INSTALL_FAILURE);
+ (void)dplane_pbr_ipset_entry_add(ipset);
}
void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
@@ -726,7 +779,7 @@ void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset)
struct zebra_pbr_ipset_entry *lookup;
lookup = hash_lookup(zrouter.ipset_entry_hash, ipset);
- hook_call(zebra_pbr_ipset_entry_update, 0, ipset);
+ (void)dplane_pbr_ipset_entry_delete(ipset);
if (lookup) {
hash_release(zrouter.ipset_entry_hash, lookup);
XFREE(MTYPE_TMP, lookup);
@@ -761,13 +814,8 @@ static void *pbr_iptable_alloc_intern(void *arg)
void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable)
{
- int ret;
-
(void)hash_get(zrouter.iptable_hash, iptable, pbr_iptable_alloc_intern);
- ret = hook_call(zebra_pbr_iptable_update, 1, iptable);
- kernel_pbr_iptable_add_del_status(iptable,
- ret ? ZEBRA_DPLANE_INSTALL_SUCCESS
- : ZEBRA_DPLANE_INSTALL_FAILURE);
+ (void)dplane_pbr_iptable_add(iptable);
}
void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
@@ -775,7 +823,7 @@ void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable)
struct zebra_pbr_iptable *lookup;
lookup = hash_lookup(zrouter.iptable_hash, iptable);
- hook_call(zebra_pbr_iptable_update, 0, iptable);
+ (void)dplane_pbr_iptable_delete(iptable);
if (lookup) {
struct listnode *node, *nnode;
char *name;
@@ -812,6 +860,36 @@ void zebra_pbr_dplane_result(struct zebra_dplane_ctx *ctx)
zsend_rule_notify_owner(ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
? ZAPI_RULE_REMOVED
: ZAPI_RULE_FAIL_REMOVE);
+ else if (op == DPLANE_OP_IPTABLE_ADD)
+ zsend_iptable_notify_owner(ctx,
+ res == ZEBRA_DPLANE_REQUEST_SUCCESS
+ ? ZAPI_IPTABLE_INSTALLED
+ : ZAPI_IPTABLE_FAIL_INSTALL);
+ else if (op == DPLANE_OP_IPTABLE_DELETE)
+ zsend_iptable_notify_owner(ctx,
+ res == ZEBRA_DPLANE_REQUEST_SUCCESS
+ ? ZAPI_IPTABLE_REMOVED
+ : ZAPI_IPTABLE_FAIL_REMOVE);
+ else if (op == DPLANE_OP_IPSET_ADD)
+ zsend_ipset_notify_owner(ctx,
+ res == ZEBRA_DPLANE_REQUEST_SUCCESS
+ ? ZAPI_IPSET_INSTALLED
+ : ZAPI_IPSET_FAIL_INSTALL);
+ else if (op == DPLANE_OP_IPSET_DELETE)
+ zsend_ipset_notify_owner(ctx,
+ res == ZEBRA_DPLANE_REQUEST_SUCCESS
+ ? ZAPI_IPSET_REMOVED
+ : ZAPI_IPSET_FAIL_REMOVE);
+ else if (op == DPLANE_OP_IPSET_ENTRY_ADD)
+ zsend_ipset_entry_notify_owner(
+ ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
+ ? ZAPI_IPSET_ENTRY_INSTALLED
+ : ZAPI_IPSET_ENTRY_FAIL_INSTALL);
+ else if (op == DPLANE_OP_IPSET_ENTRY_DELETE)
+ zsend_ipset_entry_notify_owner(
+ ctx, res == ZEBRA_DPLANE_REQUEST_SUCCESS
+ ? ZAPI_IPSET_ENTRY_REMOVED
+ : ZAPI_IPSET_ENTRY_FAIL_REMOVE);
else
flog_err(
EC_ZEBRA_PBR_RULE_UPDATE,
@@ -823,85 +901,6 @@ void zebra_pbr_dplane_result(struct zebra_dplane_ctx *ctx)
}
/*
- * Handle success or failure of ipset (un)install in the kernel.
- */
-void kernel_pbr_ipset_add_del_status(struct zebra_pbr_ipset *ipset,
- enum zebra_dplane_status res)
-{
- switch (res) {
- case ZEBRA_DPLANE_INSTALL_SUCCESS:
- zsend_ipset_notify_owner(ipset, ZAPI_IPSET_INSTALLED);
- break;
- case ZEBRA_DPLANE_INSTALL_FAILURE:
- zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_INSTALL);
- break;
- case ZEBRA_DPLANE_DELETE_SUCCESS:
- zsend_ipset_notify_owner(ipset, ZAPI_IPSET_REMOVED);
- break;
- case ZEBRA_DPLANE_DELETE_FAILURE:
- zsend_ipset_notify_owner(ipset, ZAPI_IPSET_FAIL_REMOVE);
- break;
- case ZEBRA_DPLANE_STATUS_NONE:
- break;
- }
-}
-
-/*
- * Handle success or failure of ipset (un)install in the kernel.
- */
-void kernel_pbr_ipset_entry_add_del_status(
- struct zebra_pbr_ipset_entry *ipset,
- enum zebra_dplane_status res)
-{
- switch (res) {
- case ZEBRA_DPLANE_INSTALL_SUCCESS:
- zsend_ipset_entry_notify_owner(ipset,
- ZAPI_IPSET_ENTRY_INSTALLED);
- break;
- case ZEBRA_DPLANE_INSTALL_FAILURE:
- zsend_ipset_entry_notify_owner(ipset,
- ZAPI_IPSET_ENTRY_FAIL_INSTALL);
- break;
- case ZEBRA_DPLANE_DELETE_SUCCESS:
- zsend_ipset_entry_notify_owner(ipset,
- ZAPI_IPSET_ENTRY_REMOVED);
- break;
- case ZEBRA_DPLANE_DELETE_FAILURE:
- zsend_ipset_entry_notify_owner(ipset,
- ZAPI_IPSET_ENTRY_FAIL_REMOVE);
- break;
- case ZEBRA_DPLANE_STATUS_NONE:
- break;
- }
-}
-
-/*
- * Handle success or failure of ipset (un)install in the kernel.
- */
-void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
- enum zebra_dplane_status res)
-{
- switch (res) {
- case ZEBRA_DPLANE_INSTALL_SUCCESS:
- zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_INSTALLED);
- break;
- case ZEBRA_DPLANE_INSTALL_FAILURE:
- zsend_iptable_notify_owner(iptable, ZAPI_IPTABLE_FAIL_INSTALL);
- break;
- case ZEBRA_DPLANE_DELETE_SUCCESS:
- zsend_iptable_notify_owner(iptable,
- ZAPI_IPTABLE_REMOVED);
- break;
- case ZEBRA_DPLANE_DELETE_FAILURE:
- zsend_iptable_notify_owner(iptable,
- ZAPI_IPTABLE_FAIL_REMOVE);
- break;
- case ZEBRA_DPLANE_STATUS_NONE:
- break;
- }
-}
-
-/*
* Handle rule delete notification from kernel.
*/
int kernel_pbr_rule_del(struct zebra_pbr_rule *rule)
diff --git a/zebra/zebra_pbr.h b/zebra/zebra_pbr.h
index e7504a3547..ef93033661 100644
--- a/zebra/zebra_pbr.h
+++ b/zebra/zebra_pbr.h
@@ -64,6 +64,15 @@ struct zebra_pbr_rule {
*
* This is a filter mapped on ipset entries
*/
+struct zebra_pbr_ipset_info {
+ /* type is encoded as uint32_t
+ * but value is an enum ipset_type
+ */
+ uint32_t type;
+
+ char ipset_name[ZEBRA_IPSET_NAME_SIZE];
+};
+
struct zebra_pbr_ipset {
/*
* Originating zclient sock fd, so we can know who to send
@@ -85,6 +94,7 @@ struct zebra_pbr_ipset {
char ipset_name[ZEBRA_IPSET_NAME_SIZE];
};
+
/*
* An IPSet Entry Filter
*
@@ -177,6 +187,9 @@ void zebra_pbr_del_ipset_entry(struct zebra_pbr_ipset_entry *ipset);
void zebra_pbr_add_iptable(struct zebra_pbr_iptable *iptable);
void zebra_pbr_del_iptable(struct zebra_pbr_iptable *iptable);
+void zebra_pbr_process_iptable(struct zebra_dplane_ctx *ctx);
+void zebra_pbr_process_ipset(struct zebra_dplane_ctx *ctx);
+void zebra_pbr_process_ipset_entry(struct zebra_dplane_ctx *ctx);
/*
* Get to know existing PBR rules in the kernel - typically called at startup.
@@ -198,9 +211,6 @@ extern void kernel_pbr_ipset_entry_add_del_status(
struct zebra_pbr_ipset_entry *ipset,
enum zebra_dplane_status res);
-extern void kernel_pbr_iptable_add_del_status(struct zebra_pbr_iptable *iptable,
- enum zebra_dplane_status res);
-
/*
* Handle rule delete notification from kernel.
*/
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index c5d977017e..bc3c68638d 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -2830,8 +2830,10 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
struct vrf *vrf = vrf_lookup_by_id(re->vrf_id);
struct nexthop_group *nhg;
+ prefix2str(pp, straddr, sizeof(straddr));
+
zlog_debug("%s: dumping RE entry %p for %s%s%s vrf %s(%u)", func,
- (const void *)re, prefix2str(pp, straddr, sizeof(straddr)),
+ (const void *)re, straddr,
is_srcdst ? " from " : "",
is_srcdst ? prefix2str(src_pp, srcaddr, sizeof(srcaddr))
: "",
@@ -3887,6 +3889,12 @@ static int rib_process_dplane_results(struct thread *thread)
case DPLANE_OP_RULE_ADD:
case DPLANE_OP_RULE_DELETE:
case DPLANE_OP_RULE_UPDATE:
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
zebra_pbr_dplane_result(ctx);
break;
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 424c00d5eb..e5efbe0d4a 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -1226,7 +1226,6 @@ static int zl3vni_rmac_install(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
*/
static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
{
- char buf[ETHER_ADDR_STRLEN];
const struct zebra_if *zif = NULL, *br_zif;
const struct zebra_l2info_vxlan *vxl = NULL;
const struct interface *br_ifp;
@@ -1240,10 +1239,8 @@ static int zl3vni_rmac_uninstall(zebra_l3vni_t *zl3vni, zebra_mac_t *zrmac)
if (!zl3vni->vxlan_if) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "RMAC %s on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
- prefix_mac2str(&zrmac->macaddr,
- buf, sizeof(buf)),
- zl3vni->vni, zl3vni);
+ "RMAC %pEA on L3-VNI %u hash %p couldn't be uninstalled - no vxlan_if",
+ &zrmac->macaddr, zl3vni->vni, zl3vni);
return -1;
}
@@ -1277,8 +1274,6 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni,
const struct ipaddr *vtep_ip,
const struct prefix *host_prefix)
{
- char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
zebra_mac_t *zrmac = NULL;
zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
@@ -1288,11 +1283,8 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni,
zrmac = zl3vni_rmac_add(zl3vni, rmac);
if (!zrmac) {
zlog_debug(
- "Failed to add RMAC %s L3VNI %u Remote VTEP %s, prefix %pFX",
- prefix_mac2str(rmac, buf, sizeof(buf)),
- zl3vni->vni,
- ipaddr2str(vtep_ip, buf1, sizeof(buf1)),
- host_prefix);
+ "Failed to add RMAC %pEA L3VNI %u Remote VTEP %pIA, prefix %pFX",
+ rmac, zl3vni->vni, vtep_ip, host_prefix);
return -1;
}
memset(&zrmac->fwd_info, 0, sizeof(zrmac->fwd_info));
@@ -1308,12 +1300,9 @@ static int zl3vni_remote_rmac_add(zebra_l3vni_t *zl3vni,
&vtep_ip->ipaddr_v4)) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "L3VNI %u Remote VTEP change(%pI4 -> %s) for RMAC %s, prefix %pFX",
- zl3vni->vni,
- &zrmac->fwd_info.r_vtep_ip,
- ipaddr2str(vtep_ip, buf1, sizeof(buf1)),
- prefix_mac2str(rmac, buf, sizeof(buf)),
- host_prefix);
+ "L3VNI %u Remote VTEP change(%pI4 -> %pIA) for RMAC %pEA, prefix %pFX",
+ zl3vni->vni, &zrmac->fwd_info.r_vtep_ip,
+ vtep_ip, rmac, host_prefix);
zrmac->fwd_info.r_vtep_ip = vtep_ip->ipaddr_v4;
@@ -1470,9 +1459,6 @@ static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni,
const struct ethaddr *rmac,
const struct prefix *host_prefix)
{
- char buf[ETHER_ADDR_STRLEN];
- char buf1[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
zebra_neigh_t *nh = NULL;
/* Create the next hop entry, or update its mac, if necessary. */
@@ -1481,10 +1467,8 @@ static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni,
nh = zl3vni_nh_add(zl3vni, vtep_ip, rmac);
if (!nh) {
zlog_debug(
- "Failed to add NH %s as Neigh (RMAC %s L3-VNI %u prefix %pFX)",
- ipaddr2str(vtep_ip, buf1, sizeof(buf2)),
- prefix_mac2str(rmac, buf, sizeof(buf)),
- zl3vni->vni, host_prefix);
+ "Failed to add NH %pIA as Neigh (RMAC %pEA L3-VNI %u prefix %pFX)",
+ vtep_ip, rmac, zl3vni->vni, host_prefix);
return -1;
}
@@ -1493,11 +1477,8 @@ static int zl3vni_remote_nh_add(zebra_l3vni_t *zl3vni,
} else if (memcmp(&nh->emac, rmac, ETH_ALEN) != 0) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "L3VNI %u RMAC change(%s --> %s) for nexthop %s, prefix %pFX",
- zl3vni->vni,
- prefix_mac2str(&nh->emac, buf, sizeof(buf)),
- prefix_mac2str(rmac, buf1, sizeof(buf1)),
- ipaddr2str(vtep_ip, buf2, sizeof(buf2)),
+ "L3VNI %u RMAC change(%pEA --> %pEA) for nexthop %pIA, prefix %pFX",
+ zl3vni->vni, &nh->emac, rmac, vtep_ip,
host_prefix);
memcpy(&nh->emac, rmac, ETH_ALEN);
@@ -1878,8 +1859,6 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
struct zserv *client = NULL;
struct ethaddr svi_rmac, vrr_rmac = {.octet = {0} };
struct zebra_vrf *zvrf;
- char buf[ETHER_ADDR_STRLEN];
- char buf1[ETHER_ADDR_STRLEN];
bool is_anycast_mac = true;
client = zserv_find_client(ZEBRA_ROUTE_BGP, 0);
@@ -1920,11 +1899,9 @@ static int zl3vni_send_add_to_client(zebra_l3vni_t *zl3vni)
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Send L3_VNI_ADD %u VRF %s RMAC %s VRR %s local-ip %pI4 filter %s to %s",
+ "Send L3_VNI_ADD %u VRF %s RMAC %pEA VRR %pEA local-ip %pI4 filter %s to %s",
zl3vni->vni, vrf_id_to_name(zl3vni_vrf_id(zl3vni)),
- prefix_mac2str(&svi_rmac, buf, sizeof(buf)),
- prefix_mac2str(&vrr_rmac, buf1, sizeof(buf1)),
- &zl3vni->local_vtep_ip,
+ &svi_rmac, &vrr_rmac, &zl3vni->local_vtep_ip,
CHECK_FLAG(zl3vni->filter, PREFIX_ROUTES_ONLY)
? "prefix-routes-only"
: "none",
@@ -2138,7 +2115,6 @@ static void zl3vni_del_nh_hash_entry(struct hash_bucket *bucket, void *ctx)
static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,
struct ethaddr *rmac)
{
- char buf[ETHER_ADDR_STRLEN];
zebra_mac_t *zrmac = NULL;
zrmac = zl3vni_rmac_lookup(zl3vni, rmac);
@@ -2146,8 +2122,8 @@ static int zebra_vxlan_readd_remote_rmac(zebra_l3vni_t *zl3vni,
return 0;
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Del remote RMAC %s L3VNI %u - readd",
- prefix_mac2str(rmac, buf, sizeof(buf)), zl3vni->vni);
+ zlog_debug("Del remote RMAC %pEA L3VNI %u - readd",
+ rmac, zl3vni->vni);
zl3vni_rmac_install(zl3vni, zrmac);
return 0;
@@ -2852,11 +2828,10 @@ void zebra_vxlan_print_macs_vni(struct vty *vty, struct zebra_vrf *zvrf,
vty_out(vty,
"Number of MACs (local and remote) known for this VNI: %u\n",
num_macs);
- vty_out(vty,
- "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
- vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC",
- "Type", "Flags", "Intf/Remote ES/VTEP",
- "VLAN", "Seq #'s");
+ vty_out(vty,
+ "Flags: N=sync-neighs, I=local-inactive, P=peer-active, X=peer-proxy\n");
+ vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %s\n", "MAC", "Type",
+ "Flags", "Intf/Remote ES/VTEP", "VLAN", "Seq #'s");
} else
json_object_int_add(json, "numMacs", num_macs);
@@ -3503,6 +3478,8 @@ void zebra_vxlan_print_evpn(struct vty *vty, bool uj)
zvrf->advertise_gw_macip ? "Yes" : "No");
vty_out(vty, "Advertise svi mac-ip: %s\n",
zvrf->advertise_svi_macip ? "Yes" : "No");
+ vty_out(vty, "Advertise svi mac: %s\n",
+ zebra_evpn_mh_do_adv_svi_mac() ? "Yes" : "No");
vty_out(vty, "Duplicate address detection: %s\n",
zebra_evpn_do_dup_addr_detect(zvrf) ? "Enable"
: "Disable");
@@ -3666,7 +3643,6 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
struct interface *link_if,
struct ipaddr *ip)
{
- char buf[INET6_ADDRSTRLEN];
zebra_evpn_t *zevpn = NULL;
zebra_l3vni_t *zl3vni = NULL;
@@ -3684,9 +3660,8 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
if (!zevpn) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "%s: Del neighbor %s EVPN is not present for interface %s",
- __func__, ipaddr2str(ip, buf, sizeof(buf)),
- ifp->name);
+ "%s: Del neighbor %pIA EVPN is not present for interface %s",
+ __func__, ip, ifp->name);
return 0;
}
@@ -3698,9 +3673,8 @@ int zebra_vxlan_handle_kernel_neigh_del(struct interface *ifp,
}
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("Del neighbor %s intf %s(%u) -> L2-VNI %u",
- ipaddr2str(ip, buf, sizeof(buf)), ifp->name,
- ifp->ifindex, zevpn->vni);
+ zlog_debug("Del neighbor %pIA intf %s(%u) -> L2-VNI %u",
+ ip, ifp->name, ifp->ifindex, zevpn->vni);
return zebra_evpn_neigh_del_ip(zevpn, ip);
}
@@ -3720,8 +3694,6 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
bool is_router,
bool local_inactive, bool dp_static)
{
- char buf[ETHER_ADDR_STRLEN];
- char buf2[INET6_ADDRSTRLEN];
zebra_evpn_t *zevpn = NULL;
zebra_l3vni_t *zl3vni = NULL;
@@ -3741,9 +3713,8 @@ int zebra_vxlan_handle_kernel_neigh_update(struct interface *ifp,
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_NEIGH)
zlog_debug(
- "Add/Update neighbor %s MAC %s intf %s(%u) state 0x%x %s%s%s%s-> L2-VNI %u",
- ipaddr2str(ip, buf2, sizeof(buf2)),
- prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
+ "Add/Update neighbor %pIA MAC %pEA intf %s(%u) state 0x%x %s%s%s%s-> L2-VNI %u",
+ ip, macaddr, ifp->name,
ifp->ifindex, state, is_ext ? "ext-learned " : "",
is_router ? "router " : "",
local_inactive ? "local_inactive " : "",
@@ -3821,7 +3792,6 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
struct ipaddr ip;
struct in_addr vtep_ip;
uint16_t l = 0, ipa_len;
- char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
memset(&macaddr, 0, sizeof(struct ethaddr));
@@ -3841,9 +3811,8 @@ void zebra_vxlan_remote_macip_del(ZAPI_HANDLER_ARGS)
l += res_length;
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Recv MACIP DEL VNI %u MAC %s%s%s Remote VTEP %pI4 from %s",
- vni,
- prefix_mac2str(&macaddr, buf, sizeof(buf)),
+ "Recv MACIP DEL VNI %u MAC %pEA%s%s Remote VTEP %pI4 from %s",
+ vni, &macaddr,
ipa_len ? " IP " : "",
ipa_len ?
ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
@@ -3871,7 +3840,6 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
uint16_t l = 0, ipa_len;
uint8_t flags = 0;
uint32_t seq;
- char buf[ETHER_ADDR_STRLEN];
char buf1[INET6_ADDRSTRLEN];
esi_t esi;
char esi_buf[ESI_STR_LEN];
@@ -3902,11 +3870,10 @@ void zebra_vxlan_remote_macip_add(ZAPI_HANDLER_ARGS)
else
strlcpy(esi_buf, "-", ESI_STR_LEN);
zlog_debug(
- "Recv %sMACIP ADD VNI %u MAC %s%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
+ "Recv %sMACIP ADD VNI %u MAC %pEA%s%s flags 0x%x seq %u VTEP %pI4 ESI %s from %s",
(flags & ZEBRA_MACIP_TYPE_SYNC_PATH) ?
"sync-" : "",
- vni,
- prefix_mac2str(&macaddr, buf, sizeof(buf)),
+ vni, &macaddr,
ipa_len ? " IP " : "",
ipa_len ?
ipaddr2str(&ip, buf1, sizeof(buf1)) : "",
@@ -3983,7 +3950,6 @@ static int zebra_vxlan_check_del_local_mac(struct interface *ifp,
vni_t vni;
zebra_evpn_t *zevpn;
zebra_mac_t *mac;
- char buf[ETHER_ADDR_STRLEN];
zif = ifp->info;
assert(zif);
@@ -4010,9 +3976,8 @@ static int zebra_vxlan_check_del_local_mac(struct interface *ifp,
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- "Add/update remote MAC %s intf %s(%u) VNI %u flags 0x%x - del local",
- prefix_mac2str(macaddr, buf, sizeof(buf)), ifp->name,
- ifp->ifindex, vni, mac->flags);
+ "Add/update remote MAC %pEA intf %s(%u) VNI %u flags 0x%x - del local",
+ macaddr, ifp->name, ifp->ifindex, vni, mac->flags);
/* Remove MAC from BGP. */
zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags,
@@ -4025,6 +3990,7 @@ static int zebra_vxlan_check_del_local_mac(struct interface *ifp,
if (!listcount(mac->neigh_list)) {
zebra_evpn_mac_del(zevpn, mac);
} else {
+ zebra_evpn_mac_clear_fwd_info(mac);
UNSET_FLAG(mac->flags, ZEBRA_MAC_ALL_LOCAL_FLAGS);
UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
@@ -4121,7 +4087,8 @@ int zebra_vxlan_dp_network_mac_del(struct interface *ifp,
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug("dpDel local-nw-MAC %pEA VNI %u", macaddr,
vni);
- return zebra_evpn_del_local_mac(zevpn, mac);
+
+ zebra_evpn_del_local_mac(zevpn, mac, false);
}
return 0;
@@ -4158,7 +4125,7 @@ int zebra_vxlan_local_mac_del(struct interface *ifp, struct interface *br_if,
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
return 0;
- return zebra_evpn_del_local_mac(zevpn, mac);
+ return zebra_evpn_del_local_mac(zevpn, mac, false);
}
/*
@@ -4172,7 +4139,6 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
{
zebra_evpn_t *zevpn;
struct zebra_vrf *zvrf;
- char buf[ETHER_ADDR_STRLEN];
assert(ifp);
@@ -4183,9 +4149,8 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
if (!zevpn) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
- " Add/Update %sMAC %s intf %s(%u) VID %u, could not find EVPN",
- sticky ? "sticky " : "",
- prefix_mac2str(macaddr, buf, sizeof(buf)),
+ " Add/Update %sMAC %pEA intf %s(%u) VID %u, could not find EVPN",
+ sticky ? "sticky " : "", macaddr,
ifp->name, ifp->ifindex, vid);
return 0;
}
@@ -4207,7 +4172,7 @@ int zebra_vxlan_local_mac_add_update(struct interface *ifp,
return zebra_evpn_add_update_local_mac(zvrf, zevpn, ifp, macaddr, vid,
sticky, local_inactive,
- dp_static);
+ dp_static, NULL);
}
/*
@@ -4493,6 +4458,16 @@ int zebra_vxlan_add_del_gw_macip(struct interface *ifp, struct prefix *p,
return -1;
}
+ /* VRR IP is advertised only if gw-macip-adv-enabled */
+ if (IS_ZEBRA_IF_MACVLAN(ifp)) {
+ if (!advertise_gw_macip_enabled(zevpn))
+ return 0;
+ } else {
+ /* SVI IP is advertised if gw or svi macip-adv-enabled */
+ if (!advertise_svi_macip_enabled(zevpn)
+ && !advertise_gw_macip_enabled(zevpn))
+ return 0;
+ }
memcpy(&macaddr.octet, ifp->hw_addr, ETH_ALEN);
@@ -4539,10 +4514,14 @@ int zebra_vxlan_svi_down(struct interface *ifp, struct interface *link_if)
} else {
zebra_evpn_t *zevpn = NULL;
+ /* Unlink the SVI from the access VLAN */
+ zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, false);
+
/* since we dont have svi corresponding to zevpn, we associate it
* to default vrf. Note: the corresponding neigh entries on the
* SVI would have already been deleted */
zevpn = zebra_evpn_from_svi(ifp, link_if);
+
if (zevpn) {
zevpn->vrf_id = VRF_DEFAULT;
@@ -4606,6 +4585,9 @@ int zebra_vxlan_svi_up(struct interface *ifp, struct interface *link_if)
n_wctx.zevpn = zevpn;
hash_iterate(zevpn->neigh_table, zebra_evpn_install_neigh_hash,
&n_wctx);
+
+ /* Link the SVI from the access VLAN */
+ zebra_evpn_acc_bd_svi_set(ifp->info, link_if->info, true);
}
return 0;