summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.clang-format18
-rw-r--r--.git-blame-ignore-revs2
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.md97
-rw-r--r--.github/ISSUE_TEMPLATE/bug_report.yml78
-rw-r--r--.github/workflows/build-test-docker.yml163
-rw-r--r--.github/workflows/conflicts.yml3
-rw-r--r--.gitignore1
-rw-r--r--babeld/message.c136
-rw-r--r--babeld/neighbour.c67
-rw-r--r--bfdd/bfd.h4
-rw-r--r--bfdd/bfd_packet.c6
-rw-r--r--bgpd/bgp_addpath.h6
-rw-r--r--bgpd/bgp_advertise.c11
-rw-r--r--bgpd/bgp_advertise.h9
-rw-r--r--bgpd/bgp_aspath.c49
-rw-r--r--bgpd/bgp_aspath.h7
-rw-r--r--bgpd/bgp_attr.c206
-rw-r--r--bgpd/bgp_attr.h13
-rw-r--r--bgpd/bgp_bfd.c3
-rw-r--r--bgpd/bgp_bmp.c98
-rw-r--r--bgpd/bgp_bmp.h2
-rw-r--r--bgpd/bgp_clist.c44
-rw-r--r--bgpd/bgp_clist.h26
-rw-r--r--bgpd/bgp_damp.c516
-rw-r--r--bgpd/bgp_damp.h49
-rw-r--r--bgpd/bgp_debug.c15
-rw-r--r--bgpd/bgp_debug.h9
-rw-r--r--bgpd/bgp_ecommunity.c196
-rw-r--r--bgpd/bgp_ecommunity.h62
-rw-r--r--bgpd/bgp_evpn.c421
-rw-r--r--bgpd/bgp_evpn.h15
-rw-r--r--bgpd/bgp_evpn_mh.c193
-rw-r--r--bgpd/bgp_evpn_mh.h10
-rw-r--r--bgpd/bgp_evpn_private.h3
-rw-r--r--bgpd/bgp_filter.c41
-rw-r--r--bgpd/bgp_filter.h13
-rw-r--r--bgpd/bgp_fsm.c28
-rw-r--r--bgpd/bgp_fsm.h3
-rw-r--r--bgpd/bgp_label.c129
-rw-r--r--bgpd/bgp_label.h24
-rw-r--r--bgpd/bgp_mac.c12
-rw-r--r--bgpd/bgp_main.c8
-rw-r--r--bgpd/bgp_memory.c3
-rw-r--r--bgpd/bgp_memory.h3
-rw-r--r--bgpd/bgp_mpath.c36
-rw-r--r--bgpd/bgp_mplsvpn.c185
-rw-r--r--bgpd/bgp_mplsvpn.h10
-rw-r--r--bgpd/bgp_network.c12
-rw-r--r--bgpd/bgp_nexthop.c4
-rw-r--r--bgpd/bgp_nexthop.h1
-rw-r--r--bgpd/bgp_nht.c139
-rw-r--r--bgpd/bgp_open.c180
-rw-r--r--bgpd/bgp_open.h4
-rw-r--r--bgpd/bgp_packet.c307
-rw-r--r--bgpd/bgp_route.c1007
-rw-r--r--bgpd/bgp_route.h28
-rw-r--r--bgpd/bgp_routemap.c153
-rw-r--r--bgpd/bgp_routemap_nb_config.c6
-rw-r--r--bgpd/bgp_rpki.c211
-rw-r--r--bgpd/bgp_snmp_bgp4v2.c6
-rw-r--r--bgpd/bgp_table.c4
-rw-r--r--bgpd/bgp_table.h9
-rw-r--r--bgpd/bgp_trace.c2
-rw-r--r--bgpd/bgp_updgrp.c40
-rw-r--r--bgpd/bgp_updgrp.h1
-rw-r--r--bgpd/bgp_updgrp_adv.c52
-rw-r--r--bgpd/bgp_updgrp_packet.c25
-rw-r--r--bgpd/bgp_vty.c877
-rw-r--r--bgpd/bgp_vty.h2
-rw-r--r--bgpd/bgp_zebra.c535
-rw-r--r--bgpd/bgp_zebra.h15
-rw-r--r--bgpd/bgpd.c158
-rw-r--r--bgpd/bgpd.h45
-rw-r--r--bgpd/rfapi/rfapi.c14
-rw-r--r--bgpd/rfapi/rfapi_import.c20
-rw-r--r--bgpd/rfapi/rfapi_rib.c5
-rw-r--r--bgpd/rfapi/rfapi_vty.c14
-rw-r--r--bgpd/rfapi/vnc_import_bgp.c127
-rw-r--r--configure.ac50
-rw-r--r--doc/developer/building-libyang.rst2
-rw-r--r--doc/developer/checkpatch.rst9
-rw-r--r--doc/developer/cross-compiling.rst2
-rw-r--r--doc/developer/logging.rst17
-rw-r--r--doc/developer/mgmtd-dev.rst53
-rw-r--r--doc/developer/northbound/advanced-topics.rst12
-rw-r--r--doc/developer/northbound/architecture.rst2
-rw-r--r--doc/developer/northbound/demos.rst20
-rw-r--r--doc/developer/northbound/links.rst8
-rw-r--r--doc/developer/northbound/operational-data-rpcs-and-notifications.rst50
-rw-r--r--doc/developer/northbound/plugins-sysrepo.rst4
-rw-r--r--doc/developer/static-linking.rst2
-rw-r--r--doc/developer/topotests-markers.rst13
-rw-r--r--doc/developer/topotests.rst39
-rw-r--r--doc/developer/workflow.rst8
-rw-r--r--doc/developer/zebra.rst15
-rw-r--r--doc/user/bgp.rst113
-rw-r--r--doc/user/bmp.rst7
-rw-r--r--doc/user/installation.rst23
-rw-r--r--doc/user/isisd.rst54
-rw-r--r--doc/user/mgmtd.rst31
-rw-r--r--doc/user/ospf6d.rst6
-rw-r--r--doc/user/ospf_fundamentals.rst10
-rw-r--r--doc/user/ospfd.rst66
-rw-r--r--doc/user/ripngd.rst2
-rw-r--r--doc/user/routemap.rst10
-rw-r--r--doc/user/rpki.rst32
-rw-r--r--doc/user/zebra.rst33
-rw-r--r--docker/debian/Dockerfile2
-rw-r--r--docker/ubuntu-ci/Dockerfile26
-rwxr-xr-xdocker/ubuntu-ci/docker-start5
-rw-r--r--docker/ubuntu22-ci/README.md21
-rw-r--r--eigrpd/eigrp_main.c8
-rw-r--r--eigrpd/eigrp_routemap.h2
-rw-r--r--fpm/fpm.proto145
-rw-r--r--fpm/fpm_pb.c5
-rw-r--r--fpm/fpm_pb.h400
-rw-r--r--grpc/frrgrpc_pb.c9
-rw-r--r--grpc/subdir.am4
-rw-r--r--include/linux/compiler_types.h246
-rw-r--r--include/linux/if.h296
-rw-r--r--include/linux/libc-compat.h267
-rw-r--r--include/subdir.am3
-rw-r--r--isisd/isis_adjacency.c8
-rw-r--r--isisd/isis_lfa.c12
-rw-r--r--isisd/isis_lsp.c78
-rw-r--r--isisd/isis_main.c2
-rw-r--r--isisd/isis_nb_config.c3
-rw-r--r--isisd/isis_pdu.c2
-rw-r--r--isisd/isis_spf.c183
-rw-r--r--isisd/isis_sr.c37
-rw-r--r--isisd/isis_sr.h2
-rw-r--r--isisd/isis_srv6.c6
-rw-r--r--isisd/isis_srv6.h2
-rw-r--r--isisd/isis_te.c105
-rw-r--r--isisd/isis_te.h7
-rw-r--r--isisd/isis_tlvs.c1030
-rw-r--r--isisd/isis_zebra.c2
-rw-r--r--isisd/isisd.c320
-rw-r--r--ldpd/lde.c5
-rw-r--r--ldpd/ldpd.c62
-rw-r--r--ldpd/ldpd.h2
-rw-r--r--ldpd/ldpe.c5
-rw-r--r--ldpd/log.c138
-rw-r--r--ldpd/log.h43
-rw-r--r--ldpd/neighbor.c12
-rw-r--r--ldpd/subdir.am1
-rw-r--r--lib/affinitymap.c2
-rw-r--r--lib/agentx.c44
-rw-r--r--lib/atomlist.h2
-rw-r--r--lib/base64.c9
-rw-r--r--lib/base64.h1
-rw-r--r--lib/checksum.c2
-rw-r--r--lib/checksum.h2
-rw-r--r--lib/command.c22
-rw-r--r--lib/command.h3
-rw-r--r--lib/compiler.h6
-rw-r--r--lib/elf_py.c9
-rw-r--r--lib/explicit_bzero.c2
-rw-r--r--lib/filter.c18
-rw-r--r--lib/frr_pthread.c35
-rw-r--r--lib/frr_pthread.h11
-rw-r--r--lib/frr_zmq.c2
-rw-r--r--lib/if.c51
-rw-r--r--lib/ipaddr.h13
-rw-r--r--lib/keychain.c1011
-rw-r--r--lib/keychain.h38
-rw-r--r--lib/keychain_cli.c1033
-rw-r--r--lib/keychain_nb.c898
-rw-r--r--lib/lib_errors.c18
-rw-r--r--lib/lib_errors.h3
-rw-r--r--lib/libagentx.c63
-rw-r--r--lib/libagentx.h14
-rw-r--r--lib/libfrr.c48
-rw-r--r--lib/libfrr.h13
-rw-r--r--lib/libfrr_trace.c2
-rw-r--r--lib/libospf.h1
-rw-r--r--lib/link_state.c124
-rw-r--r--lib/link_state.h23
-rw-r--r--lib/memory.h27
-rw-r--r--lib/mgmt.proto1
-rw-r--r--lib/mgmt_be_client.c143
-rw-r--r--lib/mgmt_be_client.h2
-rw-r--r--lib/mgmt_fe_client.c99
-rw-r--r--lib/mgmt_fe_client.h80
-rw-r--r--lib/mgmt_msg_native.c5
-rw-r--r--lib/mgmt_msg_native.h125
-rw-r--r--lib/netns_other.c5
-rw-r--r--lib/nexthop.c343
-rw-r--r--lib/nexthop.h6
-rw-r--r--lib/northbound.c234
-rw-r--r--lib/northbound.h54
-rw-r--r--lib/northbound_cli.c75
-rw-r--r--lib/northbound_cli.h34
-rw-r--r--lib/northbound_confd.c1494
-rw-r--r--lib/northbound_grpc.cpp61
-rw-r--r--lib/northbound_oper.c39
-rw-r--r--lib/northbound_sysrepo.c67
-rw-r--r--lib/plist.c30
-rw-r--r--lib/prefix.c15
-rw-r--r--lib/prefix.h10
-rw-r--r--lib/printf/README1
-rw-r--r--lib/printf/printflocal.h1
-rw-r--r--lib/printf/vfprintf.c44
-rw-r--r--lib/routemap_cli.c47
-rw-r--r--lib/routing_nb.h2
-rw-r--r--lib/sigevent.c12
-rw-r--r--lib/smux.h1
-rw-r--r--lib/srv6.c4
-rw-r--r--lib/stream.c8
-rw-r--r--lib/stream.h4
-rw-r--r--lib/subdir.am22
-rw-r--r--lib/typerb.h2
-rw-r--r--lib/typesafe.h2
-rw-r--r--lib/vty.c146
-rw-r--r--lib/vty.h12
-rw-r--r--lib/yang.c196
-rw-r--r--lib/yang.h50
-rw-r--r--lib/yang_wrappers.c56
-rw-r--r--lib/yang_wrappers.h10
-rw-r--r--lib/zclient.c42
-rw-r--r--lib/zclient.h2
-rw-r--r--lib/zlog.c97
-rw-r--r--lib/zlog.h3
-rw-r--r--lib/zlog_recirculate.c56
-rw-r--r--lib/zlog_recirculate.h12
-rw-r--r--mgmtd/mgmt_be_adapter.c165
-rw-r--r--mgmtd/mgmt_be_adapter.h12
-rw-r--r--mgmtd/mgmt_be_nb.c6
-rw-r--r--mgmtd/mgmt_fe_adapter.c352
-rw-r--r--mgmtd/mgmt_fe_adapter.h41
-rw-r--r--mgmtd/mgmt_main.c23
-rw-r--r--mgmtd/mgmt_memory.c2
-rw-r--r--mgmtd/mgmt_memory.h2
-rw-r--r--mgmtd/mgmt_testc.c38
-rw-r--r--mgmtd/mgmt_txn.c368
-rw-r--r--mgmtd/mgmt_txn.h78
-rw-r--r--mgmtd/mgmt_vty.c77
-rw-r--r--mgmtd/subdir.am2
-rw-r--r--mlag/mlag_pb.c9
-rw-r--r--mlag/subdir.am1
-rw-r--r--nhrpd/debug.h2
-rw-r--r--nhrpd/nhrp_nhs.c12
-rw-r--r--nhrpd/os.h1
-rw-r--r--nhrpd/reqid.c2
-rw-r--r--nhrpd/vici.h1
-rw-r--r--ospf6d/ospf6_abr.c48
-rw-r--r--ospf6d/ospf6_abr.h5
-rw-r--r--ospf6d/ospf6_asbr.c112
-rw-r--r--ospf6d/ospf6_asbr.h11
-rw-r--r--ospf6d/ospf6_auth_trailer.c9
-rw-r--r--ospf6d/ospf6_flood.c4
-rw-r--r--ospf6d/ospf6_gr.c4
-rw-r--r--ospf6d/ospf6_gr_helper.c9
-rw-r--r--ospf6d/ospf6_intra.c65
-rw-r--r--ospf6d/ospf6_lsa.c30
-rw-r--r--ospf6d/ospf6_lsa.h19
-rw-r--r--ospf6d/ospf6_lsdb.c5
-rw-r--r--ospf6d/ospf6_main.c25
-rw-r--r--ospf6d/ospf6_message.c45
-rw-r--r--ospf6d/ospf6_neighbor.c2
-rw-r--r--ospf6d/ospf6_nssa.c27
-rw-r--r--ospf6d/ospf6_route.h3
-rw-r--r--ospf6d/ospf6_snmp.c2
-rw-r--r--ospf6d/ospf6_spf.c47
-rw-r--r--ospf6d/ospf6_zebra.c2
-rw-r--r--ospfd/ospf_apiserver.c27
-rw-r--r--ospfd/ospf_apiserver.h8
-rw-r--r--ospfd/ospf_asbr.c3
-rw-r--r--ospfd/ospf_ase.c2
-rw-r--r--ospfd/ospf_flood.c5
-rw-r--r--ospfd/ospf_interface.c97
-rw-r--r--ospfd/ospf_interface.h18
-rw-r--r--ospfd/ospf_ism.c2
-rw-r--r--ospfd/ospf_ldp_sync.c4
-rw-r--r--ospfd/ospf_main.c28
-rw-r--r--ospfd/ospf_neighbor.c4
-rw-r--r--ospfd/ospf_nsm.c4
-rw-r--r--ospfd/ospf_packet.c117
-rw-r--r--ospfd/ospf_ri.c15
-rw-r--r--ospfd/ospf_sr.c4
-rw-r--r--ospfd/ospf_te.c1
-rw-r--r--ospfd/ospf_vty.c304
-rw-r--r--ospfd/ospf_zebra.c14
-rw-r--r--ospfd/ospfd.c7
-rw-r--r--pathd/path_main.c2
-rw-r--r--pathd/path_zebra.c65
-rw-r--r--pimd/pim_cmd.c15
-rw-r--r--pimd/pim_iface.c2
-rw-r--r--pimd/pim_mroute.c12
-rw-r--r--pimd/pim_msdp.c8
-rw-r--r--pimd/pim_nb_config.c12
-rw-r--r--python/clippy/__init__.py1
-rw-r--r--python/clippy/elf.py11
-rw-r--r--python/tsexpand.py131
-rw-r--r--python/xref2vtysh.py4
-rw-r--r--python/xrelfo.py15
-rw-r--r--qpb/qpb.c5
-rw-r--r--redhat/frr.spec.in90
-rw-r--r--ripd/rip_cli.c19
-rw-r--r--ripd/rip_main.c6
-rw-r--r--ripd/rip_nb_rpcs.c9
-rw-r--r--ripd/ripd.c35
-rw-r--r--ripd/subdir.am1
-rw-r--r--ripngd/ripng_cli.c19
-rw-r--r--ripngd/ripng_nb_rpcs.c9
-rw-r--r--ripngd/ripngd.c33
-rw-r--r--ripngd/subdir.am1
-rw-r--r--sharpd/sharp_vty.c6
-rw-r--r--staticd/static_zebra.c3
-rw-r--r--tests/bgpd/test_mp_attr.c2
-rw-r--r--tests/bgpd/test_peer_attr.c2
-rw-r--r--tests/lib/northbound/test_oper_data.c47
-rw-r--r--tests/lib/northbound/test_oper_data.in1
-rw-r--r--tests/lib/northbound/test_oper_data.refout2
-rw-r--r--tests/lib/subdir.am4
-rw-r--r--tests/lib/test_printfrr.c24
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref6
-rw-r--r--tests/topotests/all_protocol_startup/r1/show_ip_ospf_interface.ref4
-rw-r--r--tests/topotests/all_protocol_startup/test_all_protocol_startup.py409
-rwxr-xr-xtests/topotests/analyze.py10
-rw-r--r--tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json45
-rw-r--r--tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json44
-rw-r--r--tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py16
-rw-r--r--tests/topotests/bfd_topo3/test_bfd_topo3.py2
-rw-r--r--tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py7
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/__init__.py (renamed from eigrpd/eigrp_pkt_tlv1.c)0
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/h1/zebra.conf4
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/h2/zebra.conf8
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_summary.json13
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_vrf_ipv6.json116
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgpd.conf32
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe1/ipv6_routes_vrf.json142
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe1/isisd.conf23
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe1/zebra.conf11
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_summary.json13
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_vrf_ipv6.json116
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgpd.conf31
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe2/isisd.conf22
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/pe2/zebra.conf15
-rw-r--r--tests/topotests/bgp_6vpe_ebgp_topo1/test_bgp_6vpe_ebgp_topo1.py179
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/__init__.py (renamed from eigrpd/eigrp_pkt_tlv2.c)0
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/r1/frr.conf13
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/r2/frr.conf37
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/r3/frr.conf16
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/r4/frr.conf16
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/r5/frr.conf16
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/r6/frr.conf16
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/r7/frr.conf13
-rw-r--r--tests/topotests/bgp_addpath_paths_limit/test_bgp_addpath_paths_limit.py128
-rw-r--r--tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py2
-rw-r--r--tests/topotests/bgp_bmp/r1/bgpd.conf28
-rw-r--r--tests/topotests/bgp_bmp/r1/zebra.conf2
-rw-r--r--tests/topotests/bgp_bmp/r2/bgpd.conf27
-rw-r--r--tests/topotests/bgp_bmp/test_bgp_bmp.py73
-rw-r--r--tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py4
-rw-r--r--tests/topotests/bgp_community_alias/test_bgp-community-alias.py2
-rw-r--r--tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py4
-rw-r--r--tests/topotests/bgp_confed1/r2/bgpd.conf5
-rw-r--r--tests/topotests/bgp_confed1/test_bgp_confed1.py5
-rw-r--r--tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py4
-rw-r--r--tests/topotests/bgp_dampening_per_peer/__init__.py (renamed from tests/topotests/isis_tilfa_topo1/rt1/step10/show_ip_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_dampening_per_peer/r1/frr.conf15
-rw-r--r--tests/topotests/bgp_dampening_per_peer/r2/frr.conf17
-rw-r--r--tests/topotests/bgp_dampening_per_peer/test_bgp_dampening_per_peer.py177
-rw-r--r--tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py2
-rw-r--r--tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py282
-rw-r--r--tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py78
-rw-r--r--tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py354
-rw-r--r--tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py5
-rw-r--r--tests/topotests/bgp_dynamic_capability/r1/frr.conf1
-rw-r--r--tests/topotests/bgp_dynamic_capability/r2/frr.conf1
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py164
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py4
-rw-r--r--tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py4
-rw-r--r--tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py2
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/__init__.py (renamed from tests/topotests/isis_tilfa_topo1/rt1/step10/show_ipv6_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf4
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf4
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf30
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf25
-rw-r--r--tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py92
-rw-r--r--tests/topotests/bgp_evpn_mh/leaf1/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/leaf2/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/spine1/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/spine2/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/test_evpn_mh.py27
-rw-r--r--tests/topotests/bgp_evpn_mh/torm11/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm12/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm21/evpn.conf1
-rw-r--r--tests/topotests/bgp_evpn_mh/torm22/evpn.conf1
-rwxr-xr-xtests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py6
-rw-r--r--tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py4
-rw-r--r--tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/evpn.vni.json2
-rw-r--r--tests/topotests/bgp_evpn_vxlan_svd_topo1/PE2/evpn.vni.json2
-rw-r--r--tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py9
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/__init__.py (renamed from tests/topotests/isis_tilfa_topo1/rt1/step10/show_mpls_table.ref.diff)0
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf32
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf10
-rw-r--r--tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py95
-rw-r--r--tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py4
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf (renamed from tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf)7
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf (renamed from tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf)5
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf5
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf19
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf13
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py108
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py19
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py36
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py24
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py4
-rw-r--r--tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py4
-rw-r--r--tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json2
-rw-r--r--tests/topotests/bgp_link_bw_ip/r5/bgpd.conf1
-rw-r--r--tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py34
-rw-r--r--tests/topotests/bgp_llgr/test_bgp_llgr.py2
-rw-r--r--tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py2
-rw-r--r--tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py10
-rw-r--r--tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py73
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/__init__.py (renamed from tests/topotests/isis_tilfa_topo1/rt1/step11/show_ip_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/h1/zebra.conf6
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/h2/zebra.conf6
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/h3/zebra.conf6
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv4.json70
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step1.json90
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step2.json90
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgpd.conf23
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r1/zebra.conf16
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv4.json46
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step1.json53
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgpd.conf11
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r2/isisd.conf24
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r2/zebra.conf12
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv4.json46
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step1.json53
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgpd.conf11
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r3/isisd.conf24
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r3/zebra.conf12
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv4.json46
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step1.json49
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step2.json49
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgpd.conf13
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r4/isisd.conf26
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r4/zebra.conf12
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv4.json46
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step1.json49
-rwxr-xr-xtests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step2.json49
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgpd.conf13
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r5/isisd.conf26
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r5/zebra.conf12
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv4.json46
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step1.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step2.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgpd.conf17
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r6/isisd.conf31
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r6/zebra.conf16
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv4.json46
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step1.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step2.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgpd.conf21
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r7/zebra.conf12
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv4.json46
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step1.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step2.json48
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgpd.conf21
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/r8/zebra.conf12
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv4.json58
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step1.json62
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step2.json62
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgpd.conf26
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/isisd.conf40
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/zebra.conf21
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/bgpd.conf21
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/isisd.conf36
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/zebra.conf8
-rw-r--r--tests/topotests/bgp_nexthop_mp_ipv4_6/test_nexthop_mp_ipv4_6.py283
-rw-r--r--tests/topotests/bgp_oad/test_bgp_oad.py4
-rw-r--r--tests/topotests/bgp_orf/test_bgp_orf.py4
-rw-r--r--tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py1
-rw-r--r--tests/topotests/bgp_path_selection/test_bgp_path_selection.py27
-rw-r--r--tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py4
-rw-r--r--tests/topotests/bgp_peer_group/r1/bgpd.conf4
-rw-r--r--tests/topotests/bgp_peer_group/r1/zebra.conf3
-rw-r--r--tests/topotests/bgp_peer_group/r2/bgpd.conf4
-rw-r--r--tests/topotests/bgp_peer_group/r2/zebra.conf3
-rw-r--r--tests/topotests/bgp_peer_group/test_bgp_peer-group.py49
-rwxr-xr-xtests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py1
-rw-r--r--tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py4
-rw-r--r--tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py4
-rw-r--r--tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py4
-rw-r--r--tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py7
-rw-r--r--tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py4
-rw-r--r--tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py4
-rw-r--r--tests/topotests/bgp_route_map_match_tag_untagged/__init__.py (renamed from tests/topotests/isis_tilfa_topo1/rt1/step11/show_ipv6_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_route_map_match_tag_untagged/r1/frr.conf19
-rw-r--r--tests/topotests/bgp_route_map_match_tag_untagged/test_bgp_route_map_match_tag_untagged.py83
-rw-r--r--tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py4
-rw-r--r--tests/topotests/bgp_rpki_topo1/r2/bgpd.conf2
-rw-r--r--tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py6
-rw-r--r--tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py77
-rw-r--r--tests/topotests/bgp_set_aspath_exclude/r1/bgpd.conf9
-rw-r--r--tests/topotests/bgp_set_aspath_exclude/r3/zebra.conf1
-rw-r--r--tests/topotests/bgp_set_aspath_exclude/test_bgp_set_aspath_exclude.py70
-rw-r--r--tests/topotests/bgp_software_version/test_bgp_software_version.py4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c11/bgpd.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step11/show_mpls_table.ref.diff)0
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c11/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c11/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c12/bgpd.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step2/show_ip_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c12/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c12/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c21/bgpd.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step2/show_ipv6_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c21/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c21/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c22/bgpd.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step2/show_mpls_table.ref.diff)0
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c22/staticd.conf5
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c22/zebra.conf9
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c31/bgpd.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step3/show_ip_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c31/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c31/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c32/bgpd.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step3/show_ipv6_route.ref.diff)0
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c32/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/c32/zebra.conf6
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r1/bgpd.conf61
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r1/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r1/zebra.conf32
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r2/bgpd.conf50
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r2/staticd.conf4
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r2/zebra.conf29
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r3/bgpd.conf50
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r3/staticd.conf6
-rw-r--r--tests/topotests/bgp_srv6_sid_reachability/r3/zebra.conf29
-rwxr-xr-xtests/topotests/bgp_srv6_sid_reachability/test_bgp_srv6_sid_reachability.py169
-rwxr-xr-xtests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py20
-rw-r--r--tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py3
-rw-r--r--tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py2
-rw-r--r--tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py135
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json50
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py168
-rw-r--r--tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py49
-rw-r--r--tests/topotests/bgp_vrf_different_asn/__init__.py (renamed from tests/topotests/isis_tilfa_topo1/rt1/step3/show_mpls_table.ref.diff)0
-rw-r--r--tests/topotests/bgp_vrf_different_asn/r1/frr.conf18
-rw-r--r--tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py107
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py104
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py27
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py52
-rw-r--r--tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py78
-rw-r--r--tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf10_ipv4_unicast.json7
-rw-r--r--tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf20_ipv4_unicast.json7
-rwxr-xr-xtests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py18
-rw-r--r--tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py334
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf6
-rw-r--r--tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py237
-rw-r--r--tests/topotests/config_timing/test_config_timing.py8
-rwxr-xr-xtests/topotests/conftest.py111
-rw-r--r--tests/topotests/eigrp_topo1/test_eigrp_topo1.py1
-rw-r--r--tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py6
-rw-r--r--tests/topotests/example_test/test_template.py1
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/fpm_counters.json8
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/fpm_stub.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step6/show_ip_route.ref.diff)0
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/routes_summ.json27
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json20
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/sharpd.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step6/show_ipv6_route.ref.diff)0
-rw-r--r--tests/topotests/fpm_testing_topo1/r1/zebra.conf5
-rw-r--r--tests/topotests/fpm_testing_topo1/test_fpm_topo1.py135
-rw-r--r--tests/topotests/grpc_basic/test_basic_grpc.py94
-rwxr-xr-xtests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py19
-rw-r--r--tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py105
-rw-r--r--tests/topotests/isis_te_topo1/test_isis_te_topo1.py36
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step1/show_mpls_table.ref18
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref4
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step12/show_ip_route.ref.diff19
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step12/show_ipv6_route.ref.diff18
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step12/show_mpls_table.ref.diff28
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step2/show_ip_route.ref294
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step2/show_ipv6_route.ref121
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step2/show_mpls_table.ref140
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step3/show_ip_route.ref294
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step3/show_ipv6_route.ref121
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step3/show_mpls_table.ref140
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref291
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref118
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref115
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref.diff33
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref294
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref121
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref140
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref.diff33
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step6/show_ip_route.ref294
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step6/show_ipv6_route.ref121
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step6/show_mpls_table.ref140
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref291
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref118
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref115
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref.diff33
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref294
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref121
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref.diff14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref140
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref.diff33
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref294
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref121
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref140
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref.diff64
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step1/show_ipv6_route.ref4
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step1/show_mpls_table.ref39
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step10/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step10/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step10/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step11/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step11/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step11/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step12/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step12/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step12/show_mpls_table.ref.diff20
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step2/show_ip_route.ref447
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step2/show_ip_route.ref.diff169
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref181
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref.diff72
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref233
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref.diff102
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step3/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step3/show_ip_route.ref.diff169
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref.diff72
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref.diff102
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step4/show_ip_route.ref464
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step4/show_ip_route.ref.diff192
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref162
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref.diff146
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref142
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref.diff200
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step5/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step5/show_ip_route.ref.diff192
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref.diff146
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref.diff200
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step6/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step6/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step7/show_ip_route.ref405
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step7/show_ip_route.ref.diff288
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref155
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref.diff139
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref155
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref.diff207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step8/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step8/show_ip_route.ref.diff288
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref.diff139
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref.diff207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step9/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step9/show_ip_route.ref.diff119
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref.diff74
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref.diff182
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step1/show_ipv6_route.ref14
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step1/show_mpls_table.ref39
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref8
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step10/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step10/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step10/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step11/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step11/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step11/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step12/show_ip_route.ref.diff58
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step12/show_ipv6_route.ref.diff45
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step12/show_mpls_table.ref.diff60
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step4/show_ip_route.ref405
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step4/show_ip_route.ref.diff288
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref155
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref.diff139
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref155
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref.diff206
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref.diff288
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref.diff139
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref.diff206
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref.diff101
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref.diff83
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref.diff130
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref556
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref.diff32
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref222
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref.diff32
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref236
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref.diff71
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref.diff32
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref.diff32
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref.diff71
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref563
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref.diff133
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step1/show_ipv6_route.ref12
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step1/show_mpls_table.ref27
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step10/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step10/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step10/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step11/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step11/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step11/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step12/show_ip_route.ref.diff144
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step12/show_ipv6_route.ref.diff50
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step12/show_mpls_table.ref.diff78
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step2/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step2/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step3/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step3/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step4/show_ip_route.ref296
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step4/show_ip_route.ref.diff367
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref121
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref.diff161
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref1
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref.diff265
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step5/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step5/show_ip_route.ref.diff367
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref.diff161
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref.diff265
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step6/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step6/show_ip_route.ref.diff56
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref.diff38
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref.diff74
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step7/show_ip_route.ref500
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step7/show_ip_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref201
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref229
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref.diff53
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step8/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step8/show_ip_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref.diff53
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step9/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step9/show_ip_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref.diff110
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step1/show_ipv6_route.ref12
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step1/show_mpls_table.ref27
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref485
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref194
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref301
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step11/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step11/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step11/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step12/show_ip_route.ref.diff151
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step12/show_ipv6_route.ref.diff53
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step12/show_mpls_table.ref.diff80
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref439
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref.diff161
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref175
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref.diff95
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref189
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref.diff166
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref.diff161
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref.diff95
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref.diff166
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref.diff146
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref506
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref207
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref275
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step1/show_ipv6_route.ref4
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step1/show_mpls_table.ref22
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_down.ref6
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_up.ref6
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref354
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref147
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref127
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step11/show_ip_route.ref.diff125
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step11/show_ipv6_route.ref.diff56
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step11/show_mpls_table.ref.diff106
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step12/show_ip_route.ref.diff153
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step12/show_ipv6_route.ref.diff66
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step12/show_mpls_table.ref.diff78
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref413
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref173
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref224
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref413
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref173
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref224
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref.diff0
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref395
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref.diff70
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref155
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref.diff70
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref165
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref.diff109
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref413
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref.diff70
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref173
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref.diff70
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref224
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref.diff112
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref413
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref.diff38
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref173
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref.diff38
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref224
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref.diff74
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref407
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref167
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref178
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref.diff52
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref413
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref173
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref.diff24
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref224
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref.diff52
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref413
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref173
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref.diff11
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref224
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref.diff39
-rw-r--r--tests/topotests/isis_tilfa_topo1/rt6/zebra.conf1
-rwxr-xr-xtests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py613
-rw-r--r--tests/topotests/isis_topo1/test_isis_topo1.py2
-rw-r--r--tests/topotests/key_sendaccept/r1/frr.conf31
-rw-r--r--tests/topotests/key_sendaccept/r2/frr.conf20
-rw-r--r--tests/topotests/key_sendaccept/test_keychain.py150
-rw-r--r--tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync.ref4
-rw-r--r--tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r1_eth1_shutdown.ref4
-rw-r--r--tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r2_eth1_shutdown.ref4
-rw-r--r--tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync.ref4
-rw-r--r--tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r1_eth1_shutdown.ref4
-rw-r--r--tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r2_eth1_shutdown.ref4
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/open/__init__.py32
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/__init__.py30
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/af.py6
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/nlri.py62
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py119
-rw-r--r--tests/topotests/lib/bmp_collector/bgp/update/rd.py24
-rw-r--r--tests/topotests/lib/bmp_collector/bmp.py173
-rwxr-xr-xtests/topotests/lib/bmp_collector/bmpserver4
-rw-r--r--tests/topotests/lib/checkping.py12
-rw-r--r--tests/topotests/lib/common_config.py16
-rwxr-xr-xtests/topotests/lib/fe_client.py2
-rwxr-xr-xtests/topotests/lib/grpc-query.py96
-rw-r--r--tests/topotests/lib/snmptest.py13
-rw-r--r--tests/topotests/lib/topogen.py25
-rw-r--r--tests/topotests/lib/topojson.py8
-rw-r--r--tests/topotests/lib/topotest.py64
-rw-r--r--tests/topotests/mgmt_fe_client/mgmt_pb2.py5035
-rw-r--r--tests/topotests/mgmt_oper/oper.py92
-rw-r--r--tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json3
-rw-r--r--tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json3
-rw-r--r--tests/topotests/mgmt_oper/test_oper.py1
-rw-r--r--tests/topotests/mgmt_oper/test_scale.py1
-rw-r--r--tests/topotests/mgmt_rpc/r1/frr.conf (renamed from tests/topotests/isis_tilfa_topo1/rt1/step6/show_mpls_table.ref.diff)0
-rw-r--r--tests/topotests/mgmt_rpc/test_rpc.py74
-rw-r--r--tests/topotests/mgmt_tests/test_yang_mgmt.py239
-rwxr-xr-xtests/topotests/msdp_topo1/test_msdp_topo1.py4
-rw-r--r--tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py2
-rw-r--r--tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py2
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py4
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py4
-rwxr-xr-xtests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py17
-rw-r--r--tests/topotests/munet/__main__.py63
-rw-r--r--tests/topotests/munet/args.py89
-rw-r--r--tests/topotests/munet/base.py66
-rw-r--r--tests/topotests/munet/cleanup.py34
-rw-r--r--tests/topotests/munet/cli.py12
-rw-r--r--tests/topotests/munet/logconf-mutest.yaml5
-rw-r--r--tests/topotests/munet/mucmd.py16
-rw-r--r--tests/topotests/munet/mulog.py26
-rw-r--r--tests/topotests/munet/munet-schema.json51
-rw-r--r--tests/topotests/munet/mutest/__main__.py89
-rw-r--r--tests/topotests/munet/mutest/userapi.py102
-rw-r--r--tests/topotests/munet/native.py467
-rw-r--r--tests/topotests/munet/parser.py10
-rw-r--r--tests/topotests/munet/testing/fixtures.py36
-rw-r--r--tests/topotests/munet/testing/hooks.py93
-rw-r--r--tests/topotests/nb_config/test_nb_config.py22
-rw-r--r--tests/topotests/nhrp_topo/test_nhrp_topo.py2
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf22
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf15
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf15
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf3
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf13
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf3
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf11
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf5
-rw-r--r--tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py117
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py33
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_nssa.py2
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py6
-rw-r--r--tests/topotests/ospf_basic_functionality/test_ospf_single_area.py4
-rw-r--r--tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py6
-rw-r--r--tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py28
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/show_ip_route-1.json19
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/show_ip_route-2.json19
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/show_ip_route-3.json19
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/show_ip_route-4.json19
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/show_ip_route-5.json19
-rw-r--r--tests/topotests/ospf_metric_propagation/r1/show_ip_route-6.json19
-rw-r--r--tests/topotests/ospf_metric_propagation/r2/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/r3/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/r4/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/ra/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/rb/frr.conf6
-rw-r--r--tests/topotests/ospf_metric_propagation/rc/frr.conf4
-rw-r--r--tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py12
-rw-r--r--tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py8
-rw-r--r--tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py4
-rw-r--r--tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf26
-rw-r--r--tests/topotests/ospf_p2mp/r1/frr-p2mp.conf23
-rw-r--r--tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf29
-rw-r--r--tests/topotests/ospf_p2mp/r2/frr-p2mp.conf26
-rw-r--r--tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf28
-rw-r--r--tests/topotests/ospf_p2mp/r3/frr-p2mp.conf25
-rw-r--r--tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf28
-rw-r--r--tests/topotests/ospf_p2mp/r4/frr-p2mp.conf25
-rw-r--r--tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py472
-rw-r--r--tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py467
-rw-r--r--tests/topotests/ospf_single_switch/r1_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/r2_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/r3_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/r4_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/r5_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/r6_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/r7_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/r8_frr.conf18
-rw-r--r--tests/topotests/ospf_single_switch/test_ospf_single_switch.py199
-rw-r--r--tests/topotests/ospf_suppress_fa/r2/ospfd.conf1
-rw-r--r--tests/topotests/ospfapi/test_ospf_clientapi.py24
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py131
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py2
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py4
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py2
-rw-r--r--tests/topotests/pim_basic/test_pim.py5
-rw-r--r--tests/topotests/pim_igmp_vrf/r1/ospf_blue_route.json54
-rw-r--r--tests/topotests/pim_igmp_vrf/r1/ospf_red_route.json54
-rw-r--r--tests/topotests/pim_igmp_vrf/r1/ospfd.conf2
-rw-r--r--tests/topotests/pim_igmp_vrf/r1/pimd.conf1
-rw-r--r--tests/topotests/pim_igmp_vrf/r11/ospfd.conf2
-rw-r--r--tests/topotests/pim_igmp_vrf/r12/ospfd.conf2
-rwxr-xr-xtests/topotests/pim_igmp_vrf/test_pim_vrf.py76
-rw-r--r--tests/topotests/pytest.ini1
-rw-r--r--tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py222
-rw-r--r--tests/topotests/route_scale/scale_test_common.py2
-rw-r--r--tests/topotests/route_scale/test_route_scale1.py18
-rw-r--r--tests/topotests/route_scale/test_route_scale2.py18
-rwxr-xr-xtests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py24
-rw-r--r--tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py14
-rw-r--r--tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py12
-rwxr-xr-xtests/topotests/tc_basic/test_tc_basic.py17
-rw-r--r--tests/topotests/zebra_netlink/test_zebra_netlink.py2
-rw-r--r--tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py49
-rw-r--r--tests/topotests/zebra_seg6_route/r1/routes_setup.json28
-rwxr-xr-xtests/topotests/zebra_seg6_route/test_zebra_seg6_route.py10
-rwxr-xr-xtools/checkpatch.pl13
-rw-r--r--tools/cocci.h2
-rw-r--r--tools/etc/iproute2/rt_protos.d/frr.conf1
-rwxr-xr-xtools/frr-reload.py28
-rw-r--r--tools/gcc-plugins/frr-format.c6
-rwxr-xr-xtools/indent.py4
-rw-r--r--vtysh/vtysh.c341
-rw-r--r--vtysh/vtysh.h20
-rw-r--r--yang/confd/confd.frr-ripd.yang24
-rw-r--r--yang/confd/confd.frr-ripngd.yang24
-rw-r--r--yang/frr-bgp-route-map.yang104
-rw-r--r--yang/frr-isisd.yang4
-rw-r--r--yang/frr-ospf-route-map.yang2
-rw-r--r--yang/frr-ospf6-route-map.yang2
-rw-r--r--yang/frr-route-map.yang2
-rw-r--r--yang/frr-test-module.yang17
-rw-r--r--yang/frr-zebra.yang14
-rw-r--r--yang/ietf/frr-deviations-ietf-key-chain.yang29
-rw-r--r--yang/ietf/frr-deviations-ietf-routing.yang3
-rw-r--r--yang/ietf/ietf-key-chain.yang382
-rw-r--r--yang/subdir.am29
-rw-r--r--zebra/.gitignore1
-rw-r--r--zebra/debug_nl.c6
-rw-r--r--zebra/dpdk/zebra_dplane_dpdk.c82
-rw-r--r--zebra/dpdk/zebra_dplane_dpdk.h2
-rw-r--r--zebra/dplane_fpm_nl.c96
-rw-r--r--zebra/fpm_listener.c814
-rw-r--r--zebra/if_netlink.c1
-rw-r--r--zebra/interface.c115
-rw-r--r--zebra/interface.h5
-rw-r--r--zebra/kernel_netlink.c20
-rw-r--r--zebra/main.c3
-rw-r--r--zebra/redistribute.c4
-rw-r--r--zebra/rt_netlink.c163
-rw-r--r--zebra/rtadv.c10
-rw-r--r--zebra/subdir.am7
-rw-r--r--zebra/zapi_msg.c7
-rw-r--r--zebra/zebra_dplane.c20
-rw-r--r--zebra/zebra_dplane.h7
-rw-r--r--zebra/zebra_evpn.c146
-rw-r--r--zebra/zebra_evpn_mac.c528
-rw-r--r--zebra/zebra_evpn_mh.c45
-rw-r--r--zebra/zebra_evpn_mh.h3
-rw-r--r--zebra/zebra_fpm_netlink.c8
-rw-r--r--zebra/zebra_gr.c10
-rw-r--r--zebra/zebra_l2.c33
-rw-r--r--zebra/zebra_mpls.c28
-rw-r--r--zebra/zebra_mpls.h5
-rw-r--r--zebra/zebra_mpls_openbsd.c28
-rw-r--r--zebra/zebra_mpls_vty.c2
-rw-r--r--zebra/zebra_nb.c6
-rw-r--r--zebra/zebra_nb.h1
-rw-r--r--zebra/zebra_nb_config.c4
-rw-r--r--zebra/zebra_nb_rpcs.c63
-rw-r--r--zebra/zebra_nb_state.c70
-rw-r--r--zebra/zebra_neigh.c12
-rw-r--r--zebra/zebra_netns_id.c4
-rw-r--r--zebra/zebra_netns_notify.c19
-rw-r--r--zebra/zebra_nhg.c116
-rw-r--r--zebra/zebra_nhg.h10
-rw-r--r--zebra/zebra_rnh.c332
-rw-r--r--zebra/zebra_rnh.h4
-rw-r--r--zebra/zebra_routemap_nb_config.c2
-rw-r--r--zebra/zebra_srv6_vty.c12
-rw-r--r--zebra/zebra_trace.c2
-rw-r--r--zebra/zebra_vty.c324
-rw-r--r--zebra/zebra_vxlan.c85
-rw-r--r--zebra/zebra_vxlan_if.c35
-rw-r--r--zebra/zserv.c65
-rw-r--r--zebra/zserv.h1
1134 files changed, 76153 insertions, 24138 deletions
diff --git a/.clang-format b/.clang-format
index d16263d..06769c9 100644
--- a/.clang-format
+++ b/.clang-format
@@ -1,5 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
# clang-format configuration file. Intended for clang-format >= 11.
+# If the version is changed also check that CI tool frrbot is updated.
#
# For more information, see:
#
@@ -206,4 +207,21 @@ SpacesInSquareBrackets: false
Standard: Cpp03
TabWidth: 8
UseTab: Always
+WhitespaceSensitiveMacros:
+ - "DEFPY"
+ - "DEFPY_HIDDEN"
+ - "DEFPY_NOSH"
+ - "DEFPY_YANG"
+ - "DEFPY_YANG_HIDDEN"
+ - "DEFPY_YANG_NOSH"
+ - "DEFSH"
+ - "DEFSH_HIDDEN"
+ - "DEFUN"
+ - "DEFUN_HIDDEN"
+ - "DEFUN_NOSH"
+ - "DEFUN_YANG"
+ - "DEFUN_YANG_HIDDEN"
+ - "DEFUN_YANG_NOSH"
+ - "DEFUNSH"
+ - "DEFUNSH_HIDDEN"
...
diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs
index 1ecdfd2..9b6932c 100644
--- a/.git-blame-ignore-revs
+++ b/.git-blame-ignore-revs
@@ -20,3 +20,5 @@ c14777c6bfd0a446c85243d3a9835054a259c276
8451921b70044a2c1075e7ba391f095fabee2550
bf8d3d6aca3f20255a621ed1c148fd05b3a8ae5c
96941f80927ce31a41f7d1905717f099187be723
+# apply `black` python formatting for all tests/topotests
+1a1c2a9f84d0ad1bdadc0cb47d6175d4ccc32544
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
deleted file mode 100644
index 895e8ad..0000000
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ /dev/null
@@ -1,97 +0,0 @@
----
-name: Bug report
-about: Create a report to help us improve
-title: ''
-labels: triage
-assignees: ''
-
----
-
-<!--
-
-*** ATTENTION ***
-
-YOU MUST READ THIS TO HAVE YOUR ISSUE ADDRESSED
-
-PLEASE READ AND FILL OUT THIS TEMPLATE
-
-NEGLECTING TO PROVIDE INFORMATION REQUESTED HERE WILL RESULT IN
-SIGNIFICANT DELAYS ADDRESSING YOUR ISSUE
-
-ALWAYS PROVIDE:
-- FRR VERSION
-- OPERATING SYSTEM VERSION
-- KERNEL VERSION
-
-FAILURE TO PROVIDE THIS MAY RESULT IN YOUR ISSUE BEING IGNORED
-
-FOLLOW THESE GUIDELINES:
-
-- When reporting a crash, provide a backtrace
-- When pasting configs, logs, shell output, backtraces, and other large chunks
- of text, surround this text with triple backtics
-
- ```
- like this
- ```
-
-- Include the FRR version; if you built from Git, please provide the commit
- hash
-- Write your issue in English
-
--->
-
----------------
-
-**Describe the bug**
-<!--
-A clear and concise description of what the bug is.
-
-Put "x" in "[ ]" if you already tried following:
--->
-
-- [ ] Did you check if this is a duplicate issue?
-- [ ] Did you test it on the latest FRRouting/frr master branch?
-
-
-**To Reproduce**
-<!--
-Describe the steps to reproduce the behavior.
-Be as descriptive as possible.
-
-For example:
-
-1. Go to '...'
-2. Click on '....'
-3. Scroll down to '....'
-4. See error
--->
-
-**Expected behavior**
-<!--
-Write here a clear and concise description of what you expected to happen when
-using the reproduction steps you provided above
--->
-
-**Screenshots**
-<!--
-If applicable, add screenshots to help explain your problem.
--->
-
-**Versions**
-<!--
-Include your operating system type and version here
-
-FAILURE TO PROVIDE THIS MAY RESULT IN YOUR ISSUE BEING IGNORED
--->
-<!-- e.g. Fedora 24, Debian 10] -->
- - OS Version:
-<!-- [e.g. Linux 5.4, OpenBSD 6.6] -->
- - Kernel:
-<!-- e.g. 6.0, 7.4 -->
- - FRR Version:
-
-**Additional context**
-<!--
-Add any other context about the problem here.
--->
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml
new file mode 100644
index 0000000..7319550
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/bug_report.yml
@@ -0,0 +1,78 @@
+name: Bug report
+description: Report a bug in the FRRouting software
+labels: triage
+body:
+ - type: markdown
+ attributes:
+ value: >
+ **This form is only for reporting a bug in the FRRouting software.**
+ If you need help troubleshooting your configuration, have a problem
+ building or installing the software, or want to ask a question or
+ discuss the project, learn how to [connect with the FRRouting
+ community](https://frrouting.org/community/).
+
+
+ **Do not include sensitive information in this report.** IP addresses
+ should be masked (example: 192.XXX.XXX.32/24).
+ - type: textarea
+ id: description
+ attributes:
+ label: Description
+ description: Provide a clear and concise description of the bug.
+ validations:
+ required: true
+ - type: textarea
+ id: version
+ attributes:
+ label: Version
+ description: >
+ Run the `show version` command in the VTY shell, and provide the output
+ here. (If possible, test the current development version of FRRouting
+ for this bug.)
+ render: text
+ validations:
+ required: true
+ - type: textarea
+ id: how-to-reproduce
+ attributes:
+ label: How to reproduce
+ description: >
+ Give a list of steps that someone else can follow to observe
+ the bug. Be as descriptive as possible, including any relevant
+ configuration files and commands used. Topology diagrams are
+ helpful when the bug involves more than one router.
+ validations:
+ required: true
+ - type: textarea
+ id: expected-behavior
+ attributes:
+ label: Expected behavior
+ description: >
+ What do you expect to happen when following the steps above?
+ validations:
+ required: true
+ - type: textarea
+ id: actual-behavior
+ attributes:
+ label: Actual behavior
+ description: >
+ What actually happens when following the steps above? Include
+ screenshots, log file snippets, and/or platform routing tables
+ as appropriate. If a crash occurs, provide a backtrace.
+ validations:
+ required: true
+ - type: textarea
+ id: additional-context
+ attributes:
+ label: Additional context
+ description: >
+ Include any other relevant information about this bug here.
+ - type: checkboxes
+ id: checklist
+ attributes:
+ label: Checklist
+ options:
+ - label: I have searched the open issues for this bug.
+ required: true
+ - label: I have not included sensitive information in this report.
+ required: true
diff --git a/.github/workflows/build-test-docker.yml b/.github/workflows/build-test-docker.yml
new file mode 100644
index 0000000..3f53f32
--- /dev/null
+++ b/.github/workflows/build-test-docker.yml
@@ -0,0 +1,163 @@
+name: build-test
+
+on:
+ pull_request:
+ push:
+ branches:
+ - 'master'
+ - 'stable/**'
+
+defaults:
+ run:
+ shell: bash
+
+jobs:
+ build-docker:
+ name: Build the ubuntu 22.04 docker image
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+ - name: Build docker image
+ run: |
+ docker build -t frr-ubuntu22 -f docker/ubuntu-ci/Dockerfile .
+ docker save --output /tmp/frr-ubuntu22.tar frr-ubuntu22
+ - name: Upload docker image artifact
+ uses: actions/upload-artifact@v4
+ with:
+ name: ubuntu-image
+ path: /tmp/frr-ubuntu22.tar
+ - name: Clear any previous results
+ # So if all jobs are re-run then all tests will be re-run
+ run: |
+ rm -rf test-results*
+ mkdir -p test-results
+ touch test-results/cleared-results.txt
+ - name: Save cleared previous results
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-results
+ path: test-results
+ overwrite: true
+ - name: Cleanup
+ if: ${{ always() }}
+ run: rm -rf test-results* /tmp/frr-ubuntu22.tar
+
+ test-docker:
+ name: Test ubuntu docker image
+ needs: build-docker
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 1
+ - name: Fetch docker image artifact
+ uses: actions/download-artifact@v4
+ with:
+ name: ubuntu-image
+ path: /tmp
+ - name: Fetch previous results
+ if: ${{ github.run_attempt > 1 }}
+ uses: actions/download-artifact@v4
+ with:
+ name: test-results
+ path: test-results
+ - name: Run topotests
+ run: |
+ uname -a
+ MODPKGVER=$(uname -r)
+ sudo apt-get update -y
+ # Github is running old kernels but installing newer packages :(
+ sudo apt-get install -y linux-modules-extra-azure linux-modules-${MODPKGVER} linux-modules-extra-${MODPKGVER} python3-xmltodict
+ sudo modprobe vrf || true
+ sudo modprobe mpls-iptunnel
+ sudo modprobe mpls-router
+ docker load --input /tmp/frr-ubuntu22.tar
+
+ if ! grep CONFIG_IP_MROUTE_MULTIPLE_TABLES=y /boot/config*; then
+ ADD_DOCKER_ENV+="-e MROUTE_VRF_MISSING=1"
+ fi
+ echo "ADD_DOCKER_ENV: ${ADD_DOCKER_ENV}"
+
+ if [ -f test-results/topotests.xml ]; then
+ ./tests/topotests/analyze.py -r test-results
+ ls -l test-results/topotests.xml
+ run_tests=$(./tests/topotests/analyze.py -r test-results | cut -f1 -d: | sort -u)
+ else
+ echo "No test results dir"
+ run_tests=""
+ fi
+ rm -rf test-results* /tmp/topotests
+
+ echo RUN_TESTS: $run_tests
+ if docker run --init -i --privileged --name frr-ubuntu-cont ${ADD_DOCKER_ENV} -v /lib/modules:/lib/modules frr-ubuntu22 \
+ bash -c 'cd ~/frr/tests/topotests ; sudo -E pytest -n$(($(nproc) * 5 / 2)) --dist=loadfile '$run_tests; then
+ echo "All tests passed."
+ exit 0
+ fi
+
+ # Grab the results from the container
+ if ! ./tests/topotests/analyze.py -Ar test-results -C frr-ubuntu-cont; then
+ if [ ! -d test-results ]; then
+ echo "ERROR: Basic failure in docker run, no test results directory available." >&2
+ exit 1;
+ fi
+ if [ ! -f test-results/topotests.xml ]; then
+ # In this case we may be missing topotests.xml
+ echo "ERROR: No topotests.xml available perhaps docker run aborted?" >&2
+ exit 1;
+ fi
+ echo "WARNING: analyyze.py returned error but grabbed results anyway." >&2
+ fi
+
+ # Save some information useful for debugging
+ cp /boot/config* test-results/
+ sysctl -a > test-results/sysctl.out 2> /dev/null
+
+ # Now get the failed tests (if any) from the archived results directory.
+ rerun_tests=$(./tests/topotests/analyze.py -r test-results | cut -f1 -d: | sort -u)
+ if [ -z "$rerun_tests" ]; then
+ echo "All tests passed during parallel run."
+ exit 0
+ fi
+
+ echo "ERROR: Some tests failed during parallel run, rerunning serially." >&2
+ echo RERUN_TESTS: $rerun_tests >&2
+ docker stop frr-ubuntu-cont
+ docker rm frr-ubuntu-cont
+
+ mv test-results test-results-initial
+ if docker run --init -i --privileged --name frr-ubuntu-cont ${ADD_DOCKER_ENV} -v /lib/modules:/lib/modules frr-ubuntu22 \
+ bash -c 'cd ~/frr/tests/topotests ; sudo -E pytest '$rerun_tests; then
+ echo "All rerun tests passed."
+ exit 0
+ fi
+ echo "Some rerun tests still failed."
+ exit 1
+ - name: Gather results
+ if: ${{ always() }}
+ run: |
+ if [ ! -d test-results ]; then
+ if ! ./tests/topotests/analyze.py -Ar test-results -C frr-ubuntu-cont; then
+ echo "ERROR: gathering results produced an error, perhaps due earlier run cancellation." >&2
+ fi
+ fi
+ - name: Upload test results
+ if: ${{ always() }}
+ uses: actions/upload-artifact@v4
+ with:
+ name: test-results
+ path: |
+ test-results
+ test-results-initial
+ overwrite: true
+ - name: Cleanup
+ if: ${{ always() }}
+ run: |
+ rm -rf test-results* /tmp/frr-ubuntu22.tar
+ docker stop frr-ubuntu-cont || true
+ docker rm frr-ubuntu-cont || true
+
diff --git a/.github/workflows/conflicts.yml b/.github/workflows/conflicts.yml
index 100f557..4b4e99f 100644
--- a/.github/workflows/conflicts.yml
+++ b/.github/workflows/conflicts.yml
@@ -1,9 +1,8 @@
name: Add a conflict label if PR needs to rebase
on:
- push:
pull_request_target:
- types: [synchronize]
+ types: [opened, reopened, synchronize]
jobs:
conflicts:
diff --git a/.gitignore b/.gitignore
index 07cdb11..60b4189 100644
--- a/.gitignore
+++ b/.gitignore
@@ -62,6 +62,7 @@
*.cg.dot
*.cg.svg
*.xref
+*_tsexpand.h
### gcov outputs
diff --git a/babeld/message.c b/babeld/message.c
index f854932..1b83eb9 100644
--- a/babeld/message.c
+++ b/babeld/message.c
@@ -139,7 +139,7 @@ static bool parse_update_subtlv(const unsigned char *a, int alen,
return false;
}
- if (type & SUBTLV_MANDATORY) {
+ if (CHECK_FLAG(type, SUBTLV_MANDATORY)) {
/*
* RFC 8966 - 4.4
* If the mandatory bit is set, then the whole enclosing
@@ -162,8 +162,7 @@ static bool parse_update_subtlv(const unsigned char *a, int alen,
}
if (memchr(a + i + 2, 0, len) != NULL) {
/* 0 is reserved. */
- flog_err(EC_BABEL_PACKET,
- "Channel information contains 0!");
+ flog_err(EC_BABEL_PACKET, "Channel information contains 0!");
return false;
}
memset(channels, 0, DIVERSITY_HOPS);
@@ -203,7 +202,7 @@ parse_hello_subtlv(const unsigned char *a, int alen,
return -1;
}
- if (type & SUBTLV_MANDATORY) {
+ if (CHECK_FLAG(type, SUBTLV_MANDATORY)) {
/*
* RFC 8966 4.4
* If the mandatory bit is set, then the whole enclosing
@@ -417,7 +416,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
unsigned int hello_send_us = 0, hello_rtt_receive_time = 0;
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
- if(babel_ifp->flags & BABEL_IF_TIMESTAMPS) {
+ if (CHECK_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS)) {
/* We want to track exactly when we received this packet. */
gettime(&babel_now);
}
@@ -513,8 +512,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
schedule_neighbours_check(interval * 15, 0);
/* Sub-TLV handling. */
if (len > 8) {
- if (parse_hello_subtlv(message + 8, len - 6,
- &timestamp) > 0) {
+ if (parse_hello_subtlv(message + 8, len - 6, &timestamp) > 0) {
neigh->hello_send_us = timestamp;
neigh->hello_rtt_receive_time = babel_now;
have_hello_rtt = 1;
@@ -554,8 +552,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
} else if(type == MESSAGE_NH) {
unsigned char nh[16];
int rc;
- rc = network_address(message[2], message + 4, len - 2,
- nh);
+ rc = network_address(message[2], message + 4, len - 2, nh);
if(rc <= 0) {
have_v4_nh = 0;
have_v6_nh = 0;
@@ -577,9 +574,9 @@ parse_packet(const unsigned char *from, struct interface *ifp,
unsigned char channels[DIVERSITY_HOPS];
unsigned short interval, seqno, metric;
int rc, parsed_len;
- bool ignore_update = false;
+ bool ignore_update = false;
- DO_NTOHS(interval, message + 6);
+ DO_NTOHS(interval, message + 6);
DO_NTOHS(seqno, message + 8);
DO_NTOHS(metric, message + 10);
if(message[5] == 0 ||
@@ -651,7 +648,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
goto done;
}
- if((babel_get_if_nfo(ifp)->flags & BABEL_IF_FARAWAY)) {
+ if(CHECK_FLAG(babel_get_if_nfo(ifp)->flags, BABEL_IF_FARAWAY)) {
channels[0] = 0;
} else {
/* This will be overwritten by parse_update_subtlv below. */
@@ -665,15 +662,14 @@ parse_packet(const unsigned char *from, struct interface *ifp,
}
if(parsed_len < len)
- ignore_update =
- parse_update_subtlv(message + 2 + parsed_len,
- len - parsed_len, channels);
+ ignore_update =
+ parse_update_subtlv(message + 2 + parsed_len,
+ len - parsed_len, channels);
}
if (!ignore_update)
update_route(router_id, prefix, plen, seqno, metric,
- interval, neigh, nh, channels,
- channels_len(channels));
+ interval, neigh, nh, channels, channels_len(channels));
} else if(type == MESSAGE_REQUEST) {
unsigned char prefix[16], src_prefix[16], plen, src_plen;
int rc, is_ss;
@@ -738,8 +734,7 @@ parse_packet(const unsigned char *from, struct interface *ifp,
format_prefix(prefix, plen),
format_address(from), ifp->name,
format_eui64(message + 8), seqno);
- handle_request(neigh, prefix, plen, message[6],
- seqno, message + 8);
+ handle_request(neigh, prefix, plen, message[6], seqno, message + 8);
} else {
debugf(BABEL_DEBUG_COMMON,"Received unknown packet type %d from %s on %s.",
type, format_address(from), ifp->name);
@@ -821,11 +816,10 @@ check_bucket(struct interface *ifp)
}
}
-static int
-fill_rtt_message(struct interface *ifp)
+static int fill_rtt_message(struct interface *ifp)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
- if((babel_ifp->flags & BABEL_IF_TIMESTAMPS) &&
+ if(CHECK_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS) &&
(babel_ifp->buffered_hello >= 0)) {
if(babel_ifp->sendbuf[babel_ifp->buffered_hello + 8] == SUBTLV_PADN &&
babel_ifp->sendbuf[babel_ifp->buffered_hello + 9] == 4) {
@@ -845,8 +839,7 @@ fill_rtt_message(struct interface *ifp)
return 0;
}
-void
-flushbuf(struct interface *ifp)
+void flushbuf(struct interface *ifp)
{
int rc;
struct sockaddr_in6 sin6;
@@ -888,8 +881,7 @@ flushbuf(struct interface *ifp)
babel_ifp->flush_timeout.tv_usec = 0;
}
-static void
-schedule_flush(struct interface *ifp)
+static void schedule_flush(struct interface *ifp)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
unsigned msecs = jitter(babel_ifp, 0);
@@ -899,8 +891,7 @@ schedule_flush(struct interface *ifp)
set_timeout(&babel_ifp->flush_timeout, msecs);
}
-static void
-schedule_flush_now(struct interface *ifp)
+static void schedule_flush_now(struct interface *ifp)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
/* Almost now */
@@ -911,8 +902,7 @@ schedule_flush_now(struct interface *ifp)
set_timeout(&babel_ifp->flush_timeout, msecs);
}
-static void
-schedule_unicast_flush(unsigned msecs)
+static void schedule_unicast_flush(unsigned msecs)
{
if(!unicast_neighbour)
return;
@@ -924,16 +914,14 @@ schedule_unicast_flush(unsigned msecs)
babel_now.tv_sec + (babel_now.tv_usec / 1000 + msecs) / 1000;
}
-static void
-ensure_space(struct interface *ifp, int space)
+static void ensure_space(struct interface *ifp, int space)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
if(babel_ifp->bufsize - babel_ifp->buffered < space)
flushbuf(ifp);
}
-static void
-start_message(struct interface *ifp, int type, int len)
+static void start_message(struct interface *ifp, int type, int len)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
if(babel_ifp->bufsize - babel_ifp->buffered < len + 2)
@@ -942,8 +930,7 @@ start_message(struct interface *ifp, int type, int len)
babel_ifp->sendbuf[babel_ifp->buffered++] = len;
}
-static void
-end_message(struct interface *ifp, int type, int bytes)
+static void end_message(struct interface *ifp, int type, int bytes)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
assert(babel_ifp->buffered >= bytes + 2 &&
@@ -952,23 +939,20 @@ end_message(struct interface *ifp, int type, int bytes)
schedule_flush(ifp);
}
-static void
-accumulate_byte(struct interface *ifp, unsigned char value)
+static void accumulate_byte(struct interface *ifp, unsigned char value)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
babel_ifp->sendbuf[babel_ifp->buffered++] = value;
}
-static void
-accumulate_short(struct interface *ifp, unsigned short value)
+static void accumulate_short(struct interface *ifp, unsigned short value)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
DO_HTONS(babel_ifp->sendbuf + babel_ifp->buffered, value);
babel_ifp->buffered += 2;
}
-static void
-accumulate_int(struct interface *ifp, unsigned int value)
+static void accumulate_int(struct interface *ifp, unsigned int value)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
DO_HTONL(babel_ifp->sendbuf + babel_ifp->buffered, value);
@@ -984,8 +968,7 @@ accumulate_bytes(struct interface *ifp,
babel_ifp->buffered += len;
}
-static int
-start_unicast_message(struct neighbour *neigh, int type, int len)
+static int start_unicast_message(struct neighbour *neigh, int type, int len)
{
if(unicast_neighbour) {
if(neigh != unicast_neighbour ||
@@ -1008,8 +991,7 @@ start_unicast_message(struct neighbour *neigh, int type, int len)
return 1;
}
-static void
-end_unicast_message(struct neighbour *neigh, int type, int bytes)
+static void end_unicast_message(struct neighbour *neigh, int type, int bytes)
{
assert(unicast_neighbour == neigh && unicast_buffered >= bytes + 2 &&
unicast_buffer[unicast_buffered - bytes - 2] == type &&
@@ -1030,8 +1012,7 @@ accumulate_unicast_short(struct neighbour *neigh, unsigned short value)
unicast_buffered += 2;
}
-static void
-accumulate_unicast_int(struct neighbour *neigh, unsigned int value)
+static void accumulate_unicast_int(struct neighbour *neigh, unsigned int value)
{
DO_HTONL(unicast_buffer + unicast_buffered, value);
unicast_buffered += 4;
@@ -1051,15 +1032,16 @@ send_ack(struct neighbour *neigh, unsigned short nonce, unsigned short interval)
int rc;
debugf(BABEL_DEBUG_COMMON,"Sending ack (%04x) to %s on %s.",
nonce, format_address(neigh->address), neigh->ifp->name);
- rc = start_unicast_message(neigh, MESSAGE_ACK, 2); if(rc < 0) return;
+ rc = start_unicast_message(neigh, MESSAGE_ACK, 2);
+ if(rc < 0)
+ return;
accumulate_unicast_short(neigh, nonce);
end_unicast_message(neigh, MESSAGE_ACK, 2);
/* Roughly yields a value no larger than 3/2, so this meets the deadline */
schedule_unicast_flush(roughly(interval * 6));
}
-void
-send_hello_noupdate(struct interface *ifp, unsigned interval)
+void send_hello_noupdate(struct interface *ifp, unsigned interval)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
/* This avoids sending multiple hellos in a single packet, which breaks
@@ -1082,7 +1064,7 @@ send_hello_noupdate(struct interface *ifp, unsigned interval)
accumulate_short(ifp, 0);
accumulate_short(ifp, babel_ifp->hello_seqno);
accumulate_short(ifp, interval > 0xFFFF ? 0xFFFF : interval);
- if(babel_ifp->flags & BABEL_IF_TIMESTAMPS) {
+ if (CHECK_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS)) {
/* Sub-TLV containing the local time of emission. We use a
Pad4 sub-TLV, which we'll fill just before sending. */
accumulate_byte(ifp, SUBTLV_PADN);
@@ -1090,11 +1072,10 @@ send_hello_noupdate(struct interface *ifp, unsigned interval)
accumulate_int(ifp, 0);
}
end_message(ifp, MESSAGE_HELLO,
- (babel_ifp->flags & BABEL_IF_TIMESTAMPS) ? 12 : 6);
+ CHECK_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS) ? 12 : 6);
}
-void
-send_hello(struct interface *ifp)
+void send_hello(struct interface *ifp)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
send_hello_noupdate(ifp, (babel_ifp->hello_interval + 9) / 10);
@@ -1105,8 +1086,7 @@ send_hello(struct interface *ifp)
send_marginal_ihu(ifp);
}
-void
-flush_unicast(int dofree)
+void flush_unicast(int dofree)
{
struct sockaddr_in6 sin6;
int rc;
@@ -1183,7 +1163,7 @@ really_send_update(struct interface *ifp,
/* Worst case */
ensure_space(ifp, 20 + 12 + 28);
- v4 = plen >= 96 && v4mapped(prefix);
+ v4 = (plen >= 96) && v4mapped(prefix);
if(v4) {
if(!babel_ifp->ipv4)
@@ -1208,7 +1188,7 @@ really_send_update(struct interface *ifp,
omit++;
}
if(!babel_ifp->have_buffered_prefix || plen >= 48)
- flags |= 0x80;
+ SET_FLAG(flags, 0x80);
real_prefix = prefix;
real_plen = plen;
}
@@ -1216,7 +1196,7 @@ really_send_update(struct interface *ifp,
if(!babel_ifp->have_buffered_id
|| memcmp(id, babel_ifp->buffered_id, 8) != 0) {
if(real_plen == 128 && memcmp(real_prefix + 8, id, 8) == 0) {
- flags |= 0x40;
+ SET_FLAG(flags, 0x40);
} else {
start_message(ifp, MESSAGE_ROUTER_ID, 10);
accumulate_short(ifp, 0);
@@ -1248,14 +1228,13 @@ really_send_update(struct interface *ifp,
end_message(ifp, MESSAGE_UPDATE, 10 + (real_plen + 7) / 8 - omit +
channels_size);
- if(flags & 0x80) {
+ if (CHECK_FLAG(flags, 0x80)) {
memcpy(babel_ifp->buffered_prefix, prefix, 16);
babel_ifp->have_buffered_prefix = 1;
}
}
-static int
-compare_buffered_updates(const void *av, const void *bv)
+static int compare_buffered_updates(const void *av, const void *bv)
{
const struct buffered_update *a = av, *b = bv;
int rc, v4a, v4b, ma, mb;
@@ -1288,8 +1267,7 @@ compare_buffered_updates(const void *av, const void *bv)
return memcmp(a->prefix, b->prefix, 16);
}
-void
-flushupdates(struct interface *ifp)
+void flushupdates(struct interface *ifp)
{
babel_interface_nfo *babel_ifp = NULL;
struct xroute *xroute;
@@ -1299,7 +1277,7 @@ flushupdates(struct interface *ifp)
int i;
if(ifp == NULL) {
- struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+ struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp_aux;
FOR_ALL_INTERFACES(vrf, ifp_aux)
flushupdates(ifp_aux);
@@ -1372,7 +1350,7 @@ flushupdates(struct interface *ifp)
if(metric < INFINITY)
satisfy_request(route->src->prefix, route->src->plen,
seqno, route->src->id, ifp);
- if((babel_ifp->flags & BABEL_IF_SPLIT_HORIZON) &&
+ if(CHECK_FLAG(babel_ifp->flags, BABEL_IF_SPLIT_HORIZON) &&
route->neigh->ifp == ifp)
continue;
@@ -1414,11 +1392,11 @@ flushupdates(struct interface *ifp)
babel_ifp->update_flush_timeout.tv_usec = 0;
}
-static void
-schedule_update_flush(struct interface *ifp, int urgent)
+static void schedule_update_flush(struct interface *ifp, int urgent)
{
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
unsigned msecs;
+
msecs = update_jitter(babel_ifp, urgent);
if(babel_ifp->update_flush_timeout.tv_sec != 0 &&
timeval_minus_msec(&babel_ifp->update_flush_timeout, &babel_now) < msecs)
@@ -1528,10 +1506,10 @@ send_update_resend(struct interface *ifp,
record_resend(RESEND_UPDATE, prefix, plen, 0, NULL, NULL, resend_delay);
}
-void
-send_wildcard_retraction(struct interface *ifp)
+void send_wildcard_retraction(struct interface *ifp)
{
babel_interface_nfo *babel_ifp = NULL;
+
if(ifp == NULL) {
struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
struct interface *ifp_aux;
@@ -1557,14 +1535,12 @@ send_wildcard_retraction(struct interface *ifp)
babel_ifp->have_buffered_id = 0;
}
-void
-update_myseqno(void)
+void update_myseqno(void)
{
myseqno = seqno_plus(myseqno, 1);
}
-void
-send_self_update(struct interface *ifp)
+void send_self_update(struct interface *ifp)
{
struct xroute_stream *xroutes;
if(ifp == NULL) {
@@ -1592,8 +1568,7 @@ send_self_update(struct interface *ifp)
}
}
-void
-send_ihu(struct neighbour *neigh, struct interface *ifp)
+void send_ihu(struct neighbour *neigh, struct interface *ifp)
{
babel_interface_nfo *babel_ifp = NULL;
int rxcost, interval;
@@ -1645,7 +1620,7 @@ send_ihu(struct neighbour *neigh, struct interface *ifp)
ll = linklocal(neigh->address);
- if((babel_ifp->flags & BABEL_IF_TIMESTAMPS) && neigh->hello_send_us
+ if(CHECK_FLAG(babel_ifp->flags, BABEL_IF_TIMESTAMPS) && neigh->hello_send_us
/* Checks whether the RTT data is not too old to be sent. */
&& timeval_minus_msec(&babel_now,
&neigh->hello_rtt_receive_time) < 1000000) {
@@ -1700,14 +1675,13 @@ send_ihu(struct neighbour *neigh, struct interface *ifp)
}
/* Send IHUs to all marginal neighbours */
-void
-send_marginal_ihu(struct interface *ifp)
+void send_marginal_ihu(struct interface *ifp)
{
struct neighbour *neigh;
FOR_ALL_NEIGHBOURS(neigh) {
if(ifp && neigh->ifp != ifp)
continue;
- if(neigh->txcost >= 384 || (neigh->reach & 0xF000) != 0xF000)
+ if(neigh->txcost >= 384 || CHECK_FLAG(neigh->reach, 0xF000) != 0xF000)
send_ihu(neigh, ifp);
}
}
diff --git a/babeld/neighbour.c b/babeld/neighbour.c
index 51e595a..65e613c 100644
--- a/babeld/neighbour.c
+++ b/babeld/neighbour.c
@@ -34,15 +34,13 @@ find_neighbour_nocreate(const unsigned char *address, struct interface *ifp)
{
struct neighbour *neigh;
FOR_ALL_NEIGHBOURS(neigh) {
- if(memcmp(address, neigh->address, 16) == 0 &&
- neigh->ifp == ifp)
+ if(memcmp(address, neigh->address, 16) == 0 && neigh->ifp == ifp)
return neigh;
}
return NULL;
}
-void
-flush_neighbour(struct neighbour *neigh)
+void flush_neighbour(struct neighbour *neigh)
{
debugf(BABEL_DEBUG_COMMON,"Flushing neighbour %s (reach 0x%04x)",
format_address(neigh->address), neigh->reach);
@@ -102,8 +100,7 @@ find_neighbour(const unsigned char *address, struct interface *ifp)
}
/* Recompute a neighbour's rxcost. Return true if anything changed. */
-int
-update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
+int update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
{
int missed_hellos;
int rc = 0;
@@ -160,26 +157,26 @@ update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
if(hello >= 0) {
neigh->hello_seqno = hello;
neigh->reach >>= 1;
- neigh->reach |= 0x8000;
- if((neigh->reach & 0xFC00) != 0xFC00)
+ SET_FLAG(neigh->reach, 0x8000);
+ if(CHECK_FLAG(neigh->reach, 0xFC00) != 0xFC00)
rc = 1;
}
/* Make sure to give neighbours some feedback early after association */
- if((neigh->reach & 0xBF00) == 0x8000) {
+ if(CHECK_FLAG(neigh->reach, 0xBF00) == 0x8000) {
/* A new neighbour */
send_hello(neigh->ifp);
} else {
/* Don't send hellos, in order to avoid a positive feedback loop. */
- int a = (neigh->reach & 0xC000);
- int b = (neigh->reach & 0x3000);
+ int a = CHECK_FLAG(neigh->reach, 0xC000);
+ int b = CHECK_FLAG(neigh->reach, 0x3000);
if((a == 0xC000 && b == 0) || (a == 0 && b == 0x3000)) {
/* Reachability is either 1100 or 0011 */
send_self_update(neigh->ifp);
}
}
- if((neigh->reach & 0xFC00) == 0xC000) {
+ if(CHECK_FLAG(neigh->reach, 0xFC00) == 0xC000) {
/* This is a newish neighbour, let's request a full route dump.
We ought to avoid this when the network is dense */
send_unicast_request(neigh, NULL, 0);
@@ -188,8 +185,7 @@ update_neighbour(struct neighbour *neigh, int hello, int hello_interval)
return rc;
}
-static int
-reset_txcost(struct neighbour *neigh)
+static int reset_txcost(struct neighbour *neigh)
{
unsigned delay;
@@ -199,9 +195,8 @@ reset_txcost(struct neighbour *neigh)
return 0;
/* If we're losing a lot of packets, we probably lost an IHU too */
- if(delay >= 180000 || (neigh->reach & 0xFFF0) == 0 ||
- (neigh->ihu_interval > 0 &&
- delay >= neigh->ihu_interval * 10U * 10U)) {
+ if (delay >= 180000 || CHECK_FLAG(neigh->reach, 0xFFF0) == 0 ||
+ (neigh->ihu_interval > 0 && delay >= neigh->ihu_interval * 10U * 10U)) {
neigh->txcost = INFINITY;
neigh->ihu_time = babel_now;
return 1;
@@ -210,14 +205,12 @@ reset_txcost(struct neighbour *neigh)
return 0;
}
-unsigned
-neighbour_txcost(struct neighbour *neigh)
+unsigned neighbour_txcost(struct neighbour *neigh)
{
return neigh->txcost;
}
-unsigned
-check_neighbours(void)
+unsigned check_neighbours(void)
{
struct neighbour *neigh;
int changed, rc;
@@ -253,21 +246,20 @@ check_neighbours(void)
return msecs;
}
-unsigned
-neighbour_rxcost(struct neighbour *neigh)
+unsigned neighbour_rxcost(struct neighbour *neigh)
{
unsigned delay;
unsigned short reach = neigh->reach;
delay = timeval_minus_msec(&babel_now, &neigh->hello_time);
- if((reach & 0xFFF0) == 0 || delay >= 180000) {
+ if(CHECK_FLAG(reach, 0xFFF0) == 0 || delay >= 180000) {
return INFINITY;
- } else if(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ) {
+ } else if (CHECK_FLAG(babel_get_if_nfo(neigh->ifp)->flags, BABEL_IF_LQ)) {
int sreach =
- ((reach & 0x8000) >> 2) +
- ((reach & 0x4000) >> 1) +
- (reach & 0x3FFF);
+ (CHECK_FLAG(reach, 0x8000) >> 2) +
+ (CHECK_FLAG(reach, 0x4000) >> 1) +
+ CHECK_FLAG(reach, 0x3FFF);
/* 0 <= sreach <= 0x7FFF */
int cost = (0x8000 * babel_get_if_nfo(neigh->ifp)->cost) / (sreach + 1);
/* cost >= interface->cost */
@@ -276,19 +268,18 @@ neighbour_rxcost(struct neighbour *neigh)
return MIN(cost, INFINITY);
} else {
/* To lose one hello is a misfortune, to lose two is carelessness. */
- if((reach & 0xC000) == 0xC000)
+ if (CHECK_FLAG(reach, 0xC000) == 0xC000)
return babel_get_if_nfo(neigh->ifp)->cost;
- else if((reach & 0xC000) == 0)
+ else if (CHECK_FLAG(reach, 0xC000) == 0)
return INFINITY;
- else if((reach & 0x2000))
+ else if (CHECK_FLAG(reach, 0x2000))
return babel_get_if_nfo(neigh->ifp)->cost;
else
return INFINITY;
}
}
-unsigned
-neighbour_rttcost(struct neighbour *neigh)
+unsigned neighbour_rttcost(struct neighbour *neigh)
{
struct interface *ifp = neigh->ifp;
babel_interface_nfo *babel_ifp = babel_get_if_nfo(ifp);
@@ -304,15 +295,14 @@ neighbour_rttcost(struct neighbour *neigh)
(unsigned long long)babel_ifp->max_rtt_penalty *
(neigh->rtt - babel_ifp->rtt_min) /
(babel_ifp->rtt_max - babel_ifp->rtt_min);
- assert((tmp & 0x7FFFFFFF) == tmp);
+ assert(CHECK_FLAG(tmp, 0x7FFFFFFF) == tmp);
return tmp;
} else {
return babel_ifp->max_rtt_penalty;
}
}
-unsigned
-neighbour_cost(struct neighbour *neigh)
+unsigned neighbour_cost(struct neighbour *neigh)
{
unsigned a, b, cost;
@@ -328,7 +318,7 @@ neighbour_cost(struct neighbour *neigh)
if(b >= INFINITY)
return INFINITY;
- if(!(babel_get_if_nfo(neigh->ifp)->flags & BABEL_IF_LQ)
+ if (!CHECK_FLAG(babel_get_if_nfo(neigh->ifp)->flags, BABEL_IF_LQ)
|| (a < 256 && b < 256)) {
cost = a;
} else {
@@ -347,8 +337,7 @@ neighbour_cost(struct neighbour *neigh)
return MIN(cost, INFINITY);
}
-int
-valid_rtt(struct neighbour *neigh)
+int valid_rtt(struct neighbour *neigh)
{
return (timeval_minus_msec(&babel_now, &neigh->rtt_time) < 180000) ? 1 : 0;
}
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 66bf706..f4ff884 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -105,6 +105,8 @@ struct bfd_echo_pkt {
#define BFD_CBIT 0x08
#define BFD_ABIT 0x04
#define BFD_DEMANDBIT 0x02
+#define BFD_MBIT 0x01
+#define BFD_GETMBIT(flags) (flags & BFD_MBIT)
#define BFD_SETDEMANDBIT(flags, val) \
{ \
if ((val)) \
@@ -133,7 +135,7 @@ struct bfd_echo_pkt {
if ((val)) \
flags |= val; \
}
-#define BFD_GETCBIT(flags) (flags & BFD_FBIT)
+#define BFD_GETCBIT(flags) (flags & BFD_CBIT)
#define BFD_ECHO_VERSION 1
#define BFD_ECHO_PKT_LEN sizeof(struct bfd_echo_pkt)
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index fec195c..8110f43 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -898,6 +898,12 @@ void bfd_recv_cb(struct event *t)
return;
}
+ if (BFD_GETMBIT(cp->flags)) {
+ cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
+ "detect non-zero Multipoint (M) flag");
+ return;
+ }
+
if (cp->discrs.my_discr == 0) {
cp_debug(is_mhop, &peer, &local, ifindex, vrfid,
"'my discriminator' is zero");
diff --git a/bgpd/bgp_addpath.h b/bgpd/bgp_addpath.h
index d562000..c267ebe 100644
--- a/bgpd/bgp_addpath.h
+++ b/bgpd/bgp_addpath.h
@@ -21,6 +21,12 @@ struct bgp_addpath_capability {
uint8_t flags;
};
+struct bgp_paths_limit_capability {
+ uint16_t afi;
+ uint8_t safi;
+ uint16_t paths_limit;
+} __attribute__((packed));
+
#define BGP_ADDPATH_TX_ID_FOR_DEFAULT_ORIGINATE 1
void bgp_addpath_init_bgp_data(struct bgp_addpath_bgp_data *d);
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index a81f288..d5c7e18 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -163,7 +163,7 @@ bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
- uint32_t addpath_id)
+ uint32_t addpath_id, struct bgp_labels *labels)
{
struct bgp_adj_in *adj;
@@ -173,6 +173,10 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
bgp_attr_unintern(&adj->attr);
adj->attr = bgp_attr_intern(attr);
}
+ if (!bgp_labels_cmp(adj->labels, labels)) {
+ bgp_labels_unintern(&adj->labels);
+ adj->labels = bgp_labels_intern(labels);
+ }
return;
}
}
@@ -181,13 +185,18 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
adj->attr = bgp_attr_intern(attr);
adj->uptime = monotime(NULL);
adj->addpath_rx_id = addpath_id;
+ adj->labels = bgp_labels_intern(labels);
BGP_ADJ_IN_ADD(dest, adj);
+ peer->stat_pfx_adj_rib_in++;
bgp_dest_lock_node(dest);
}
void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai)
{
bgp_attr_unintern(&bai->attr);
+ bgp_labels_unintern(&bai->labels);
+ if (bai->peer)
+ bai->peer->stat_pfx_adj_rib_in--;
BGP_ADJ_IN_DEL(*dest, bai);
*dest = bgp_dest_unlock_node(*dest);
peer_unlock(bai->peer); /* adj_in peer reference */
diff --git a/bgpd/bgp_advertise.h b/bgpd/bgp_advertise.h
index 4982106..8c83189 100644
--- a/bgpd/bgp_advertise.h
+++ b/bgpd/bgp_advertise.h
@@ -75,6 +75,9 @@ struct bgp_adj_out {
/* Advertised attribute. */
struct attr *attr;
+ /* VPN label information */
+ struct bgp_labels *labels;
+
/* Advertisement information. */
struct bgp_advertise *adv;
};
@@ -95,6 +98,9 @@ struct bgp_adj_in {
/* Received attribute. */
struct attr *attr;
+ /* VPN label information */
+ struct bgp_labels *labels;
+
/* timestamp (monotime) */
time_t uptime;
@@ -135,7 +141,8 @@ struct bgp_synchronize {
extern bool bgp_adj_out_lookup(struct peer *peer, struct bgp_dest *dest,
uint32_t addpath_tx_id);
extern void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer,
- struct attr *attr, uint32_t addpath_id);
+ struct attr *attr, uint32_t addpath_id,
+ struct bgp_labels *labels);
extern bool bgp_adj_in_unset(struct bgp_dest **dest, struct peer *peer,
uint32_t addpath_id);
extern void bgp_adj_in_remove(struct bgp_dest **dest, struct bgp_adj_in *bai);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index bc7e893..4c1615a 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -77,6 +77,9 @@ static struct hash *ashash;
/* Stream for SNMP. See aspath_snmp_pathseg */
static struct stream *snmp_stream;
+/* as-path orphan exclude list */
+static struct as_list_list_head as_exclude_list_orphan;
+
/* Callers are required to initialize the memory */
static as_t *assegment_data_new(int num)
{
@@ -1558,6 +1561,38 @@ struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2)
/* Not reached */
}
+/* insert aspath exclude in head of orphan exclude list*/
+void as_exclude_set_orphan(struct aspath_exclude *ase)
+{
+ ase->exclude_aspath_acl = NULL;
+ as_list_list_add_head(&as_exclude_list_orphan, ase);
+}
+
+void as_exclude_remove_orphan(struct aspath_exclude *ase)
+{
+ if (as_list_list_count(&as_exclude_list_orphan))
+ as_list_list_del(&as_exclude_list_orphan, ase);
+}
+
+/* currently provide only one exclude, not a list */
+struct aspath_exclude *as_exclude_lookup_orphan(const char *acl_name)
+{
+ struct aspath_exclude *ase = NULL;
+ char *name = NULL;
+
+ frr_each (as_list_list, &as_exclude_list_orphan, ase) {
+ if (ase->exclude_aspath_acl_name) {
+ name = ase->exclude_aspath_acl_name;
+ if (!strcmp(name, acl_name))
+ break;
+ }
+ }
+ if (ase)
+ as_exclude_remove_orphan(ase);
+
+ return ase;
+}
+
/* Iterate over AS_PATH segments and wipe all occurrences of the
* listed AS numbers. Hence some segments may lose some or even
* all data on the way, the operation is implemented as a smarter
@@ -2236,20 +2271,32 @@ void aspath_init(void)
{
ashash = hash_create_size(32768, aspath_key_make, aspath_cmp,
"BGP AS Path");
+
+ as_list_list_init(&as_exclude_list_orphan);
}
void aspath_finish(void)
{
+ struct aspath_exclude *ase;
+
hash_clean_and_free(&ashash, (void (*)(void *))aspath_free);
if (snmp_stream)
stream_free(snmp_stream);
+
+ while ((ase = as_list_list_pop(&as_exclude_list_orphan))) {
+ aspath_free(ase->aspath);
+ if (ase->exclude_aspath_acl_name)
+ XFREE(MTYPE_TMP, ase->exclude_aspath_acl_name);
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, ase);
+ }
+ as_list_list_fini(&as_exclude_list_orphan);
}
/* return and as path value */
const char *aspath_print(struct aspath *as)
{
- return (as ? as->str : NULL);
+ return as ? as->str : "(null)";
}
/* Printing functions */
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 2a831c3..f7e57fd 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -9,6 +9,7 @@
#include "lib/json.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_filter.h"
+#include <typesafe.h>
/* AS path segment type. */
#define AS_SET 1
@@ -67,11 +68,14 @@ struct aspath {
/* `set as-path exclude ASn' */
struct aspath_exclude {
+ struct as_list_list_item exclude_list;
struct aspath *aspath;
bool exclude_all;
char *exclude_aspath_acl_name;
struct as_list *exclude_aspath_acl;
};
+DECLARE_DLIST(as_list_list, struct aspath_exclude, exclude_list);
+
/* Prototypes. */
extern void aspath_init(void);
@@ -83,6 +87,9 @@ extern struct aspath *aspath_parse(struct stream *s, size_t length,
extern struct aspath *aspath_dup(struct aspath *aspath);
extern struct aspath *aspath_aggregate(struct aspath *as1, struct aspath *as2);
extern struct aspath *aspath_prepend(struct aspath *as1, struct aspath *as2);
+extern void as_exclude_set_orphan(struct aspath_exclude *ase);
+extern void as_exclude_remove_orphan(struct aspath_exclude *ase);
+extern struct aspath_exclude *as_exclude_lookup_orphan(const char *acl_name);
extern struct aspath *aspath_filter_exclude(struct aspath *source,
struct aspath *exclude_list);
extern struct aspath *aspath_filter_exclude_all(struct aspath *source);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 40e074d..e4ee589 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -911,9 +911,17 @@ static void attr_show_all_iterator(struct hash_bucket *bucket, struct vty *vty)
vty_out(vty,
"\tflags: %" PRIu64
- " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6\n",
+ " distance: %u med: %u local_pref: %u origin: %u weight: %u label: %u sid: %pI6 aigp_metric: %" PRIu64
+ "\n",
attr->flag, attr->distance, attr->med, attr->local_pref,
- attr->origin, attr->weight, attr->label, sid);
+ attr->origin, attr->weight, attr->label, sid, attr->aigp_metric);
+ vty_out(vty, "\taspath: %s Community: %s Large Community: %s\n",
+ aspath_print(attr->aspath),
+ community_str(attr->community, false, false),
+ lcommunity_str(attr->lcommunity, false, false));
+ vty_out(vty, "\tExtended Community: %s Extended IPv6 Community: %s\n",
+ ecommunity_str(attr->ecommunity),
+ ecommunity_str(attr->ipv6_ecommunity));
}
void attr_show_all(struct vty *vty)
@@ -2368,6 +2376,12 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
return BGP_ATTR_PARSE_WITHDRAW;
}
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
+ if (if_is_operative(peer->nexthop.ifp))
+ SET_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_IF_OPERSTATE);
+ else
+ UNSET_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_IF_OPERSTATE);
}
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
@@ -2385,6 +2399,12 @@ int bgp_mp_reach_parse(struct bgp_attr_parser_args *args,
return BGP_ATTR_PARSE_WITHDRAW;
}
attr->nh_ifindex = peer->nexthop.ifp->ifindex;
+ if (if_is_operative(peer->nexthop.ifp))
+ SET_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_IF_OPERSTATE);
+ else
+ UNSET_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_IF_OPERSTATE);
}
if (attr->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
@@ -2640,10 +2660,7 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
if (peer->discard_attrs[args->type] || peer->withdraw_attrs[args->type])
goto ipv6_ext_community_ignore;
- ipv6_ecomm = ecommunity_parse_ipv6(
- stream_pnt(peer->curr), length,
- CHECK_FLAG(peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+ ipv6_ecomm = ecommunity_parse_ipv6(stream_pnt(peer->curr), length);
bgp_attr_set_ipv6_ecommunity(attr, ipv6_ecomm);
/* XXX: fix ecommunity_parse to use stream API */
@@ -2653,6 +2670,10 @@ bgp_attr_ipv6_ext_communities(struct bgp_attr_parser_args *args)
return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
args->total);
+ /* Extract link bandwidth, if any. */
+ (void)ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(attr),
+ &attr->link_bw);
+
return BGP_ATTR_PARSE_PROCEED;
ipv6_ext_community_ignore:
@@ -2700,17 +2721,20 @@ static int bgp_attr_encap(struct bgp_attr_parser_args *args)
}
}
- while (length >= 4) {
+ while (STREAM_READABLE(BGP_INPUT(peer)) >= 4) {
uint16_t subtype = 0;
uint16_t sublength = 0;
struct bgp_attr_encap_subtlv *tlv;
if (BGP_ATTR_ENCAP == type) {
subtype = stream_getc(BGP_INPUT(peer));
- sublength = (subtype < 128)
- ? stream_getc(BGP_INPUT(peer))
- : stream_getw(BGP_INPUT(peer));
- length -= 2;
+ if (subtype < 128) {
+ sublength = stream_getc(BGP_INPUT(peer));
+ length -= 2;
+ } else {
+ sublength = stream_getw(BGP_INPUT(peer));
+ length -= 3;
+ }
#ifdef ENABLE_BGP_VNC
} else {
subtype = stream_getw(BGP_INPUT(peer));
@@ -2727,6 +2751,14 @@ static int bgp_attr_encap(struct bgp_attr_parser_args *args)
args->total);
}
+ if (STREAM_READABLE(BGP_INPUT(peer)) < sublength) {
+ zlog_err("Tunnel Encap attribute sub-tlv length %d exceeds remaining stream length %zu",
+ sublength, STREAM_READABLE(BGP_INPUT(peer)));
+ return bgp_attr_malformed(args,
+ BGP_NOTIFY_UPDATE_OPT_ATTR_ERR,
+ args->total);
+ }
+
/* alloc and copy sub-tlv */
/* TBD make sure these are freed when attributes are released */
tlv = XCALLOC(MTYPE_ENCAP_TLV,
@@ -4137,7 +4169,7 @@ size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer, afi_t afi,
void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
const struct prefix *p,
const struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, bool addpath_capable,
+ uint8_t num_labels, bool addpath_capable,
uint32_t addpath_tx_id, struct attr *attr)
{
switch (safi) {
@@ -4344,13 +4376,76 @@ static bool bgp_append_local_as(struct peer *peer, afi_t afi, safi_t safi)
return false;
}
+static void bgp_packet_ecommunity_attribute(struct stream *s, struct peer *peer,
+ struct ecommunity *ecomm,
+ bool transparent, int attribute)
+{
+ if (peer->sort == BGP_PEER_IBGP || peer->sort == BGP_PEER_CONFED ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD || transparent) {
+ if (ecomm->size * ecomm->unit_size > 255) {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS |
+ BGP_ATTR_FLAG_EXTLEN);
+ stream_putc(s, attribute);
+ stream_putw(s, ecomm->size * ecomm->unit_size);
+ } else {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, attribute);
+ stream_putc(s, ecomm->size * ecomm->unit_size);
+ }
+ stream_put(s, ecomm->val, ecomm->size * ecomm->unit_size);
+ } else {
+ uint8_t *pnt;
+ int tbit;
+ int ecom_tr_size = 0;
+ uint32_t i;
+
+ for (i = 0; i < ecomm->size; i++) {
+ pnt = ecomm->val + (i * ecomm->unit_size);
+ tbit = *pnt;
+
+ if (CHECK_FLAG(tbit, ECOMMUNITY_FLAG_NON_TRANSITIVE))
+ continue;
+
+ ecom_tr_size++;
+ }
+
+ if (ecom_tr_size) {
+ if (ecom_tr_size * ecomm->unit_size > 255) {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS |
+ BGP_ATTR_FLAG_EXTLEN);
+ stream_putc(s, attribute);
+ stream_putw(s, ecom_tr_size * ecomm->unit_size);
+ } else {
+ stream_putc(s, BGP_ATTR_FLAG_OPTIONAL |
+ BGP_ATTR_FLAG_TRANS);
+ stream_putc(s, attribute);
+ stream_putc(s, ecom_tr_size * ecomm->unit_size);
+ }
+
+ for (i = 0; i < ecomm->size; i++) {
+ pnt = ecomm->val + (i * ecomm->unit_size);
+ tbit = *pnt;
+
+ if (CHECK_FLAG(tbit,
+ ECOMMUNITY_FLAG_NON_TRANSITIVE))
+ continue;
+
+ stream_put(s, pnt, ecomm->unit_size);
+ }
+ }
+ }
+}
+
/* Make attribute packet. */
bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
struct stream *s, struct attr *attr,
struct bpacket_attr_vec_arr *vecarr,
struct prefix *p, afi_t afi, safi_t safi,
struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
bool addpath_capable, uint32_t addpath_tx_id,
struct bgp_path_info *bpi)
{
@@ -4646,82 +4741,31 @@ bgp_size_t bgp_packet_attribute(struct bgp *bgp, struct peer *peer,
}
}
- /* Extended Communities attribute. */
- if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)
- && (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
- struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
+ /* Extended IPv6/Communities attributes. */
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_SEND_EXT_COMMUNITY)) {
bool transparent = CHECK_FLAG(peer->af_flags[afi][safi],
PEER_FLAG_RSERVER_CLIENT) &&
from &&
CHECK_FLAG(from->af_flags[afi][safi],
PEER_FLAG_RSERVER_CLIENT);
- if (peer->sort == BGP_PEER_IBGP ||
- peer->sort == BGP_PEER_CONFED || transparent) {
- if (ecomm->size * 8 > 255) {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS
- | BGP_ATTR_FLAG_EXTLEN);
- stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
- stream_putw(s, ecomm->size * 8);
- } else {
- stream_putc(s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
- stream_putc(s, BGP_ATTR_EXT_COMMUNITIES);
- stream_putc(s, ecomm->size * 8);
- }
- stream_put(s, ecomm->val, ecomm->size * 8);
- } else {
- uint8_t *pnt;
- int tbit;
- int ecom_tr_size = 0;
- uint32_t i;
-
- for (i = 0; i < ecomm->size; i++) {
- pnt = ecomm->val + (i * 8);
- tbit = *pnt;
+ if (CHECK_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES))) {
+ struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
- if (CHECK_FLAG(tbit,
- ECOMMUNITY_FLAG_NON_TRANSITIVE))
- continue;
+ bgp_packet_ecommunity_attribute(s, peer, ecomm,
+ transparent,
+ BGP_ATTR_EXT_COMMUNITIES);
+ }
- ecom_tr_size++;
- }
+ if (CHECK_FLAG(attr->flag,
+ ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES))) {
+ struct ecommunity *ecomm =
+ bgp_attr_get_ipv6_ecommunity(attr);
- if (ecom_tr_size) {
- if (ecom_tr_size * 8 > 255) {
- stream_putc(
- s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS
- | BGP_ATTR_FLAG_EXTLEN);
- stream_putc(s,
- BGP_ATTR_EXT_COMMUNITIES);
- stream_putw(s, ecom_tr_size * 8);
- } else {
- stream_putc(
- s,
- BGP_ATTR_FLAG_OPTIONAL
- | BGP_ATTR_FLAG_TRANS);
- stream_putc(s,
- BGP_ATTR_EXT_COMMUNITIES);
- stream_putc(s, ecom_tr_size * 8);
- }
-
- for (i = 0; i < ecomm->size; i++) {
- pnt = ecomm->val + (i * 8);
- tbit = *pnt;
-
- if (CHECK_FLAG(
- tbit,
- ECOMMUNITY_FLAG_NON_TRANSITIVE))
- continue;
-
- stream_put(s, pnt, 8);
- }
- }
+ bgp_packet_ecommunity_attribute(s, peer, ecomm,
+ transparent,
+ BGP_ATTR_IPV6_EXT_COMMUNITIES);
}
}
@@ -4930,7 +4974,7 @@ size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi, safi_t safi)
void bgp_packet_mpunreach_prefix(struct stream *s, const struct prefix *p,
afi_t afi, safi_t safi,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
bool addpath_capable, uint32_t addpath_tx_id,
struct attr *attr)
{
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index d78f04c..f353e76 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -158,6 +158,8 @@ struct attr {
uint8_t nh_flags;
#define BGP_ATTR_NH_VALID 0x01
+#define BGP_ATTR_NH_IF_OPERSTATE 0x02
+#define BGP_ATTR_NH_MP_PREFER_GLOBAL 0x04 /* MP Nexthop preference */
/* Path origin attribute */
uint8_t origin;
@@ -254,9 +256,6 @@ struct attr {
/* MP Nexthop length */
uint8_t mp_nexthop_len;
- /* MP Nexthop preference */
- uint8_t mp_nexthop_prefer_global;
-
/* Static MAC for EVPN */
uint8_t sticky;
@@ -302,7 +301,7 @@ struct attr {
uint32_t rmap_table_id;
/* Link bandwidth value, if any. */
- uint32_t link_bw;
+ uint64_t link_bw;
/* EVPN ES */
esi_t esi;
@@ -394,7 +393,7 @@ extern bgp_size_t bgp_packet_attribute(
struct bgp *bgp, struct peer *peer, struct stream *s, struct attr *attr,
struct bpacket_attr_vec_arr *vecarr, struct prefix *p, afi_t afi,
safi_t safi, struct peer *from, struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels, bool addpath_capable,
+ mpls_label_t *label, uint8_t num_labels, bool addpath_capable,
uint32_t addpath_tx_id, struct bgp_path_info *bpi);
extern void bgp_dump_routes_attr(struct stream *s, struct bgp_path_info *bpi,
const struct prefix *p);
@@ -452,7 +451,7 @@ extern size_t bgp_packet_mpattr_start(struct stream *s, struct peer *peer,
extern void bgp_packet_mpattr_prefix(struct stream *s, afi_t afi, safi_t safi,
const struct prefix *p,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
bool addpath_capable,
uint32_t addpath_tx_id, struct attr *);
extern size_t bgp_packet_mpattr_prefix_size(afi_t afi, safi_t safi,
@@ -463,7 +462,7 @@ extern size_t bgp_packet_mpunreach_start(struct stream *s, afi_t afi,
safi_t safi);
extern void bgp_packet_mpunreach_prefix(
struct stream *s, const struct prefix *p, afi_t afi, safi_t safi,
- const struct prefix_rd *prd, mpls_label_t *label, uint32_t num_labels,
+ const struct prefix_rd *prd, mpls_label_t *label, uint8_t num_labels,
bool addpath_capable, uint32_t addpath_tx_id, struct attr *attr);
extern void bgp_packet_mpunreach_end(struct stream *s, size_t attrlen_pnt);
diff --git a/bgpd/bgp_bfd.c b/bgpd/bgp_bfd.c
index 21864cf..14ff5f2 100644
--- a/bgpd/bgp_bfd.c
+++ b/bgpd/bgp_bfd.c
@@ -597,6 +597,9 @@ DEFUN(no_neighbor_bfd_profile, no_neighbor_bfd_profile_cmd,
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
+ if (!peer->bfd_config)
+ return CMD_SUCCESS;
+
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP))
bgp_group_configure_bfd(peer);
else
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index 1de48a0..43f8006 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -38,6 +38,7 @@
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_trace.h"
#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_label.h"
static void bmp_close(struct bmp *bmp);
static struct bmp_bgp *bmp_bgp_find(struct bgp *bgp);
@@ -391,11 +392,11 @@ static int bmp_send_initiation(struct bmp *bmp)
bmp_common_hdr(s, BMP_VERSION_3, BMP_TYPE_INITIATION);
-#define BMP_INFO_TYPE_SYSDESCR 1
-#define BMP_INFO_TYPE_SYSNAME 2
- bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSDESCR,
- FRR_FULL_NAME " " FRR_VER_SHORT);
- bmp_put_info_tlv(s, BMP_INFO_TYPE_SYSNAME, cmd_hostname_get());
+#define BMP_INIT_INFO_TYPE_SYSDESCR 1
+#define BMP_INIT_INFO_TYPE_SYSNAME 2
+ bmp_put_info_tlv(s, BMP_INIT_INFO_TYPE_SYSDESCR,
+ FRR_FULL_NAME " " FRR_VER_SHORT);
+ bmp_put_info_tlv(s, BMP_INIT_INFO_TYPE_SYSNAME, cmd_hostname_get());
len = stream_get_endp(s);
stream_putl_at(s, BMP_LENGTH_POS, len); /* message length is set. */
@@ -438,6 +439,7 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
monotime_to_realtime(&uptime, &uptime_real);
#define BGP_BMP_MAX_PACKET_SIZE 1024
+#define BMP_PEERUP_INFO_TYPE_STRING 0
s = stream_new(BGP_MAX_PACKET_SIZE);
if (peer_established(peer->connection) && !down) {
@@ -493,7 +495,8 @@ static struct stream *bmp_peerstate(struct peer *peer, bool down)
}
if (peer->desc)
- bmp_put_info_tlv(s, 0, peer->desc);
+ bmp_put_info_tlv(s, BMP_PEERUP_INFO_TYPE_STRING,
+ peer->desc);
} else {
uint8_t type;
size_t type_pos;
@@ -910,7 +913,8 @@ static void bmp_eor(struct bmp *bmp, afi_t afi, safi_t safi, uint8_t flags,
static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
struct peer *peer, struct attr *attr,
- afi_t afi, safi_t safi)
+ afi_t afi, safi_t safi, mpls_label_t *label,
+ uint32_t num_labels)
{
struct bpacket_attr_vec_arr vecarr;
struct stream *s;
@@ -946,8 +950,8 @@ static struct stream *bmp_update(const struct prefix *p, struct prefix_rd *prd,
mpattrlen_pos = bgp_packet_mpattr_start(s, peer, afi, safi,
&vecarr, attr);
- bgp_packet_mpattr_prefix(s, afi, safi, p, prd, NULL, 0, 0, 0,
- attr);
+ bgp_packet_mpattr_prefix(s, afi, safi, p, prd, label,
+ num_labels, 0, 0, attr);
bgp_packet_mpattr_end(s, mpattrlen_pos);
total_attr_len += stream_get_endp(s) - p1;
}
@@ -1002,7 +1006,8 @@ static struct stream *bmp_withdraw(const struct prefix *p,
static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
uint8_t peer_type_flag, const struct prefix *p,
struct prefix_rd *prd, struct attr *attr, afi_t afi,
- safi_t safi, time_t uptime)
+ safi_t safi, time_t uptime, mpls_label_t *label,
+ uint32_t num_labels)
{
struct stream *hdr, *msg;
struct timeval tv = { .tv_sec = uptime, .tv_usec = 0 };
@@ -1019,7 +1024,8 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
monotime_to_realtime(&tv, &uptime_real);
if (attr)
- msg = bmp_update(p, prd, peer, attr, afi, safi);
+ msg = bmp_update(p, prd, peer, attr, afi, safi, label,
+ num_labels);
else
msg = bmp_withdraw(p, prd, afi, safi);
@@ -1041,6 +1047,7 @@ static void bmp_monitor(struct bmp *bmp, struct peer *peer, uint8_t flags,
static bool bmp_wrsync(struct bmp *bmp, struct pullwr *pullwr)
{
+ uint8_t bpi_num_labels;
afi_t afi;
safi_t safi;
@@ -1214,23 +1221,31 @@ afibreak:
(safi == SAFI_MPLS_VPN))
prd = (struct prefix_rd *)bgp_dest_get_prefix(bmp->syncrdpos);
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+
if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_SELECTED) &&
CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_LOC_RIB)) {
bmp_monitor(bmp, bpi->peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE,
bn_p, prd, bpi->attr, afi, safi,
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
- : (time_t)(-1L));
+ : (time_t)(-1L),
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
}
if (bpi && CHECK_FLAG(bpi->flags, BGP_PATH_VALID) &&
CHECK_FLAG(bmp->targets->afimon[afi][safi], BMP_MON_POSTPOLICY))
bmp_monitor(bmp, bpi->peer, BMP_PEER_FLAG_L,
BMP_PEER_TYPE_GLOBAL_INSTANCE, bn_p, prd, bpi->attr,
- afi, safi, bpi->uptime);
+ afi, safi, bpi->uptime,
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
if (adjin)
+ /* TODO: set label here when adjin supports labels */
bmp_monitor(bmp, adjin->peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
- bn_p, prd, adjin->attr, afi, safi, adjin->uptime);
+ bn_p, prd, adjin->attr, afi, safi, adjin->uptime,
+ NULL, 0);
if (bn)
bgp_dest_unlock_node(bn);
@@ -1281,6 +1296,7 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr)
struct peer *peer;
struct bgp_dest *bn = NULL;
bool written = false;
+ uint8_t bpi_num_labels;
bqe = bmp_pull_locrib(bmp);
if (!bqe)
@@ -1340,10 +1356,14 @@ static bool bmp_wrqueue_locrib(struct bmp *bmp, struct pullwr *pullwr)
break;
}
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+
bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_LOC_RIB_INSTANCE, &bqe->p, prd,
bpi ? bpi->attr : NULL, afi, safi,
bpi && bpi->extra ? bpi->extra->bgp_rib_uptime
- : (time_t)(-1L));
+ : (time_t)(-1L),
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
written = true;
out:
@@ -1362,6 +1382,7 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
struct peer *peer;
struct bgp_dest *bn = NULL;
bool written = false;
+ uint8_t bpi_num_labels;
bqe = bmp_pull(bmp);
if (!bqe)
@@ -1413,10 +1434,14 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
break;
}
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+
bmp_monitor(bmp, peer, BMP_PEER_FLAG_L,
BMP_PEER_TYPE_GLOBAL_INSTANCE, &bqe->p, prd,
bpi ? bpi->attr : NULL, afi, safi,
- bpi ? bpi->uptime : monotime(NULL));
+ bpi ? bpi->uptime : monotime(NULL),
+ bpi_num_labels ? bpi->extra->labels->label : NULL,
+ bpi_num_labels);
written = true;
}
@@ -1428,9 +1453,10 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
if (adjin->peer == peer)
break;
}
+ /* TODO: set label here when adjin supports labels */
bmp_monitor(bmp, peer, 0, BMP_PEER_TYPE_GLOBAL_INSTANCE,
&bqe->p, prd, adjin ? adjin->attr : NULL, afi, safi,
- adjin ? adjin->uptime : monotime(NULL));
+ adjin ? adjin->uptime : monotime(NULL), NULL, 0);
written = true;
}
@@ -1578,6 +1604,15 @@ static void bmp_stat_put_u32(struct stream *s, size_t *cnt, uint16_t type,
(*cnt)++;
}
+static void bmp_stat_put_u64(struct stream *s, size_t *cnt, uint16_t type,
+ uint64_t value)
+{
+ stream_putw(s, type);
+ stream_putw(s, 8);
+ stream_putq(s, value);
+ (*cnt)++;
+}
+
static void bmp_stats(struct event *thread)
{
struct bmp_targets *bt = EVENT_ARG(thread);
@@ -1619,8 +1654,13 @@ static void bmp_stats(struct event *thread)
peer->stat_pfx_dup_withdraw);
bmp_stat_put_u32(s, &count, BMP_STATS_UPD_7606_WITHDRAW,
peer->stat_upd_7606);
- bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID,
- peer->stat_pfx_nh_invalid);
+ if (bt->stats_send_experimental)
+ bmp_stat_put_u32(s, &count, BMP_STATS_FRR_NH_INVALID,
+ peer->stat_pfx_nh_invalid);
+ bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_ADJ_RIB_IN,
+ peer->stat_pfx_adj_rib_in);
+ bmp_stat_put_u64(s, &count, BMP_STATS_SIZE_LOC_RIB,
+ peer->stat_pfx_loc_rib);
stream_putl_at(s, count_pos, count);
@@ -1875,6 +1915,7 @@ static struct bmp_targets *bmp_targets_get(struct bgp *bgp, const char *name)
bt->name = XSTRDUP(MTYPE_BMP_TARGETSNAME, name);
bt->bgp = bgp;
bt->bmpbgp = bmp_bgp_get(bgp);
+ bt->stats_send_experimental = true;
bmp_session_init(&bt->sessions);
bmp_qhash_init(&bt->updhash);
bmp_qlist_init(&bt->updlist);
@@ -2455,6 +2496,21 @@ DEFPY(bmp_stats_cfg,
return CMD_SUCCESS;
}
+DEFPY(bmp_stats_send_experimental,
+ bmp_stats_send_experimental_cmd,
+ "[no] bmp stats send-experimental",
+ NO_STR
+ BMP_STR
+ "Send BMP statistics messages\n"
+ "Send experimental BMP stats [65531-65534]\n")
+{
+ VTY_DECLVAR_CONTEXT_SUB(bmp_targets, bt);
+
+ bt->stats_send_experimental = !no;
+
+ return CMD_SUCCESS;
+}
+
#define BMP_POLICY_IS_LOCRIB(str) ((str)[0] == 'l') /* __l__oc-rib */
#define BMP_POLICY_IS_PRE(str) ((str)[1] == 'r') /* p__r__e-policy */
@@ -2747,6 +2803,9 @@ static int bmp_config_write(struct bgp *bgp, struct vty *vty)
if (bt->acl_name)
vty_out(vty, " ip access-list %s\n", bt->acl_name);
+ if (!bt->stats_send_experimental)
+ vty_out(vty, " no bmp stats send-experimental\n");
+
if (bt->stat_msec)
vty_out(vty, " bmp stats interval %d\n",
bt->stat_msec);
@@ -2802,6 +2861,7 @@ static int bgp_bmp_init(struct event_loop *tm)
install_element(BMP_NODE, &no_bmp_listener_cmd);
install_element(BMP_NODE, &bmp_connect_cmd);
install_element(BMP_NODE, &bmp_acl_cmd);
+ install_element(BMP_NODE, &bmp_stats_send_experimental_cmd);
install_element(BMP_NODE, &bmp_stats_cmd);
install_element(BMP_NODE, &bmp_monitor_cmd);
install_element(BMP_NODE, &bmp_mirror_cmd);
diff --git a/bgpd/bgp_bmp.h b/bgpd/bgp_bmp.h
index dadd99e..33247c4 100644
--- a/bgpd/bgp_bmp.h
+++ b/bgpd/bgp_bmp.h
@@ -240,6 +240,8 @@ struct bmp_targets {
uint64_t cnt_accept, cnt_aclrefused;
+ bool stats_send_experimental;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bmp_targets);
diff --git a/bgpd/bgp_clist.c b/bgpd/bgp_clist.c
index 8336d6f..153cbd6 100644
--- a/bgpd/bgp_clist.c
+++ b/bgpd/bgp_clist.c
@@ -904,9 +904,9 @@ int community_list_set(struct community_list_handler *ch, const char *name,
}
/* Unset community-list */
-int community_list_unset(struct community_list_handler *ch, const char *name,
- const char *str, const char *seq, int direct,
- int style)
+void community_list_unset(struct community_list_handler *ch, const char *name,
+ const char *str, const char *seq, int direct,
+ int style)
{
struct community_list_master *cm = NULL;
struct community_entry *entry = NULL;
@@ -916,14 +916,14 @@ int community_list_unset(struct community_list_handler *ch, const char *name,
/* Lookup community list. */
list = community_list_lookup(ch, name, 0, COMMUNITY_LIST_MASTER);
if (list == NULL)
- return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ return;
cm = community_list_master_lookup(ch, COMMUNITY_LIST_MASTER);
/* Delete all of entry belongs to this community-list. */
if (!str) {
community_list_delete(cm, list);
route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
- return 0;
+ return;
}
if (style == COMMUNITY_LIST_STANDARD)
@@ -936,12 +936,10 @@ int community_list_unset(struct community_list_handler *ch, const char *name,
entry = community_list_entry_lookup(list, str, direct);
if (!entry)
- return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ return;
community_list_entry_delete(cm, list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_CLIST_DELETED);
-
- return 0;
}
bool lcommunity_list_any_match(struct lcommunity *lcom,
@@ -1172,9 +1170,9 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name,
/* Unset community-list. When str is NULL, delete all of
community-list entry belongs to the specified name. */
-int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
- const char *str, const char *seq, int direct,
- int style)
+void lcommunity_list_unset(struct community_list_handler *ch, const char *name,
+ const char *str, const char *seq, int direct,
+ int style)
{
struct community_list_master *cm = NULL;
struct community_entry *entry = NULL;
@@ -1185,14 +1183,14 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
/* Lookup community list. */
list = community_list_lookup(ch, name, 0, LARGE_COMMUNITY_LIST_MASTER);
if (list == NULL)
- return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ return;
cm = community_list_master_lookup(ch, LARGE_COMMUNITY_LIST_MASTER);
/* Delete all of entry belongs to this community-list. */
if (!str) {
community_list_delete(cm, list);
route_map_notify_dependencies(name, RMAP_EVENT_LLIST_DELETED);
- return 0;
+ return;
}
if (style == LARGE_COMMUNITY_LIST_STANDARD)
@@ -1201,7 +1199,7 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
regex = bgp_regcomp(str);
if (!lcom && !regex)
- return COMMUNITY_LIST_ERR_MALFORMED_VAL;
+ return;
if (lcom)
entry = community_list_entry_lookup(list, lcom, direct);
@@ -1214,12 +1212,10 @@ int lcommunity_list_unset(struct community_list_handler *ch, const char *name,
bgp_regex_free(regex);
if (!entry)
- return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ return;
community_list_entry_delete(cm, list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_LLIST_DELETED);
-
- return 0;
}
/* Set extcommunity-list. */
@@ -1299,9 +1295,9 @@ int extcommunity_list_set(struct community_list_handler *ch, const char *name,
* When str is NULL, delete all extcommunity-list entries belonging to the
* specified name.
*/
-int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
- const char *str, const char *seq, int direct,
- int style)
+void extcommunity_list_unset(struct community_list_handler *ch,
+ const char *name, const char *str, const char *seq,
+ int direct, int style)
{
struct community_list_master *cm = NULL;
struct community_entry *entry = NULL;
@@ -1311,14 +1307,14 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
/* Lookup extcommunity list. */
list = community_list_lookup(ch, name, 0, EXTCOMMUNITY_LIST_MASTER);
if (list == NULL)
- return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ return;
cm = community_list_master_lookup(ch, EXTCOMMUNITY_LIST_MASTER);
/* Delete all of entry belongs to this extcommunity-list. */
if (!str) {
community_list_delete(cm, list);
route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
- return 0;
+ return;
}
if (style == EXTCOMMUNITY_LIST_STANDARD)
@@ -1331,12 +1327,10 @@ int extcommunity_list_unset(struct community_list_handler *ch, const char *name,
entry = community_list_entry_lookup(list, str, direct);
if (!entry)
- return COMMUNITY_LIST_ERR_CANT_FIND_LIST;
+ return;
community_list_entry_delete(cm, list, entry);
route_map_notify_dependencies(name, RMAP_EVENT_ECLIST_DELETED);
-
- return 0;
}
/* Initializa community-list. Return community-list handler. */
diff --git a/bgpd/bgp_clist.h b/bgpd/bgp_clist.h
index a435b92..29bd880 100644
--- a/bgpd/bgp_clist.h
+++ b/bgpd/bgp_clist.h
@@ -109,11 +109,9 @@ struct community_list_handler {
};
/* Error code of community-list. */
-#define COMMUNITY_LIST_ERR_CANT_FIND_LIST -1
-#define COMMUNITY_LIST_ERR_MALFORMED_VAL -2
-#define COMMUNITY_LIST_ERR_STANDARD_CONFLICT -3
-#define COMMUNITY_LIST_ERR_EXPANDED_CONFLICT -4
-
+#define COMMUNITY_LIST_ERR_MALFORMED_VAL -1
+#define COMMUNITY_LIST_ERR_STANDARD_CONFLICT -2
+#define COMMUNITY_LIST_ERR_EXPANDED_CONFLICT -3
/* Handler. */
extern struct community_list_handler *bgp_clist;
@@ -124,22 +122,22 @@ extern void community_list_terminate(struct community_list_handler *ch);
extern int community_list_set(struct community_list_handler *ch,
const char *name, const char *str,
const char *seq, int direct, int style);
-extern int community_list_unset(struct community_list_handler *ch,
- const char *name, const char *str,
- const char *seq, int direct, int style);
+extern void community_list_unset(struct community_list_handler *ch,
+ const char *name, const char *str,
+ const char *seq, int direct, int style);
extern int extcommunity_list_set(struct community_list_handler *ch,
const char *name, const char *str,
const char *seq, int direct, int style);
-extern int extcommunity_list_unset(struct community_list_handler *ch,
- const char *name, const char *str,
- const char *seq, int direct, int style);
+extern void extcommunity_list_unset(struct community_list_handler *ch,
+ const char *name, const char *str,
+ const char *seq, int direct, int style);
extern int lcommunity_list_set(struct community_list_handler *ch,
const char *name, const char *str,
const char *seq, int direct, int style);
extern bool lcommunity_list_valid(const char *community, int style);
-extern int lcommunity_list_unset(struct community_list_handler *ch,
- const char *name, const char *str,
- const char *seq, int direct, int style);
+extern void lcommunity_list_unset(struct community_list_handler *ch,
+ const char *name, const char *str,
+ const char *seq, int direct, int style);
extern struct community_list_master *
community_list_master_lookup(struct community_list_handler *ch, int master);
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 80425eb..339bfae 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -22,19 +22,76 @@
#include "bgpd/bgp_advertise.h"
#include "bgpd/bgp_vty.h"
-/* Global variable to access damping configuration */
-static struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
+static void bgp_reuselist_add(struct reuselist *list, struct bgp_damp_info *info)
+{
+ assert(info);
+ SLIST_INSERT_HEAD(list, info, entry);
+}
+
+static void bgp_reuselist_del(struct reuselist *list, struct bgp_damp_info *info)
+{
+ assert(info);
+ SLIST_REMOVE(list, info, bgp_damp_info, entry);
+}
-/* Utility macro to add and delete BGP dampening information to no
- used list. */
-#define BGP_DAMP_LIST_ADD(N, A) BGP_PATH_INFO_ADD(N, A, no_reuse_list)
-#define BGP_DAMP_LIST_DEL(N, A) BGP_PATH_INFO_DEL(N, A, no_reuse_list)
+static void bgp_reuselist_switch(struct reuselist *source,
+ struct bgp_damp_info *info,
+ struct reuselist *target)
+{
+ assert(source && target && info);
+ SLIST_REMOVE(source, info, bgp_damp_info, entry);
+ SLIST_INSERT_HEAD(target, info, entry);
+}
+
+static void bgp_damp_info_unclaim(struct bgp_damp_info *bdi,
+ struct reuselist *list)
+{
+ assert(bdi && bdi->config);
+ if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX)
+ bgp_reuselist_del(&bdi->config->no_reuse_list, bdi);
+ else
+ bgp_reuselist_del(list ? list
+ : &bdi->config->reuse_list[bdi->index],
+ bdi);
+ bdi->config = NULL;
+}
+
+static void bgp_damp_info_claim(struct bgp_damp_info *bdi,
+ struct bgp_damp_config *bdc)
+{
+ assert(bdc && bdi);
+ if (bdi->config == NULL) {
+ bdi->config = bdc;
+ return;
+ }
+ bgp_damp_info_unclaim(bdi, NULL);
+ bdi->config = bdc;
+ bdi->afi = bdc->afi;
+ bdi->safi = bdc->safi;
+}
+
+struct bgp_damp_config *get_active_bdc_from_pi(struct bgp_path_info *pi,
+ afi_t afi, safi_t safi)
+{
+ if (!pi)
+ return NULL;
+ if (CHECK_FLAG(pi->peer->af_flags[afi][safi],
+ PEER_FLAG_CONFIG_DAMPENING))
+ return &pi->peer->damp[afi][safi];
+ if (peer_group_active(pi->peer))
+ if (CHECK_FLAG(pi->peer->group->conf->af_flags[afi][safi],
+ PEER_FLAG_CONFIG_DAMPENING))
+ return &pi->peer->group->conf->damp[afi][safi];
+ if (CHECK_FLAG(pi->peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
+ return &pi->peer->bgp->damp[afi][safi];
+ return NULL;
+}
/* Calculate reuse list index by penalty value. */
static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc)
{
unsigned int i;
- int index;
+ unsigned int index;
/*
* reuse_limit can't be zero, this is for Coverity
@@ -57,27 +114,28 @@ static int bgp_reuse_index(int penalty, struct bgp_damp_config *bdc)
static void bgp_reuse_list_add(struct bgp_damp_info *bdi,
struct bgp_damp_config *bdc)
{
- int index;
-
- index = bdi->index = bgp_reuse_index(bdi->penalty, bdc);
-
- bdi->prev = NULL;
- bdi->next = bdc->reuse_list[index];
- if (bdc->reuse_list[index])
- bdc->reuse_list[index]->prev = bdi;
- bdc->reuse_list[index] = bdi;
+ bgp_damp_info_claim(bdi, bdc);
+ bdi->index = bgp_reuse_index(bdi->penalty, bdc);
+ bgp_reuselist_add(&bdc->reuse_list[bdi->index], bdi);
}
/* Delete BGP dampening information from reuse list. */
-static void bgp_reuse_list_delete(struct bgp_damp_info *bdi,
+static void bgp_reuse_list_delete(struct bgp_damp_info *bdi)
+{
+ bgp_damp_info_unclaim(bdi, NULL);
+}
+
+static void bgp_no_reuse_list_add(struct bgp_damp_info *bdi,
struct bgp_damp_config *bdc)
{
- if (bdi->next)
- bdi->next->prev = bdi->prev;
- if (bdi->prev)
- bdi->prev->next = bdi->next;
- else
- bdc->reuse_list[bdi->index] = bdi->next;
+ bgp_damp_info_claim(bdi, bdc);
+ bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX;
+ bgp_reuselist_add(&bdc->no_reuse_list, bdi);
+}
+
+static void bgp_no_reuse_list_delete(struct bgp_damp_info *bdi)
+{
+ bgp_damp_info_unclaim(bdi, NULL);
}
/* Return decayed penalty value. */
@@ -100,10 +158,10 @@ int bgp_damp_decay(time_t tdiff, int penalty, struct bgp_damp_config *bdc)
is evaluated. RFC2439 Section 4.8.7. */
static void bgp_reuse_timer(struct event *t)
{
- struct bgp_damp_info *bdi;
- struct bgp_damp_info *next;
+ struct bgp_damp_info *bdi, *bdi_next;
+ struct reuselist plist;
+ struct bgp *bgp;
time_t t_now, t_diff;
-
struct bgp_damp_config *bdc = EVENT_ARG(t);
bdc->t_reuse = NULL;
@@ -112,20 +170,20 @@ static void bgp_reuse_timer(struct event *t)
t_now = monotime(NULL);
- /* 1. save a pointer to the current zeroth queue head and zero the
- list head entry. */
- bdi = bdc->reuse_list[bdc->reuse_offset];
- bdc->reuse_list[bdc->reuse_offset] = NULL;
+ /* 1. save a pointer to the current queue head and zero the list head
+ * list head entry. */
+ assert(bdc->reuse_offset < bdc->reuse_list_size);
+ plist = bdc->reuse_list[bdc->reuse_offset];
+ SLIST_INIT(&bdc->reuse_list[bdc->reuse_offset]);
/* 2. set offset = modulo reuse-list-size ( offset + 1 ), thereby
rotating the circular queue of list-heads. */
bdc->reuse_offset = (bdc->reuse_offset + 1) % bdc->reuse_list_size;
+ assert(bdc->reuse_offset < bdc->reuse_list_size);
/* 3. if ( the saved list head pointer is non-empty ) */
- for (; bdi; bdi = next) {
- struct bgp *bgp = bdi->path->peer->bgp;
-
- next = bdi->next;
+ SLIST_FOREACH_SAFE (bdi, &plist, entry, bdi_next) {
+ bgp = bdi->path->peer->bgp;
/* Set t-diff = t-now - t-updated. */
t_diff = t_now - bdi->t_updated;
@@ -150,19 +208,27 @@ static void bgp_reuse_timer(struct event *t)
bgp_aggregate_increment(
bgp, bgp_dest_get_prefix(bdi->dest),
bdi->path, bdi->afi, bdi->safi);
- bgp_process(bgp, bdi->dest, bdi->afi,
+ bgp_process(bgp, bdi->dest, bdi->path, bdi->afi,
bdi->safi);
}
- if (bdi->penalty <= bdc->reuse_limit / 2.0)
- bgp_damp_info_free(bdi, 1, bdc->afi, bdc->safi);
- else
- BGP_DAMP_LIST_ADD(bdc, bdi);
- } else
+ if (bdi->penalty <= bdc->reuse_limit / 2.0) {
+ bgp_damp_info_free(bdi, &plist, 1);
+ } else {
+ bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX;
+ bgp_reuselist_switch(&plist, bdi,
+ &bdc->no_reuse_list);
+ }
+ } else {
/* Re-insert into another list (See RFC2439 Section
* 4.8.6). */
- bgp_reuse_list_add(bdi, bdc);
+ bdi->index = bgp_reuse_index(bdi->penalty, bdc);
+ bgp_reuselist_switch(&plist, bdi,
+ &bdc->reuse_list[bdi->index]);
+ }
}
+
+ assert(SLIST_EMPTY(&plist));
}
/* A route becomes unreachable (RFC2439 Section 4.8.2). */
@@ -172,10 +238,13 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
time_t t_now;
struct bgp_damp_info *bdi = NULL;
unsigned int last_penalty = 0;
- struct bgp_damp_config *bdc = &damp[afi][safi];
+ struct bgp_damp_config *bdc;
- t_now = monotime(NULL);
+ bdc = get_active_bdc_from_pi(path, afi, safi);
+ if (!bdc)
+ return BGP_DAMP_USED;
+ t_now = monotime(NULL);
/* Processing Unreachable Messages. */
if (path->extra)
bdi = path->extra->damp_info;
@@ -197,12 +266,20 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
bdi->flap = 1;
bdi->start_time = t_now;
bdi->suppress_time = 0;
- bdi->index = -1;
+ bdi->index = BGP_DAMP_NO_REUSE_LIST_INDEX;
bdi->afi = afi;
bdi->safi = safi;
(bgp_path_info_extra_get(path))->damp_info = bdi;
- BGP_DAMP_LIST_ADD(bdc, bdi);
+ bgp_no_reuse_list_add(bdi, bdc);
} else {
+ if (bdi->config != bdc) {
+ bgp_damp_info_claim(bdi, bdc);
+ if (bdi->index == BGP_DAMP_NO_REUSE_LIST_INDEX)
+ bgp_reuselist_add(&bdc->no_reuse_list, bdi);
+ else
+ bgp_reuselist_add(&bdc->reuse_list[bdi->index],
+ bdi);
+ }
last_penalty = bdi->penalty;
/* 1. Set t-diff = t-now - t-updated. */
@@ -228,8 +305,8 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
/* Remove the route from a reuse list if it is on one. */
if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)) {
/* If decay rate isn't equal to 0, reinsert brn. */
- if (bdi->penalty != last_penalty && bdi->index >= 0) {
- bgp_reuse_list_delete(bdi, bdc);
+ if (bdi->penalty != last_penalty) {
+ bgp_reuse_list_delete(bdi);
bgp_reuse_list_add(bdi, bdc);
}
return BGP_DAMP_SUPPRESSED;
@@ -240,10 +317,9 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
if (bdi->penalty >= bdc->suppress_value) {
bgp_path_info_set_flag(dest, path, BGP_PATH_DAMPED);
bdi->suppress_time = t_now;
- BGP_DAMP_LIST_DEL(bdc, bdi);
+ bgp_no_reuse_list_delete(bdi);
bgp_reuse_list_add(bdi, bdc);
}
-
return BGP_DAMP_USED;
}
@@ -253,7 +329,10 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
time_t t_now;
struct bgp_damp_info *bdi;
int status;
- struct bgp_damp_config *bdc = &damp[afi][safi];
+ struct bgp_damp_config *bdc;
+
+ bdc = get_active_bdc_from_pi(path, afi, safi);
+ assert(bdc);
if (!path->extra || !((bdi = path->extra->damp_info)))
return BGP_DAMP_USED;
@@ -271,8 +350,8 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
else if (CHECK_FLAG(bdi->path->flags, BGP_PATH_DAMPED)
&& (bdi->penalty < bdc->reuse_limit)) {
bgp_path_info_unset_flag(dest, path, BGP_PATH_DAMPED);
- bgp_reuse_list_delete(bdi, bdc);
- BGP_DAMP_LIST_ADD(bdc, bdi);
+ bgp_reuse_list_delete(bdi);
+ bgp_no_reuse_list_add(bdi, bdc);
bdi->suppress_time = 0;
status = BGP_DAMP_USED;
} else
@@ -281,33 +360,32 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
if (bdi->penalty > bdc->reuse_limit / 2.0)
bdi->t_updated = t_now;
else
- bgp_damp_info_free(bdi, 0, afi, safi);
+ bgp_damp_info_free(bdi, NULL, 0);
return status;
}
-void bgp_damp_info_free(struct bgp_damp_info *bdi, int withdraw, afi_t afi,
- safi_t safi)
+void bgp_damp_info_free(struct bgp_damp_info *bdi, struct reuselist *list,
+ int withdraw)
{
- struct bgp_path_info *path;
- struct bgp_damp_config *bdc = &damp[afi][safi];
-
- if (!bdi)
- return;
-
- path = bdi->path;
- path->extra->damp_info = NULL;
-
- if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
- bgp_reuse_list_delete(bdi, bdc);
- else
- BGP_DAMP_LIST_DEL(bdc, bdi);
-
- bgp_path_info_unset_flag(bdi->dest, path,
- BGP_PATH_HISTORY | BGP_PATH_DAMPED);
-
- if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw)
- bgp_path_info_delete(bdi->dest, path);
+ assert(bdi);
+
+ afi_t afi = bdi->afi;
+ safi_t safi = bdi->safi;
+ struct bgp_path_info *bpi = bdi->path;
+ struct bgp_dest *dest = bdi->dest;
+ struct bgp *bgp = bpi->peer->bgp;
+ const struct prefix *p = bgp_dest_get_prefix(bdi->dest);
+
+ bgp_damp_info_unclaim(bdi, list);
+
+ bpi->extra->damp_info = NULL;
+ bgp_path_info_unset_flag(dest, bpi, BGP_PATH_HISTORY | BGP_PATH_DAMPED);
+ if (bdi->lastrecord == BGP_RECORD_WITHDRAW && withdraw) {
+ bgp_aggregate_decrement(bgp, p, bpi, afi, SAFI_UNICAST);
+ bgp_path_info_delete(dest, bpi);
+ bgp_process(bgp, dest, bpi, afi, safi);
+ }
XFREE(MTYPE_BGP_DAMP_INFO, bdi);
}
@@ -353,8 +431,7 @@ static void bgp_damp_parameter_set(time_t hlife, unsigned int reuse,
bdc->reuse_list =
XCALLOC(MTYPE_BGP_DAMP_ARRAY,
- bdc->reuse_list_size * sizeof(struct bgp_reuse_node *));
-
+ bdc->reuse_list_size * sizeof(struct reuselist));
/* Reuse-array computations */
bdc->reuse_index = XCALLOC(MTYPE_BGP_DAMP_ARRAY,
sizeof(int) * bdc->reuse_index_size);
@@ -381,7 +458,7 @@ static void bgp_damp_parameter_set(time_t hlife, unsigned int reuse,
int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
unsigned int reuse, unsigned int suppress, time_t max)
{
- struct bgp_damp_config *bdc = &damp[afi][safi];
+ struct bgp_damp_config *bdc = &bgp->damp[afi][safi];
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
if (bdc->half_life == half && bdc->reuse_limit == reuse
@@ -393,6 +470,8 @@ int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
SET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
bgp_damp_parameter_set(half, reuse, suppress, max, bdc);
+ bdc->afi = afi;
+ bdc->safi = safi;
/* Register reuse timer. */
event_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
@@ -401,8 +480,34 @@ int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
return 0;
}
-static void bgp_damp_config_clean(struct bgp_damp_config *bdc)
+/* Clean all the bgp_damp_info stored in reuse_list and no_reuse_list. */
+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 *list;
+ unsigned int i;
+
+ bdc->reuse_offset = 0;
+ for (i = 0; i < bdc->reuse_list_size; ++i) {
+ list = &bdc->reuse_list[i];
+ while ((bdi = SLIST_FIRST(list)) != NULL) {
+ if (bdi->lastrecord == BGP_RECORD_UPDATE) {
+ bgp_aggregate_increment(bgp,
+ bgp_dest_get_prefix(
+ bdi->dest),
+ bdi->path, bdi->afi,
+ bdi->safi);
+ bgp_process(bgp, bdi->dest, bdi->path, bdi->afi,
+ bdi->safi);
+ }
+ bgp_damp_info_free(bdi, list, 1);
+ }
+ }
+
+ while ((bdi = SLIST_FIRST(&bdc->no_reuse_list)) != NULL)
+ bgp_damp_info_free(bdi, &bdc->no_reuse_list, 1);
+
/* Free decay array */
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->decay_array);
bdc->decay_array_size = 0;
@@ -411,41 +516,25 @@ static void bgp_damp_config_clean(struct bgp_damp_config *bdc)
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_index);
bdc->reuse_index_size = 0;
- /* Free reuse list array. */
XFREE(MTYPE_BGP_DAMP_ARRAY, bdc->reuse_list);
bdc->reuse_list_size = 0;
-}
-
-/* Clean all the bgp_damp_info stored in reuse_list. */
-void bgp_damp_info_clean(afi_t afi, safi_t safi)
-{
- unsigned int i;
- struct bgp_damp_info *bdi, *next;
- struct bgp_damp_config *bdc = &damp[afi][safi];
-
- bdc->reuse_offset = 0;
- for (i = 0; i < bdc->reuse_list_size; i++) {
- if (!bdc->reuse_list[i])
- continue;
-
- for (bdi = bdc->reuse_list[i]; bdi; bdi = next) {
- next = bdi->next;
- bgp_damp_info_free(bdi, 1, afi, safi);
- }
- bdc->reuse_list[i] = NULL;
- }
-
- for (bdi = bdc->no_reuse_list; bdi; bdi = next) {
- next = bdi->next;
- bgp_damp_info_free(bdi, 1, afi, safi);
- }
- bdc->no_reuse_list = NULL;
+ EVENT_OFF(bdc->t_reuse);
}
+/* Disable route flap dampening for a bgp instance.
+ *
+ * Please note that this function also gets used to free memory when deleting a
+ * bgp instance.
+ */
int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi)
{
- struct bgp_damp_config *bdc = &damp[afi][safi];
+ struct bgp_damp_config *bdc;
+
+ bdc = &bgp->damp[afi][safi];
+ if (!bdc)
+ return 0;
+
/* If it wasn't enabled, there's nothing to do. */
if (!CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
return 0;
@@ -454,54 +543,51 @@ int bgp_damp_disable(struct bgp *bgp, afi_t afi, safi_t safi)
EVENT_OFF(bdc->t_reuse);
/* Clean BGP dampening information. */
- bgp_damp_info_clean(afi, safi);
-
- /* Clear configuration */
- bgp_damp_config_clean(bdc);
+ bgp_damp_info_clean(bgp, bdc, afi, safi);
UNSET_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING);
+
return 0;
}
-void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi)
+void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi,
+ safi_t safi)
{
- if (damp[afi][safi].half_life == DEFAULT_HALF_LIFE * 60
- && damp[afi][safi].reuse_limit == DEFAULT_REUSE
- && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
- && damp[afi][safi].max_suppress_time
- == damp[afi][safi].half_life * 4)
+ struct bgp_damp_config *bdc;
+
+ bdc = &bgp->damp[afi][safi];
+ if (bdc->half_life == DEFAULT_HALF_LIFE * 60 &&
+ bdc->reuse_limit == DEFAULT_REUSE &&
+ bdc->suppress_value == DEFAULT_SUPPRESS &&
+ bdc->max_suppress_time == bdc->half_life * 4)
vty_out(vty, " bgp dampening\n");
- else if (damp[afi][safi].half_life != DEFAULT_HALF_LIFE * 60
- && damp[afi][safi].reuse_limit == DEFAULT_REUSE
- && damp[afi][safi].suppress_value == DEFAULT_SUPPRESS
- && damp[afi][safi].max_suppress_time
- == damp[afi][safi].half_life * 4)
- vty_out(vty, " bgp dampening %lld\n",
- damp[afi][safi].half_life / 60LL);
+ else if (bdc->half_life != DEFAULT_HALF_LIFE * 60 &&
+ bdc->reuse_limit == DEFAULT_REUSE &&
+ bdc->suppress_value == DEFAULT_SUPPRESS &&
+ bdc->max_suppress_time == bdc->half_life * 4)
+ vty_out(vty, " bgp dampening %lld\n", bdc->half_life / 60LL);
else
vty_out(vty, " bgp dampening %lld %d %d %lld\n",
- damp[afi][safi].half_life / 60LL,
- damp[afi][safi].reuse_limit,
- damp[afi][safi].suppress_value,
- damp[afi][safi].max_suppress_time / 60LL);
+ bdc->half_life / 60LL, bdc->reuse_limit,
+ bdc->suppress_value, bdc->max_suppress_time / 60LL);
}
-static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
- size_t len, afi_t afi, safi_t safi,
- bool use_json, json_object *json)
+static const char *bgp_get_reuse_time(struct bgp_damp_config *bdc,
+ unsigned int penalty, char *buf,
+ size_t len, bool use_json,
+ json_object *json)
{
time_t reuse_time = 0;
struct tm tm;
int time_store = 0;
- if (penalty > damp[afi][safi].reuse_limit) {
- reuse_time = (int)(DELTA_T
- * ((log((double)damp[afi][safi].reuse_limit
- / penalty))
- / (log(damp[afi][safi].decay_array[1]))));
+ if (penalty > bdc->reuse_limit) {
+ reuse_time = (int)(DELTA_T *
+ ((log((double)bdc->reuse_limit / penalty)) /
+ (log(bdc->decay_array[1]))));
- if (reuse_time > damp[afi][safi].max_suppress_time)
- reuse_time = damp[afi][safi].max_suppress_time;
+ if (reuse_time > bdc->max_suppress_time)
+ reuse_time = bdc->max_suppress_time;
gmtime_r(&reuse_time, &tm);
} else
@@ -553,14 +639,15 @@ static const char *bgp_get_reuse_time(unsigned int penalty, char *buf,
return buf;
}
-void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
- safi_t safi, json_object *json_path)
+void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp,
+ struct bgp_path_info *path, afi_t afi, safi_t safi,
+ json_object *json_path)
{
struct bgp_damp_info *bdi;
time_t t_now, t_diff;
char timebuf[BGP_UPTIME_LEN] = {};
int penalty;
- struct bgp_damp_config *bdc = &damp[afi][safi];
+ struct bgp_damp_config *bdc = &bgp->damp[afi][safi];
if (!path->extra)
return;
@@ -588,8 +675,8 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
- bgp_get_reuse_time(penalty, timebuf, BGP_UPTIME_LEN,
- afi, safi, 1, json_path);
+ bgp_get_reuse_time(bdc, penalty, timebuf,
+ BGP_UPTIME_LEN, 1, json_path);
} else {
vty_out(vty,
" Dampinfo: penalty %d, flapped %d times in %s",
@@ -600,14 +687,15 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
vty_out(vty, ", reuse in %s",
- bgp_get_reuse_time(penalty, timebuf,
- BGP_UPTIME_LEN, afi, safi, 0,
+ bgp_get_reuse_time(bdc, penalty, timebuf,
+ BGP_UPTIME_LEN, 0,
json_path));
vty_out(vty, "\n");
}
}
+
const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
char *timebuf, size_t len, afi_t afi,
safi_t safi, bool use_json,
@@ -616,7 +704,11 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
struct bgp_damp_info *bdi;
time_t t_now, t_diff;
int penalty;
- struct bgp_damp_config *bdc = &damp[afi][safi];
+ struct bgp_damp_config *bdc;
+
+ bdc = get_active_bdc_from_pi(path, afi, safi);
+ if (!bdc)
+ return NULL;
if (!path->extra)
return NULL;
@@ -636,15 +728,15 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
- return bgp_get_reuse_time(penalty, timebuf, len, afi, safi, use_json,
- json);
+ return bgp_get_reuse_time(bdc, penalty, timebuf, len, use_json, json);
}
+
static int bgp_print_dampening_parameters(struct bgp *bgp, struct vty *vty,
afi_t afi, safi_t safi, bool use_json)
{
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)) {
- struct bgp_damp_config *bdc = &damp[afi][safi];
+ struct bgp_damp_config *bdc = &bgp->damp[afi][safi];
if (use_json) {
json_object *json = json_object_new_object();
@@ -687,7 +779,6 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
bool use_json = CHECK_FLAG(show_flags, BGP_SHOW_OPT_JSON);
bgp = bgp_get_default();
-
if (bgp == NULL) {
vty_out(vty, "No BGP process is configured\n");
return CMD_WARNING;
@@ -729,3 +820,130 @@ int bgp_show_dampening_parameters(struct vty *vty, afi_t afi, safi_t safi,
}
return CMD_SUCCESS;
}
+
+void bgp_peer_damp_enable(struct peer *peer, afi_t afi, safi_t safi, time_t half,
+ unsigned int reuse, unsigned int suppress, time_t max)
+{
+ struct bgp_damp_config *bdc;
+
+ if (!peer)
+ return;
+ bdc = &peer->damp[afi][safi];
+ if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING)) {
+ if (bdc->half_life == half && bdc->reuse_limit == reuse &&
+ bdc->suppress_value == suppress &&
+ bdc->max_suppress_time == max)
+ return;
+ bgp_peer_damp_disable(peer, afi, safi);
+ }
+ SET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING);
+ bgp_damp_parameter_set(half, reuse, suppress, max, bdc);
+ bdc->afi = afi;
+ bdc->safi = safi;
+ event_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
+ &bdc->t_reuse);
+}
+
+/* Disable route flap dampening for a peer.
+ *
+ * Please note that this function also gets used to free memory when deleting a
+ * peer or peer group.
+ */
+void bgp_peer_damp_disable(struct peer *peer, afi_t afi, safi_t safi)
+{
+ struct bgp_damp_config *bdc;
+
+ if (!peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING))
+ return;
+ bdc = &peer->damp[afi][safi];
+ if (!bdc)
+ return;
+ bgp_damp_info_clean(peer->bgp, bdc, afi, safi);
+ UNSET_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING);
+}
+
+void bgp_config_write_peer_damp(struct vty *vty, struct peer *peer, afi_t afi,
+ safi_t safi)
+{
+ struct bgp_damp_config *bdc;
+
+ bdc = &peer->damp[afi][safi];
+ if (bdc->half_life == DEFAULT_HALF_LIFE * 60 &&
+ bdc->reuse_limit == DEFAULT_REUSE &&
+ bdc->suppress_value == DEFAULT_SUPPRESS &&
+ bdc->max_suppress_time == bdc->half_life * 4)
+ vty_out(vty, " neighbor %s dampening\n", peer->host);
+ else if (bdc->half_life != DEFAULT_HALF_LIFE * 60 &&
+ bdc->reuse_limit == DEFAULT_REUSE &&
+ bdc->suppress_value == DEFAULT_SUPPRESS &&
+ bdc->max_suppress_time == bdc->half_life * 4)
+ vty_out(vty, " neighbor %s dampening %lld\n", peer->host,
+ bdc->half_life / 60LL);
+ else
+ vty_out(vty, " neighbor %s dampening %lld %d %d %lld\n",
+ peer->host, bdc->half_life / 60LL, bdc->reuse_limit,
+ bdc->suppress_value, bdc->max_suppress_time / 60LL);
+}
+
+static void bgp_print_peer_dampening_parameters(struct vty *vty,
+ struct peer *peer, afi_t afi,
+ safi_t safi, bool use_json,
+ json_object *json)
+{
+ struct bgp_damp_config *bdc;
+
+ if (!peer)
+ return;
+ if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_CONFIG_DAMPENING)) {
+ bdc = &peer->damp[afi][safi];
+ if (!bdc)
+ return;
+ if (use_json) {
+ json_object_int_add(json, "halfLifeSecs",
+ bdc->half_life);
+ json_object_int_add(json, "reusePenalty",
+ bdc->reuse_limit);
+ json_object_int_add(json, "suppressPenalty",
+ bdc->suppress_value);
+ json_object_int_add(json, "maxSuppressTimeSecs",
+ bdc->max_suppress_time);
+ json_object_int_add(json, "maxSuppressPenalty",
+ bdc->ceiling);
+ } else {
+ vty_out(vty, "Half-life time: %lld min\n",
+ (long long)bdc->half_life / 60);
+ vty_out(vty, "Reuse penalty: %d\n", bdc->reuse_limit);
+ vty_out(vty, "Suppress penalty: %d\n",
+ bdc->suppress_value);
+ vty_out(vty, "Max suppress time: %lld min\n",
+ (long long)bdc->max_suppress_time / 60);
+ vty_out(vty, "Max suppress penalty: %u\n", bdc->ceiling);
+ vty_out(vty, "\n");
+ }
+ } else if (!use_json)
+ vty_out(vty, "neighbor dampening not enabled for %s\n",
+ get_afi_safi_str(afi, safi, false));
+}
+
+void bgp_show_peer_dampening_parameters(struct vty *vty, struct peer *peer,
+ afi_t afi, safi_t safi, bool use_json)
+{
+ json_object *json;
+
+ if (use_json) {
+ json = json_object_new_object();
+ json_object_string_add(json, "addressFamily",
+ get_afi_safi_str(afi, safi, false));
+ bgp_print_peer_dampening_parameters(vty, peer, afi, safi, true,
+ json);
+ vty_out(vty, "%s\n",
+ json_object_to_json_string_ext(json,
+ JSON_C_TO_STRING_PRETTY));
+ json_object_free(json);
+ } else {
+ vty_out(vty, "\nFor address family: %s\n",
+ get_afi_safi_str(afi, safi, false));
+ bgp_print_peer_dampening_parameters(vty, peer, afi, safi, false,
+ NULL);
+ }
+}
diff --git a/bgpd/bgp_damp.h b/bgpd/bgp_damp.h
index 6033c34..851c6f9 100644
--- a/bgpd/bgp_damp.h
+++ b/bgpd/bgp_damp.h
@@ -10,11 +10,6 @@
/* Structure maintained on a per-route basis. */
struct bgp_damp_info {
- /* Doubly linked list. This information must be linked to
- reuse_list or no_reuse_list. */
- struct bgp_damp_info *next;
- struct bgp_damp_info *prev;
-
/* Figure-of-merit. */
unsigned int penalty;
@@ -30,6 +25,9 @@ struct bgp_damp_info {
/* Time of route start to be suppressed. */
time_t suppress_time;
+ /* Back reference to associated dampening configuration. */
+ struct bgp_damp_config *config;
+
/* Back reference to bgp_path_info. */
struct bgp_path_info *path;
@@ -38,6 +36,8 @@ struct bgp_damp_info {
/* Current index in the reuse_list. */
int index;
+#define BGP_DAMP_NO_REUSE_LIST_INDEX \
+ (-1) /* index for elements on no_reuse_list */
/* Last time message type. */
uint8_t lastrecord;
@@ -46,8 +46,12 @@ struct bgp_damp_info {
afi_t afi;
safi_t safi;
+
+ SLIST_ENTRY(bgp_damp_info) entry;
};
+SLIST_HEAD(reuselist, bgp_damp_info);
+
/* Specified parameter set configuration. */
struct bgp_damp_config {
/* Value over which routes suppressed. */
@@ -84,12 +88,12 @@ struct bgp_damp_config {
int *reuse_index;
/* Reuse list array per-set based. */
- struct bgp_damp_info **reuse_list;
- int reuse_offset;
+ struct reuselist *reuse_list;
+ unsigned int reuse_offset;
safi_t safi;
/* All dampening information which is not on reuse list. */
- struct bgp_damp_info *no_reuse_list;
+ struct reuselist no_reuse_list;
/* Reuse timer thread per-set base. */
struct event *t_reuse;
@@ -116,6 +120,8 @@ struct bgp_damp_config {
#define REUSE_LIST_SIZE 256
#define REUSE_ARRAY_SIZE 1024
+extern struct bgp_damp_config *get_active_bdc_from_pi(struct bgp_path_info *pi,
+ afi_t afi, safi_t safi);
extern int bgp_damp_enable(struct bgp *bgp, afi_t afi, safi_t safi, time_t half,
unsigned int reuse, unsigned int suppress,
time_t max);
@@ -124,14 +130,18 @@ extern int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
afi_t afi, safi_t safi, int attr_change);
extern int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
afi_t afi, safi_t saff);
-extern void bgp_damp_info_free(struct bgp_damp_info *path, int withdraw,
- afi_t afi, safi_t safi);
-extern void bgp_damp_info_clean(afi_t afi, safi_t safi);
+extern void bgp_damp_info_free(struct bgp_damp_info *bdi,
+ struct reuselist *list, int withdraw);
+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 tdiff, int penalty,
- struct bgp_damp_config *damp);
-extern void bgp_config_write_damp(struct vty *vty, afi_t afi, safi_t safi);
-extern void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path,
- afi_t afi, safi_t safi, json_object *json_path);
+ struct bgp_damp_config *bdc);
+extern void bgp_config_write_damp(struct vty *vty, struct bgp *bgp, afi_t afi,
+ safi_t safi);
+extern void bgp_damp_info_vty(struct vty *vty, struct bgp *bgp,
+ struct bgp_path_info *path, afi_t afi,
+ safi_t safi, json_object *json_path);
extern const char *bgp_damp_reuse_time_vty(struct vty *vty,
struct bgp_path_info *path,
char *timebuf, size_t len, afi_t afi,
@@ -139,5 +149,14 @@ extern const char *bgp_damp_reuse_time_vty(struct vty *vty,
json_object *json);
extern int bgp_show_dampening_parameters(struct vty *vty, afi_t afi,
safi_t safi, uint16_t show_flags);
+extern void bgp_peer_damp_enable(struct peer *peer, afi_t afi, safi_t safi,
+ time_t half, unsigned int reuse,
+ unsigned int suppress, time_t max);
+extern void bgp_peer_damp_disable(struct peer *peer, afi_t afi, safi_t safi);
+extern void bgp_config_write_peer_damp(struct vty *vty, struct peer *peer,
+ afi_t afi, safi_t safi);
+extern void bgp_show_peer_dampening_parameters(struct vty *vty,
+ struct peer *peer, afi_t afi,
+ safi_t safi, bool use_json);
#endif /* _QUAGGA_BGP_DAMP_H */
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index 3ecdc0d..6228432 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -50,7 +50,6 @@ unsigned long conf_bgp_debug_keepalive;
unsigned long conf_bgp_debug_update;
unsigned long conf_bgp_debug_bestpath;
unsigned long conf_bgp_debug_zebra;
-unsigned long conf_bgp_debug_allow_martians;
unsigned long conf_bgp_debug_nht;
unsigned long conf_bgp_debug_update_groups;
unsigned long conf_bgp_debug_vpn;
@@ -71,7 +70,6 @@ unsigned long term_bgp_debug_keepalive;
unsigned long term_bgp_debug_update;
unsigned long term_bgp_debug_bestpath;
unsigned long term_bgp_debug_zebra;
-unsigned long term_bgp_debug_allow_martians;
unsigned long term_bgp_debug_nht;
unsigned long term_bgp_debug_update_groups;
unsigned long term_bgp_debug_vpn;
@@ -116,6 +114,7 @@ static const struct message bgp_notify_msg[] = {
{BGP_NOTIFY_FSM_ERR, "Neighbor Events Error"},
{BGP_NOTIFY_CEASE, "Cease"},
{BGP_NOTIFY_ROUTE_REFRESH_ERR, "ROUTE-REFRESH Message Error"},
+ {BGP_NOTIFY_SEND_HOLD_ERR, "Send Hold Timer Expired"},
{0}};
static const struct message bgp_notify_head_msg[] = {
@@ -515,6 +514,7 @@ const char *bgp_notify_subcode_str(char code, char subcode)
return lookup_msg(bgp_notify_update_msg, subcode,
"Unrecognized Error Subcode");
case BGP_NOTIFY_HOLD_ERR:
+ case BGP_NOTIFY_SEND_HOLD_ERR:
break;
case BGP_NOTIFY_FSM_ERR:
return lookup_msg(bgp_notify_fsm_msg, subcode,
@@ -2163,7 +2163,6 @@ DEFUN (no_debug_bgp,
TERM_DEBUG_OFF(as4, AS4_SEGMENT);
TERM_DEBUG_OFF(neighbor_events, NEIGHBOR_EVENTS);
TERM_DEBUG_OFF(zebra, ZEBRA);
- TERM_DEBUG_OFF(allow_martians, ALLOW_MARTIANS);
TERM_DEBUG_OFF(nht, NHT);
TERM_DEBUG_OFF(vpn, VPN_LEAK_FROM_VRF);
TERM_DEBUG_OFF(vpn, VPN_LEAK_TO_VRF);
@@ -2239,9 +2238,6 @@ DEFUN_NOSH (show_debugging_bgp,
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
vty_out(vty, " BGP graceful-restart debugging is on\n");
- if (BGP_DEBUG(allow_martians, ALLOW_MARTIANS))
- vty_out(vty, " BGP allow martian next hop debugging is on\n");
-
if (BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF))
vty_out(vty,
" BGP route leak from vrf to vpn debugging is on\n");
@@ -2354,11 +2350,6 @@ static int bgp_config_write_debug(struct vty *vty)
}
}
- if (CONF_BGP_DEBUG(allow_martians, ALLOW_MARTIANS)) {
- vty_out(vty, "debug bgp allow-martians\n");
- write++;
- }
-
if (CONF_BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF)) {
vty_out(vty, "debug bgp vpn leak-from-vrf\n");
write++;
@@ -2722,7 +2713,7 @@ bool bgp_debug_zebra(const struct prefix *p)
const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
const struct prefix_rd *prd,
union prefixconstptr pu,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
int addpath_valid, uint32_t addpath_id,
struct bgp_route_evpn *overlay_index,
char *str, int size)
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index 5b09501..061d966 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -61,7 +61,6 @@ extern unsigned long conf_bgp_debug_keepalive;
extern unsigned long conf_bgp_debug_update;
extern unsigned long conf_bgp_debug_bestpath;
extern unsigned long conf_bgp_debug_zebra;
-extern unsigned long conf_bgp_debug_allow_martians;
extern unsigned long conf_bgp_debug_nht;
extern unsigned long conf_bgp_debug_update_groups;
extern unsigned long conf_bgp_debug_vpn;
@@ -80,7 +79,6 @@ extern unsigned long term_bgp_debug_keepalive;
extern unsigned long term_bgp_debug_update;
extern unsigned long term_bgp_debug_bestpath;
extern unsigned long term_bgp_debug_zebra;
-extern unsigned long term_bgp_debug_allow_martians;
extern unsigned long term_bgp_debug_nht;
extern unsigned long term_bgp_debug_update_groups;
extern unsigned long term_bgp_debug_vpn;
@@ -120,7 +118,6 @@ struct bgp_debug_filter {
#define BGP_DEBUG_UPDATE_PREFIX 0x04
#define BGP_DEBUG_UPDATE_DETAIL 0x08
#define BGP_DEBUG_ZEBRA 0x01
-#define BGP_DEBUG_ALLOW_MARTIANS 0x01
#define BGP_DEBUG_NHT 0x01
#define BGP_DEBUG_UPDATE_GROUPS 0x01
#define BGP_DEBUG_VPN_LEAK_FROM_VRF 0x01
@@ -156,8 +153,8 @@ struct bgp_debug_filter {
TERM_DEBUG_OFF(a, b); \
} while (0)
-#define BGP_DEBUG(a, b) (term_bgp_debug_ ## a & BGP_DEBUG_ ## b)
-#define CONF_BGP_DEBUG(a, b) (conf_bgp_debug_ ## a & BGP_DEBUG_ ## b)
+#define BGP_DEBUG(a, b) (unlikely(term_bgp_debug_##a & BGP_DEBUG_##b))
+#define CONF_BGP_DEBUG(a, b) (unlikely(conf_bgp_debug_##a & BGP_DEBUG_##b))
extern const char *const bgp_type_str[];
@@ -178,7 +175,7 @@ extern bool bgp_debug_zebra(const struct prefix *p);
extern const char *bgp_debug_rdpfxpath2str(
afi_t afi, safi_t safi, const struct prefix_rd *prd,
- union prefixconstptr pu, mpls_label_t *label, uint32_t num_labels,
+ union prefixconstptr pu, mpls_label_t *label, uint8_t num_labels,
int addpath_valid, uint32_t addpath_id,
struct bgp_route_evpn *overlay_index, char *str, int size);
const char *bgp_notify_admin_message(char *buf, size_t bufsz, uint8_t *data,
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index a8ae177..1beb030 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -237,11 +237,10 @@ struct ecommunity *ecommunity_parse(uint8_t *pnt, unsigned short length,
disable_ieee_floating);
}
-struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length,
- bool disable_ieee_floating)
+struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt, unsigned short length)
{
return ecommunity_parse_internal(pnt, length, IPV6_ECOMMUNITY_SIZE,
- disable_ieee_floating);
+ false);
}
/* Duplicate the Extended Communities Attribute structure. */
@@ -263,8 +262,11 @@ struct ecommunity *ecommunity_dup(struct ecommunity *ecom)
}
/* Return string representation of ecommunities attribute. */
-char *ecommunity_str(struct ecommunity *ecom)
+const char *ecommunity_str(struct ecommunity *ecom)
{
+ if (!ecom)
+ return "(null)";
+
if (!ecom->str)
ecom->str =
ecommunity_ecom2str(ecom, ECOMMUNITY_FORMAT_DISPLAY, 0);
@@ -724,15 +726,21 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,
memset(buf, 0, INET_ADDRSTRLEN + 1);
memcpy(buf, str, p - str);
- if (dot) {
+ if (dot == 3) {
/* Parsing A.B.C.D in:
* A.B.C.D:MN
*/
ret = inet_aton(buf, &ip);
if (ret == 0)
goto error;
+ } else if (dot == 1) {
+ /* Parsing A.B AS number in:
+ * A.B:MN
+ */
+ if (!asn_str2asn(buf, &as))
+ goto error;
} else {
- /* ASN */
+ /* Parsing A AS number in A:MN */
errno = 0;
tmp_as = strtoul(buf, &endptr, 10);
/* 'unsigned long' is a uint64 on 64-bit
@@ -750,8 +758,11 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,
} else if (*p == '.') {
if (separator)
goto error;
+ /* either IP or AS format */
dot++;
- if (dot > 4)
+ if (dot > 1)
+ ecomm_type = ECOMMUNITY_ENCODE_IP;
+ if (dot >= 4)
goto error;
} else {
digit = 1;
@@ -776,19 +787,18 @@ static const char *ecommunity_gettoken(const char *str, void *eval_ptr,
if (!digit && (!separator || !val_color_set))
goto error;
- /* Encode result into extended community. */
- if (dot)
- ecomm_type = ECOMMUNITY_ENCODE_IP;
- else if (as > BGP_AS_MAX)
- ecomm_type = ECOMMUNITY_ENCODE_AS4;
- else if (as > 0)
- ecomm_type = ECOMMUNITY_ENCODE_AS;
- else if (val_color) {
- ecomm_type = ECOMMUNITY_ENCODE_OPAQUE;
- sub_type = ECOMMUNITY_COLOR;
- val = val_color;
+ if (ecomm_type != ECOMMUNITY_ENCODE_IP) {
+ /* Encode result into extended community for AS format or color. */
+ if (as > BGP_AS_MAX)
+ ecomm_type = ECOMMUNITY_ENCODE_AS4;
+ else if (as > 0)
+ ecomm_type = ECOMMUNITY_ENCODE_AS;
+ else if (val_color) {
+ ecomm_type = ECOMMUNITY_ENCODE_OPAQUE;
+ sub_type = ECOMMUNITY_COLOR;
+ val = val_color;
+ }
}
-
if (ecommunity_encode(ecomm_type, sub_type, 1, as, ip, val, eval))
goto error;
*token = ecommunity_token_val;
@@ -1015,10 +1025,6 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
uint32_t bw_tmp, bw;
char bps_buf[20] = {0};
-#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
-#define ONE_MBPS_BYTES (1000 * 1000 / 8)
-#define ONE_KBPS_BYTES (1000 / 8)
-
as = (*pnt++ << 8);
as |= (*pnt++);
(void)ptr_get_be32(pnt, &bw_tmp);
@@ -1042,6 +1048,38 @@ static int ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
return len;
}
+static int ipv6_ecommunity_lb_str(char *buf, size_t bufsz, const uint8_t *pnt,
+ size_t length)
+{
+ int len = 0;
+ as_t as = 0;
+ uint64_t bw = 0;
+ char bps_buf[20] = { 0 };
+
+ if (length < IPV6_ECOMMUNITY_SIZE)
+ goto done;
+
+ pnt += 2; /* Reserved */
+ pnt = ptr_get_be64(pnt, &bw);
+ (void)ptr_get_be32(pnt, &as);
+
+ if (bw >= ONE_GBPS_BYTES)
+ snprintf(bps_buf, sizeof(bps_buf), "%.3f Gbps",
+ (float)(bw / ONE_GBPS_BYTES));
+ else if (bw >= ONE_MBPS_BYTES)
+ snprintf(bps_buf, sizeof(bps_buf), "%.3f Mbps",
+ (float)(bw / ONE_MBPS_BYTES));
+ else if (bw >= ONE_KBPS_BYTES)
+ snprintf(bps_buf, sizeof(bps_buf), "%.3f Kbps",
+ (float)(bw / ONE_KBPS_BYTES));
+ else
+ snprintfrr(bps_buf, sizeof(bps_buf), "%" PRIu64 " bps", bw * 8);
+
+done:
+ len = snprintfrr(buf, bufsz, "LB:%u:%" PRIu64 " (%s)", as, bw, bps_buf);
+ return len;
+}
+
bool ecommunity_has_route_target(struct ecommunity *ecom)
{
uint32_t i;
@@ -1110,7 +1148,7 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
char encbuf[128];
for (i = 0; i < ecom->size; i++) {
- int unk_ecom = 0;
+ bool unk_ecom = false;
memset(encbuf, 0x00, sizeof(encbuf));
/* Space between each value. */
@@ -1120,6 +1158,18 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
/* Retrieve value field */
pnt = ecom->val + (i * ecom->unit_size);
+ uint8_t *data = pnt;
+ uint8_t *end = data + ecom->unit_size;
+ size_t len = end - data;
+
+ /* Sanity check for extended communities lenght, to avoid
+ * overrun when dealing with bits, e.g. ptr_get_be64().
+ */
+ if (len < ecom->unit_size) {
+ unk_ecom = true;
+ goto unknown;
+ }
+
/* High-order octet is the type */
type = *pnt++;
@@ -1142,13 +1192,19 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
ecommunity_lb_str(
encbuf, sizeof(encbuf), pnt,
ecom->disable_ieee_floating);
+ } else if (sub_type ==
+ ECOMMUNITY_EXTENDED_LINK_BANDWIDTH &&
+ type == ECOMMUNITY_ENCODE_AS4) {
+ ipv6_ecommunity_lb_str(encbuf,
+ sizeof(encbuf),
+ pnt, len);
} else if (sub_type == ECOMMUNITY_NODE_TARGET &&
type == ECOMMUNITY_ENCODE_IP) {
ecommunity_node_target_str(
encbuf, sizeof(encbuf), pnt,
format);
} else
- unk_ecom = 1;
+ unk_ecom = true;
} else {
ecommunity_rt_soo_str(encbuf, sizeof(encbuf),
pnt, type, sub_type,
@@ -1171,7 +1227,7 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
ecommunity_color_str(encbuf, sizeof(encbuf),
pnt);
} else {
- unk_ecom = 1;
+ unk_ecom = true;
}
} else if (type == ECOMMUNITY_ENCODE_EVPN) {
if (filter == ECOMMUNITY_ROUTE_TARGET)
@@ -1264,14 +1320,14 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
"DF: (alg: %u, pref: %u)", alg,
pref);
} else
- unk_ecom = 1;
+ unk_ecom = true;
} else if (type == ECOMMUNITY_ENCODE_REDIRECT_IP_NH) {
sub_type = *pnt++;
if (sub_type == ECOMMUNITY_REDIRECT_IP_NH) {
snprintf(encbuf, sizeof(encbuf),
"FS:redirect IP 0x%x", *(pnt + 5));
} else
- unk_ecom = 1;
+ unk_ecom = true;
} else if (type == ECOMMUNITY_ENCODE_TRANS_EXP ||
type == ECOMMUNITY_EXTENDED_COMMUNITY_PART_2 ||
type == ECOMMUNITY_EXTENDED_COMMUNITY_PART_3) {
@@ -1318,7 +1374,7 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
snprintf(encbuf, sizeof(encbuf),
"FS:redirect VRF %s", buf);
} else if (type != ECOMMUNITY_ENCODE_TRANS_EXP)
- unk_ecom = 1;
+ unk_ecom = true;
else if (sub_type == ECOMMUNITY_TRAFFIC_ACTION) {
char action[64];
@@ -1351,33 +1407,37 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
snprintf(encbuf, sizeof(encbuf),
"FS:marking %u", *(pnt + 5));
} else
- unk_ecom = 1;
+ unk_ecom = true;
} else if (type == ECOMMUNITY_ENCODE_AS_NON_TRANS) {
sub_type = *pnt++;
if (sub_type == ECOMMUNITY_LINK_BANDWIDTH)
ecommunity_lb_str(encbuf, sizeof(encbuf), pnt,
ecom->disable_ieee_floating);
+ else if (sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH)
+ ipv6_ecommunity_lb_str(encbuf, sizeof(encbuf),
+ pnt, len);
else
- unk_ecom = 1;
+ unk_ecom = true;
} else if (type == ECOMMUNITY_ENCODE_IP_NON_TRANS) {
sub_type = *pnt++;
if (sub_type == ECOMMUNITY_NODE_TARGET)
ecommunity_node_target_str(
encbuf, sizeof(encbuf), pnt, format);
else
- unk_ecom = 1;
+ unk_ecom = true;
} else if (type == ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS) {
sub_type = *pnt++;
if (sub_type == ECOMMUNITY_ORIGIN_VALIDATION_STATE)
ecommunity_origin_validation_state_str(
encbuf, sizeof(encbuf), pnt);
else
- unk_ecom = 1;
+ unk_ecom = true;
} else {
sub_type = *pnt++;
- unk_ecom = 1;
+ unk_ecom = true;
}
+unknown:
if (unk_ecom)
snprintf(encbuf, sizeof(encbuf), "UNK:%d, %d", type,
sub_type);
@@ -1794,9 +1854,9 @@ ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
* return the BGP link bandwidth extended community, if present;
* the actual bandwidth is returned via param
*/
-const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
+const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint64_t *bw)
{
- const uint8_t *eval;
+ const uint8_t *data;
uint32_t i;
if (bw)
@@ -1808,24 +1868,49 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
for (i = 0; i < ecom->size; i++) {
const uint8_t *pnt;
uint8_t type, sub_type;
- uint32_t bwval;
- eval = pnt = (ecom->val + (i * ECOMMUNITY_SIZE));
+ data = pnt = (ecom->val + (i * ecom->unit_size));
type = *pnt++;
sub_type = *pnt++;
+ const uint8_t *end = data + ecom->unit_size;
+ size_t len = end - data;
+
+ /* Sanity check for extended communities lenght, to avoid
+ * overrun when dealing with bits, e.g. ptr_get_be64().
+ */
+ if (len < ecom->unit_size)
+ return NULL;
+
if ((type == ECOMMUNITY_ENCODE_AS ||
type == ECOMMUNITY_ENCODE_AS_NON_TRANS) &&
sub_type == ECOMMUNITY_LINK_BANDWIDTH) {
+ uint32_t bwval;
+
pnt += 2; /* bandwidth is encoded as AS:val */
pnt = ptr_get_be32(pnt, &bwval);
(void)pnt; /* consume value */
if (bw)
- *bw = ecom->disable_ieee_floating
- ? bwval
- : ieee_float_uint32_to_uint32(
- bwval);
- return eval;
+ *bw = (uint64_t)(ecom->disable_ieee_floating
+ ? bwval
+ : ieee_float_uint32_to_uint32(
+ bwval));
+ return data;
+ } else if (type == ECOMMUNITY_ENCODE_AS4 &&
+ sub_type == ECOMMUNITY_EXTENDED_LINK_BANDWIDTH) {
+ uint64_t bwval;
+
+ if (len < IPV6_ECOMMUNITY_SIZE)
+ return NULL;
+
+ pnt += 2; /* Reserved */
+ pnt = ptr_get_be64(pnt, &bwval);
+ (void)pnt;
+
+ if (bw)
+ *bw = bwval;
+
+ return data;
}
}
@@ -1835,13 +1920,13 @@ const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom, uint32_t *bw)
struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
uint64_t cum_bw,
- bool disable_ieee_floating)
+ bool disable_ieee_floating,
+ bool extended)
{
struct ecommunity *new;
- struct ecommunity_val lb_eval;
const uint8_t *eval;
uint8_t type;
- uint32_t cur_bw;
+ uint64_t cur_bw;
/* Nothing to replace if link-bandwidth doesn't exist or
* is non-transitive - just return existing extcommunity.
@@ -1865,10 +1950,21 @@ struct ecommunity *ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom,
*/
if (cum_bw > 0xFFFFFFFF)
cum_bw = 0xFFFFFFFF;
- encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw, false,
- &lb_eval, disable_ieee_floating);
- new = ecommunity_dup(ecom);
- ecommunity_add_val(new, &lb_eval, true, true);
+
+ if (extended) {
+ struct ecommunity_val_ipv6 lb_eval;
+
+ encode_lb_extended_extcomm(as, cum_bw, false, &lb_eval);
+ new = ecommunity_dup(ecom);
+ ecommunity_add_val_ipv6(new, &lb_eval, true, true);
+ } else {
+ struct ecommunity_val lb_eval;
+
+ encode_lb_extcomm(as > BGP_AS_MAX ? BGP_AS_TRANS : as, cum_bw,
+ false, &lb_eval, disable_ieee_floating);
+ new = ecommunity_dup(ecom);
+ ecommunity_add_val(new, &lb_eval, true, true);
+ }
return new;
}
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index 62e0430..929e4e6 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -10,6 +10,10 @@
#include "bgpd/bgp_rpki.h"
#include "bgpd/bgpd.h"
+#define ONE_GBPS_BYTES (1000 * 1000 * 1000 / 8)
+#define ONE_MBPS_BYTES (1000 * 1000 / 8)
+#define ONE_KBPS_BYTES (1000 / 8)
+
/* Refer to rfc7153 for the IANA registry definitions. These are
* updated by other standards like rfc7674.
*/
@@ -52,10 +56,14 @@
* 0x0c Flow-spec Redirect to IPv4 - draft-ietf-idr-flowspec-redirect
*/
#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV4 0x0c
-/* from draft-ietf-idr-flow-spec-v6-09
- * 0x0b Flow-spec Redirect to IPv6
+/* RFC 8956 */
+#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0d
+
+/* https://datatracker.ietf.org/doc/html/draft-li-idr-link-bandwidth-ext-01
+ * Sub-type is allocated by IANA, just the draft is not yet updated with the
+ * new value.
*/
-#define ECOMMUNITY_FLOWSPEC_REDIRECT_IPV6 0x0b
+#define ECOMMUNITY_EXTENDED_LINK_BANDWIDTH 0x0006
/* Low-order octet of the Extended Communities type field for EVPN types */
#define ECOMMUNITY_EVPN_SUBTYPE_MACMOBILITY 0x00
@@ -226,12 +234,13 @@ static uint32_t uint32_to_ieee_float_uint32(uint32_t u)
* Encode BGP Link Bandwidth extended community
* bandwidth (bw) is in bytes-per-sec
*/
-static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
+static inline void encode_lb_extcomm(as_t as, uint64_t bw, bool non_trans,
struct ecommunity_val *eval,
bool disable_ieee_floating)
{
- uint32_t bandwidth =
- disable_ieee_floating ? bw : uint32_to_ieee_float_uint32(bw);
+ uint64_t bandwidth = disable_ieee_floating
+ ? bw
+ : uint32_to_ieee_float_uint32(bw);
memset(eval, 0, sizeof(*eval));
eval->val[0] = ECOMMUNITY_ENCODE_AS;
@@ -246,6 +255,33 @@ static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
eval->val[7] = bandwidth & 0xff;
}
+/*
+ * Encode BGP Link Bandwidth inside IPv6 Extended Community,
+ * bandwidth is in bytes per second.
+ */
+static inline void encode_lb_extended_extcomm(as_t as, uint64_t bandwidth,
+ bool non_trans,
+ struct ecommunity_val_ipv6 *eval)
+{
+ memset(eval, 0, sizeof(*eval));
+ eval->val[0] = ECOMMUNITY_ENCODE_AS4;
+ if (non_trans)
+ eval->val[0] |= ECOMMUNITY_FLAG_NON_TRANSITIVE;
+ eval->val[1] = ECOMMUNITY_EXTENDED_LINK_BANDWIDTH;
+ eval->val[4] = (bandwidth >> 56) & 0xff;
+ eval->val[5] = (bandwidth >> 48) & 0xff;
+ eval->val[6] = (bandwidth >> 40) & 0xff;
+ eval->val[7] = (bandwidth >> 32) & 0xff;
+ eval->val[8] = (bandwidth >> 24) & 0xff;
+ eval->val[9] = (bandwidth >> 16) & 0xff;
+ eval->val[10] = (bandwidth >> 8) & 0xff;
+ eval->val[11] = bandwidth & 0xff;
+ eval->val[12] = (as >> 24) & 0xff;
+ eval->val[13] = (as >> 16) & 0xff;
+ eval->val[14] = (as >> 8) & 0xff;
+ eval->val[15] = as & 0xff;
+}
+
static inline void encode_origin_validation_state(enum rpki_states state,
struct ecommunity_val *eval)
{
@@ -327,8 +363,7 @@ extern void ecommunity_free(struct ecommunity **);
extern struct ecommunity *ecommunity_parse(uint8_t *, unsigned short,
bool disable_ieee_floating);
extern struct ecommunity *ecommunity_parse_ipv6(uint8_t *pnt,
- unsigned short length,
- bool disable_ieee_floating);
+ unsigned short length);
extern struct ecommunity *ecommunity_dup(struct ecommunity *);
extern struct ecommunity *ecommunity_merge(struct ecommunity *,
struct ecommunity *);
@@ -346,7 +381,7 @@ extern void ecommunity_strfree(char **s);
extern bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2);
extern bool ecommunity_match(const struct ecommunity *,
const struct ecommunity *);
-extern char *ecommunity_str(struct ecommunity *ecom);
+extern const char *ecommunity_str(struct ecommunity *ecom);
extern struct ecommunity_val *ecommunity_lookup(const struct ecommunity *,
uint8_t, uint8_t);
@@ -387,11 +422,10 @@ extern void bgp_remove_ecomm_from_aggregate_hash(
struct ecommunity *ecommunity);
extern void bgp_aggr_ecommunity_remove(void *arg);
extern const uint8_t *ecommunity_linkbw_present(struct ecommunity *ecom,
- uint32_t *bw);
-extern struct ecommunity *ecommunity_replace_linkbw(as_t as,
- struct ecommunity *ecom,
- uint64_t cum_bw,
- bool disable_ieee_floating);
+ uint64_t *bw);
+extern struct ecommunity *
+ecommunity_replace_linkbw(as_t as, struct ecommunity *ecom, uint64_t cum_bw,
+ bool disable_ieee_floating, bool extended);
extern bool soo_in_ecom(struct ecommunity *ecom, struct ecommunity *soo);
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index a846484..e660ca5 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -892,11 +892,10 @@ struct bgp_dest *bgp_evpn_vni_node_lookup(const struct bgpevpn *vpn,
/*
* Add (update) or delete MACIP from zebra.
*/
-static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- const struct ethaddr *mac,
- struct in_addr remote_vtep_ip, int add,
- uint8_t flags, uint32_t seq, esi_t *esi)
+static enum zclient_send_status bgp_zebra_send_remote_macip(
+ struct bgp *bgp, struct bgpevpn *vpn, const struct prefix_evpn *p,
+ const struct ethaddr *mac, struct in_addr remote_vtep_ip, int add,
+ uint8_t flags, uint32_t seq, esi_t *esi)
{
struct stream *s;
uint16_t ipa_len;
@@ -904,8 +903,12 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
bool esi_valid;
/* Check socket. */
- if (!zclient || zclient->sock < 0)
- return 0;
+ if (!zclient || zclient->sock < 0) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: No zclient or zclient->sock exists",
+ __func__);
+ return ZCLIENT_SEND_SUCCESS;
+ }
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
@@ -913,7 +916,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
zlog_debug(
"%s: No zebra instance to talk to, not installing remote macip",
__func__);
- return 0;
+ return ZCLIENT_SEND_SUCCESS;
}
if (!esi)
@@ -979,24 +982,26 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
frrtrace(5, frr_bgp, evpn_mac_ip_zsend, add, vpn, p, remote_vtep_ip,
esi);
- if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
- return -1;
-
- return 0;
+ return zclient_send_message(zclient);
}
/*
* Add (update) or delete remote VTEP from zebra.
*/
-static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- int flood_control, int add)
+static enum zclient_send_status
+bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p, int flood_control,
+ int add)
{
struct stream *s;
/* Check socket. */
- if (!zclient || zclient->sock < 0)
- return 0;
+ if (!zclient || zclient->sock < 0) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: No zclient or zclient->sock exists",
+ __func__);
+ return ZCLIENT_SEND_SUCCESS;
+ }
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
@@ -1004,7 +1009,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
zlog_debug(
"%s: No zebra instance to talk to, not installing remote vtep",
__func__);
- return 0;
+ return ZCLIENT_SEND_SUCCESS;
}
s = zclient->obuf;
@@ -1021,7 +1026,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
EC_BGP_VTEP_INVALID,
"Bad remote IP when trying to %s remote VTEP for VNI %u",
add ? "ADD" : "DEL", (vpn ? vpn->vni : 0));
- return -1;
+ return ZCLIENT_SEND_FAILURE;
}
stream_putl(s, flood_control);
@@ -1034,10 +1039,7 @@ static int bgp_zebra_send_remote_vtep(struct bgp *bgp, struct bgpevpn *vpn,
frrtrace(3, frr_bgp, evpn_bum_vtep_zsend, add, vpn, p);
- if (zclient_send_message(zclient) == ZCLIENT_SEND_FAILURE)
- return -1;
-
- return 0;
+ return zclient_send_message(zclient);
}
/*
@@ -1263,14 +1265,14 @@ static void add_mac_mobility_to_attr(uint32_t seq_num, struct attr *attr)
}
/* Install EVPN route into zebra. */
-static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- struct bgp_path_info *pi)
+enum zclient_send_status evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p,
+ struct bgp_path_info *pi)
{
- int ret;
uint8_t flags;
int flood_control = VXLAN_FLOOD_DISABLED;
uint32_t seq;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
flags = 0;
@@ -1348,6 +1350,7 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
flood_control = VXLAN_FLOOD_DISABLED;
break;
}
+
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p, flood_control, 1);
}
@@ -1355,11 +1358,13 @@ static int evpn_zebra_install(struct bgp *bgp, struct bgpevpn *vpn,
}
/* Uninstall EVPN route from zebra. */
-static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p,
- struct bgp_path_info *pi, bool is_sync)
+enum zclient_send_status evpn_zebra_uninstall(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p,
+ struct bgp_path_info *pi,
+ bool is_sync)
{
- int ret;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE)
ret = bgp_zebra_send_remote_macip(
@@ -1374,7 +1379,7 @@ static int evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
ret = bgp_evpn_remote_es_evi_del(bgp, vpn, p);
else
ret = bgp_zebra_send_remote_vtep(bgp, vpn, p,
- VXLAN_FLOOD_DISABLED, 0);
+ VXLAN_FLOOD_DISABLED, 0);
return ret;
}
@@ -1424,7 +1429,7 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -1438,14 +1443,29 @@ static void evpn_delete_old_local_route(struct bgp *bgp, struct bgpevpn *vpn,
* Note: vpn is NULL for local EAD-ES routes.
*/
int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct bgp_dest *dest)
+ struct bgp_dest *dest, struct bgp_path_info *pi)
{
- struct bgp_path_info *old_select, *new_select;
+ struct bgp_path_info *old_select, *new_select, *first;
struct bgp_path_info_pair old_and_new;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
int ret = 0;
+ first = bgp_dest_get_bgp_path_info(dest);
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+ if (pi != first) {
+ if (pi->next)
+ pi->next->prev = pi->prev;
+ if (pi->prev)
+ pi->prev->next = pi->next;
+
+ if (first)
+ first->prev = pi;
+ pi->next = first;
+ pi->prev = NULL;
+ bgp_dest_set_bgp_path_info(dest, pi);
+ }
+
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
@@ -1465,12 +1485,19 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
&& !CHECK_FLAG(dest->flags, BGP_NODE_USER_CLEAR)
&& !CHECK_FLAG(old_select->flags, BGP_PATH_ATTR_CHANGED)
&& !bgp_addpath_is_addpath_used(&bgp->tx_addpath, afi, safi)) {
- if (bgp_zebra_has_route_changed(old_select))
- ret = evpn_zebra_install(
- bgp, vpn,
- (const struct prefix_evpn *)bgp_dest_get_prefix(
- dest),
- old_select);
+ if (bgp_zebra_has_route_changed(old_select)) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+ ret = evpn_zebra_install(bgp, vpn,
+ (const struct prefix_evpn
+ *)
+ bgp_dest_get_prefix(
+ dest),
+ old_select);
+ else
+ bgp_zebra_route_install(dest, old_select, bgp,
+ true, vpn, false);
+ }
+
UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
UNSET_FLAG(old_select->flags, BGP_PATH_LINK_BW_CHG);
bgp_zebra_clear_route_change_flags(dest);
@@ -1502,10 +1529,15 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
if (new_select && new_select->type == ZEBRA_ROUTE_BGP
&& (new_select->sub_type == BGP_ROUTE_IMPORTED ||
bgp_evpn_attr_is_sync(new_select->attr))) {
- ret = evpn_zebra_install(
- bgp, vpn,
- (struct prefix_evpn *)bgp_dest_get_prefix(dest),
- new_select);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+ ret = evpn_zebra_install(bgp, vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(
+ dest),
+ new_select);
+ else
+ bgp_zebra_route_install(dest, new_select, bgp, true,
+ vpn, false);
/* If an old best existed and it was a "local" route, the only
* reason
@@ -1522,13 +1554,20 @@ int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
evpn_delete_old_local_route(bgp, vpn, dest,
old_select, new_select);
} else {
- if (old_select && old_select->type == ZEBRA_ROUTE_BGP
- && old_select->sub_type == BGP_ROUTE_IMPORTED)
- ret = evpn_zebra_uninstall(
- bgp, vpn,
- (const struct prefix_evpn *)bgp_dest_get_prefix(
- dest),
- old_select, false);
+ if (old_select && old_select->type == ZEBRA_ROUTE_BGP &&
+ old_select->sub_type == BGP_ROUTE_IMPORTED) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
+ CHECK_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN))
+ ret = evpn_zebra_uninstall(bgp, vpn,
+ (const struct prefix_evpn
+ *)
+ bgp_dest_get_prefix(
+ dest),
+ old_select, false);
+ else
+ bgp_zebra_route_install(dest, old_select, bgp,
+ false, vpn, false);
+ }
}
/* Clear any route change flags. */
@@ -1561,11 +1600,12 @@ static struct bgp_path_info *bgp_evpn_route_get_local_path(
static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
struct bgp *bgp_vrf, afi_t afi,
safi_t safi, struct bgp_dest *dest,
- struct attr *attr, int *route_changed)
+ struct attr *attr, int *route_changed,
+ struct bgp_path_info **entry)
{
struct attr *attr_new = NULL;
struct bgp_path_info *pi = NULL;
- mpls_label_t label = MPLS_INVALID_LABEL;
+ struct bgp_labels bgp_labels = {};
struct bgp_path_info *local_pi = NULL;
struct bgp_path_info *tmp_pi = NULL;
@@ -1593,14 +1633,19 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
/* Type-5 routes advertise the L3-VNI */
bgp_path_info_extra_get(pi);
- vni2label(bgp_vrf->l3vni, &label);
- memcpy(&pi->extra->label, &label, sizeof(label));
- pi->extra->num_labels = 1;
+ vni2label(bgp_vrf->l3vni, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
+ if (!bgp_path_info_labels_same(pi, &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&pi->extra->labels);
+ pi->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
+
/* add the route entry to route node*/
bgp_path_info_add(dest, pi);
+ *entry = pi;
} else {
-
tmp_pi = local_pi;
if (!attrhash_cmp(tmp_pi->attr, attr)) {
@@ -1622,6 +1667,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
tmp_pi->attr = attr_new;
tmp_pi->uptime = monotime(NULL);
}
+ *entry = local_pi;
}
return 0;
}
@@ -1637,6 +1683,7 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
struct bgp_dest *dest = NULL;
struct bgp *bgp_evpn = NULL;
int route_changed = 0;
+ struct bgp_path_info *pi = NULL;
bgp_evpn = bgp_get_evpn();
if (!bgp_evpn)
@@ -1718,11 +1765,11 @@ static int update_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp,
/* create or update the route entry within the route node */
update_evpn_type5_route_entry(bgp_evpn, bgp_vrf, afi, safi, dest, &attr,
- &route_changed);
+ &route_changed, &pi);
/* schedule for processing and unlock node */
if (route_changed) {
- bgp_process(bgp_evpn, dest, afi, safi);
+ bgp_process(bgp_evpn, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -1891,15 +1938,13 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
struct bgp_path_info *local_pi;
struct attr *attr_new;
struct attr local_attr;
- mpls_label_t label[BGP_MAX_LABELS];
- uint32_t num_labels = 1;
+ struct bgp_labels bgp_labels = {};
int route_change = 1;
uint8_t sticky = 0;
const struct prefix_evpn *evp;
*pi = NULL;
evp = (const struct prefix_evpn *)bgp_dest_get_prefix(dest);
- memset(&label, 0, sizeof(label));
/* See if this is an update of an existing route, or a new add. */
local_pi = bgp_evpn_route_get_local_path(bgp, dest);
@@ -1941,7 +1986,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
bgp_path_info_extra_get(tmp_pi);
/* The VNI goes into the 'label' field of the route */
- vni2label(vpn->vni, &label[0]);
+ vni2label(vpn->vni, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
/* Type-2 routes may carry a second VNI - the L3-VNI.
* Only attach second label if we are advertising two labels for
@@ -1953,13 +1999,16 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
l3vni = bgpevpn_get_l3vni(vpn);
if (l3vni) {
- vni2label(l3vni, &label[1]);
- num_labels++;
+ vni2label(l3vni, &bgp_labels.label[1]);
+ bgp_labels.num_labels++;
}
}
- memcpy(&tmp_pi->extra->label, label, sizeof(label));
- tmp_pi->extra->num_labels = num_labels;
+ if (!bgp_path_info_labels_same(tmp_pi, &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&tmp_pi->extra->labels);
+ tmp_pi->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
if (mac)
@@ -1983,7 +2032,8 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* The attributes have changed, type-2 routes needs to
* be advertised with right labels.
*/
- vni2label(vpn->vni, &label[0]);
+ vni2label(vpn->vni, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
&& CHECK_FLAG(vpn->flags,
VNI_FLAG_USE_TWO_LABELS)) {
@@ -1991,12 +2041,17 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
l3vni = bgpevpn_get_l3vni(vpn);
if (l3vni) {
- vni2label(l3vni, &label[1]);
- num_labels++;
+ vni2label(l3vni, &bgp_labels.label[1]);
+ bgp_labels.num_labels++;
}
}
- memcpy(&tmp_pi->extra->label, label, sizeof(label));
- tmp_pi->extra->num_labels = num_labels;
+ if (!bgp_path_info_labels_same(tmp_pi,
+ &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&tmp_pi->extra->labels);
+ tmp_pi->extra->labels =
+ bgp_labels_intern(&bgp_labels);
+ }
if (evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE) {
if (mac)
@@ -2062,9 +2117,19 @@ static void evpn_zebra_reinstall_best_route(struct bgp *bgp,
if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP
&& (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
bgp_evpn_attr_is_sync(curr_select->attr)))
- evpn_zebra_install(bgp, vpn,
- (const struct prefix_evpn *)bgp_dest_get_prefix(dest),
- curr_select);
+ if (curr_select && curr_select->type == ZEBRA_ROUTE_BGP &&
+ (curr_select->sub_type == BGP_ROUTE_IMPORTED ||
+ bgp_evpn_attr_is_sync(curr_select->attr))) {
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS))
+ evpn_zebra_install(bgp, vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(
+ dest),
+ curr_select);
+ else
+ bgp_zebra_route_install(dest, curr_select, bgp,
+ true, vpn, false);
+ }
}
/*
@@ -2222,7 +2287,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* route would win, and we should evict the defunct local route
* and (re)install the remote route into zebra.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
/*
* If the new local route was not selected evict it and tell zebra
* to re-add the best remote dest. BGP doesn't retain non-best local
@@ -2245,8 +2310,16 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* has been removed.
*/
new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
- if (!new_is_sync && old_is_sync)
- evpn_zebra_uninstall(bgp, vpn, p, pi, true);
+ if (!new_is_sync && old_is_sync) {
+ if (CHECK_FLAG(bgp->flags,
+ BGP_FLAG_DELETE_IN_PROGRESS))
+ evpn_zebra_uninstall(bgp, vpn, p, pi,
+ true);
+ else
+ bgp_zebra_route_install(dest, pi, bgp,
+ false, vpn,
+ true);
+ }
}
}
bgp_path_info_unlock(pi);
@@ -2270,7 +2343,7 @@ static int update_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
false /* setup_sync */, NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -2330,7 +2403,7 @@ static int delete_evpn_type5_route(struct bgp *bgp_vrf, struct prefix_evpn *evp)
delete_evpn_route_entry(bgp_evpn, afi, safi, dest, &pi);
if (pi)
- bgp_process(bgp_evpn, dest, afi, safi);
+ bgp_process(bgp_evpn, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
return 0;
}
@@ -2370,7 +2443,7 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -2378,9 +2451,8 @@ static int delete_evpn_route(struct bgp *bgp, struct bgpevpn *vpn,
*/
delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
if (pi) {
- dest = bgp_path_info_reap(dest, pi);
- assert(dest);
- evpn_route_select_install(bgp, vpn, dest);
+ bgp_path_info_delete(dest, pi);
+ evpn_route_select_install(bgp, vpn, dest, pi);
}
/* dest should still exist due to locking make coverity happy */
@@ -2494,7 +2566,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* advertised to peers; otherwise, ensure it is evicted and
* (re)install the remote route into zebra.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED)) {
route_change = 0;
@@ -2512,8 +2584,17 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
* has been removed.
*/
new_is_sync = bgp_evpn_attr_is_sync(pi->attr);
- if (!new_is_sync && old_is_sync)
- evpn_zebra_uninstall(bgp, vpn, &evp, pi, true);
+ if (!new_is_sync && old_is_sync) {
+ if (CHECK_FLAG(bgp->flags,
+ BGP_FLAG_DELETE_IN_PROGRESS))
+ (void)evpn_zebra_uninstall(bgp, vpn,
+ &evp, pi,
+ true);
+ else
+ bgp_zebra_route_install(dest, pi, bgp,
+ false, vpn,
+ true);
+ }
}
}
@@ -2533,7 +2614,7 @@ void bgp_evpn_update_type2_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, global_pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -2618,7 +2699,7 @@ static void delete_global_type2_routes(struct bgp *bgp, struct bgpevpn *vpn)
delete_evpn_route_entry(bgp, afi, safi, dest, &pi);
if (pi)
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
/* Unlock RD node. */
@@ -2795,7 +2876,22 @@ static int delete_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
delete_all_type2_routes(bgp, vpn);
build_evpn_type3_prefix(&p, vpn->originator_ip);
+
+ /*
+ * To handle the following scenario:
+ * - Say, the new zebra announce fifo list has few vni Evpn prefixes yet
+ * to be sent to zebra.
+ * - At this point if we have triggers like "no advertise-all-vni" or
+ * "networking restart", where a vni is going down.
+ *
+ * Perform the below
+ * 1) send withdraw routes to zebra immediately in case it is installed.
+ * 2) before we blow up the vni table, we need to walk the list and
+ * pop all the dest whose za_vpn points to this vni.
+ */
+ SET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
ret = delete_evpn_route(bgp, vpn, &p);
+ UNSET_FLAG(bgp->flags, BGP_FLAG_VNI_DOWN);
if (ret)
return ret;
@@ -2903,12 +2999,11 @@ bgp_create_evpn_bgp_path_info(struct bgp_path_info *parent_pi,
sizeof(struct bgp_path_info_extra_vrfleak));
pi->extra->vrfleak->parent = bgp_path_info_lock(parent_pi);
bgp_dest_lock_node((struct bgp_dest *)parent_pi->net);
- if (parent_pi->extra) {
- memcpy(&pi->extra->label, &parent_pi->extra->label,
- sizeof(pi->extra->label));
- pi->extra->num_labels = parent_pi->extra->num_labels;
+ if (parent_pi->extra)
pi->extra->igpmetric = parent_pi->extra->igpmetric;
- }
+
+ if (bgp_path_info_num_labels(parent_pi))
+ pi->extra->labels = bgp_labels_intern(parent_pi->extra->labels);
bgp_path_info_add(dest, pi);
@@ -2945,6 +3040,9 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
vrf_id_to_name(bgp_vrf->vrf_id), evp, parent_pi,
parent_pi->flags);
+ if (bgp_vrf->vrf_id == VRF_UNKNOWN)
+ return -1;
+
/* Create (or fetch) route within the VRF. */
/* NOTE: There is no RD here. */
if (is_evpn_prefix_ipaddr_v4(evp)) {
@@ -3072,7 +3170,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
safi);
/* Perform route selection and update zebra, if required. */
- bgp_process(bgp_vrf, dest, afi, safi);
+ bgp_process(bgp_vrf, dest, pi, afi, safi);
/* Process for route leaking. */
vpn_leak_from_vrf_update(bgp_get_default(), bgp_vrf, pi);
@@ -3184,7 +3282,7 @@ static int install_evpn_route_entry_in_vni_common(
bgp_evpn_remote_ip_hash_add(vpn, pi);
/* Perform route selection and update zebra, if required. */
- ret = evpn_route_select_install(bgp, vpn, dest);
+ ret = evpn_route_select_install(bgp, vpn, dest, pi);
/* if the best path is a local path with a non-zero ES
* sync info against the local path may need to be updated
@@ -3226,7 +3324,7 @@ static int uninstall_evpn_route_entry_in_vni_common(
bgp_path_info_delete(dest, pi);
/* Perform route selection and update zebra, if required. */
- ret = evpn_route_select_install(bgp, vpn, dest);
+ ret = evpn_route_select_install(bgp, vpn, dest, pi);
/* if the best path is a local path with a non-zero ES
* sync info against the local path may need to be updated
@@ -3434,7 +3532,7 @@ static int uninstall_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
bgp_evpn_path_nh_del(bgp_vrf, pi);
/* Perform route selection and update zebra, if required. */
- bgp_process(bgp_vrf, dest, afi, safi);
+ bgp_process(bgp_vrf, dest, pi, afi, safi);
/* Unlock route node. */
bgp_dest_unlock_node(dest);
@@ -3799,7 +3897,7 @@ int bgp_evpn_route_entry_install_if_vrf_match(struct bgp *bgp_vrf,
* Install or uninstall mac-ip routes are appropriate for this
* particular VRF.
*/
-static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
+static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, bool install)
{
afi_t afi;
safi_t safi;
@@ -3863,9 +3961,7 @@ static int install_uninstall_routes_for_vrf(struct bgp *bgp_vrf, int install)
* particular VNI.
*/
static int install_uninstall_routes_for_vni(struct bgp *bgp,
- struct bgpevpn *vpn,
- bgp_evpn_route_type rtype,
- int install)
+ struct bgpevpn *vpn, bool install)
{
afi_t afi;
safi_t safi;
@@ -3896,7 +3992,9 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
(const struct prefix_evpn *)bgp_dest_get_prefix(
dest);
- if (evp->prefix.route_type != rtype)
+ if (evp->prefix.route_type != BGP_EVPN_IMET_ROUTE &&
+ evp->prefix.route_type != BGP_EVPN_AD_ROUTE &&
+ evp->prefix.route_type != BGP_EVPN_MAC_IP_ROUTE)
continue;
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
@@ -3923,16 +4021,16 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
bgp, vpn, evp, pi);
if (ret) {
- flog_err(
- EC_BGP_EVPN_FAIL,
- "%u: Failed to %s EVPN %s route in VNI %u",
- bgp->vrf_id,
- install ? "install"
- : "uninstall",
- rtype == BGP_EVPN_MAC_IP_ROUTE
- ? "MACIP"
- : "IMET",
- vpn->vni);
+ flog_err(EC_BGP_EVPN_FAIL,
+ "%u: Failed to %s EVPN %s route in VNI %u",
+ bgp->vrf_id,
+ install ? "install"
+ : "uninstall",
+ evp->prefix.route_type ==
+ BGP_EVPN_MAC_IP_ROUTE
+ ? "MACIP"
+ : "IMET",
+ vpn->vni);
bgp_dest_unlock_node(rd_dest);
bgp_dest_unlock_node(dest);
@@ -3950,7 +4048,7 @@ static int install_uninstall_routes_for_vni(struct bgp *bgp,
*/
static int install_routes_for_vrf(struct bgp *bgp_vrf)
{
- install_uninstall_routes_for_vrf(bgp_vrf, 1);
+ install_uninstall_routes_for_vrf(bgp_vrf, true);
return 0;
}
@@ -3961,29 +4059,17 @@ static int install_routes_for_vrf(struct bgp *bgp_vrf)
*/
static int install_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
{
- int ret;
-
- /* Install type-3 routes followed by type-2 routes - the ones applicable
+ /*
+ * Install type-3 routes followed by type-2 routes - the ones applicable
* for this VNI.
*/
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
- 1);
- if (ret)
- return ret;
-
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
- 1);
- if (ret)
- return ret;
-
- return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
- 1);
+ return install_uninstall_routes_for_vni(bgp, vpn, true);
}
/* uninstall routes from l3vni vrf. */
static int uninstall_routes_for_vrf(struct bgp *bgp_vrf)
{
- install_uninstall_routes_for_vrf(bgp_vrf, 0);
+ install_uninstall_routes_for_vrf(bgp_vrf, false);
return 0;
}
@@ -3993,25 +4079,11 @@ static int uninstall_routes_for_vrf(struct bgp *bgp_vrf)
*/
static int uninstall_routes_for_vni(struct bgp *bgp, struct bgpevpn *vpn)
{
- int ret;
-
- /* Uninstall type-2 routes followed by type-3 routes - the ones
- * applicable
- * for this VNI.
+ /*
+ * Uninstall type-2 routes followed by type-3 routes - the ones
+ * applicable for this VNI.
*/
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_MAC_IP_ROUTE,
- 0);
- if (ret)
- return ret;
-
- ret = install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_AD_ROUTE,
- 0);
- if (ret)
- return ret;
-
-
- return install_uninstall_routes_for_vni(bgp, vpn, BGP_EVPN_IMET_ROUTE,
- 0);
+ return install_uninstall_routes_for_vni(bgp, vpn, false);
}
/*
@@ -4431,7 +4503,7 @@ static void update_advertise_vni_route(struct bgp *bgp, struct bgpevpn *vpn,
}
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, global_pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -4481,7 +4553,7 @@ static void update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
false /* setup_sync */, NULL /* old_is_sync */);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -4526,7 +4598,7 @@ static int delete_withdraw_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -4622,7 +4694,7 @@ static int process_type2_route(struct peer *peer, afi_t afi, safi_t safi,
uint8_t macaddr_len;
/* holds the VNI(s) as in packet */
mpls_label_t label[BGP_MAX_LABELS] = {};
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
uint32_t eth_tag;
int ret = 0;
@@ -4965,7 +5037,7 @@ static int process_type5_route(struct peer *peer, afi_t afi, safi_t safi,
static void evpn_mpattr_encode_type5(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
struct attr *attr)
{
int len;
@@ -5755,7 +5827,7 @@ int bgp_evpn_uninstall_routes(struct bgp *bgp, struct bgpevpn *vpn)
/*
* TODO: Hardcoded for a maximum of 2 VNIs right now
*/
-char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels, char *buf,
+char *bgp_evpn_label2str(mpls_label_t *label, uint8_t num_labels, char *buf,
int len)
{
vni_t vni1, vni2;
@@ -5839,7 +5911,7 @@ void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json)
*/
void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, struct attr *attr,
+ uint8_t num_labels, struct attr *attr,
bool addpath_capable, uint32_t addpath_tx_id)
{
struct prefix_evpn *evp = (struct prefix_evpn *)p;
@@ -6262,6 +6334,19 @@ struct bgpevpn *bgp_evpn_new(struct bgp *bgp, vni_t vni,
*/
void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
{
+ struct bgp_dest *dest = NULL;
+ struct bgp_dest *dest_next = NULL;
+
+ for (dest = zebra_announce_first(&bm->zebra_announce_head); dest;
+ dest = dest_next) {
+ dest_next = zebra_announce_next(&bm->zebra_announce_head, dest);
+ if (dest->za_vpn == vpn) {
+ zebra_announce_del(&bm->zebra_announce_head, dest);
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_dest_unlock_node(dest);
+ }
+ }
+
bgp_evpn_remote_ip_hash_destroy(vpn);
bgp_evpn_vni_es_cleanup(vpn);
bgpevpn_unlink_from_l3vni(vpn);
@@ -6425,9 +6510,10 @@ void bgp_filter_evpn_routes_upon_martian_change(
for (dest = bgp_table_top(table); dest;
dest = bgp_route_next(dest)) {
+ struct bgp_path_info *next;
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
bool affected = false;
const struct prefix *p;
@@ -6904,6 +6990,17 @@ int bgp_evpn_local_l3vni_del(vni_t l3vni, vrf_id_t vrf_id)
}
/*
+ * When bgp instance goes down also clean up what might have been left over
+ * from evpn.
+ */
+void bgp_evpn_instance_down(struct bgp *bgp)
+{
+ /* If we have a stale local vni, delete it */
+ if (bgp->l3vni)
+ bgp_evpn_local_l3vni_del(bgp->l3vni, bgp->vrf_id);
+}
+
+/*
* Handle del of a local VNI.
*/
int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni)
@@ -7669,7 +7766,7 @@ void bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket,
*
*/
mpls_label_t *bgp_evpn_path_info_labels_get_l3vni(mpls_label_t *labels,
- uint32_t num_labels)
+ uint8_t num_labels)
{
if (!labels)
return NULL;
@@ -7688,8 +7785,10 @@ vni_t bgp_evpn_path_info_get_l3vni(const struct bgp_path_info *pi)
if (!pi->extra)
return 0;
- return label2vni(bgp_evpn_path_info_labels_get_l3vni(
- pi->extra->label, pi->extra->num_labels));
+ return label2vni(
+ bgp_evpn_path_info_labels_get_l3vni(pi->extra->labels->label,
+ pi->extra->labels
+ ->num_labels));
}
/*
diff --git a/bgpd/bgp_evpn.h b/bgpd/bgp_evpn.h
index c641a64..dc82bcf 100644
--- a/bgpd/bgp_evpn.h
+++ b/bgpd/bgp_evpn.h
@@ -115,12 +115,12 @@ extern void bgp_evpn_advertise_type5_routes(struct bgp *bgp_vrf, afi_t afi,
safi_t safi);
extern void bgp_evpn_vrf_delete(struct bgp *bgp_vrf);
extern void bgp_evpn_handle_router_id_update(struct bgp *bgp, int withdraw);
-extern char *bgp_evpn_label2str(mpls_label_t *label, uint32_t num_labels,
+extern char *bgp_evpn_label2str(mpls_label_t *label, uint8_t num_labels,
char *buf, int len);
extern void bgp_evpn_route2json(const struct prefix_evpn *p, json_object *json);
extern void bgp_evpn_encode_prefix(struct stream *s, const struct prefix *p,
const struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
struct attr *attr, bool addpath_capable,
uint32_t addpath_tx_id);
extern int bgp_nlri_parse_evpn(struct peer *peer, struct attr *attr,
@@ -153,6 +153,7 @@ extern int bgp_evpn_local_l3vni_add(vni_t vni, vrf_id_t vrf_id,
struct in_addr originator_ip, int filter,
ifindex_t svi_ifindex, bool is_anycast_mac);
extern int bgp_evpn_local_l3vni_del(vni_t vni, vrf_id_t vrf_id);
+extern void bgp_evpn_instance_down(struct bgp *bgp);
extern int bgp_evpn_local_vni_del(struct bgp *bgp, vni_t vni);
extern int bgp_evpn_local_vni_add(struct bgp *bgp, vni_t vni,
struct in_addr originator_ip,
@@ -177,7 +178,7 @@ extern void
bgp_evpn_handle_resolve_overlay_index_unset(struct hash_bucket *bucket,
void *arg);
extern mpls_label_t *bgp_evpn_path_info_labels_get_l3vni(mpls_label_t *labels,
- uint32_t num_labels);
+ uint8_t num_labels);
extern vni_t bgp_evpn_path_info_get_l3vni(const struct bgp_path_info *pi);
extern bool bgp_evpn_mpath_has_dvni(const struct bgp *bgp_vrf,
struct bgp_path_info *mpinfo);
@@ -186,4 +187,12 @@ extern bool is_route_injectable_into_evpn_non_supp(struct bgp_path_info *pi);
extern void bgp_aggr_supp_withdraw_from_evpn(struct bgp *bgp, afi_t afi,
safi_t safi);
+extern enum zclient_send_status evpn_zebra_install(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p,
+ struct bgp_path_info *pi);
+extern enum zclient_send_status
+evpn_zebra_uninstall(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p, struct bgp_path_info *pi,
+ bool is_sync);
#endif /* _QUAGGA_BGP_EVPN_H */
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index d88c52d..d723a2b 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -45,13 +45,14 @@ static void bgp_evpn_local_es_down(struct bgp *bgp,
struct bgp_evpn_es *es);
static void bgp_evpn_local_type1_evi_route_del(struct bgp *bgp,
struct bgp_evpn_es *es);
-static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
+static struct bgp_evpn_es_vtep *
+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct in_addr vtep_ip, bool esr, uint8_t df_alg,
+ uint16_t df_pref, int *zret);
+static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp,
struct bgp_evpn_es *es,
struct in_addr vtep_ip,
- bool esr, uint8_t df_alg,
- uint16_t df_pref);
-static void bgp_evpn_es_vtep_del(struct bgp *bgp,
- struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr);
+ bool esr);
static void bgp_evpn_es_cons_checks_pend_add(struct bgp_evpn_es *es);
static void bgp_evpn_es_cons_checks_pend_del(struct bgp_evpn_es *es);
static struct bgp_evpn_es_evi *
@@ -91,15 +92,19 @@ static void bgp_evpn_path_nh_unlink(struct bgp_path_evpn_nh_info *nh_info);
*/
static int bgp_evpn_es_route_select_install(struct bgp *bgp,
struct bgp_evpn_es *es,
- struct bgp_dest *dest)
+ struct bgp_dest *dest,
+ struct bgp_path_info *pi)
{
int ret = 0;
+ int zret = 0;
afi_t afi = AFI_L2VPN;
safi_t safi = SAFI_EVPN;
struct bgp_path_info *old_select; /* old best */
struct bgp_path_info *new_select; /* new best */
struct bgp_path_info_pair old_and_new;
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+
/* Compute the best path. */
bgp_best_selection(bgp, dest, &bgp->maxpaths[afi][safi], &old_and_new,
afi, safi);
@@ -120,7 +125,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
bgp_evpn_es_vtep_add(bgp, es, old_select->attr->nexthop,
true /*esr*/,
old_select->attr->df_alg,
- old_select->attr->df_pref);
+ old_select->attr->df_pref, &zret);
}
UNSET_FLAG(old_select->flags, BGP_PATH_MULTIPATH_CHG);
bgp_zebra_clear_route_change_flags(dest);
@@ -149,7 +154,7 @@ static int bgp_evpn_es_route_select_install(struct bgp *bgp,
&& new_select->sub_type == BGP_ROUTE_IMPORTED) {
bgp_evpn_es_vtep_add(bgp, es, new_select->attr->nexthop,
true /*esr */, new_select->attr->df_alg,
- new_select->attr->df_pref);
+ new_select->attr->df_pref, &zret);
} else {
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
&& old_select->sub_type == BGP_ROUTE_IMPORTED)
@@ -231,7 +236,7 @@ static int bgp_evpn_es_route_install(struct bgp *bgp,
}
/* Perform route selection and update zebra, if required. */
- ret = bgp_evpn_es_route_select_install(bgp, es, dest);
+ ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi);
bgp_dest_unlock_node(dest);
@@ -272,7 +277,7 @@ static int bgp_evpn_es_route_uninstall(struct bgp *bgp, struct bgp_evpn_es *es,
bgp_path_info_delete(dest, pi);
/* Perform route selection and update zebra, if required. */
- ret = bgp_evpn_es_route_select_install(bgp, es, dest);
+ ret = bgp_evpn_es_route_select_install(bgp, es, dest, pi);
/* Unlock route node. */
bgp_dest_unlock_node(dest);
@@ -353,6 +358,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
struct bgp_path_info *tmp_pi = NULL;
struct bgp_path_info *local_pi = NULL; /* local route entry if any */
struct bgp_path_info *remote_pi = NULL; /* remote route entry if any */
+ struct bgp_labels bgp_labels = {};
struct attr *attr_new = NULL;
struct prefix_evpn *evp;
@@ -399,11 +405,16 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
if (evp->prefix.route_type == BGP_EVPN_AD_ROUTE) {
bgp_path_info_extra_get(tmp_pi);
- tmp_pi->extra->num_labels = 1;
+ bgp_labels.num_labels = 1;
if (vpn)
- vni2label(vpn->vni, &tmp_pi->extra->label[0]);
- else
- tmp_pi->extra->label[0] = 0;
+ vni2label(vpn->vni, &bgp_labels.label[0]);
+ if (!bgp_path_info_labels_same(tmp_pi,
+ &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_labels_unintern(&tmp_pi->extra->labels);
+ tmp_pi->extra->labels =
+ bgp_labels_intern(&bgp_labels);
+ }
}
/* add the newly created path to the route-node */
@@ -447,7 +458,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
attr->mp_nexthop_global_in);
}
- /* Return back the route entry. */
+ /* Return back th*e route entry. */
*ri = tmp_pi;
return 0;
}
@@ -511,7 +522,7 @@ static int bgp_evpn_mh_route_delete(struct bgp *bgp, struct bgp_evpn_es *es,
* this table.
*/
if (pi)
- bgp_process(bgp, global_dest, afi, safi);
+ bgp_process(bgp, global_dest, pi, afi, safi);
bgp_dest_unlock_node(global_dest);
}
@@ -562,7 +573,7 @@ int delete_global_ead_evi_routes(struct bgp *bgp, struct bgpevpn *vpn)
delete_evpn_route_entry(bgp, afi, safi, bd, &pi);
if (pi)
- bgp_process(bgp, bd, afi, safi);
+ bgp_process(bgp, bd, pi, afi, safi);
}
}
@@ -668,7 +679,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp,
* this is just to set the flags correctly
* as local route in the ES always wins.
*/
- bgp_evpn_es_route_select_install(bgp, es, dest);
+ bgp_evpn_es_route_select_install(bgp, es, dest, pi);
bgp_dest_unlock_node(dest);
/* If this is a new route or some attribute has changed, export the
@@ -686,7 +697,7 @@ static int bgp_evpn_type4_route_update(struct bgp *bgp,
attr_new, &global_pi, &route_changed);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -1008,7 +1019,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
* this is just to set the flags correctly as local route in
* the ES always wins.
*/
- evpn_route_select_install(bgp, vpn, dest);
+ evpn_route_select_install(bgp, vpn, dest, pi);
bgp_dest_unlock_node(dest);
/* If this is a new route or some attribute has changed, export the
@@ -1025,7 +1036,7 @@ static int bgp_evpn_type1_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
attr_new, &global_pi, &route_changed);
/* Schedule for processing and unlock node. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, global_pi, afi, safi);
bgp_dest_unlock_node(dest);
}
@@ -1371,23 +1382,28 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_find(struct bgp_evpn_es *es,
}
/* Send the remote ES to zebra for NHG programming */
-static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
- struct bgp_evpn_es_vtep *es_vtep, bool add)
+static enum zclient_send_status
+bgp_zebra_send_remote_es_vtep(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep,
+ bool add)
{
struct bgp_evpn_es *es = es_vtep->es;
struct stream *s;
uint32_t flags = 0;
/* Check socket. */
- if (!zclient || zclient->sock < 0)
- return 0;
+ if (!zclient || zclient->sock < 0) {
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("%s: No zclient or zclient->sock exists",
+ __func__);
+ return ZCLIENT_SEND_SUCCESS;
+ }
/* Don't try to register if Zebra doesn't know of this instance. */
if (!IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("No zebra instance, not installing remote es %s",
es->esi_str);
- return 0;
+ return ZCLIENT_SEND_SUCCESS;
}
if (es_vtep->flags & BGP_EVPNES_VTEP_ESR)
@@ -1418,12 +1434,12 @@ static int bgp_zebra_send_remote_es_vtep(struct bgp *bgp,
return zclient_send_message(zclient);
}
-static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
- struct bgp_evpn_es_vtep *es_vtep,
- bool param_change)
+static enum zclient_send_status bgp_evpn_es_vtep_re_eval_active(
+ struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep, bool param_change)
{
bool old_active;
bool new_active;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
old_active = CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE);
/* currently we need an active EVI reference to use the VTEP as
@@ -1445,7 +1461,7 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
es_vtep->df_alg, es_vtep->df_pref);
/* send remote ES to zebra */
- bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
+ ret = bgp_zebra_send_remote_es_vtep(bgp, es_vtep, new_active);
/* The NHG is updated first for efficient failover handling.
* Note the NHG can be de-activated while there are bgp
@@ -1457,13 +1473,14 @@ static void bgp_evpn_es_vtep_re_eval_active(struct bgp *bgp,
/* queue up the es for background consistency checks */
bgp_evpn_es_cons_checks_pend_add(es_vtep->es);
}
+
+ return ret;
}
-static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
- struct bgp_evpn_es *es,
- struct in_addr vtep_ip,
- bool esr, uint8_t df_alg,
- uint16_t df_pref)
+static struct bgp_evpn_es_vtep *
+bgp_evpn_es_vtep_add(struct bgp *bgp, struct bgp_evpn_es *es,
+ struct in_addr vtep_ip, bool esr, uint8_t df_alg,
+ uint16_t df_pref, int *zret)
{
struct bgp_evpn_es_vtep *es_vtep;
bool param_change = false;
@@ -1490,15 +1507,17 @@ static struct bgp_evpn_es_vtep *bgp_evpn_es_vtep_add(struct bgp *bgp,
++es_vtep->evi_cnt;
}
- bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
+ *zret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
return es_vtep;
}
-static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
- struct bgp_evpn_es_vtep *es_vtep, bool esr)
+static enum zclient_send_status
+bgp_evpn_es_vtep_do_del(struct bgp *bgp, struct bgp_evpn_es_vtep *es_vtep,
+ bool esr)
{
bool param_change = false;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("es %s vtep %pI4 del %s", es_vtep->es->esi_str,
@@ -1515,18 +1534,25 @@ static void bgp_evpn_es_vtep_do_del(struct bgp *bgp,
--es_vtep->evi_cnt;
}
- bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
+ ret = bgp_evpn_es_vtep_re_eval_active(bgp, es_vtep, param_change);
bgp_evpn_es_vtep_free(es_vtep);
+
+ return ret;
}
-static void bgp_evpn_es_vtep_del(struct bgp *bgp,
- struct bgp_evpn_es *es, struct in_addr vtep_ip, bool esr)
+static enum zclient_send_status bgp_evpn_es_vtep_del(struct bgp *bgp,
+ struct bgp_evpn_es *es,
+ struct in_addr vtep_ip,
+ bool esr)
{
struct bgp_evpn_es_vtep *es_vtep;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
es_vtep = bgp_evpn_es_vtep_find(es, vtep_ip);
if (es_vtep)
- bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
+ ret = bgp_evpn_es_vtep_do_del(bgp, es_vtep, esr);
+
+ return ret;
}
/********************** ES MAC-IP paths *************************************
@@ -2435,7 +2461,7 @@ static void bgp_evpn_es_frag_show_detail(struct vty *vty,
}
static char *bgp_evpn_es_vteps_str(char *vtep_str, struct bgp_evpn_es *es,
- uint8_t vtep_str_size)
+ size_t vtep_str_size)
{
char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
struct listnode *node;
@@ -3399,12 +3425,14 @@ static struct bgp_evpn_es_evi_vtep *bgp_evpn_es_evi_vtep_find(
/* A VTEP can be added as "active" attach to an ES if EAD-per-ES and
* EAD-per-EVI routes are rxed from it.
*/
-static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
- struct bgp_evpn_es_evi_vtep *evi_vtep)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
+ struct bgp_evpn_es_evi_vtep *evi_vtep)
{
bool old_active;
bool new_active;
uint32_t ead_activity_flags;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
old_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
@@ -3425,7 +3453,7 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
new_active = CHECK_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_ACTIVE);
if (old_active == new_active)
- return;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("es %s evi %u vtep %pI4 %s",
@@ -3434,24 +3462,27 @@ static void bgp_evpn_es_evi_vtep_re_eval_active(struct bgp *bgp,
new_active ? "active" : "inactive");
/* add VTEP to parent es */
- if (new_active)
- evi_vtep->es_vtep = bgp_evpn_es_vtep_add(
- bgp, evi_vtep->es_evi->es, evi_vtep->vtep_ip,
- false /*esr*/, 0, 0);
- else {
+ if (new_active) {
+ evi_vtep->es_vtep =
+ bgp_evpn_es_vtep_add(bgp, evi_vtep->es_evi->es,
+ evi_vtep->vtep_ip, false /*esr*/,
+ 0, 0, &ret);
+ } else {
if (evi_vtep->es_vtep) {
- bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
- false /*esr*/);
+ ret = bgp_evpn_es_vtep_do_del(bgp, evi_vtep->es_vtep,
+ false /*esr*/);
evi_vtep->es_vtep = NULL;
}
}
/* queue up the parent es for background consistency checks */
bgp_evpn_es_cons_checks_pend_add(evi_vtep->es_evi->es);
+
+ return ret;
}
-static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
- struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
- bool ead_es)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_add(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi,
+ struct in_addr vtep_ip, bool ead_es)
{
struct bgp_evpn_es_evi_vtep *evi_vtep;
@@ -3475,18 +3506,19 @@ static void bgp_evpn_es_evi_vtep_add(struct bgp *bgp,
else
SET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
- bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
+ return bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
}
-static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
- struct bgp_evpn_es_evi *es_evi, struct in_addr vtep_ip,
- bool ead_es)
+static enum zclient_send_status
+bgp_evpn_es_evi_vtep_del(struct bgp *bgp, struct bgp_evpn_es_evi *es_evi,
+ struct in_addr vtep_ip, bool ead_es)
{
struct bgp_evpn_es_evi_vtep *evi_vtep;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
evi_vtep = bgp_evpn_es_evi_vtep_find(es_evi, vtep_ip);
if (!evi_vtep)
- return;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("del es %s evi %u vtep %pI4 %s",
@@ -3503,8 +3535,10 @@ static void bgp_evpn_es_evi_vtep_del(struct bgp *bgp,
else
UNSET_FLAG(evi_vtep->flags, BGP_EVPN_EVI_VTEP_EAD_PER_EVI);
- bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
+ ret = bgp_evpn_es_evi_vtep_re_eval_active(bgp, evi_vtep);
bgp_evpn_es_evi_vtep_free(evi_vtep);
+
+ return ret;
}
/* compare ES-IDs for the ES-EVI RB tree maintained per-VNI */
@@ -3780,18 +3814,20 @@ int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni)
/* Add remote ES-EVI entry. This is actually the remote VTEP add and the
* ES-EVI is implicity created on first VTEP's reference.
*/
-int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p)
+enum zclient_send_status bgp_evpn_remote_es_evi_add(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p)
{
char buf[ESI_STR_LEN];
struct bgp_evpn_es *es;
struct bgp_evpn_es_evi *es_evi;
bool ead_es;
const esi_t *esi = &p->prefix.ead_addr.esi;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (!vpn)
/* local EAD-ES need not be sent back to zebra */
- return 0;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug("add remote %s es %s evi %u vtep %pI4",
@@ -3808,27 +3844,29 @@ int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
es_evi = bgp_evpn_es_evi_new(es, vpn);
ead_es = !!p->prefix.ead_addr.eth_tag;
- bgp_evpn_es_evi_vtep_add(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
- ead_es);
+ ret = bgp_evpn_es_evi_vtep_add(bgp, es_evi,
+ p->prefix.ead_addr.ip.ipaddr_v4, ead_es);
bgp_evpn_es_evi_remote_info_re_eval(es_evi);
- return 0;
+ return ret;
}
/* A remote VTEP has withdrawn. The es-evi-vtep will be deleted and the
* parent es-evi freed up implicitly in last VTEP's deref.
*/
-int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p)
+enum zclient_send_status bgp_evpn_remote_es_evi_del(struct bgp *bgp,
+ struct bgpevpn *vpn,
+ const struct prefix_evpn *p)
{
char buf[ESI_STR_LEN];
struct bgp_evpn_es *es;
struct bgp_evpn_es_evi *es_evi;
bool ead_es;
+ enum zclient_send_status ret = ZCLIENT_SEND_SUCCESS;
if (!vpn)
/* local EAD-ES need not be sent back to zebra */
- return 0;
+ return ret;
if (BGP_DEBUG(evpn_mh, EVPN_MH_ES))
zlog_debug(
@@ -3847,7 +3885,7 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
esi_to_str(&p->prefix.ead_addr.esi, buf,
sizeof(buf)),
vpn->vni, &p->prefix.ead_addr.ip.ipaddr_v4);
- return 0;
+ return ret;
}
es_evi = bgp_evpn_es_evi_find(es, vpn);
if (!es_evi) {
@@ -3860,14 +3898,15 @@ int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
sizeof(buf)),
vpn->vni,
&p->prefix.ead_addr.ip.ipaddr_v4);
- return 0;
+ return ret;
}
ead_es = !!p->prefix.ead_addr.eth_tag;
- bgp_evpn_es_evi_vtep_del(bgp, es_evi, p->prefix.ead_addr.ip.ipaddr_v4,
- ead_es);
+ ret = bgp_evpn_es_evi_vtep_del(bgp, es_evi,
+ p->prefix.ead_addr.ip.ipaddr_v4, ead_es);
bgp_evpn_es_evi_remote_info_re_eval(es_evi);
- return 0;
+
+ return ret;
}
/* If a VNI is being deleted we need to force del all remote VTEPs */
@@ -3923,7 +3962,7 @@ void bgp_evpn_vni_es_cleanup(struct bgpevpn *vpn)
static char *bgp_evpn_es_evi_vteps_str(char *vtep_str,
struct bgp_evpn_es_evi *es_evi,
- uint8_t vtep_str_size)
+ size_t vtep_str_size)
{
char vtep_flag_str[BGP_EVPN_FLAG_STR_SZ];
struct listnode *node;
diff --git a/bgpd/bgp_evpn_mh.h b/bgpd/bgp_evpn_mh.h
index cebabb9..5d393c3 100644
--- a/bgpd/bgp_evpn_mh.h
+++ b/bgpd/bgp_evpn_mh.h
@@ -418,10 +418,12 @@ extern int bgp_evpn_local_es_add(struct bgp *bgp, esi_t *esi,
extern int bgp_evpn_local_es_del(struct bgp *bgp, esi_t *esi);
extern int bgp_evpn_local_es_evi_add(struct bgp *bgp, esi_t *esi, vni_t vni);
extern int bgp_evpn_local_es_evi_del(struct bgp *bgp, esi_t *esi, vni_t vni);
-extern int bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p);
-extern int bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
- const struct prefix_evpn *p);
+extern enum zclient_send_status
+bgp_evpn_remote_es_evi_add(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p);
+extern enum zclient_send_status
+bgp_evpn_remote_es_evi_del(struct bgp *bgp, struct bgpevpn *vpn,
+ const struct prefix_evpn *p);
extern void bgp_evpn_mh_init(void);
extern void bgp_evpn_mh_finish(void);
void bgp_evpn_vni_es_init(struct bgpevpn *vpn);
diff --git a/bgpd/bgp_evpn_private.h b/bgpd/bgp_evpn_private.h
index 5af99af..07bba9b 100644
--- a/bgpd/bgp_evpn_private.h
+++ b/bgpd/bgp_evpn_private.h
@@ -716,7 +716,8 @@ extern void delete_evpn_route_entry(struct bgp *bgp, afi_t afi, safi_t safi,
struct bgp_path_info **pi);
int vni_list_cmp(void *p1, void *p2);
extern int evpn_route_select_install(struct bgp *bgp, struct bgpevpn *vpn,
- struct bgp_dest *dest);
+ struct bgp_dest *dest,
+ struct bgp_path_info *pi);
extern struct bgp_dest *
bgp_evpn_global_node_get(struct bgp_table *table, afi_t afi, safi_t safi,
const struct prefix_evpn *evp, struct prefix_rd *prd,
diff --git a/bgpd/bgp_filter.c b/bgpd/bgp_filter.c
index a851179..002f054 100644
--- a/bgpd/bgp_filter.c
+++ b/bgpd/bgp_filter.c
@@ -16,7 +16,7 @@
#include "bgpd/bgp_aspath.h"
#include "bgpd/bgp_regex.h"
-/* List of AS filter list. */
+/* List of AS list. */
struct as_list_list {
struct as_list *head;
struct as_list *tail;
@@ -205,14 +205,6 @@ static struct as_list *as_list_new(void)
static void as_list_free(struct as_list *aslist)
{
- struct aspath_exclude_list *cur_bp = aslist->exclude_list;
- struct aspath_exclude_list *next_bp = NULL;
-
- while (cur_bp) {
- next_bp = cur_bp->next;
- XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_bp);
- cur_bp = next_bp;
- }
XFREE (MTYPE_AS_STR, aslist->name);
XFREE (MTYPE_AS_LIST, aslist);
@@ -299,7 +291,6 @@ static void as_list_delete(struct as_list *aslist)
{
struct as_list_list *list;
struct as_filter *filter, *next;
- struct aspath_exclude_list *cur_bp;
for (filter = aslist->head; filter; filter = next) {
next = filter->next;
@@ -318,12 +309,6 @@ static void as_list_delete(struct as_list *aslist)
else
list->head = aslist->next;
- cur_bp = aslist->exclude_list;
- while (cur_bp) {
- cur_bp->bp_as_excl->exclude_aspath_acl = NULL;
- cur_bp = cur_bp->next;
- }
-
as_list_free(aslist);
}
@@ -431,6 +416,7 @@ DEFUN(as_path, bgp_as_path_cmd,
enum as_filter_type type;
struct as_filter *asfilter;
struct as_list *aslist;
+ struct aspath_exclude *ase;
regex_t *regex;
char *regstr;
int64_t seqnum = ASPATH_SEQ_NUMBER_AUTO;
@@ -482,6 +468,22 @@ DEFUN(as_path, bgp_as_path_cmd,
else
as_list_filter_add(aslist, asfilter);
+ /* init the exclude rule list*/
+ as_list_list_init(&aslist->exclude_rule);
+
+ /* get aspath orphan exclude that are using this acl */
+ ase = as_exclude_lookup_orphan(alname);
+ if (ase) {
+ as_list_list_add_head(&aslist->exclude_rule, ase);
+ /* set reverse pointer */
+ ase->exclude_aspath_acl = aslist;
+ /* set list of aspath excludes using that acl */
+ while ((ase = as_exclude_lookup_orphan(alname))) {
+ as_list_list_add_head(&aslist->exclude_rule, ase);
+ ase->exclude_aspath_acl = aslist;
+ }
+ }
+
return CMD_SUCCESS;
}
@@ -502,6 +504,7 @@ DEFUN(no_as_path, no_bgp_as_path_cmd,
enum as_filter_type type;
struct as_filter *asfilter;
struct as_list *aslist;
+ struct aspath_exclude *ase;
char *regstr;
regex_t *regex;
@@ -556,6 +559,12 @@ DEFUN(no_as_path, no_bgp_as_path_cmd,
XFREE(MTYPE_TMP, regstr);
+ /* put aspath exclude list into orphan */
+ if (as_list_list_count(&aslist->exclude_rule))
+ while ((ase = as_list_list_pop(&aslist->exclude_rule)))
+ as_exclude_set_orphan(ase);
+
+ as_list_list_fini(&aslist->exclude_rule);
as_list_filter_delete(aslist, asfilter);
return CMD_SUCCESS;
diff --git a/bgpd/bgp_filter.h b/bgpd/bgp_filter.h
index 2d9f07c..77a3f3c 100644
--- a/bgpd/bgp_filter.h
+++ b/bgpd/bgp_filter.h
@@ -6,11 +6,12 @@
#ifndef _QUAGGA_BGP_FILTER_H
#define _QUAGGA_BGP_FILTER_H
+#include <typesafe.h>
+
#define ASPATH_SEQ_NUMBER_AUTO -1
enum as_filter_type { AS_FILTER_DENY, AS_FILTER_PERMIT };
-
/* Element of AS path filter. */
struct as_filter {
struct as_filter *next;
@@ -25,11 +26,7 @@ struct as_filter {
int64_t seq;
};
-struct aspath_exclude_list {
- struct aspath_exclude_list *next;
- struct aspath_exclude *bp_as_excl;
-};
-
+PREDECL_DLIST(as_list_list);
/* AS path filter list. */
struct as_list {
char *name;
@@ -39,7 +36,9 @@ struct as_list {
struct as_filter *head;
struct as_filter *tail;
- struct aspath_exclude_list *exclude_list;
+
+ /* Changes in AS path */
+ struct as_list_list_head exclude_rule;
};
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index 5043439..d41ef8a 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -260,6 +260,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
peer->afc_recv[afi][safi] = from_peer->afc_recv[afi][safi];
peer->orf_plist[afi][safi] = from_peer->orf_plist[afi][safi];
peer->llgr[afi][safi] = from_peer->llgr[afi][safi];
+ peer->addpath_paths_limit[afi][safi] =
+ from_peer->addpath_paths_limit[afi][safi];
}
if (bgp_getsockname(peer) < 0) {
@@ -1239,7 +1241,7 @@ void bgp_fsm_change_status(struct peer_connection *connection,
/* Transition into Clearing or Deleted must /always/ clear all routes..
* (and must do so before actually changing into Deleted..
*/
- if (status >= Clearing) {
+ if (status >= Clearing && (peer->established || peer == bgp->peer_self)) {
bgp_clear_route_all(peer);
/* If no route was queued for the clear-node processing,
@@ -1587,7 +1589,7 @@ bgp_stop_with_error(struct peer_connection *connection)
/* something went wrong, send notify and tear down */
-static enum bgp_fsm_state_progress
+enum bgp_fsm_state_progress
bgp_stop_with_notify(struct peer_connection *connection, uint8_t code,
uint8_t sub_code)
{
@@ -1794,6 +1796,26 @@ bgp_connect_fail(struct peer_connection *connection)
return bgp_stop(connection);
}
+/* after connect is called(), getpeername is able to return
+ * port and address on non established streams
+ */
+static void bgp_connect_in_progress_update_connection(struct peer *peer)
+{
+ if (bgp_getsockname(peer) < 0) {
+ if (!peer->su_remote &&
+ !BGP_CONNECTION_SU_UNSPEC(peer->connection)) {
+ /* if connect initiated, then dest port and dest addresses are well known */
+ peer->su_remote = sockunion_dup(&peer->connection->su);
+ if (sockunion_family(peer->su_remote) == AF_INET)
+ peer->su_remote->sin.sin_port =
+ htons(peer->port);
+ else if (sockunion_family(peer->su_remote) == AF_INET6)
+ peer->su_remote->sin6.sin6_port =
+ htons(peer->port);
+ }
+ }
+}
+
/* This function is the first starting point of all BGP connection. It
* try to connect to remote peer with non-blocking IO.
*/
@@ -1890,6 +1912,8 @@ static enum bgp_fsm_state_progress bgp_start(struct peer_connection *connection)
__func__, peer->connection->fd);
return BGP_FSM_FAILURE;
}
+ bgp_connect_in_progress_update_connection(peer);
+
/*
* - when the socket becomes ready, poll() will signify POLLOUT
* - if it fails to connect, poll() will signify POLLHUP
diff --git a/bgpd/bgp_fsm.h b/bgpd/bgp_fsm.h
index 2e96ac4..bcdd491 100644
--- a/bgpd/bgp_fsm.h
+++ b/bgpd/bgp_fsm.h
@@ -122,6 +122,9 @@ extern void bgp_maxmed_update(struct bgp *);
extern bool bgp_maxmed_onstartup_configured(struct bgp *);
extern bool bgp_maxmed_onstartup_active(struct bgp *);
extern int bgp_fsm_error_subcode(int status);
+extern enum bgp_fsm_state_progress
+bgp_stop_with_notify(struct peer_connection *connection, uint8_t code,
+ uint8_t sub_code);
/**
* Start the route advertisement timer (that honors MRAI) for all the
diff --git a/bgpd/bgp_label.c b/bgpd/bgp_label.c
index 7327ab5..839437e 100644
--- a/bgpd/bgp_label.c
+++ b/bgpd/bgp_label.c
@@ -15,6 +15,7 @@
#include "memory.h"
#include "nexthop.h"
#include "mpls.h"
+#include "jhash.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
@@ -27,6 +28,124 @@
extern struct zclient *zclient;
+
+/* MPLS Labels hash routines. */
+static struct hash *labels_hash;
+
+static void *bgp_labels_hash_alloc(void *p)
+{
+ const struct bgp_labels *labels = p;
+ struct bgp_labels *new;
+ uint8_t i;
+
+ new = XMALLOC(MTYPE_BGP_LABELS, sizeof(struct bgp_labels));
+
+ new->num_labels = labels->num_labels;
+ for (i = 0; i < labels->num_labels; i++)
+ new->label[i] = labels->label[i];
+
+ return new;
+}
+
+static uint32_t bgp_labels_hash_key_make(const void *p)
+{
+ const struct bgp_labels *labels = p;
+ uint32_t key = 0;
+
+ if (labels->num_labels)
+ key = jhash(&labels->label,
+ labels->num_labels * sizeof(mpls_label_t), key);
+
+ return key;
+}
+
+static bool bgp_labels_hash_cmp(const void *p1, const void *p2)
+{
+ return bgp_labels_cmp(p1, p2);
+}
+
+void bgp_labels_init(void)
+{
+ labels_hash = hash_create(bgp_labels_hash_key_make, bgp_labels_hash_cmp,
+ "BGP Labels hash");
+}
+
+/*
+ * special for hash_clean below
+ */
+static void bgp_labels_free(void *labels)
+{
+ XFREE(MTYPE_BGP_LABELS, labels);
+}
+
+void bgp_labels_finish(void)
+{
+ hash_clean_and_free(&labels_hash, bgp_labels_free);
+}
+
+struct bgp_labels *bgp_labels_intern(struct bgp_labels *labels)
+{
+ struct bgp_labels *find;
+
+ if (!labels)
+ return NULL;
+
+ if (!labels->num_labels)
+ /* do not intern void labels structure */
+ return NULL;
+
+ find = (struct bgp_labels *)hash_get(labels_hash, labels,
+ bgp_labels_hash_alloc);
+ find->refcnt++;
+
+ return find;
+}
+
+void bgp_labels_unintern(struct bgp_labels **plabels)
+{
+ struct bgp_labels *labels = *plabels;
+ struct bgp_labels *ret;
+
+ if (!*plabels)
+ return;
+
+ /* Decrement labels reference. */
+ labels->refcnt--;
+
+ /* If reference becomes zero then free labels object. */
+ if (labels->refcnt == 0) {
+ ret = hash_release(labels_hash, labels);
+ assert(ret != NULL);
+ bgp_labels_free(labels);
+ *plabels = NULL;
+ }
+}
+
+bool bgp_labels_cmp(const struct bgp_labels *labels1,
+ const struct bgp_labels *labels2)
+{
+ uint8_t i;
+
+ if (!labels1 && !labels2)
+ return true;
+
+ if (!labels1 && labels2)
+ return false;
+
+ if (labels1 && !labels2)
+ return false;
+
+ if (labels1->num_labels != labels2->num_labels)
+ return false;
+
+ for (i = 0; i < labels1->num_labels; i++) {
+ if (labels1->label[i] != labels2->label[i])
+ return false;
+ }
+
+ return true;
+}
+
int bgp_parse_fec_update(void)
{
struct stream *s;
@@ -74,7 +193,7 @@ int bgp_parse_fec_update(void)
bgp_set_valid_label(&dest->local_label);
}
SET_FLAG(dest->flags, BGP_NODE_LABEL_CHANGED);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, NULL, afi, safi);
bgp_dest_unlock_node(dest);
return 1;
}
@@ -89,7 +208,9 @@ mpls_label_t bgp_adv_label(struct bgp_dest *dest, struct bgp_path_info *pi,
if (!dest || !pi || !to)
return MPLS_INVALID_LABEL;
- remote_label = pi->extra ? pi->extra->label[0] : MPLS_INVALID_LABEL;
+ remote_label = bgp_path_info_num_labels(pi)
+ ? pi->extra->labels->label[0]
+ : MPLS_INVALID_LABEL;
from = pi->peer;
reflect =
((from->sort == BGP_PEER_IBGP) && (to->sort == BGP_PEER_IBGP));
@@ -471,8 +592,8 @@ int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
return BGP_NLRI_PARSE_OK;
}
-bool bgp_labels_same(const mpls_label_t *tbl_a, const uint32_t num_labels_a,
- const mpls_label_t *tbl_b, const uint32_t num_labels_b)
+bool bgp_labels_same(const mpls_label_t *tbl_a, const uint8_t num_labels_a,
+ const mpls_label_t *tbl_b, const uint8_t num_labels_b)
{
uint32_t i;
diff --git a/bgpd/bgp_label.h b/bgpd/bgp_label.h
index b54403e..2ffd5b6 100644
--- a/bgpd/bgp_label.h
+++ b/bgpd/bgp_label.h
@@ -15,6 +15,26 @@ struct bgp_dest;
struct bgp_path_info;
struct peer;
+/* Maximum number of labels we can process or send with a prefix. We
+ * really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN.
+ */
+#define BGP_MAX_LABELS 2
+
+/* MPLS label(s) - VNI(s) for EVPN-VxLAN */
+struct bgp_labels {
+ mpls_label_t label[BGP_MAX_LABELS];
+ uint8_t num_labels;
+
+ unsigned long refcnt;
+};
+
+extern void bgp_labels_init(void);
+extern void bgp_labels_finish(void);
+extern struct bgp_labels *bgp_labels_intern(struct bgp_labels *labels);
+extern void bgp_labels_unintern(struct bgp_labels **plabels);
+extern bool bgp_labels_cmp(const struct bgp_labels *labels1,
+ const struct bgp_labels *labels2);
+
extern int bgp_reg_for_label_callback(mpls_label_t new_label, void *labelid,
bool allocated);
extern void bgp_reg_dereg_for_label(struct bgp_dest *dest,
@@ -27,9 +47,9 @@ extern mpls_label_t bgp_adv_label(struct bgp_dest *dest,
extern int bgp_nlri_parse_label(struct peer *peer, struct attr *attr,
struct bgp_nlri *packet);
extern bool bgp_labels_same(const mpls_label_t *tbl_a,
- const uint32_t num_labels_a,
+ const uint8_t num_labels_a,
const mpls_label_t *tbl_b,
- const uint32_t num_labels_b);
+ const uint8_t num_labels_b);
static inline int bgp_labeled_safi(safi_t safi)
{
diff --git a/bgpd/bgp_mac.c b/bgpd/bgp_mac.c
index e629732..31e84d1 100644
--- a/bgpd/bgp_mac.c
+++ b/bgpd/bgp_mac.c
@@ -14,6 +14,7 @@
#include "bgpd/bgpd.h"
#include "bgpd/bgp_mac.h"
#include "bgpd/bgp_memory.h"
+#include "bgpd/bgp_label.h"
#include "bgpd/bgp_route.h"
#include "bgpd/bgp_packet.h"
#include "bgpd/bgp_rd.h"
@@ -125,6 +126,8 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
{
struct bgp_dest *pdest, *dest;
struct bgp_path_info *pi;
+ uint8_t num_labels;
+ mpls_label_t *label_pnt;
for (pdest = bgp_table_top(table); pdest;
pdest = bgp_route_next(pdest)) {
@@ -140,8 +143,6 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
const struct prefix *p = bgp_dest_get_prefix(dest);
struct prefix_evpn *pevpn = (struct prefix_evpn *)dest;
struct prefix_rd prd;
- uint32_t num_labels = 0;
- mpls_label_t *label_pnt = NULL;
struct bgp_route_evpn *evpn;
if (pevpn->family == AF_EVPN
@@ -169,10 +170,9 @@ static void bgp_process_mac_rescan_table(struct bgp *bgp, struct peer *peer,
&& !dest_affected)
continue;
- if (pi->extra)
- num_labels = pi->extra->num_labels;
- if (num_labels)
- label_pnt = &pi->extra->label[0];
+ num_labels = bgp_path_info_num_labels(pi);
+ label_pnt = num_labels ? &pi->extra->labels->label[0]
+ : NULL;
prd.family = AF_UNSPEC;
prd.prefixlen = 64;
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index 851c488..97658d3 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -26,6 +26,7 @@
#include "bfd.h"
#include "libfrr.h"
#include "ns.h"
+#include "libagentx.h"
#include "bgpd/bgpd.h"
#include "bgpd/bgp_attr.h"
@@ -207,6 +208,8 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
bgp_evpn_mh_finish();
bgp_nhg_finish();
+ zebra_announce_fini(&bm->zebra_announce_head);
+
/* reverse bgp_dump_init */
bgp_dump_finish();
@@ -222,6 +225,9 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
/* reverse bgp_attr_init */
bgp_attr_finish();
+ /* reverse bgp_labels_init */
+ bgp_labels_finish();
+
/* stop pthreads */
bgp_pthreads_finish();
@@ -514,8 +520,10 @@ int main(int argc, char **argv)
bgp_option_set(BGP_OPT_NO_ZEBRA);
bgp_error_init();
/* Initializations. */
+ libagentx_init();
bgp_vrf_init();
+
#ifdef HAVE_SCRIPTING
bgp_script_init();
#endif
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index 0764f1e..c1804fb 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -91,6 +91,7 @@ DEFINE_MTYPE(BGPD, PEER_UPDATE_SOURCE, "BGP peer update interface");
DEFINE_MTYPE(BGPD, PEER_CONF_IF, "BGP peer config interface");
DEFINE_MTYPE(BGPD, BGP_DAMP_INFO, "Dampening info");
DEFINE_MTYPE(BGPD, BGP_DAMP_ARRAY, "BGP Dampening array");
+DEFINE_MTYPE(BGPD, BGP_DAMP_REUSELIST, "BGP Dampening reuse list");
DEFINE_MTYPE(BGPD, BGP_REGEXP, "BGP regexp");
DEFINE_MTYPE(BGPD, BGP_AGGREGATE, "BGP aggregate");
DEFINE_MTYPE(BGPD, BGP_ADDR, "BGP own address");
@@ -101,6 +102,8 @@ DEFINE_MTYPE(BGPD, BGP_FILTER_NAME, "BGP Filter Information");
DEFINE_MTYPE(BGPD, BGP_DUMP_STR, "BGP Dump String Information");
DEFINE_MTYPE(BGPD, ENCAP_TLV, "ENCAP TLV");
+DEFINE_MTYPE(BGPD, BGP_LABELS, "BGP LABELS");
+
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS, "BGP TEA Options");
DEFINE_MTYPE(BGPD, BGP_TEA_OPTIONS_VALUE, "BGP TEA Options Value");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index 29584cd..4ae49a2 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -87,6 +87,7 @@ DECLARE_MTYPE(PEER_UPDATE_SOURCE);
DECLARE_MTYPE(PEER_CONF_IF);
DECLARE_MTYPE(BGP_DAMP_INFO);
DECLARE_MTYPE(BGP_DAMP_ARRAY);
+DECLARE_MTYPE(BGP_DAMP_REUSELIST);
DECLARE_MTYPE(BGP_REGEXP);
DECLARE_MTYPE(BGP_AGGREGATE);
DECLARE_MTYPE(BGP_ADDR);
@@ -97,6 +98,8 @@ DECLARE_MTYPE(BGP_FILTER_NAME);
DECLARE_MTYPE(BGP_DUMP_STR);
DECLARE_MTYPE(ENCAP_TLV);
+DECLARE_MTYPE(BGP_LABELS);
+
DECLARE_MTYPE(BGP_TEA_OPTIONS);
DECLARE_MTYPE(BGP_TEA_OPTIONS_VALUE);
diff --git a/bgpd/bgp_mpath.c b/bgpd/bgp_mpath.c
index c773c21..e12d84b 100644
--- a/bgpd/bgp_mpath.c
+++ b/bgpd/bgp_mpath.c
@@ -129,15 +129,19 @@ int bgp_path_info_nexthop_cmp(struct bgp_path_info *bpi1,
&bpi2->attr->mp_nexthop_global);
break;
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- addr1 = (bpi1->attr->mp_nexthop_prefer_global)
+ addr1 = (CHECK_FLAG(bpi1->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
? bpi1->attr->mp_nexthop_global
: bpi1->attr->mp_nexthop_local;
- addr2 = (bpi2->attr->mp_nexthop_prefer_global)
+ addr2 = (CHECK_FLAG(bpi2->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
? bpi2->attr->mp_nexthop_global
: bpi2->attr->mp_nexthop_local;
- if (!bpi1->attr->mp_nexthop_prefer_global
- && !bpi2->attr->mp_nexthop_prefer_global)
+ if (!CHECK_FLAG(bpi1->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL) &&
+ !CHECK_FLAG(bpi2->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
compare = !bgp_interface_same(
bpi1->peer->ifp,
bpi2->peer->ifp);
@@ -517,7 +521,7 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_maxpaths_cfg *mpath_cfg)
{
uint16_t maxpaths, mpath_count, old_mpath_count;
- uint32_t bwval;
+ uint64_t bwval;
uint64_t cum_bw, old_cum_bw;
struct listnode *mp_node, *mp_next_node;
struct bgp_path_info *cur_mpath, *new_mpath, *next_mpath, *prev_mpath;
@@ -609,8 +613,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
cur_mpath);
prev_mpath = cur_mpath;
mpath_count++;
- if (ecommunity_linkbw_present(
- bgp_attr_get_ecommunity(
+ if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
+ cur_mpath->attr),
+ &bwval) ||
+ ecommunity_linkbw_present(
+ bgp_attr_get_ipv6_ecommunity(
cur_mpath->attr),
&bwval))
cum_bw += bwval;
@@ -696,8 +703,11 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
prev_mpath = new_mpath;
mpath_changed = 1;
mpath_count++;
- if (ecommunity_linkbw_present(
- bgp_attr_get_ecommunity(
+ if (ecommunity_linkbw_present(bgp_attr_get_ecommunity(
+ new_mpath->attr),
+ &bwval) ||
+ ecommunity_linkbw_present(
+ bgp_attr_get_ipv6_ecommunity(
new_mpath->attr),
&bwval))
cum_bw += bwval;
@@ -720,8 +730,12 @@ void bgp_path_info_mpath_update(struct bgp *bgp, struct bgp_dest *dest,
if (new_best) {
bgp_path_info_mpath_count_set(new_best, mpath_count - 1);
if (mpath_count <= 1 ||
- !ecommunity_linkbw_present(
- bgp_attr_get_ecommunity(new_best->attr), &bwval))
+ (!ecommunity_linkbw_present(bgp_attr_get_ecommunity(
+ new_best->attr),
+ &bwval) &&
+ !ecommunity_linkbw_present(bgp_attr_get_ipv6_ecommunity(
+ new_best->attr),
+ &bwval)))
all_paths_lb = false;
else
cum_bw += bwval;
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 58e3097..1bc1a47 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -964,50 +964,6 @@ void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
}
}
-static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label,
- uint32_t n)
-{
- if (!bpi->extra) {
- if (!n)
- return true;
- else
- return false;
- }
-
- return bgp_labels_same((const mpls_label_t *)bpi->extra->label,
- bpi->extra->num_labels,
- (const mpls_label_t *)label, n);
-}
-
-/*
- * make encoded route labels match specified encoded label set
- */
-static void setlabels(struct bgp_path_info *bpi,
- mpls_label_t *label, /* array of labels */
- uint32_t num_labels)
-{
- if (num_labels)
- assert(label);
- assert(num_labels <= BGP_MAX_LABELS);
-
- if (!num_labels) {
- if (bpi->extra)
- bpi->extra->num_labels = 0;
- return;
- }
-
- struct bgp_path_info_extra *extra = bgp_path_info_extra_get(bpi);
- uint32_t i;
-
- for (i = 0; i < num_labels; ++i) {
- extra->label[i] = label[i];
- if (!bgp_is_valid_label(&label[i])) {
- bgp_set_valid_label(&extra->label[i]);
- }
- }
- extra->num_labels = num_labels;
-}
-
static bool leak_update_nexthop_valid(struct bgp *to_bgp, struct bgp_dest *bn,
struct attr *new_attr, afi_t afi,
safi_t safi,
@@ -1086,7 +1042,7 @@ static struct bgp_path_info *
leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
struct attr *new_attr, /* already interned */
afi_t afi, safi_t safi, struct bgp_path_info *source_bpi,
- mpls_label_t *label, uint32_t num_labels, struct bgp *bgp_orig,
+ mpls_label_t *label, uint8_t num_labels, struct bgp *bgp_orig,
struct prefix *nexthop_orig, int nexthop_self_flag, int debug)
{
const struct prefix *p = bgp_dest_get_prefix(bn);
@@ -1094,6 +1050,9 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
struct bgp_path_info *new;
struct bgp_path_info_extra *extra;
struct bgp_path_info *parent = source_bpi;
+ struct bgp_labels bgp_labels = {};
+ bool labelssame;
+ uint8_t i;
if (debug)
zlog_debug(
@@ -1128,8 +1087,15 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
break;
}
+ bgp_labels.num_labels = num_labels;
+ for (i = 0; i < num_labels; i++) {
+ bgp_labels.label[i] = label[i];
+ bgp_set_valid_label(&bgp_labels.label[i]);
+ }
+
if (bpi) {
- bool labelssame = labels_same(bpi, label, num_labels);
+ labelssame = bgp_path_info_labels_same(bpi, bgp_labels.label,
+ bgp_labels.num_labels);
if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)
&& CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
@@ -1187,11 +1153,13 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
bpi->uptime = monotime(NULL);
/*
- * rewrite labels
+ * update labels
*/
- if (!labelssame)
- setlabels(bpi, label, num_labels);
-
+ if (!labelssame) {
+ bgp_path_info_extra_get(bpi);
+ bgp_labels_unintern(&bpi->extra->labels);
+ bpi->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
if (nexthop_self_flag)
bgp_path_info_set_flag(bn, bpi, BGP_PATH_ANNC_NH_SELF);
@@ -1208,7 +1176,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
/* Process change. */
bgp_aggregate_increment(to_bgp, p, bpi, afi, safi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
if (debug)
zlog_debug("%s: ->%s: %pBD Found route, changed attr",
@@ -1249,8 +1217,8 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
if (CHECK_FLAG(source_bpi->flags, BGP_PATH_ACCEPT_OWN))
bgp_path_info_set_flag(bn, new, BGP_PATH_ACCEPT_OWN);
- if (num_labels)
- setlabels(new, label, num_labels);
+ if (bgp_labels.num_labels)
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
new->extra->vrfleak->parent = bgp_path_info_lock(parent);
bgp_dest_lock_node(
@@ -1270,7 +1238,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
bgp_aggregate_increment(to_bgp, p, new, afi, safi);
bgp_path_info_add(bn, new);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, new, afi, safi);
if (debug)
zlog_debug("%s: ->%s: %pBD: Added new route", __func__,
@@ -1441,6 +1409,16 @@ _vpn_leak_from_vrf_get_per_nexthop_label(struct bgp_path_info *pi,
return blnc->label;
}
+static mpls_label_t bgp_mplsvpn_get_vpn_label(struct vpn_policy *bgp_policy)
+{
+ if (bgp_policy->tovpn_label == MPLS_LABEL_NONE &&
+ CHECK_FLAG(bgp_policy->flags, BGP_VPN_POLICY_TOVPN_LABEL_AUTO)) {
+ bgp_lp_get(LP_TYPE_VRF, bgp_policy, vpn_leak_label_callback);
+ return MPLS_INVALID_LABEL;
+ }
+ return bgp_policy->tovpn_label;
+}
+
/* Filter out all the cases where a per nexthop label is not possible:
* - return an invalid label when the nexthop is invalid
* - return the per VRF label when the per nexthop label is not supported
@@ -1469,7 +1447,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to the per VRF label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
if (is_bgp_static_route == false && afi == AFI_IP &&
@@ -1481,7 +1459,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to the per VRF label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
if (is_bgp_static_route == false && afi == AFI_IP6 &&
@@ -1495,7 +1473,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to the per VRF label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
/* Check the next-hop reachability.
@@ -1517,7 +1495,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* table. Fallback to the per-vrf label
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
if (!nh_valid || !pi->nexthop || pi->nexthop->nexthop_num == 0 ||
@@ -1540,7 +1518,7 @@ vpn_leak_from_vrf_get_per_nexthop_label(afi_t afi, struct bgp_path_info *pi,
* Fallback to per-vrf label.
*/
bgp_mplsvpn_path_nh_label_unlink(pi);
- return from_bgp->vpn_policy[afi].tovpn_label;
+ return bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
}
return _vpn_leak_from_vrf_get_per_nexthop_label(pi, to_bgp, from_bgp,
@@ -1755,12 +1733,10 @@ void vpn_leak_from_vrf_update(struct bgp *to_bgp, /* to */
label_val = vpn_leak_from_vrf_get_per_nexthop_label(
afi, path_vrf, from_bgp, to_bgp);
else
- /* per VRF label mode */
- label_val = from_bgp->vpn_policy[afi].tovpn_label;
+ label_val =
+ bgp_mplsvpn_get_vpn_label(&from_bgp->vpn_policy[afi]);
- if (label_val == MPLS_INVALID_LABEL &&
- CHECK_FLAG(from_bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_PER_NEXTHOP)) {
+ if (label_val == MPLS_INVALID_LABEL) {
/* no valid label for the moment
* when the 'bgp_mplsvpn_get_label_per_nexthop_cb' callback gets
* a valid label value, it will call the current function again.
@@ -1956,7 +1932,7 @@ void vpn_leak_from_vrf_withdraw(struct bgp *to_bgp, /* to */
bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
}
bgp_dest_unlock_node(bn);
}
@@ -1976,7 +1952,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
struct bgp_table *table;
struct bgp_dest *bn;
- struct bgp_path_info *bpi;
+ struct bgp_path_info *bpi, *next;
/* This is the per-RD table of prefixes */
table = bgp_dest_get_bgp_table_info(pdest);
@@ -1991,7 +1967,8 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
__func__, bn);
}
- for (; bpi; bpi = bpi->next) {
+ for (; (bpi != NULL) && (next = bpi->next, 1);
+ bpi = next) {
if (debug)
zlog_debug("%s: type %d, sub_type %d",
__func__, bpi->type,
@@ -2012,7 +1989,7 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *to_bgp, struct bgp *from_bgp,
to_bgp, bgp_dest_get_prefix(bn),
bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
bgp_mplsvpn_path_nh_label_unlink(
bpi->extra->vrfleak->parent);
}
@@ -2093,15 +2070,16 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
safi_t safi = SAFI_UNICAST;
const char *debugmsg;
struct prefix nexthop_orig;
- mpls_label_t *pLabels = NULL;
- uint32_t num_labels = 0;
+ mpls_label_t *label_pnt = NULL;
+ uint8_t num_labels = 0;
int nexthop_self_flag = 1;
struct bgp_path_info *bpi_ultimate = NULL;
struct bgp_path_info *bpi;
int origin_local = 0;
struct bgp *src_vrf;
- struct interface *ifp;
+ struct interface *ifp = NULL;
char rd_buf[RD_ADDRSTRLEN];
+
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
if (!vpn_leak_from_vpn_active(to_bgp, afi, &debugmsg)) {
@@ -2268,6 +2246,15 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
break;
}
+ if (!ifp && static_attr.nh_ifindex)
+ ifp = if_lookup_by_index(static_attr.nh_ifindex,
+ src_vrf->vrf_id);
+
+ if (ifp && if_is_operative(ifp))
+ SET_FLAG(static_attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
+ else
+ UNSET_FLAG(static_attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
+
/*
* route map handling
*/
@@ -2330,21 +2317,16 @@ static void vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
origin_local = 1;
}
- /* copy labels */
- if (!origin_local && path_vpn->extra
- && path_vpn->extra->num_labels) {
- num_labels = path_vpn->extra->num_labels;
- if (num_labels > BGP_MAX_LABELS)
- num_labels = BGP_MAX_LABELS;
- pLabels = path_vpn->extra->label;
- }
+ num_labels = origin_local ? 0
+ : bgp_path_info_num_labels(path_vpn);
+ label_pnt = num_labels ? path_vpn->extra->labels->label : NULL;
}
if (debug)
zlog_debug("%s: pfx %pBD: num_labels %d", __func__,
path_vpn->net, num_labels);
- if (!leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, pLabels,
+ if (!leak_update(to_bgp, bn, new_attr, afi, safi, path_vpn, label_pnt,
num_labels, src_vrf, &nexthop_orig, nexthop_self_flag,
debug))
bgp_dest_unlock_node(bn);
@@ -2497,7 +2479,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
bpi);
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
}
bgp_dest_unlock_node(bn);
}
@@ -2506,7 +2488,7 @@ void vpn_leak_to_vrf_withdraw(struct bgp_path_info *path_vpn)
void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
{
struct bgp_dest *bn;
- struct bgp_path_info *bpi;
+ struct bgp_path_info *bpi, *next;
safi_t safi = SAFI_UNICAST;
int debug = BGP_DEBUG(vpn, VPN_LEAK_TO_VRF);
@@ -2517,9 +2499,8 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
*/
for (bn = bgp_table_top(to_bgp->rib[afi][safi]); bn;
bn = bgp_route_next(bn)) {
-
- for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
- bpi = bpi->next) {
+ for (bpi = bgp_dest_get_bgp_path_info(bn);
+ (bpi != NULL) && (next = bpi->next, 1); bpi = next) {
if (bpi->extra && bpi->extra->vrfleak &&
bpi->extra->vrfleak->bgp_orig != to_bgp &&
bpi->extra->vrfleak->parent &&
@@ -2529,7 +2510,7 @@ void vpn_leak_to_vrf_withdraw_all(struct bgp *to_bgp, afi_t afi)
bgp_dest_get_prefix(bn),
bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(to_bgp, bn, afi, safi);
+ bgp_process(to_bgp, bn, bpi, afi, safi);
}
}
}
@@ -2558,8 +2539,11 @@ void vpn_leak_no_retain(struct bgp *to_bgp, struct bgp *vpn_from, afi_t afi)
continue;
for (bn = bgp_table_top(table); bn; bn = bgp_route_next(bn)) {
- for (bpi = bgp_dest_get_bgp_path_info(bn); bpi;
- bpi = bpi->next) {
+ struct bgp_path_info *next;
+
+ for (bpi = bgp_dest_get_bgp_path_info(bn);
+ (bpi != NULL) && (next = bpi->next, 1);
+ bpi = next) {
if (bpi->extra && bpi->extra->vrfleak &&
bpi->extra->vrfleak->bgp_orig == to_bgp)
continue;
@@ -3746,6 +3730,9 @@ void vpn_leak_postchange_all(void)
if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
continue;
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
vpn_leak_postchange(
BGP_VPN_POLICY_DIR_TOVPN,
AFI_IP,
@@ -3765,6 +3752,9 @@ void vpn_leak_postchange_all(void)
if (bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
continue;
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
vpn_leak_postchange(
BGP_VPN_POLICY_DIR_FROMVPN,
AFI_IP,
@@ -3974,7 +3964,7 @@ static void bgp_mplsvpn_nh_label_bind_send_nexthop_label(
struct bgp_mplsvpn_nh_label_bind_cache *bmnc, int cmd)
{
struct prefix pfx_nh, *p = NULL;
- uint32_t num_labels = 0, lsp_num_labels;
+ uint8_t num_labels = 0, lsp_num_labels;
mpls_label_t label[MPLS_MAX_LABELS];
struct nexthop *nh;
ifindex_t ifindex = IFINDEX_INTERNAL;
@@ -4109,7 +4099,7 @@ bool bgp_mplsvpn_path_uses_valid_mpls_label(struct bgp_path_info *pi)
/* prefix_sid attribute */
return false;
- if (!pi->extra || !bgp_is_valid_label(&pi->extra->label[0]))
+ if (!bgp_path_info_has_valid_label(pi))
/* invalid MPLS label */
return false;
return true;
@@ -4180,7 +4170,7 @@ static int bgp_mplsvpn_nh_label_bind_get_local_label_cb(mpls_label_t label,
if (!table)
continue;
SET_FLAG(pi->net->flags, BGP_NODE_LABEL_CHANGED);
- bgp_process(table->bgp, pi->net, table->afi, table->safi);
+ bgp_process(table->bgp, pi->net, pi, table->afi, table->safi);
}
return 0;
@@ -4216,14 +4206,17 @@ void bgp_mplsvpn_nh_label_bind_register_local_label(struct bgp *bgp,
{
struct bgp_mplsvpn_nh_label_bind_cache *bmnc;
struct bgp_mplsvpn_nh_label_bind_cache_head *tree;
+ mpls_label_t label;
+
+ label = bgp_path_info_num_labels(pi)
+ ? decode_label(&pi->extra->labels->label[0])
+ : MPLS_INVALID_LABEL;
tree = &bgp->mplsvpn_nh_label_bind;
- bmnc = bgp_mplsvpn_nh_label_bind_find(
- tree, &pi->nexthop->prefix, decode_label(&pi->extra->label[0]));
+ bmnc = bgp_mplsvpn_nh_label_bind_find(tree, &pi->nexthop->prefix, label);
if (!bmnc) {
- bmnc = bgp_mplsvpn_nh_label_bind_new(
- tree, &pi->nexthop->prefix,
- decode_label(&pi->extra->label[0]));
+ bmnc = bgp_mplsvpn_nh_label_bind_new(tree, &pi->nexthop->prefix,
+ label);
bmnc->bgp_vpn = bgp;
bmnc->allocation_in_progress = true;
bgp_lp_get(LP_TYPE_BGP_L3VPN_BIND, bmnc,
diff --git a/bgpd/bgp_mplsvpn.h b/bgpd/bgp_mplsvpn.h
index cd25899..92a9fba 100644
--- a/bgpd/bgp_mplsvpn.h
+++ b/bgpd/bgp_mplsvpn.h
@@ -170,16 +170,6 @@ static inline int vpn_leak_to_vpn_active(struct bgp *bgp_vrf, afi_t afi,
return 0;
}
- /* Is there an "auto" export label that isn't allocated yet? */
- if (CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
- (bgp_vrf->vpn_policy[afi].tovpn_label == MPLS_LABEL_NONE)) {
-
- if (pmsg)
- *pmsg = "auto label not allocated";
- return 0;
- }
-
/* Is there a "manual" export label that isn't allocated yet? */
if (!CHECK_FLAG(bgp_vrf->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO) &&
diff --git a/bgpd/bgp_network.c b/bgpd/bgp_network.c
index dbb34b0..e09dbc2 100644
--- a/bgpd/bgp_network.c
+++ b/bgpd/bgp_network.c
@@ -817,9 +817,9 @@ int bgp_connect(struct peer_connection *connection)
#ifdef IPTOS_PREC_INTERNETCONTROL
frr_with_privs(&bgpd_privs) {
if (sockunion_family(&connection->su) == AF_INET)
- setsockopt_ipv4_tos(connection->fd, bm->tcp_dscp);
+ setsockopt_ipv4_tos(connection->fd, bm->ip_tos);
else if (sockunion_family(&connection->su) == AF_INET6)
- setsockopt_ipv6_tclass(connection->fd, bm->tcp_dscp);
+ setsockopt_ipv6_tclass(connection->fd, bm->ip_tos);
}
#endif
@@ -875,11 +875,7 @@ int bgp_getsockname(struct peer *peer)
}
peer->su_local = sockunion_getsockname(peer->connection->fd);
- if (!peer->su_local)
- return -1;
peer->su_remote = sockunion_getpeername(peer->connection->fd);
- if (!peer->su_remote)
- return -1;
if (!bgp_zebra_nexthop_set(peer->su_local, peer->su_remote,
&peer->nexthop, peer)) {
@@ -909,9 +905,9 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
#ifdef IPTOS_PREC_INTERNETCONTROL
if (sa->sa_family == AF_INET)
- setsockopt_ipv4_tos(sock, bm->tcp_dscp);
+ setsockopt_ipv4_tos(sock, bm->ip_tos);
else if (sa->sa_family == AF_INET6)
- setsockopt_ipv6_tclass(sock, bm->tcp_dscp);
+ setsockopt_ipv6_tclass(sock, bm->ip_tos);
#endif
sockopt_v6only(sa->sa_family, sock);
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index d12dc22..98eb956 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -1003,6 +1003,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
if (bnc->is_evpn_gwip_nexthop)
json_object_boolean_true_add(json_nexthop,
"isEvpnGatewayIp");
+ json_object_string_addf(json, "resolvedPrefix", "%pFX",
+ &bnc->resolved_prefix);
} else {
vty_out(vty, " %s valid [IGP metric %d], #paths %d",
buf, bnc->metric, bnc->path_count);
@@ -1010,6 +1012,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
vty_out(vty, ", peer %s", peer->host);
if (bnc->is_evpn_gwip_nexthop)
vty_out(vty, " EVPN Gateway IP");
+ vty_out(vty, "\n Resolved prefix %pFX",
+ &bnc->resolved_prefix);
vty_out(vty, "\n");
}
bgp_show_nexthops_detail(vty, bgp, bnc, json_nexthop);
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 8308838..430c8f1 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -90,6 +90,7 @@ struct bgp_nexthop_cache {
struct bgp_nexthop_cache_head *tree;
struct prefix prefix;
+ struct prefix resolved_prefix;
void *nht_info; /* In BGP, peer session */
LIST_HEAD(path_list, bgp_path_info) paths;
unsigned int path_count;
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index e2c103b..8ce4555 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -116,24 +116,36 @@ static int bgp_isvalid_nexthop_for_mplsovergre(struct bgp_nexthop_cache *bnc,
static int bgp_isvalid_nexthop_for_mpls(struct bgp_nexthop_cache *bnc,
struct bgp_path_info *path)
{
+ return (bnc && (bnc->nexthop_num > 0 &&
+ (CHECK_FLAG(path->flags, BGP_PATH_ACCEPT_OWN) ||
+ CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
+ bgp_isvalid_nexthop_for_ebgp(bnc, path) ||
+ bgp_isvalid_nexthop_for_mplsovergre(bnc, path))));
+}
+
+static bool bgp_isvalid_nexthop_for_l3vpn(struct bgp_nexthop_cache *bnc,
+ struct bgp_path_info *path)
+{
+ if (bgp_zebra_num_connects() == 0)
+ return 1;
+
+ if (path->attr->srv6_l3vpn || path->attr->srv6_vpn) {
+ /* In the case of SRv6-VPN, we need to track the reachability to the
+ * SID (in other words, IPv6 address). We check that the SID is
+ * available in the BGP update; then if it is available, we check
+ * for the nexthop reachability.
+ */
+ if (bnc && (bnc->nexthop_num > 0 && bgp_isvalid_nexthop(bnc)))
+ return 1;
+ return 0;
+ }
/*
- * - In the case of MPLS-VPN, the label is learned from LDP or other
+ * In the case of MPLS-VPN, the label is learned from LDP or other
* protocols, and nexthop tracking is enabled for the label.
* The value is recorded as BGP_NEXTHOP_LABELED_VALID.
- * - In the case of SRv6-VPN, we need to track the reachability to the
- * SID (in other words, IPv6 address). As in MPLS, we need to record
- * the value as BGP_NEXTHOP_SID_VALID. However, this function is
- * currently not implemented, and this function assumes that all
- * Transit routes for SRv6-VPN are valid.
* - Otherwise check for mpls-gre acceptance
*/
- return (bgp_zebra_num_connects() == 0 ||
- (bnc && (bnc->nexthop_num > 0 &&
- (CHECK_FLAG(path->flags, BGP_PATH_ACCEPT_OWN) ||
- CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
- bnc->bgp->srv6_enabled ||
- bgp_isvalid_nexthop_for_ebgp(bnc, path) ||
- bgp_isvalid_nexthop_for_mplsovergre(bnc, path)))));
+ return bgp_isvalid_nexthop_for_mpls(bnc, path);
}
static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
@@ -308,11 +320,6 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
afi = BGP_ATTR_MP_NEXTHOP_LEN_IP6(pi->attr) ? AFI_IP6
: AFI_IP;
- /* Validation for the ipv4 mapped ipv6 nexthop. */
- if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
- afi = AFI_IP;
- }
-
/* This will return true if the global IPv6 NH is a link local
* addr */
if (make_prefix(afi, pi, &p) < 0)
@@ -345,9 +352,7 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
return 0;
}
- if (CHECK_FLAG(pi->attr->flag,
- ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- srte_color = bgp_attr_get_color(pi->attr);
+ srte_color = bgp_attr_get_color(pi->attr);
} else if (peer) {
/*
@@ -494,9 +499,9 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
return 1;
else if (safi == SAFI_UNICAST && pi &&
- pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra &&
- pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop)
- return bgp_isvalid_nexthop_for_mpls(bnc, pi);
+ pi->sub_type == BGP_ROUTE_IMPORTED &&
+ bgp_path_info_num_labels(pi) && !bnc->is_evpn_gwip_nexthop)
+ return bgp_isvalid_nexthop_for_l3vpn(bnc, pi);
else if (safi == SAFI_MPLS_VPN && pi &&
pi->sub_type != BGP_ROUTE_IMPORTED)
/* avoid not redistributing mpls vpn routes */
@@ -614,6 +619,8 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
} else if (nhr->nexthop_num) {
struct peer *peer = bnc->nht_info;
+ prefix_copy(&bnc->resolved_prefix, &nhr->prefix);
+
/* notify bgp fsm if nbr ip goes from invalid->valid */
if (!bnc->nexthop_num)
UNSET_FLAG(bnc->flags, BGP_NEXTHOP_PEER_NOTIFIED);
@@ -719,6 +726,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
}
}
} else {
+ memset(&bnc->resolved_prefix, 0, sizeof(bnc->resolved_prefix));
bnc->flags &= ~BGP_NEXTHOP_EVPN_INCOMPLETE;
bnc->flags &= ~BGP_NEXTHOP_VALID;
bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID;
@@ -964,14 +972,13 @@ void bgp_nexthop_update(struct vrf *vrf, struct prefix *match,
* which should provide a better infrastructure to solve this issue in
* a more efficient and elegant way.
*/
- if (nhr->srte_color == 0 && bnc_nhc) {
+ if (nhr->srte_color == 0) {
struct bgp_nexthop_cache *bnc_iter;
frr_each (bgp_nexthop_cache, &bgp->nexthop_cache_table[afi],
bnc_iter) {
- if (!prefix_same(&bnc_nhc->prefix, &bnc_iter->prefix) ||
- bnc_iter->srte_color == 0 ||
- CHECK_FLAG(bnc_iter->flags, BGP_NEXTHOP_VALID))
+ if (!prefix_same(match, &bnc_iter->prefix) ||
+ bnc_iter->srte_color == 0)
continue;
bgp_process_nexthop_update(bnc_iter, nhr, false);
@@ -1028,52 +1035,57 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
p->u.prefix4 = p_orig->u.prefix4;
p->prefixlen = p_orig->prefixlen;
} else {
- if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
- ipv4_mapped_ipv6_to_ipv4(
- &pi->attr->mp_nexthop_global, &ipv4);
- p->u.prefix4 = ipv4;
- p->prefixlen = IPV4_MAX_BITLEN;
- } else {
- if (p_orig->family == AF_EVPN)
- p->u.prefix4 =
- pi->attr->mp_nexthop_global_in;
- else
- p->u.prefix4 = pi->attr->nexthop;
- p->prefixlen = IPV4_MAX_BITLEN;
- }
+ if (p_orig->family == AF_EVPN)
+ p->u.prefix4 = pi->attr->mp_nexthop_global_in;
+ else
+ p->u.prefix4 = pi->attr->nexthop;
+ p->prefixlen = IPV4_MAX_BITLEN;
}
break;
case AFI_IP6:
p->family = AF_INET6;
-
- if (is_bgp_static) {
+ if (pi->attr->srv6_l3vpn) {
+ IPV6_ADDR_COPY(&(p->u.prefix6),
+ &(pi->attr->srv6_l3vpn->sid));
+ p->prefixlen = IPV6_MAX_BITLEN;
+ } else if (is_bgp_static) {
p->u.prefix6 = p_orig->u.prefix6;
p->prefixlen = p_orig->prefixlen;
} else {
/* If we receive MP_REACH nexthop with ::(LL)
* or LL(LL), use LL address as nexthop cache.
*/
- if (pi->attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL
- && (IN6_IS_ADDR_UNSPECIFIED(
- &pi->attr->mp_nexthop_global)
- || IN6_IS_ADDR_LINKLOCAL(
- &pi->attr->mp_nexthop_global)))
+ p->prefixlen = IPV6_MAX_BITLEN;
+ if (pi->attr &&
+ pi->attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL &&
+ (IN6_IS_ADDR_UNSPECIFIED(
+ &pi->attr->mp_nexthop_global) ||
+ IN6_IS_ADDR_LINKLOCAL(&pi->attr->mp_nexthop_global)))
p->u.prefix6 = pi->attr->mp_nexthop_local;
/* If we receive MR_REACH with (GA)::(LL)
* then check for route-map to choose GA or LL
*/
- else if (pi->attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
- if (pi->attr->mp_nexthop_prefer_global)
- p->u.prefix6 =
- pi->attr->mp_nexthop_global;
- else
+ else if (pi->attr &&
+ pi->attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) {
+ if (CHECK_FLAG(pi->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)) {
+ if (IS_MAPPED_IPV6(
+ &pi->attr->mp_nexthop_global)) {
+ ipv4_mapped_ipv6_to_ipv4(
+ &pi->attr->mp_nexthop_global,
+ &ipv4);
+ p->u.prefix4 = ipv4;
+ p->prefixlen = IPV4_MAX_BITLEN;
+ } else
+ p->u.prefix6 =
+ pi->attr->mp_nexthop_global;
+ } else
p->u.prefix6 =
pi->attr->mp_nexthop_local;
} else
p->u.prefix6 = pi->attr->mp_nexthop_global;
- p->prefixlen = IPV6_MAX_BITLEN;
}
break;
default:
@@ -1289,13 +1301,14 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
bool bnc_is_valid_nexthop = false;
bool path_valid = false;
- if (safi == SAFI_UNICAST && path->sub_type == BGP_ROUTE_IMPORTED
- && path->extra && path->extra->num_labels
- && (path->attr->evpn_overlay.type
- != OVERLAY_INDEX_GATEWAY_IP)) {
+ if (safi == SAFI_UNICAST &&
+ path->sub_type == BGP_ROUTE_IMPORTED &&
+ bgp_path_info_num_labels(path) &&
+ (path->attr->evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP)) {
bnc_is_valid_nexthop =
- bgp_isvalid_nexthop_for_mpls(bnc, path) ? true
- : false;
+ bgp_isvalid_nexthop_for_l3vpn(bnc, path)
+ ? true
+ : false;
} else if (safi == SAFI_MPLS_VPN &&
path->sub_type != BGP_ROUTE_IMPORTED) {
/* avoid not redistributing mpls vpn routes */
@@ -1414,7 +1427,7 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
}
}
- bgp_process(bgp_path, dest, afi, safi);
+ bgp_process(bgp_path, dest, path, afi, safi);
}
if (peer) {
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 6c96ffc..248d478 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -42,25 +42,27 @@ const struct message capcode_str[] = {
{ CAPABILITY_CODE_LLGR, "Long-lived BGP Graceful Restart" },
{ CAPABILITY_CODE_ROLE, "Role" },
{ CAPABILITY_CODE_SOFT_VERSION, "Software Version" },
+ { CAPABILITY_CODE_PATHS_LIMIT, "Paths-Limit" },
{ 0 }
};
/* Minimum sizes for length field of each cap (so not inc. the header) */
-static const size_t cap_minsizes[] = {
- [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
- [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
- [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
- [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
- [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
- [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
- [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
- [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_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,
- [CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
- [CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN,
- [CAPABILITY_CODE_SOFT_VERSION] = CAPABILITY_CODE_SOFT_VERSION_LEN,
+const size_t cap_minsizes[] = {
+ [CAPABILITY_CODE_MP] = CAPABILITY_CODE_MP_LEN,
+ [CAPABILITY_CODE_REFRESH] = CAPABILITY_CODE_REFRESH_LEN,
+ [CAPABILITY_CODE_ORF] = CAPABILITY_CODE_ORF_LEN,
+ [CAPABILITY_CODE_RESTART] = CAPABILITY_CODE_RESTART_LEN,
+ [CAPABILITY_CODE_AS4] = CAPABILITY_CODE_AS4_LEN,
+ [CAPABILITY_CODE_ADDPATH] = CAPABILITY_CODE_ADDPATH_LEN,
+ [CAPABILITY_CODE_DYNAMIC] = CAPABILITY_CODE_DYNAMIC_LEN,
+ [CAPABILITY_CODE_ENHE] = CAPABILITY_CODE_ENHE_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,
+ [CAPABILITY_CODE_LLGR] = CAPABILITY_CODE_LLGR_LEN,
+ [CAPABILITY_CODE_ROLE] = CAPABILITY_CODE_ROLE_LEN,
+ [CAPABILITY_CODE_SOFT_VERSION] = CAPABILITY_CODE_SOFT_VERSION_LEN,
+ [CAPABILITY_CODE_PATHS_LIMIT] = CAPABILITY_CODE_PATHS_LIMIT_LEN,
};
/* value the capability must be a multiple of.
@@ -68,21 +70,22 @@ static const size_t cap_minsizes[] = {
* Other capabilities whose data doesn't fall on convenient boundaries for this
* table should be set to 1.
*/
-static const size_t cap_modsizes[] = {
- [CAPABILITY_CODE_MP] = 4,
- [CAPABILITY_CODE_REFRESH] = 1,
- [CAPABILITY_CODE_ORF] = 1,
- [CAPABILITY_CODE_RESTART] = 1,
- [CAPABILITY_CODE_AS4] = 4,
- [CAPABILITY_CODE_ADDPATH] = 4,
- [CAPABILITY_CODE_DYNAMIC] = 1,
- [CAPABILITY_CODE_ENHE] = 6,
- [CAPABILITY_CODE_FQDN] = 1,
- [CAPABILITY_CODE_ENHANCED_RR] = 1,
- [CAPABILITY_CODE_EXT_MESSAGE] = 1,
- [CAPABILITY_CODE_LLGR] = 1,
- [CAPABILITY_CODE_ROLE] = 1,
- [CAPABILITY_CODE_SOFT_VERSION] = 1,
+const size_t cap_modsizes[] = {
+ [CAPABILITY_CODE_MP] = 4,
+ [CAPABILITY_CODE_REFRESH] = 1,
+ [CAPABILITY_CODE_ORF] = 1,
+ [CAPABILITY_CODE_RESTART] = 1,
+ [CAPABILITY_CODE_AS4] = 4,
+ [CAPABILITY_CODE_ADDPATH] = 4,
+ [CAPABILITY_CODE_DYNAMIC] = 1,
+ [CAPABILITY_CODE_ENHE] = 6,
+ [CAPABILITY_CODE_FQDN] = 1,
+ [CAPABILITY_CODE_ENHANCED_RR] = 1,
+ [CAPABILITY_CODE_EXT_MESSAGE] = 1,
+ [CAPABILITY_CODE_LLGR] = 1,
+ [CAPABILITY_CODE_ROLE] = 1,
+ [CAPABILITY_CODE_SOFT_VERSION] = 1,
+ [CAPABILITY_CODE_PATHS_LIMIT] = 5,
};
/* BGP-4 Multiprotocol Extentions lead us to the complex world. We can
@@ -739,6 +742,62 @@ static int bgp_capability_addpath(struct peer *peer,
return 0;
}
+static int bgp_capability_paths_limit(struct peer *peer,
+ struct capability_header *hdr)
+{
+ struct stream *s = BGP_INPUT(peer);
+ size_t end = stream_get_getp(s) + hdr->length;
+
+ if (hdr->length % CAPABILITY_CODE_PATHS_LIMIT_LEN) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "Paths-Limit: Received invalid length %d, non-multiple of %d",
+ hdr->length, CAPABILITY_CODE_PATHS_LIMIT_LEN);
+ return -1;
+ }
+
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV)) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_DATA,
+ "Paths-Limit: Received Paths-Limit capability without Add-Path capability");
+ return -1;
+ }
+
+ SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_RCV);
+
+ while (stream_get_getp(s) + CAPABILITY_CODE_PATHS_LIMIT_LEN <= end) {
+ afi_t afi;
+ safi_t safi;
+ iana_afi_t pkt_afi = stream_getw(s);
+ iana_safi_t pkt_safi = stream_getc(s);
+ uint16_t paths_limit = stream_getw(s);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s limit: %u",
+ peer->host,
+ lookup_msg(capcode_str, hdr->code, NULL),
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi), paths_limit);
+
+ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi, &safi)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not supported. Ignore the Paths-Limit capability for this AFI/SAFI",
+ peer->host, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ continue;
+ } else if (!peer->afc[afi][safi]) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Paths-Limit capability for this AFI/SAFI",
+ peer->host, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ continue;
+ }
+
+ SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_PATHS_LIMIT_AF_RCV);
+ peer->addpath_paths_limit[afi][safi].receive = paths_limit;
+ }
+
+ return 0;
+}
+
static int bgp_capability_enhe(struct peer *peer, struct capability_header *hdr)
{
struct stream *s = BGP_INPUT(peer);
@@ -1012,6 +1071,7 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
case CAPABILITY_CODE_EXT_MESSAGE:
case CAPABILITY_CODE_ROLE:
case CAPABILITY_CODE_SOFT_VERSION:
+ case CAPABILITY_CODE_PATHS_LIMIT:
/* Check length. */
if (caphdr.length < cap_minsizes[caphdr.code]) {
zlog_info(
@@ -1113,6 +1173,9 @@ static int bgp_capability_parse(struct peer *peer, size_t length,
case CAPABILITY_CODE_SOFT_VERSION:
ret = bgp_capability_software_version(peer, &caphdr);
break;
+ case CAPABILITY_CODE_PATHS_LIMIT:
+ ret = bgp_capability_paths_limit(peer, &caphdr);
+ break;
default:
if (caphdr.code > 128) {
/* We don't send Notification for unknown vendor
@@ -1389,8 +1452,10 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
/* All OPEN option is parsed. Check capability when strict compare
flag is enabled.*/
if (CHECK_FLAG(peer->flags, PEER_FLAG_STRICT_CAP_MATCH)) {
- /* If Unsupported Capability exists. */
- if (error != error_data) {
+ /* If Unsupported Capability exists or local capability does
+ * not negotiated with remote peer
+ */
+ if (error != error_data || !strict_capability_same(peer)) {
bgp_notify_send_with_data(peer->connection,
BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_UNSUP_CAPBL,
@@ -1398,14 +1463,6 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
error - error_data);
return -1;
}
-
- /* Check local capability does not negotiated with remote
- peer. */
- if (!strict_capability_same(peer)) {
- bgp_notify_send(peer->connection, BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNSUP_CAPBL);
- return -1;
- }
}
/* Extended Message Support */
@@ -1440,17 +1497,11 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
"%s [Error] Configured AFI/SAFIs do not overlap with received MP capabilities",
peer->host);
- if (error != error_data)
- bgp_notify_send_with_data(peer->connection,
- BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNSUP_CAPBL,
- error_data,
- error - error_data);
- else
- bgp_notify_send(peer->connection,
- BGP_NOTIFY_OPEN_ERR,
- BGP_NOTIFY_OPEN_UNSUP_CAPBL);
- return -1;
+ bgp_notify_send_with_data(peer->connection,
+ BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_UNSUP_CAPBL,
+ error_data,
+ error - error_data);
}
}
return 0;
@@ -1874,6 +1925,31 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
}
}
+ /* Paths-Limit capability */
+ SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_ADV);
+ stream_putc(s, BGP_OPEN_OPT_CAP);
+ ext_opt_params ? stream_putw(s, (CAPABILITY_CODE_PATHS_LIMIT_LEN *
+ afi_safi_count) +
+ 2)
+ : stream_putc(s, (CAPABILITY_CODE_PATHS_LIMIT_LEN *
+ afi_safi_count) +
+ 2);
+ stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT);
+ stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT_LEN * afi_safi_count);
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
+
+ stream_putw(s, pkt_afi);
+ stream_putc(s, pkt_safi);
+ stream_putw(s, peer->addpath_paths_limit[afi][safi].send);
+
+ SET_FLAG(peer->af_cap[afi][safi], PEER_CAP_PATHS_LIMIT_AF_ADV);
+ }
+
/* ORF capability. */
FOREACH_AFI_SAFI (afi, safi) {
if (CHECK_FLAG(peer->af_flags[afi][safi],
@@ -1887,7 +1963,7 @@ uint16_t bgp_open_capability(struct stream *s, struct peer *peer,
}
/* Dynamic capability. */
- if (CHECK_FLAG(peer->flags, PEER_FLAG_DYNAMIC_CAPABILITY)) {
+ if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY)) {
SET_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV);
stream_putc(s, BGP_OPEN_OPT_CAP);
ext_opt_params
diff --git a/bgpd/bgp_open.h b/bgpd/bgp_open.h
index 34f4b76..3a8cba9 100644
--- a/bgpd/bgp_open.h
+++ b/bgpd/bgp_open.h
@@ -53,6 +53,7 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_ENHE 5 /* Extended Next Hop Encoding */
#define CAPABILITY_CODE_EXT_MESSAGE 6 /* Extended Message Support */
#define CAPABILITY_CODE_ROLE 9 /* Role Capability */
+#define CAPABILITY_CODE_PATHS_LIMIT 76 /* Paths Limit Capability */
/* Capability Length */
#define CAPABILITY_CODE_MP_LEN 4
@@ -61,6 +62,7 @@ struct graceful_restart_af {
#define CAPABILITY_CODE_RESTART_LEN 2 /* Receiving only case */
#define CAPABILITY_CODE_AS4_LEN 4
#define CAPABILITY_CODE_ADDPATH_LEN 4
+#define CAPABILITY_CODE_PATHS_LIMIT_LEN 5
#define CAPABILITY_CODE_ENHE_LEN 6 /* NRLI AFI = 2, SAFI = 2, Nexthop AFI = 2 */
#define CAPABILITY_CODE_MIN_FQDN_LEN 2
#define CAPABILITY_CODE_ENHANCED_LEN 0
@@ -110,5 +112,7 @@ extern as_t peek_for_as4_capability(struct peer *peer, uint16_t length);
extern const struct message capcode_str[];
extern const struct message orf_type_str[];
extern const struct message orf_mode_str[];
+extern const size_t cap_minsizes[];
+extern const size_t cap_modsizes[];
#endif /* _QUAGGA_BGP_OPEN_H */
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 1f808ee..010a31a 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -148,7 +148,8 @@ static void bgp_packet_add(struct peer_connection *connection,
EC_BGP_SENDQ_STUCK_PROPER,
"%pBP has not made any SendQ progress for 2 holdtimes (%jds), terminating session",
peer, sendholdtime);
- BGP_EVENT_ADD(connection, TCP_fatal_error);
+ bgp_stop_with_notify(connection,
+ BGP_NOTIFY_SEND_HOLD_ERR, 0);
} else if (delta > (intmax_t)holdtime &&
monotime(NULL) - peer->last_sendq_warn > 5) {
flog_warn(
@@ -559,40 +560,37 @@ void bgp_generate_updgrp_packets(struct event *thread)
}
}
- if (CHECK_FLAG(peer->cap,
- PEER_CAP_RESTART_RCV)) {
- if (!(PAF_SUBGRP(paf))->t_coalesce
- && peer->afc_nego[afi][safi]
- && peer->synctime
- && !CHECK_FLAG(
- peer->af_sflags[afi][safi],
- PEER_STATUS_EOR_SEND)) {
- /* If EOR is disabled,
- * the message is not sent
- */
- if (BGP_SEND_EOR(peer->bgp, afi,
- safi)) {
- SET_FLAG(
- peer->af_sflags
- [afi]
- [safi],
- PEER_STATUS_EOR_SEND);
-
- /* Update EOR
- * send time
- */
- peer->eor_stime[afi]
- [safi] =
- monotime(NULL);
-
- BGP_UPDATE_EOR_PKT(
- peer, afi, safi,
- s);
- bgp_process_pending_refresh(
- peer, afi,
- safi);
- }
- }
+ /* rfc4724 says:
+ * Although the End-of-RIB marker is
+ * specified for the purpose of BGP
+ * graceful restart, it is noted that
+ * the generation of such a marker upon
+ * completion of the initial update would
+ * be useful for routing convergence in
+ * general, and thus the practice is
+ * recommended.
+ */
+ if (!(PAF_SUBGRP(paf))->t_coalesce &&
+ peer->afc_nego[afi][safi] &&
+ peer->synctime &&
+ !CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_SEND)) {
+ /* If EOR is disabled, the message is
+ * not sent.
+ */
+ if (!BGP_SEND_EOR(peer->bgp, afi, safi))
+ continue;
+
+ SET_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_EOR_SEND);
+
+ /* Update EOR send time */
+ peer->eor_stime[afi][safi] =
+ monotime(NULL);
+
+ BGP_UPDATE_EOR_PKT(peer, afi, safi, s);
+ bgp_process_pending_refresh(peer, afi,
+ safi);
}
continue;
}
@@ -1224,7 +1222,7 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
if (!peer_established(peer->connection))
return;
- if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) &&
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV) ||
!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV))
return;
@@ -1459,6 +1457,49 @@ void bgp_capability_send(struct peer *peer, afi_t afi, safi_t safi,
COND_FLAG(peer->cap, PEER_CAP_ADDPATH_ADV,
action == CAPABILITY_ACTION_SET);
break;
+ case CAPABILITY_CODE_PATHS_LIMIT:
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ addpath_afi_safi_count++;
+ }
+
+ stream_putc(s, action);
+ stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT);
+ stream_putc(s, CAPABILITY_CODE_PATHS_LIMIT_LEN *
+ addpath_afi_safi_count);
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (!peer->afc[afi][safi])
+ continue;
+
+ bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi,
+ &pkt_safi);
+
+ stream_putw(s, pkt_afi);
+ stream_putc(s, pkt_safi);
+ stream_putw(s,
+ peer->addpath_paths_limit[afi][safi].send);
+
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%pBP sending CAPABILITY has %s %s for afi/safi: %s/%s, limit: %u",
+ peer,
+ action == CAPABILITY_ACTION_SET
+ ? "Advertising"
+ : "Removing",
+ capability, iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi),
+ peer->addpath_paths_limit[afi][safi]
+ .send);
+ }
+
+ COND_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_ADV,
+ action == CAPABILITY_ACTION_SET);
+ break;
case CAPABILITY_CODE_ORF:
/* Convert AFI, SAFI to values for packet. */
bgp_map_afi_safi_int2iana(afi, safi, &pkt_afi, &pkt_safi);
@@ -3165,6 +3206,86 @@ ignore:
}
}
+static void bgp_dynamic_capability_paths_limit(uint8_t *pnt, int action,
+ struct capability_header *hdr,
+ struct peer *peer)
+{
+ uint8_t *data = pnt + 3;
+ uint8_t *end = data + hdr->length;
+ size_t len = end - data;
+ afi_t afi;
+ safi_t safi;
+
+ if (action == CAPABILITY_ACTION_SET) {
+ if (len % CAPABILITY_CODE_PATHS_LIMIT_LEN) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_LENGTH,
+ "Paths-Limit: Received invalid length %zu, non-multiple of %d",
+ len, CAPABILITY_CODE_PATHS_LIMIT_LEN);
+ return;
+ }
+
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_ADDPATH_RCV)) {
+ flog_warn(EC_BGP_CAPABILITY_INVALID_DATA,
+ "Paths-Limit: Received Paths-Limit capability without Add-Path capability");
+ goto ignore;
+ }
+
+ SET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_RCV);
+
+ while (data + CAPABILITY_CODE_PATHS_LIMIT_LEN <= end) {
+ afi_t afi;
+ safi_t safi;
+ iana_afi_t pkt_afi;
+ iana_safi_t pkt_safi;
+ uint16_t paths_limit = 0;
+ struct bgp_paths_limit_capability bpl = {};
+
+ memcpy(&bpl, data, sizeof(bpl));
+ pkt_afi = ntohs(bpl.afi);
+ pkt_safi = safi_int2iana(bpl.safi);
+ paths_limit = ntohs(bpl.paths_limit);
+
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s OPEN has %s capability for afi/safi: %s/%s limit: %u",
+ peer->host,
+ lookup_msg(capcode_str, hdr->code,
+ NULL),
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi), paths_limit);
+
+ if (bgp_map_afi_safi_iana2int(pkt_afi, pkt_safi, &afi,
+ &safi)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not supported. Ignore the Paths-Limit capability for this AFI/SAFI",
+ peer->host,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ goto ignore;
+ } else if (!peer->afc[afi][safi]) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s Addr-family %s/%s(afi/safi) not enabled. Ignore the Paths-Limit capability for this AFI/SAFI",
+ peer->host,
+ iana_afi2str(pkt_afi),
+ iana_safi2str(pkt_safi));
+ goto ignore;
+ }
+
+ SET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV);
+ peer->addpath_paths_limit[afi][safi].receive =
+ paths_limit;
+ignore:
+ data += CAPABILITY_CODE_PATHS_LIMIT_LEN;
+ }
+ } else {
+ FOREACH_AFI_SAFI (afi, safi)
+ UNSET_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV);
+
+ UNSET_FLAG(peer->cap, PEER_CAP_PATHS_LIMIT_RCV);
+ }
+}
+
static void bgp_dynamic_capability_orf(uint8_t *pnt, int action,
struct capability_header *hdr,
struct peer *peer)
@@ -3282,6 +3403,22 @@ static void bgp_dynamic_capability_orf(uint8_t *pnt, int action,
}
}
+static void bgp_dynamic_capability_role(uint8_t *pnt, int action,
+ struct peer *peer)
+{
+ uint8_t role;
+
+ if (action == CAPABILITY_ACTION_SET) {
+ SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
+ memcpy(&role, pnt + 3, sizeof(role));
+
+ peer->remote_role = role;
+ } else {
+ UNSET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
+ peer->remote_role = ROLE_UNDEFINED;
+ }
+}
+
static void bgp_dynamic_capability_fqdn(uint8_t *pnt, int action,
struct capability_header *hdr,
struct peer *peer)
@@ -3293,14 +3430,14 @@ static void bgp_dynamic_capability_fqdn(uint8_t *pnt, int action,
if (action == CAPABILITY_ACTION_SET) {
/* hostname */
- if (data + 1 > end) {
+ if (data + 1 >= end) {
zlog_err("%pBP: Received invalid FQDN capability (host name length)",
peer);
return;
}
len = *data;
- if (data + len > end) {
+ if (data + len + 1 > end) {
zlog_err("%pBP: Received invalid FQDN capability length (host name) %d",
peer, hdr->length);
return;
@@ -3323,7 +3460,7 @@ static void bgp_dynamic_capability_fqdn(uint8_t *pnt, int action,
peer->hostname = XSTRDUP(MTYPE_BGP_PEER_HOST, str);
}
- if (data + 1 > end) {
+ if (data + 1 >= end) {
zlog_err("%pBP: Received invalid FQDN capability (domain name length)",
peer);
return;
@@ -3331,7 +3468,7 @@ static void bgp_dynamic_capability_fqdn(uint8_t *pnt, int action,
/* domainname */
len = *data;
- if (data + len > end) {
+ if (data + len + 1 > end) {
zlog_err("%pBP: Received invalid FQDN capability length (domain name) %d",
peer, len);
return;
@@ -3557,7 +3694,7 @@ static void bgp_dynamic_capability_software_version(uint8_t *pnt, int action,
char soft_version[BGP_MAX_SOFT_VERSION + 1] = {};
if (action == CAPABILITY_ACTION_SET) {
- if (data + len > end) {
+ if (data + len + 1 > end) {
zlog_err("%pBP: Received invalid Software Version capability length %d",
peer, len);
return;
@@ -3610,7 +3747,10 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
zlog_err("%pBP: Capability length error", peer);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- pnt += length;
+ /*
+ * If we did not return then
+ * pnt += length;
+ */
return BGP_Stop;
}
action = *pnt;
@@ -3635,7 +3775,10 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
zlog_err("%pBP: Capability length error", peer);
bgp_notify_send(peer->connection, BGP_NOTIFY_CEASE,
BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- pnt += length;
+ /*
+ * If we did not return then
+ * pnt += length;
+ */
return BGP_Stop;
}
@@ -3645,6 +3788,46 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
capability = lookup_msg(capcode_str, hdr->code, "Unknown");
+ /* Length sanity check, type-specific, for known capabilities */
+ switch (hdr->code) {
+ case CAPABILITY_CODE_MP:
+ case CAPABILITY_CODE_REFRESH:
+ case CAPABILITY_CODE_ORF:
+ case CAPABILITY_CODE_RESTART:
+ case CAPABILITY_CODE_AS4:
+ case CAPABILITY_CODE_ADDPATH:
+ case CAPABILITY_CODE_DYNAMIC:
+ case CAPABILITY_CODE_ENHE:
+ case CAPABILITY_CODE_FQDN:
+ case CAPABILITY_CODE_ENHANCED_RR:
+ case CAPABILITY_CODE_EXT_MESSAGE:
+ case CAPABILITY_CODE_ROLE:
+ case CAPABILITY_CODE_SOFT_VERSION:
+ case CAPABILITY_CODE_PATHS_LIMIT:
+ if (hdr->length < cap_minsizes[hdr->code]) {
+ zlog_info("%pBP: %s Capability length error: got %u, expected at least %u",
+ peer, capability, hdr->length,
+ (unsigned int)cap_minsizes[hdr->code]);
+ bgp_notify_send(peer->connection,
+ BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+ goto done;
+ }
+ if (hdr->length &&
+ hdr->length % cap_modsizes[hdr->code] != 0) {
+ zlog_info("%pBP %s Capability length error: got %u, expected a multiple of %u",
+ peer, capability, hdr->length,
+ (unsigned int)cap_modsizes[hdr->code]);
+ bgp_notify_send(peer->connection,
+ BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+ goto done;
+ }
+ break;
+ default:
+ break;
+ }
+
switch (hdr->code) {
case CAPABILITY_CODE_SOFT_VERSION:
bgp_dynamic_capability_software_version(pnt, action,
@@ -3702,15 +3885,6 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
}
break;
case CAPABILITY_CODE_RESTART:
- if ((hdr->length - 2) % 4) {
- zlog_err("%pBP: Received invalid Graceful-Restart capability length %d",
- peer, hdr->length);
- bgp_notify_send(peer->connection,
- BGP_NOTIFY_CEASE,
- BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- goto done;
- }
-
bgp_dynamic_capability_graceful_restart(pnt, action,
hdr, peer);
break;
@@ -3720,6 +3894,10 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
case CAPABILITY_CODE_ADDPATH:
bgp_dynamic_capability_addpath(pnt, action, hdr, peer);
break;
+ case CAPABILITY_CODE_PATHS_LIMIT:
+ bgp_dynamic_capability_paths_limit(pnt, action, hdr,
+ peer);
+ break;
case CAPABILITY_CODE_ORF:
bgp_dynamic_capability_orf(pnt, action, hdr, peer);
break;
@@ -3734,26 +3912,7 @@ static int bgp_capability_msg_parse(struct peer *peer, uint8_t *pnt,
case CAPABILITY_CODE_EXT_MESSAGE:
break;
case CAPABILITY_CODE_ROLE:
- if (hdr->length != CAPABILITY_CODE_ROLE_LEN) {
- zlog_err("%pBP: Capability (%s) length error",
- peer, capability);
- bgp_notify_send(peer->connection,
- BGP_NOTIFY_CEASE,
- BGP_NOTIFY_SUBCODE_UNSPECIFIC);
- goto done;
- }
-
- uint8_t role;
-
- if (action == CAPABILITY_ACTION_SET) {
- SET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
- memcpy(&role, pnt + 3, sizeof(role));
-
- peer->remote_role = role;
- } else {
- UNSET_FLAG(peer->cap, PEER_CAP_ROLE_RCV);
- peer->remote_role = ROLE_UNDEFINED;
- }
+ bgp_dynamic_capability_role(pnt, action, peer);
break;
default:
flog_warn(EC_BGP_UNRECOGNIZED_CAPABILITY,
@@ -3790,8 +3949,8 @@ int bgp_capability_receive(struct peer_connection *connection,
if (bgp_debug_neighbor_events(peer))
zlog_debug("%s rcv CAPABILITY", peer->host);
- /* If peer does not have the capability, send notification. */
- if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV)) {
+ if (!CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_ADV) ||
+ !CHECK_FLAG(peer->cap, PEER_CAP_DYNAMIC_RCV)) {
flog_err(EC_BGP_NO_CAP,
"%s [Error] BGP dynamic capability is not enabled",
peer->host);
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index a69d6ee..f6fe87e 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -114,6 +114,46 @@ static const struct message bgp_pmsi_tnltype_str[] = {
#define VRFID_NONE_STR "-"
#define SOFT_RECONFIG_TASK_MAX_PREFIX 25000
+static inline char *bgp_route_dump_path_info_flags(struct bgp_path_info *pi,
+ char *buf, size_t len)
+{
+ uint32_t flags = pi->flags;
+
+ if (flags == 0) {
+ snprintfrr(buf, len, "None ");
+ return buf;
+ }
+
+ snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ CHECK_FLAG(flags, BGP_PATH_IGP_CHANGED) ? "IGP Changed " : "",
+ CHECK_FLAG(flags, BGP_PATH_DAMPED) ? "Damped" : "",
+ CHECK_FLAG(flags, BGP_PATH_HISTORY) ? "History " : "",
+ CHECK_FLAG(flags, BGP_PATH_SELECTED) ? "Selected " : "",
+ CHECK_FLAG(flags, BGP_PATH_VALID) ? "Valid " : "",
+ CHECK_FLAG(flags, BGP_PATH_ATTR_CHANGED) ? "Attr Changed "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_DMED_CHECK) ? "Dmed Check " : "",
+ CHECK_FLAG(flags, BGP_PATH_DMED_SELECTED) ? "Dmed Selected "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_STALE) ? "Stale " : "",
+ CHECK_FLAG(flags, BGP_PATH_REMOVED) ? "Removed " : "",
+ CHECK_FLAG(flags, BGP_PATH_COUNTED) ? "Counted " : "",
+ CHECK_FLAG(flags, BGP_PATH_MULTIPATH) ? "Mpath " : "",
+ CHECK_FLAG(flags, BGP_PATH_MULTIPATH_CHG) ? "Mpath Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_RIB_ATTR_CHG) ? "Rib Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_ANNC_NH_SELF) ? "NH Self " : "",
+ CHECK_FLAG(flags, BGP_PATH_LINK_BW_CHG) ? "LinkBW Chg " : "",
+ CHECK_FLAG(flags, BGP_PATH_ACCEPT_OWN) ? "Accept Own " : "",
+ CHECK_FLAG(flags, BGP_PATH_MPLSVPN_LABEL_NH) ? "MPLS Label "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_MPLSVPN_NH_LABEL_BIND)
+ ? "MPLS Label Bind "
+ : "",
+ CHECK_FLAG(flags, BGP_PATH_UNSORTED) ? "Unsorted " : "");
+
+ return buf;
+}
+
DEFINE_HOOK(bgp_process,
(struct bgp * bgp, afi_t afi, safi_t safi, struct bgp_dest *bn,
struct peer *peer, bool withdraw),
@@ -195,8 +235,6 @@ static struct bgp_path_info_extra *bgp_path_info_extra_new(void)
struct bgp_path_info_extra *new;
new = XCALLOC(MTYPE_BGP_ROUTE_EXTRA,
sizeof(struct bgp_path_info_extra));
- new->label[0] = MPLS_INVALID_LABEL;
- new->num_labels = 0;
new->flowspec = NULL;
return new;
}
@@ -209,10 +247,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
return;
e = *extra;
- if (e->damp_info)
- bgp_damp_info_free(e->damp_info, 0, e->damp_info->afi,
- e->damp_info->safi);
+ if (e->damp_info)
+ bgp_damp_info_free(e->damp_info, NULL, 0);
e->damp_info = NULL;
if (e->vrfleak && e->vrfleak->parent) {
struct bgp_path_info *bpi =
@@ -268,6 +305,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
XFREE(MTYPE_BGP_ROUTE_EXTRA_VNC, e->vnc);
#endif
+ if (e->labels)
+ bgp_labels_unintern(&e->labels);
+
XFREE(MTYPE_BGP_ROUTE_EXTRA, *extra);
}
@@ -285,6 +325,41 @@ struct bgp_path_info_extra *bgp_path_info_extra_get(struct bgp_path_info *pi)
return pi->extra;
}
+bool bgp_path_info_has_valid_label(const struct bgp_path_info *path)
+{
+ if (!bgp_path_info_num_labels(path))
+ return false;
+
+ return bgp_is_valid_label(&path->extra->labels->label[0]);
+}
+
+bool bgp_path_info_labels_same(const struct bgp_path_info *bpi,
+ const mpls_label_t *label, uint32_t n)
+{
+ uint8_t bpi_num_labels;
+ const mpls_label_t *bpi_label;
+
+ bpi_num_labels = bgp_path_info_num_labels(bpi);
+ bpi_label = bpi_num_labels ? bpi->extra->labels->label : NULL;
+
+ return bgp_labels_same(bpi_label, bpi_num_labels,
+ (const mpls_label_t *)label, n);
+}
+
+uint8_t bgp_path_info_num_labels(const struct bgp_path_info *pi)
+{
+ if (!pi)
+ return 0;
+
+ if (!pi->extra)
+ return 0;
+
+ if (!pi->extra->labels)
+ return 0;
+
+ return pi->extra->labels->num_labels;
+}
+
/* Free bgp route information. */
void bgp_path_info_free_with_caller(const char *name,
struct bgp_path_info *path)
@@ -442,10 +517,13 @@ void bgp_path_info_add_with_caller(const char *name, struct bgp_dest *dest,
top->prev = pi;
bgp_dest_set_bgp_path_info(dest, pi);
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
bgp_path_info_lock(pi);
bgp_dest_lock_node(dest);
peer_lock(pi->peer); /* bgp_path_info peer reference */
bgp_dest_set_defer_flag(dest, false);
+ if (pi->peer)
+ pi->peer->stat_pfx_loc_rib++;
hook_call(bgp_snmp_update_stats, dest, pi, true);
}
@@ -462,8 +540,30 @@ struct bgp_dest *bgp_path_info_reap(struct bgp_dest *dest,
bgp_dest_set_bgp_path_info(dest, pi->next);
bgp_path_info_mpath_dequeue(pi);
+
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ if (pi->peer)
+ pi->peer->stat_pfx_loc_rib--;
+ hook_call(bgp_snmp_update_stats, dest, pi, false);
+
bgp_path_info_unlock(pi);
+ return bgp_dest_unlock_node(dest);
+}
+
+static struct bgp_dest *bgp_path_info_reap_unsorted(struct bgp_dest *dest,
+ struct bgp_path_info *pi)
+{
+ bgp_path_info_mpath_dequeue(pi);
+
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ if (pi->peer)
+ pi->peer->stat_pfx_loc_rib--;
hook_call(bgp_snmp_update_stats, dest, pi, false);
+ bgp_path_info_unlock(pi);
return bgp_dest_unlock_node(dest);
}
@@ -581,6 +681,11 @@ void bgp_path_info_path_with_addpath_rx_str(struct bgp_path_info *pi, char *buf,
{
struct peer *peer;
+ if (!pi) {
+ snprintf(buf, buf_len, "NONE");
+ return;
+ }
+
if (pi->sub_type == BGP_ROUTE_IMPORTED &&
bgp_get_imported_bpi_ultimate(pi))
peer = bgp_get_imported_bpi_ultimate(pi)->peer;
@@ -683,12 +788,18 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
}
if (debug) {
+ char buf1[256], buf2[256];
+
bpi_ultimate = bgp_get_imported_bpi_ultimate(exist);
bgp_path_info_path_with_addpath_rx_str(bpi_ultimate, exist_buf,
sizeof(exist_buf));
- zlog_debug("%s(%s): Comparing %s flags 0x%x with %s flags 0x%x",
- pfx_buf, bgp->name_pretty, new_buf, new->flags,
- exist_buf, exist->flags);
+ zlog_debug("%s(%s): Comparing %s flags %s with %s flags %s",
+ pfx_buf, bgp->name_pretty, new_buf,
+ bgp_route_dump_path_info_flags(new, buf1,
+ sizeof(buf1)),
+ exist_buf,
+ bgp_route_dump_path_info_flags(exist, buf2,
+ sizeof(buf2)));
}
newattr = new->attr;
@@ -1284,25 +1395,18 @@ int bgp_path_info_cmp(struct bgp *bgp, struct bgp_path_info *new,
/* If one path has a label but the other does not, do not treat
* them as equals for multipath
*/
- int newl, existl;
-
- newl = existl = 0;
-
- if (new->extra)
- newl = new->extra->num_labels;
- if (exist->extra)
- existl = exist->extra->num_labels;
- if (((new->extra &&bgp_is_valid_label(&new->extra->label[0])) !=
- (exist->extra &&
- bgp_is_valid_label(&exist->extra->label[0]))) ||
- (newl != existl)) {
+ bool new_label_valid, exist_label_valid;
+
+ new_label_valid = bgp_path_info_has_valid_label(new);
+ exist_label_valid = bgp_path_info_has_valid_label(exist);
+
+ if (new_label_valid != exist_label_valid) {
if (debug)
zlog_debug(
"%s: %s and %s cannot be multipath, one has a label while the other does not",
pfx_buf, new_buf, exist_buf);
} else if (CHECK_FLAG(bgp->flags,
BGP_FLAG_ASPATH_MULTIPATH_RELAX)) {
-
/*
* For the two paths, all comparison steps till IGP
* metric
@@ -1768,11 +1872,12 @@ static bool bgp_check_role_applicability(afi_t afi, safi_t safi)
static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
struct attr *attr, afi_t afi, safi_t safi,
const char *rmap_name, mpls_label_t *label,
- uint32_t num_labels, struct bgp_dest *dest)
+ uint8_t num_labels, struct bgp_dest *dest)
{
struct bgp_filter *filter;
struct bgp_path_info rmap_path = { 0 };
struct bgp_path_info_extra extra = { 0 };
+ struct bgp_labels bgp_labels = {};
route_map_result_t ret;
struct route_map *rmap = NULL;
@@ -1804,11 +1909,12 @@ static int bgp_input_modifier(struct peer *peer, const struct prefix *p,
rmap_path.attr = attr;
rmap_path.extra = &extra;
rmap_path.net = dest;
+ extra.labels = &bgp_labels;
- extra.num_labels = num_labels;
+ bgp_labels.num_labels = num_labels;
if (label && num_labels && num_labels <= BGP_MAX_LABELS)
- memcpy(extra.label, label,
- num_labels * sizeof(mpls_label_t));
+ memcpy(bgp_labels.label, label,
+ num_labels * sizeof(mpls_label_t));
SET_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN);
@@ -2143,8 +2249,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* off box as that the RT and RD created are localy
* significant and globaly useless.
*/
- if (safi == SAFI_MPLS_VPN && pi->extra && pi->extra->num_labels
- && pi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
+ if (safi == SAFI_MPLS_VPN && bgp_path_info_num_labels(pi) &&
+ pi->extra->labels->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
return false;
/* If it's labeled safi, make sure the route has a valid label. */
@@ -2246,7 +2352,7 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
/* AS path loop check. */
- if (peer->as_path_loop_detection &&
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_AS_LOOP_DETECTION) &&
aspath_loop_check(piattr->aspath, peer->as)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
@@ -2701,17 +2807,26 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
* the most sense. However, don't modify if the link-bandwidth has
* been explicitly set by user policy.
*/
- if (nh_reset &&
- bgp_path_info_mpath_chkwtd(bgp, pi) &&
+ if (nh_reset && bgp_path_info_mpath_chkwtd(bgp, pi) &&
(cum_bw = bgp_path_info_mpath_cumbw(pi)) != 0 &&
- !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET))
- bgp_attr_set_ecommunity(
- attr,
- ecommunity_replace_linkbw(
- bgp->as, bgp_attr_get_ecommunity(attr), cum_bw,
- CHECK_FLAG(
- peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE)));
+ !CHECK_FLAG(attr->rmap_change_flags, BATTR_RMAP_LINK_BW_SET)) {
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH))
+ bgp_attr_set_ipv6_ecommunity(
+ attr,
+ ecommunity_replace_linkbw(bgp->as,
+ bgp_attr_get_ipv6_ecommunity(
+ attr),
+ cum_bw, false, true));
+ else
+ bgp_attr_set_ecommunity(
+ attr,
+ ecommunity_replace_linkbw(
+ bgp->as, bgp_attr_get_ecommunity(attr),
+ cum_bw,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE),
+ false));
+ }
return true;
}
@@ -2740,17 +2855,18 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
struct bgp_path_info_pair *result, afi_t afi,
safi_t safi)
{
- struct bgp_path_info *new_select;
- struct bgp_path_info *old_select;
+ struct bgp_path_info *new_select, *look_thru;
+ struct bgp_path_info *old_select, *worse, *first;
struct bgp_path_info *pi;
struct bgp_path_info *pi1;
struct bgp_path_info *pi2;
- struct bgp_path_info *nextpi = NULL;
int paths_eq, do_mpath;
- bool debug;
+ bool debug, any_comparisons;
struct list mp_list;
char pfx_buf[PREFIX2STR_BUFFER] = {};
char path_buf[PATH_ADDPATH_STR_BUFFER];
+ enum bgp_path_selection_reason reason = bgp_path_selection_none;
+ bool unsorted_items = true;
bgp_mp_list_init(&mp_list);
do_mpath =
@@ -2761,16 +2877,16 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
if (debug)
prefix2str(bgp_dest_get_prefix(dest), pfx_buf, sizeof(pfx_buf));
- dest->reason = bgp_path_selection_none;
/* bgp deterministic-med */
new_select = NULL;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)) {
-
/* Clear BGP_PATH_DMED_SELECTED for all paths */
for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
- pi1 = pi1->next)
+ pi1 = pi1->next) {
bgp_path_info_unset_flag(dest, pi1,
BGP_PATH_DMED_SELECTED);
+ UNSET_FLAG(pi1->flags, BGP_PATH_DMED_CHECK);
+ }
for (pi1 = bgp_dest_get_bgp_path_info(dest); pi1;
pi1 = pi1->next) {
@@ -2786,41 +2902,35 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
}
new_select = pi1;
- if (pi1->next) {
- for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
- if (CHECK_FLAG(pi2->flags,
- BGP_PATH_DMED_CHECK))
- continue;
- if (BGP_PATH_HOLDDOWN(pi2))
- continue;
- if (pi2->peer != bgp->peer_self &&
- !CHECK_FLAG(pi2->peer->sflags,
- PEER_STATUS_NSF_WAIT) &&
- !peer_established(
- pi2->peer->connection))
- continue;
-
- if (!aspath_cmp_left(pi1->attr->aspath,
- pi2->attr->aspath)
- && !aspath_cmp_left_confed(
- pi1->attr->aspath,
- pi2->attr->aspath))
- continue;
+ for (pi2 = pi1->next; pi2; pi2 = pi2->next) {
+ if (CHECK_FLAG(pi2->flags, BGP_PATH_DMED_CHECK))
+ continue;
+ if (BGP_PATH_HOLDDOWN(pi2))
+ continue;
+ if (pi2->peer != bgp->peer_self &&
+ !CHECK_FLAG(pi2->peer->sflags,
+ PEER_STATUS_NSF_WAIT) &&
+ !peer_established(pi2->peer->connection))
+ continue;
- if (bgp_path_info_cmp(
- bgp, pi2, new_select,
- &paths_eq, mpath_cfg, debug,
- pfx_buf, afi, safi,
- &dest->reason)) {
- bgp_path_info_unset_flag(
- dest, new_select,
- BGP_PATH_DMED_SELECTED);
- new_select = pi2;
- }
+ if (!aspath_cmp_left(pi1->attr->aspath,
+ pi2->attr->aspath) &&
+ !aspath_cmp_left_confed(pi1->attr->aspath,
+ pi2->attr->aspath))
+ continue;
- bgp_path_info_set_flag(
- dest, pi2, BGP_PATH_DMED_CHECK);
+ if (bgp_path_info_cmp(bgp, pi2, new_select,
+ &paths_eq, mpath_cfg,
+ debug, pfx_buf, afi, safi,
+ &dest->reason)) {
+ bgp_path_info_unset_flag(dest,
+ new_select,
+ BGP_PATH_DMED_SELECTED);
+ new_select = pi2;
}
+
+ bgp_path_info_set_flag(dest, pi2,
+ BGP_PATH_DMED_CHECK);
}
bgp_path_info_set_flag(dest, new_select,
BGP_PATH_DMED_CHECK);
@@ -2839,69 +2949,273 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
}
}
- /* Check old selected route and new selected route. */
+ /*
+ * Let's grab the unsorted items from the list
+ */
+ struct bgp_path_info *unsorted_list = NULL;
+ struct bgp_path_info *unsorted_list_spot = NULL;
+ struct bgp_path_info *unsorted_holddown = NULL;
+
old_select = NULL;
- new_select = NULL;
- for (pi = bgp_dest_get_bgp_path_info(dest);
- (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
- enum bgp_path_selection_reason reason;
+ pi = bgp_dest_get_bgp_path_info(dest);
+ while (pi && CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED)) {
+ struct bgp_path_info *next = pi->next;
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
old_select = pi;
- if (BGP_PATH_HOLDDOWN(pi)) {
- /* reap REMOVED routes, if needs be
+ /*
+ * Pull off pi off the list
+ */
+ if (pi->next)
+ pi->next->prev = NULL;
+
+ bgp_dest_set_bgp_path_info(dest, pi->next);
+ pi->next = NULL;
+ pi->prev = NULL;
+
+ /*
+ * Place it on the unsorted list
+ */
+ if (unsorted_list_spot) {
+ unsorted_list_spot->next = pi;
+ pi->prev = unsorted_list_spot;
+ pi->next = NULL;
+ } else {
+ unsorted_list = pi;
+
+ pi->next = NULL;
+ pi->prev = NULL;
+ }
+
+ unsorted_list_spot = pi;
+ pi = next;
+ }
+
+ if (!old_select) {
+ old_select = bgp_dest_get_bgp_path_info(dest);
+ if (old_select &&
+ !CHECK_FLAG(old_select->flags, BGP_PATH_SELECTED))
+ old_select = NULL;
+ }
+
+ if (!unsorted_list)
+ unsorted_items = true;
+ else
+ unsorted_items = false;
+
+ any_comparisons = false;
+ worse = NULL;
+ while (unsorted_list) {
+ first = unsorted_list;
+ unsorted_list = unsorted_list->next;
+
+ if (unsorted_list)
+ unsorted_list->prev = NULL;
+ first->next = NULL;
+ first->prev = NULL;
+
+ /*
+ * It's not likely that the just received unsorted entry
+ * is in holddown and scheduled for removal but we should
+ * check
+ */
+ if (BGP_PATH_HOLDDOWN(first)) {
+ /*
+ * reap REMOVED routes, if needs be
* selected route must stay for a while longer though
*/
if (debug)
- zlog_debug(
- "%s: %pBD(%s) pi from %s in holddown",
- __func__, dest, bgp->name_pretty,
- pi->peer->host);
+ zlog_debug("%s: %pBD(%s) pi %p from %s in holddown",
+ __func__, dest, bgp->name_pretty,
+ first, first->peer->host);
- if (CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) &&
- (pi != old_select)) {
- dest = bgp_path_info_reap(dest, pi);
+ if (old_select != first &&
+ CHECK_FLAG(first->flags, BGP_PATH_REMOVED)) {
+ dest = bgp_path_info_reap_unsorted(dest, first);
assert(dest);
- }
+ } else {
+ /*
+ * We are in hold down, so we cannot sort this
+ * item yet. Let's wait, so hold the unsorted
+ * to the side
+ */
+ if (unsorted_holddown) {
+ first->next = unsorted_holddown;
+ unsorted_holddown->prev = first;
+ unsorted_holddown = first;
+ } else
+ unsorted_holddown = first;
+ UNSET_FLAG(first->flags, BGP_PATH_UNSORTED);
+ }
continue;
}
- if (pi->peer && pi->peer != bgp->peer_self
- && !CHECK_FLAG(pi->peer->sflags, PEER_STATUS_NSF_WAIT))
- if (!peer_established(pi->peer->connection)) {
+ bgp_path_info_unset_flag(dest, first, BGP_PATH_DMED_CHECK);
+
+ worse = NULL;
+
+ struct bgp_path_info *look_thru_next;
+
+ for (look_thru = bgp_dest_get_bgp_path_info(dest); look_thru;
+ look_thru = look_thru_next) {
+ /* look thru can be reaped save the next pointer */
+ look_thru_next = look_thru->next;
+
+ /*
+ * Now we have the first unsorted and the best selected
+ * Let's do best path comparison
+ */
+ if (BGP_PATH_HOLDDOWN(look_thru)) {
+ /* reap REMOVED routes, if needs be
+ * selected route must stay for a while longer though
+ */
if (debug)
- zlog_debug(
- "%s: %pBD(%s) non self peer %s not estab state",
- __func__, dest,
- bgp->name_pretty,
- pi->peer->host);
+ zlog_debug("%s: %pBD(%s) pi from %s %p in holddown",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host,
+ look_thru);
+
+ if (CHECK_FLAG(look_thru->flags,
+ BGP_PATH_REMOVED) &&
+ (look_thru != old_select)) {
+ dest = bgp_path_info_reap(dest,
+ look_thru);
+ assert(dest);
+ }
continue;
}
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED)
- && (!CHECK_FLAG(pi->flags, BGP_PATH_DMED_SELECTED))) {
- bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
- if (debug)
- zlog_debug("%s: %pBD(%s) pi %s dmed", __func__,
- dest, bgp->name_pretty,
- pi->peer->host);
- continue;
+ if (look_thru->peer &&
+ look_thru->peer != bgp->peer_self &&
+ !CHECK_FLAG(look_thru->peer->sflags,
+ PEER_STATUS_NSF_WAIT))
+ if (!peer_established(
+ look_thru->peer->connection)) {
+ if (debug)
+ zlog_debug("%s: %pBD(%s) non self peer %s not estab state",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host);
+
+ continue;
+ }
+
+ bgp_path_info_unset_flag(dest, look_thru,
+ BGP_PATH_DMED_CHECK);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DETERMINISTIC_MED) &&
+ (!CHECK_FLAG(look_thru->flags,
+ BGP_PATH_DMED_SELECTED))) {
+ bgp_path_info_unset_flag(dest, look_thru,
+ BGP_PATH_DMED_CHECK);
+ if (debug)
+ zlog_debug("%s: %pBD(%s) pi %s dmed",
+ __func__, dest,
+ bgp->name_pretty,
+ look_thru->peer->host);
+
+ worse = look_thru;
+ continue;
+ }
+
+ reason = dest->reason;
+ any_comparisons = true;
+ if (bgp_path_info_cmp(bgp, first, look_thru, &paths_eq,
+ mpath_cfg, debug, pfx_buf, afi,
+ safi, &reason)) {
+ first->reason = reason;
+ worse = look_thru;
+ /*
+ * We can stop looking
+ */
+ break;
+ }
+
+ look_thru->reason = reason;
}
- bgp_path_info_unset_flag(dest, pi, BGP_PATH_DMED_CHECK);
+ if (!any_comparisons)
+ first->reason = bgp_path_selection_first;
+
+ /*
+ * At this point worse if NON-NULL is where the first
+ * pointer should be before. if worse is NULL then
+ * first is bestpath too. Let's remove first from the
+ * list and place it in the right spot
+ */
+
+ if (!worse) {
+ struct bgp_path_info *end =
+ bgp_dest_get_bgp_path_info(dest);
+
+ for (; end && end->next != NULL; end = end->next)
+ ;
+
+ if (end)
+ end->next = first;
+ else
+ bgp_dest_set_bgp_path_info(dest, first);
+ first->prev = end;
+ first->next = NULL;
+
+ dest->reason = first->reason;
+ } else {
+ if (worse->prev)
+ worse->prev->next = first;
+ first->next = worse;
+ if (worse) {
+ first->prev = worse->prev;
+ worse->prev = first;
+ } else
+ first->prev = NULL;
- reason = dest->reason;
- if (bgp_path_info_cmp(bgp, pi, new_select, &paths_eq, mpath_cfg,
- debug, pfx_buf, afi, safi,
- &dest->reason)) {
- if (new_select == NULL &&
- reason != bgp_path_selection_none)
- dest->reason = reason;
- new_select = pi;
+ if (dest->info == worse) {
+ bgp_dest_set_bgp_path_info(dest, first);
+ dest->reason = first->reason;
+ }
}
+ UNSET_FLAG(first->flags, BGP_PATH_UNSORTED);
+ }
+
+ if (!unsorted_items) {
+ new_select = bgp_dest_get_bgp_path_info(dest);
+ while (new_select && BGP_PATH_HOLDDOWN(new_select))
+ new_select = new_select->next;
+
+ if (new_select) {
+ if (new_select->reason == bgp_path_selection_none)
+ new_select->reason = bgp_path_selection_first;
+ else if (new_select == bgp_dest_get_bgp_path_info(dest) &&
+ new_select->next == NULL)
+ new_select->reason = bgp_path_selection_first;
+ dest->reason = new_select->reason;
+ } else
+ dest->reason = bgp_path_selection_none;
+ } else
+ new_select = old_select;
+
+
+ /*
+ * Reinsert all the unsorted_holddown items for future processing
+ * at the end of the list.
+ */
+ if (unsorted_holddown) {
+ struct bgp_path_info *top = bgp_dest_get_bgp_path_info(dest);
+ struct bgp_path_info *prev = NULL;
+
+ while (top != NULL) {
+ prev = top;
+ top = top->next;
+ }
+
+ if (prev) {
+ prev->next = unsorted_holddown;
+ unsorted_holddown->prev = prev;
+ } else
+ bgp_dest_set_bgp_path_info(dest, unsorted_holddown);
}
/* Now that we know which path is the bestpath see if any of the other
@@ -2909,11 +3223,8 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
* qualify as multipaths
*/
if (debug) {
- if (new_select)
- bgp_path_info_path_with_addpath_rx_str(
- new_select, path_buf, sizeof(path_buf));
- else
- snprintf(path_buf, sizeof(path_buf), "NONE");
+ bgp_path_info_path_with_addpath_rx_str(new_select, path_buf,
+ sizeof(path_buf));
zlog_debug(
"%pBD(%s): After path selection, newbest is %s oldbest was %s",
dest, bgp->name_pretty, path_buf,
@@ -2921,9 +3232,7 @@ void bgp_best_selection(struct bgp *bgp, struct bgp_dest *dest,
}
if (do_mpath && new_select) {
- for (pi = bgp_dest_get_bgp_path_info(dest);
- (pi != NULL) && (nextpi = pi->next, 1); pi = nextpi) {
-
+ for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (debug)
bgp_path_info_path_with_addpath_rx_str(
pi, path_buf, sizeof(path_buf));
@@ -3177,8 +3486,7 @@ static bool bgp_lu_need_null_label(struct bgp *bgp,
|| new_select->sub_type == BGP_ROUTE_AGGREGATE
|| new_select->sub_type == BGP_ROUTE_REDISTRIBUTE)
goto need_null_label;
- else if (new_select->extra &&
- bgp_is_valid_label(&new_select->extra->label[0]))
+ else if (bgp_path_info_has_valid_label(new_select))
return false;
need_null_label:
if (label == NULL)
@@ -3355,7 +3663,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
return;
}
+#ifdef ENABLE_BGP_VNC
const struct prefix *p = bgp_dest_get_prefix(dest);
+#endif
debug = bgp_debug_bestpath(dest);
if (debug)
@@ -3418,9 +3728,9 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
&& (new_select->sub_type == BGP_ROUTE_NORMAL
|| new_select->sub_type
== BGP_ROUTE_IMPORTED))
-
- bgp_zebra_announce(dest, p, old_select,
- bgp, afi, safi);
+ bgp_zebra_route_install(dest, old_select,
+ bgp, true, NULL,
+ false);
}
}
@@ -3480,7 +3790,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
bgp_path_info_unset_flag(dest, old_select, BGP_PATH_SELECTED);
if (new_select) {
if (debug)
- zlog_debug("%s: setting SELECTED flag", __func__);
+ zlog_debug("%s: %pBD setting SELECTED flag", __func__,
+ dest);
bgp_path_info_set_flag(dest, new_select, BGP_PATH_SELECTED);
bgp_path_info_unset_flag(dest, new_select,
BGP_PATH_ATTR_CHANGED);
@@ -3529,10 +3840,10 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
*/
if (old_select &&
is_route_parent_evpn(old_select))
- bgp_zebra_withdraw(p, old_select, bgp, afi,
- safi);
+ bgp_zebra_withdraw_actual(dest, old_select, bgp);
- bgp_zebra_announce(dest, p, new_select, bgp, afi, safi);
+ bgp_zebra_route_install(dest, new_select, bgp, true,
+ NULL, false);
} else {
/* Withdraw the route from the kernel. */
if (old_select && old_select->type == ZEBRA_ROUTE_BGP
@@ -3540,8 +3851,8 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
|| old_select->sub_type == BGP_ROUTE_AGGREGATE
|| old_select->sub_type == BGP_ROUTE_IMPORTED))
- bgp_zebra_withdraw(p, old_select, bgp, afi,
- safi);
+ bgp_zebra_route_install(dest, old_select, bgp,
+ false, NULL, false);
}
}
@@ -3704,13 +4015,38 @@ static struct bgp_process_queue *bgp_processq_alloc(struct bgp *bgp)
return pqnode;
}
-void bgp_process(struct bgp *bgp, struct bgp_dest *dest, afi_t afi, safi_t safi)
+void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi)
{
#define ARBITRARY_PROCESS_QLEN 10000
struct work_queue *wq = bgp->process_queue;
struct bgp_process_queue *pqnode;
int pqnode_reuse = 0;
+ /*
+ * Indicate that *this* pi is in an unsorted
+ * situation, even if the node is already
+ * scheduled.
+ */
+ if (pi) {
+ struct bgp_path_info *first = bgp_dest_get_bgp_path_info(dest);
+
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
+
+ if (pi != first) {
+ if (pi->next)
+ pi->next->prev = pi->prev;
+ if (pi->prev)
+ pi->prev->next = pi->next;
+
+ if (first)
+ first->prev = pi;
+ pi->next = first;
+ pi->prev = NULL;
+ bgp_dest_set_bgp_path_info(dest, pi);
+ }
+ }
+
/* already scheduled for processing? */
if (CHECK_FLAG(dest->flags, BGP_NODE_PROCESS_SCHEDULED))
return;
@@ -3959,7 +4295,7 @@ void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
}
hook_call(bgp_process, peer->bgp, afi, safi, dest, peer, true);
- bgp_process(peer->bgp, dest, afi, safi);
+ bgp_process(peer->bgp, dest, pi, afi, safi);
}
static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
@@ -3971,14 +4307,16 @@ static void bgp_rib_withdraw(struct bgp_dest *dest, struct bgp_path_info *pi,
/* apply dampening, if result is suppressed, we'll be retaining
* the bgp_path_info in the RIB for historical reference.
*/
- if (CHECK_FLAG(peer->bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP)
- if ((bgp_damp_withdraw(pi, dest, afi, safi, 0))
- == BGP_DAMP_SUPPRESSED) {
- bgp_aggregate_decrement(peer->bgp, p, pi, afi,
- safi);
- return;
+ if (peer->sort == BGP_PEER_EBGP) {
+ if (get_active_bdc_from_pi(pi, afi, safi)) {
+ if (bgp_damp_withdraw(pi, dest, afi, safi, 0) ==
+ BGP_DAMP_SUPPRESSED) {
+ bgp_aggregate_decrement(peer->bgp, p, pi, afi,
+ safi);
+ return;
+ }
}
+ }
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN) {
@@ -4198,7 +4536,7 @@ static bool bgp_accept_own(struct peer *peer, afi_t afi, safi_t safi,
void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct attr *attr, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int soft_reconfig,
+ uint8_t num_labels, int soft_reconfig,
struct bgp_route_evpn *evpn)
{
int ret;
@@ -4209,16 +4547,16 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
struct attr *attr_new;
struct bgp_path_info *pi;
struct bgp_path_info *new = NULL;
- struct bgp_path_info_extra *extra;
const char *reason;
char pfx_buf[BGP_PRD_PATH_STRLEN];
int connected = 0;
int do_loop_check = 1;
- int has_valid_label = 0;
afi_t nh_afi;
bool force_evpn_import = false;
safi_t orig_safi = safi;
int allowas_in = 0;
+ struct bgp_labels bgp_labels = {};
+ uint8_t i;
if (frrtrace_enabled(frr_bgp, process_update)) {
char pfxprint[PREFIX2STR_BUFFER];
@@ -4240,15 +4578,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp = peer->bgp;
dest = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
- /* TODO: Check to see if we can get rid of "is_valid_label" */
- if (afi == AFI_L2VPN && safi == SAFI_EVPN)
- has_valid_label = (num_labels > 0) ? 1 : 0;
- else
- has_valid_label = bgp_is_valid_label(label);
-
- if (has_valid_label)
- assert(label != NULL);
+ if ((afi == AFI_L2VPN && safi == SAFI_EVPN) ||
+ bgp_is_valid_label(&label[0]))
+ bgp_labels.num_labels = num_labels;
+ for (i = 0; i < bgp_labels.num_labels; i++)
+ bgp_labels.label[i] = label[i];
/* When peer's soft reconfiguration enabled. Record input packet in
Adj-RIBs-In. */
@@ -4265,7 +4600,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
memcpy(&attr->evpn_overlay, evpn,
sizeof(struct bgp_route_evpn));
}
- bgp_adj_in_set(dest, peer, attr, addpath_id);
+ bgp_adj_in_set(dest, peer, attr, addpath_id, &bgp_labels);
}
/* Update permitted loop count */
@@ -4447,7 +4782,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
if (pi && pi->attr->rmap_table_id != new_attr.rmap_table_id) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
/* remove from RIB previous entry */
- bgp_zebra_withdraw(p, pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, false, NULL,
+ false);
}
if (peer->sort == BGP_PEER_EBGP) {
@@ -4541,15 +4877,12 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Same attribute comes in. */
if (!CHECK_FLAG(pi->flags, BGP_PATH_REMOVED) && same_attr &&
- (!has_valid_label ||
- (bgp_path_info_extra_get(pi) &&
- bgp_labels_same((const mpls_label_t *)pi->extra->label,
- pi->extra->num_labels, label,
- num_labels)))) {
- if (CHECK_FLAG(bgp->af_flags[afi][safi],
- BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP
- && CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
+ (!bgp_labels.num_labels ||
+ bgp_path_info_labels_same(pi, bgp_labels.label,
+ bgp_labels.num_labels))) {
+ if (get_active_bdc_from_pi(pi, afi, safi) &&
+ peer->sort == BGP_PEER_EBGP &&
+ CHECK_FLAG(pi->flags, BGP_PATH_HISTORY)) {
if (bgp_debug_update(peer, p, NULL, 1)) {
bgp_debug_rdpfxpath2str(
afi, safi, prd, p, label,
@@ -4564,7 +4897,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
!= BGP_DAMP_SUPPRESSED) {
bgp_aggregate_increment(bgp, p, pi, afi,
safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
} else /* Duplicate - odd */
{
@@ -4592,7 +4925,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_path_info_unset_flag(
dest, pi, BGP_PATH_STALE);
bgp_dest_set_defer_flag(dest, false);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
@@ -4650,11 +4983,11 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_path_info_set_flag(dest, pi, BGP_PATH_ATTR_CHANGED);
/* Update bgp route dampening information. */
- if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP) {
+ if (get_active_bdc_from_pi(pi, afi, safi) &&
+ peer->sort == BGP_PEER_EBGP) {
/* This is implicit withdraw so we should update
- dampening
- information. */
+ * dampening information.
+ */
if (!CHECK_FLAG(pi->flags, BGP_PATH_HISTORY))
bgp_damp_withdraw(pi, dest, afi, safi, 1);
}
@@ -4728,17 +5061,11 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
pi->attr = attr_new;
/* Update MPLS label */
- if (has_valid_label) {
- extra = bgp_path_info_extra_get(pi);
- if (!bgp_labels_same((const mpls_label_t *)extra->label,
- extra->num_labels, label,
- num_labels)) {
- memcpy(&extra->label, label,
- num_labels * sizeof(mpls_label_t));
- extra->num_labels = num_labels;
- }
- if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
- bgp_set_valid_label(&extra->label[0]);
+ if (!bgp_path_info_labels_same(pi, &bgp_labels.label[0],
+ bgp_labels.num_labels)) {
+ bgp_path_info_extra_get(pi);
+ bgp_labels_unintern(&pi->extra->labels);
+ pi->extra->labels = bgp_labels_intern(&bgp_labels);
}
#ifdef ENABLE_BGP_VNC
@@ -4765,8 +5092,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
#endif
/* Update bgp route dampening information. */
- if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING)
- && peer->sort == BGP_PEER_EBGP) {
+ if (get_active_bdc_from_pi(pi, afi, safi) &&
+ peer->sort == BGP_PEER_EBGP) {
/* Now we do normal update dampening. */
ret = bgp_damp_update(pi, dest, afi, safi);
if (ret == BGP_DAMP_SUPPRESSED) {
@@ -4882,7 +5209,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
bgp_dest_unlock_node(dest);
if (SAFI_UNICAST == safi
@@ -4929,17 +5256,8 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
new = info_make(type, sub_type, 0, peer, attr_new, dest);
/* Update MPLS label */
- if (has_valid_label) {
- extra = bgp_path_info_extra_get(new);
- if (!bgp_labels_same((const mpls_label_t *)extra->label,
- extra->num_labels, label, num_labels)) {
- memcpy(&extra->label, label,
- num_labels * sizeof(mpls_label_t));
- extra->num_labels = num_labels;
- }
- if (!(afi == AFI_L2VPN && safi == SAFI_EVPN))
- bgp_set_valid_label(&extra->label[0]);
- }
+ bgp_path_info_extra_get(new);
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
/* Nexthop reachability check. */
if (((afi == AFI_IP || afi == AFI_IP6) &&
@@ -5027,7 +5345,7 @@ void bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
hook_call(bgp_process, bgp, afi, safi, dest, peer, false);
/* Process change. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
if (SAFI_UNICAST == safi
&& (bgp->inst_type == BGP_INSTANCE_TYPE_VRF
@@ -5120,7 +5438,7 @@ filtered:
void bgp_withdraw(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, struct bgp_route_evpn *evpn)
+ uint8_t num_labels, struct bgp_route_evpn *evpn)
{
struct bgp *bgp;
char pfx_buf[BGP_PRD_PATH_STRLEN];
@@ -5347,18 +5665,16 @@ static void bgp_soft_reconfig_table_update(struct peer *peer,
safi_t safi, struct prefix_rd *prd)
{
struct bgp_path_info *pi;
- uint32_t num_labels = 0;
- mpls_label_t *label_pnt = NULL;
+ uint8_t num_labels;
+ mpls_label_t *label_pnt;
struct bgp_route_evpn evpn;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (pi->peer == peer)
break;
- if (pi && pi->extra)
- num_labels = pi->extra->num_labels;
- if (num_labels)
- label_pnt = &pi->extra->label[0];
+ num_labels = ain->labels ? ain->labels->num_labels : 0;
+ label_pnt = num_labels ? &ain->labels->label[0] : NULL;
if (pi)
memcpy(&evpn, bgp_attr_get_evpn_overlay(pi->attr),
sizeof(evpn));
@@ -5598,7 +5914,7 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
struct bgp_clear_node_queue *cnq = data;
struct bgp_dest *dest = cnq->dest;
struct peer *peer = wq->spec.data;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
struct bgp *bgp;
afi_t afi = bgp_dest_table(dest)->afi;
safi_t safi = bgp_dest_table(dest)->safi;
@@ -5609,7 +5925,8 @@ static wq_item_status bgp_clear_route_node(struct work_queue *wq, void *data)
/* It is possible that we have multiple paths for a prefix from a peer
* if that peer is using AddPath.
*/
- for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
if (pi->peer != peer)
continue;
@@ -5871,7 +6188,7 @@ void bgp_clear_adj_in(struct peer *peer, afi_t afi, safi_t safi)
void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
- struct bgp_path_info *pi;
+ struct bgp_path_info *pi, *next;
struct bgp_table *table;
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN) {
@@ -5886,8 +6203,9 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
for (rm = bgp_table_top(table); rm;
rm = bgp_route_next(rm))
- for (pi = bgp_dest_get_bgp_path_info(rm); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(rm);
+ (pi != NULL) && (next = pi->next, 1);
+ pi = next) {
if (pi->peer != peer)
continue;
if (CHECK_FLAG(
@@ -5920,8 +6238,8 @@ void bgp_clear_stale_route(struct peer *peer, afi_t afi, safi_t safi)
} else {
for (dest = bgp_table_top(peer->bgp->rib[afi][safi]); dest;
dest = bgp_route_next(dest))
- for (pi = bgp_dest_get_bgp_path_info(dest); pi;
- pi = pi->next) {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next) {
if (pi->peer != peer)
continue;
if (CHECK_FLAG(peer->af_sflags[afi][safi],
@@ -6024,7 +6342,8 @@ void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
- if (peer->sort == BGP_PEER_IBGP)
+ if (peer->sort == BGP_PEER_CONFED || peer->sort == BGP_PEER_IBGP ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD)
return true;
if (peer->sort == BGP_PEER_EBGP &&
@@ -6037,7 +6356,8 @@ bool bgp_outbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
bool bgp_inbound_policy_exists(struct peer *peer, struct bgp_filter *filter)
{
- if (peer->sort == BGP_PEER_IBGP)
+ if (peer->sort == BGP_PEER_CONFED || peer->sort == BGP_PEER_IBGP ||
+ peer->sub_sort == BGP_PEER_EBGP_OAD)
return true;
if (peer->sort == BGP_PEER_EBGP
@@ -6073,8 +6393,7 @@ static void bgp_cleanup_table(struct bgp *bgp, struct bgp_table *table,
|| pi->sub_type == BGP_ROUTE_IMPORTED)) {
if (bgp_fibupd_safi(safi))
- bgp_zebra_withdraw(p, pi, bgp, afi,
- safi);
+ bgp_zebra_withdraw_actual(dest, pi, bgp);
}
dest = bgp_path_info_reap(dest, pi);
@@ -6369,10 +6688,11 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
route_map_result_t ret;
#ifdef ENABLE_BGP_VNC
int vnc_implicit_withdraw = 0;
- mpls_label_t label = 0;
+ mpls_label_t label = MPLS_INVALID_LABEL;
#endif
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
struct bgp *bgp_nexthop = bgp;
+ struct bgp_labels labels = {};
assert(bgp_static);
@@ -6522,9 +6842,9 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp, p, pi);
}
} else {
- if (pi->extra)
+ if (bgp_path_info_num_labels(pi))
label = decode_label(
- &pi->extra->label[0]);
+ &pi->extra->labels->label[0]);
}
#endif
if (pi->extra && pi->extra->vrfleak->bgp_orig)
@@ -6535,7 +6855,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Process change. */
bgp_aggregate_increment(bgp, p, pi, afi, safi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
if (SAFI_MPLS_VPN == safi &&
bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT) {
@@ -6573,8 +6893,9 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
SET_FLAG(new->flags, BGP_PATH_VALID);
bgp_path_info_extra_get(new);
if (num_labels) {
- new->extra->label[0] = bgp_static->label;
- new->extra->num_labels = num_labels;
+ labels.num_labels = num_labels;
+ labels.label[0] = bgp_static->label;
+ new->extra->labels = bgp_labels_intern(&labels);
}
#ifdef ENABLE_BGP_VNC
label = decode_label(&bgp_static->label);
@@ -6593,7 +6914,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
bgp_dest_unlock_node(dest);
/* Process change. */
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
if (SAFI_UNICAST == safi &&
(bgp->inst_type == BGP_INSTANCE_TYPE_VRF ||
@@ -6632,6 +6953,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
/* Withdraw static BGP route from routing table. */
if (pi) {
+ SET_FLAG(pi->flags, BGP_PATH_UNSORTED);
#ifdef ENABLE_BGP_VNC
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
rfapiProcessWithdraw(pi->peer, NULL, p, prd, pi->attr,
@@ -6650,7 +6972,7 @@ void bgp_static_withdraw(struct bgp *bgp, const struct prefix *p, afi_t afi,
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
/* Unlock bgp_node_lookup. */
@@ -7055,7 +7377,7 @@ static void bgp_purge_af_static_redist_routes(struct bgp *bgp, afi_t afi,
safi);
bgp_unlink_nexthop(pi);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
}
@@ -7418,8 +7740,10 @@ static void bgp_aggregate_install(
/*
* Mark the old as unusable
*/
- if (pi)
+ if (pi) {
bgp_path_info_delete(dest, pi);
+ bgp_process(bgp, dest, pi, afi, safi);
+ }
attr = bgp_attr_aggregate_intern(
bgp, origin, aspath, community, ecommunity, lcommunity,
@@ -7444,7 +7768,7 @@ static void bgp_aggregate_install(
SET_FLAG(new->flags, BGP_PATH_VALID);
bgp_path_info_add(dest, new);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, new, afi, safi);
} else {
uninstall_aggregate_route:
for (pi = orig; pi; pi = pi->next)
@@ -7456,7 +7780,7 @@ static void bgp_aggregate_install(
/* Withdraw static BGP route from routing table. */
if (pi) {
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
@@ -7542,7 +7866,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
const struct prefix *dest_p;
struct bgp_dest *dest, *top;
struct bgp_path_info *pi;
- bool toggle_suppression;
/* We've found a different MED we must revert any suppressed routes. */
top = bgp_node_get(table, p);
@@ -7552,7 +7875,6 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- toggle_suppression = false;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -7563,17 +7885,14 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
if (suppress) {
/* Suppress route if not suppressed already. */
if (aggr_suppress_path(aggregate, pi))
- toggle_suppression = true;
+ bgp_process(bgp, dest, pi, afi, safi);
continue;
}
/* Install route if there is no more suppression. */
if (aggr_unsuppress_path(aggregate, pi))
- toggle_suppression = true;
+ bgp_process(bgp, dest, pi, afi, safi);
}
-
- if (toggle_suppression)
- bgp_process(bgp, dest, afi, safi);
}
bgp_dest_unlock_node(top);
}
@@ -7632,7 +7951,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
struct bgp_path_info *pi;
- unsigned long match = 0;
uint8_t atomic_aggregate = 0;
/* If the bgp instance is being deleted or self peer is deleted
@@ -7682,8 +8000,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (!bgp_check_advertise(bgp, dest, safi))
continue;
- match = 0;
-
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
continue;
@@ -7707,7 +8023,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (aggregate->summary_only
&& AGGREGATE_MED_VALID(aggregate)) {
if (aggr_suppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
/*
@@ -7723,7 +8039,7 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
&& AGGREGATE_MED_VALID(aggregate)
&& aggr_suppress_map_test(bgp, aggregate, pi)) {
if (aggr_suppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
aggregate->count++;
@@ -7784,8 +8100,6 @@ bool bgp_aggregate_route(struct bgp *bgp, const struct prefix *p, afi_t afi,
aggregate,
bgp_attr_get_lcommunity(pi->attr));
}
- if (match)
- bgp_process(bgp, dest, afi, safi);
}
if (aggregate->as_set) {
bgp_compute_aggregate_aspath_val(aggregate);
@@ -7845,7 +8159,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
struct bgp_dest *top;
struct bgp_dest *dest;
struct bgp_path_info *pi;
- unsigned long match;
table = bgp->rib[afi][safi];
@@ -7857,7 +8170,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (dest_p->prefixlen <= p->prefixlen)
continue;
- match = 0;
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (BGP_PATH_HOLDDOWN(pi))
@@ -7875,10 +8187,11 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
if (pi->extra && pi->extra->aggr_suppressors &&
listcount(pi->extra->aggr_suppressors)) {
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, dest, pi, afi, safi);
}
- aggregate->count--;
+ if (aggregate->count > 0)
+ aggregate->count--;
if (pi->attr->origin == BGP_ORIGIN_INCOMPLETE)
aggregate->incomplete_origin_count--;
@@ -7917,10 +8230,6 @@ void bgp_aggregate_delete(struct bgp *bgp, const struct prefix *p, afi_t afi,
pi->attr));
}
}
-
- /* If this node was suppressed, process the change. */
- if (match)
- bgp_process(bgp, dest, afi, safi);
}
if (aggregate->as_set) {
aspath_free(aggregate->aspath);
@@ -8069,7 +8378,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
struct community *community = NULL;
struct ecommunity *ecommunity = NULL;
struct lcommunity *lcommunity = NULL;
- unsigned long match = 0;
/* If the bgp instance is being deleted or self peer is deleted
* then do not create aggregate route
@@ -8086,12 +8394,12 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, pi->net, pi, afi, safi);
if (aggregate->suppress_map_name && AGGREGATE_MED_VALID(aggregate)
&& aggr_suppress_map_test(bgp, aggregate, pi))
if (aggr_unsuppress_path(aggregate, pi))
- match++;
+ bgp_process(bgp, pi->net, pi, afi, safi);
/*
* This must be called after `summary`, `suppress-map` check to avoid
@@ -8133,10 +8441,6 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
aggregate, bgp_attr_get_lcommunity(pi->attr));
}
- /* If this node was suppressed, process the change. */
- if (match)
- bgp_process(bgp, pi->net, afi, safi);
-
origin = BGP_ORIGIN_IGP;
if (aggregate->incomplete_origin_count > 0)
origin = BGP_ORIGIN_INCOMPLETE;
@@ -8594,6 +8898,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
afi_t afi;
route_map_result_t ret;
struct bgp_redist *red;
+ struct interface *ifp;
if (CHECK_FLAG(bgp->flags, BGP_FLAG_DELETE_IN_PROGRESS) ||
bgp->peer_self == NULL)
@@ -8653,6 +8958,11 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
}
attr.nh_type = nhtype;
attr.nh_ifindex = ifindex;
+ ifp = if_lookup_by_index(ifindex, bgp->vrf_id);
+ if (ifp && if_is_operative(ifp))
+ SET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
+ else
+ UNSET_FLAG(attr.nh_flags, BGP_ATTR_NH_IF_OPERSTATE);
attr.med = metric;
attr.distance = distance;
@@ -8740,7 +9050,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
/* Process change. */
bgp_aggregate_increment(bgp, p, bpi, afi,
SAFI_UNICAST);
- bgp_process(bgp, bn, afi, SAFI_UNICAST);
+ bgp_process(bgp, bn, bpi, afi, SAFI_UNICAST);
bgp_dest_unlock_node(bn);
aspath_unintern(&attr.aspath);
@@ -8763,7 +9073,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
bgp_path_info_add(bn, new);
bgp_dest_unlock_node(bn);
SET_FLAG(bn->flags, BGP_NODE_FIB_INSTALLED);
- bgp_process(bgp, bn, afi, SAFI_UNICAST);
+ bgp_process(bgp, bn, new, afi, SAFI_UNICAST);
if ((bgp->inst_type == BGP_INSTANCE_TYPE_VRF)
|| (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)) {
@@ -8804,7 +9114,7 @@ void bgp_redistribute_delete(struct bgp *bgp, struct prefix *p, uint8_t type,
}
bgp_aggregate_decrement(bgp, p, pi, afi, SAFI_UNICAST);
bgp_path_info_delete(dest, pi);
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
}
bgp_dest_unlock_node(dest);
}
@@ -8838,7 +9148,7 @@ void bgp_redistribute_withdraw(struct bgp *bgp, afi_t afi, int type,
bgp_path_info_delete(dest, pi);
if (!CHECK_FLAG(bgp->flags,
BGP_FLAG_DELETE_IN_PROGRESS))
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
else {
dest = bgp_path_info_reap(dest, pi);
assert(dest);
@@ -8984,6 +9294,9 @@ static void route_vty_short_status_out(struct vty *vty,
if (path->extra && bgp_path_suppressed(path))
json_object_boolean_true_add(json_path, "suppressed");
+ if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED))
+ json_object_boolean_true_add(json_path, "unsorted");
+
if (CHECK_FLAG(path->flags, BGP_PATH_VALID)
&& !CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
json_object_boolean_true_add(json_path, "valid");
@@ -9046,6 +9359,8 @@ static void route_vty_short_status_out(struct vty *vty,
/* Selected */
if (CHECK_FLAG(path->flags, BGP_PATH_HISTORY))
vty_out(vty, "h");
+ else if (CHECK_FLAG(path->flags, BGP_PATH_UNSORTED))
+ vty_out(vty, "u");
else if (CHECK_FLAG(path->flags, BGP_PATH_DAMPED))
vty_out(vty, "d");
else if (CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
@@ -9061,6 +9376,9 @@ static void route_vty_short_status_out(struct vty *vty,
vty_out(vty, "i");
else
vty_out(vty, " ");
+
+ /* adding space between next column */
+ vty_out(vty, " ");
}
static char *bgp_nexthop_hostname(struct peer *peer,
@@ -9341,10 +9659,8 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
json_object_string_add(json_nexthop_ll, "scope",
"link-local");
- if ((IPV6_ADDR_CMP(&attr->mp_nexthop_global,
- &attr->mp_nexthop_local)
- != 0)
- && !attr->mp_nexthop_prefer_global)
+ if (!CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
json_object_boolean_true_add(
json_nexthop_ll, "used");
else
@@ -9356,10 +9672,11 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
} else {
/* Display LL if LL/Global both in table unless
* prefer-global is set */
- if (((attr->mp_nexthop_len
- == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL)
- && !attr->mp_nexthop_prefer_global)
- || (path->peer->conf_if)) {
+ if (((attr->mp_nexthop_len ==
+ BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL) &&
+ !CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)) ||
+ (path->peer->conf_if)) {
if (path->peer->conf_if) {
len = vty_out(vty, "%s",
path->peer->conf_if);
@@ -9764,8 +10081,8 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
}
}
- if (bgp_is_valid_label(&path->extra->label[0])) {
- label = decode_label(&path->extra->label[0]);
+ if (bgp_path_info_has_valid_label(path)) {
+ label = decode_label(&path->extra->labels->label[0]);
if (json) {
json_object_int_add(json_out, "notag", label);
json_object_array_add(json, json_out);
@@ -10155,7 +10472,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object *json_paths)
{
char buf[INET6_ADDRSTRLEN];
- char tag_buf[30];
+ char vni_buf[30] = {};
struct attr *attr = path->attr;
time_t tbuf;
char timebuf[32];
@@ -10163,6 +10480,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object *json_cluster_list = NULL;
json_object *json_cluster_list_list = NULL;
json_object *json_ext_community = NULL;
+ json_object *json_ext_ipv6_community = NULL;
json_object *json_last_update = NULL;
json_object *json_pmsi = NULL;
json_object *json_nexthop_global = NULL;
@@ -10187,7 +10505,6 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
uint32_t bos = 0;
uint32_t exp = 0;
mpls_label_t label = MPLS_INVALID_LABEL;
- tag_buf[0] = '\0';
struct bgp_path_info *bpi_ultimate =
bgp_get_imported_bpi_ultimate(path);
@@ -10197,26 +10514,22 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_nexthop_global = json_object_new_object();
}
+ if (bgp_path_info_num_labels(path)) {
+ bgp_evpn_label2str(path->extra->labels->label,
+ path->extra->labels->num_labels, vni_buf,
+ sizeof(vni_buf));
+ }
+
if (safi == SAFI_EVPN) {
if (!json_paths)
vty_out(vty, " Route %pFX", p);
- }
- if (path->extra) {
- if (path->extra && path->extra->num_labels) {
- bgp_evpn_label2str(path->extra->label,
- path->extra->num_labels, tag_buf,
- sizeof(tag_buf));
- }
- if (safi == SAFI_EVPN) {
- if (!json_paths) {
- if (tag_buf[0] != '\0')
- vty_out(vty, " VNI %s", tag_buf);
- } else {
- if (tag_buf[0])
- json_object_string_add(json_path, "vni",
- tag_buf);
- }
+ if (vni_buf[0]) {
+ if (json_paths)
+ json_object_string_add(json_path, "vni",
+ vni_buf);
+ else
+ vty_out(vty, " VNI %s", vni_buf);
}
}
@@ -10256,7 +10569,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, ":%pFX, VNI %s",
(struct prefix_evpn *)
bgp_dest_get_prefix(dest),
- tag_buf);
+ vni_buf);
if (CHECK_FLAG(attr->es_flags, ATTR_ES_L3_NHG))
vty_out(vty, ", L3NHG %s",
CHECK_FLAG(
@@ -10612,7 +10925,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
json_object_boolean_true_add(json_nexthop_ll,
"accessible");
- if (!attr->mp_nexthop_prefer_global)
+ if (!CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
json_object_boolean_true_add(json_nexthop_ll,
"used");
else
@@ -10622,7 +10936,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, " (%s) %s\n",
inet_ntop(AF_INET6, &attr->mp_nexthop_local,
buf, INET6_ADDRSTRLEN),
- attr->mp_nexthop_prefer_global
+ CHECK_FLAG(attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)
? "(prefer-global)"
: "(used)");
}
@@ -10869,6 +11184,21 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
}
+ if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_IPV6_EXT_COMMUNITIES)) {
+ if (json_paths) {
+ json_ext_ipv6_community = json_object_new_object();
+ json_object_string_add(json_ext_ipv6_community, "string",
+ bgp_attr_get_ipv6_ecommunity(attr)
+ ->str);
+ json_object_object_add(json_path,
+ "extendedIpv6Community",
+ json_ext_ipv6_community);
+ } else {
+ vty_out(vty, " Extended IPv6 Community: %s\n",
+ bgp_attr_get_ipv6_ecommunity(attr)->str);
+ }
+ }
+
/* Line 6 display Large community */
if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_LARGE_COMMUNITIES)) {
if (json_paths) {
@@ -10948,13 +11278,13 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
if (path->extra && path->extra->damp_info)
- bgp_damp_info_vty(vty, path, afi, safi, json_path);
+ bgp_damp_info_vty(vty, bgp, path, afi, safi, json_path);
/* Remote Label */
- if (path->extra && bgp_is_valid_label(&path->extra->label[0])
- && (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
- mpls_lse_decode(path->extra->label[0], &label, &ttl, &exp,
- &bos);
+ if (bgp_path_info_has_valid_label(path) &&
+ (safi != SAFI_EVPN && !is_route_parent_evpn(path))) {
+ mpls_lse_decode(path->extra->labels->label[0], &label, &ttl,
+ &exp, &bos);
if (json_paths)
json_object_int_add(json_path, "remoteLabel", label);
@@ -13686,21 +14016,23 @@ enum bgp_pcounts {
PCOUNT_COUNTED,
PCOUNT_BPATH_SELECTED,
PCOUNT_PFCNT, /* the figure we display to users */
+ PCOUNT_UNSORTED,
PCOUNT_MAX,
};
static const char *const pcount_strs[] = {
- [PCOUNT_ADJ_IN] = "Adj-in",
- [PCOUNT_DAMPED] = "Damped",
- [PCOUNT_REMOVED] = "Removed",
- [PCOUNT_HISTORY] = "History",
- [PCOUNT_STALE] = "Stale",
- [PCOUNT_VALID] = "Valid",
- [PCOUNT_ALL] = "All RIB",
- [PCOUNT_COUNTED] = "PfxCt counted",
- [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
- [PCOUNT_PFCNT] = "Useable",
- [PCOUNT_MAX] = NULL,
+ [PCOUNT_ADJ_IN] = "Adj-in",
+ [PCOUNT_DAMPED] = "Damped",
+ [PCOUNT_REMOVED] = "Removed",
+ [PCOUNT_HISTORY] = "History",
+ [PCOUNT_STALE] = "Stale",
+ [PCOUNT_VALID] = "Valid",
+ [PCOUNT_ALL] = "All RIB",
+ [PCOUNT_COUNTED] = "PfxCt counted",
+ [PCOUNT_BPATH_SELECTED] = "PfxCt Best Selected",
+ [PCOUNT_PFCNT] = "Useable",
+ [PCOUNT_UNSORTED] = "Unsorted",
+ [PCOUNT_MAX] = NULL,
};
struct peer_pcounts {
@@ -13741,6 +14073,8 @@ static void bgp_peer_count_proc(struct bgp_dest *rn, struct peer_pcounts *pc)
pc->count[PCOUNT_PFCNT]++;
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED))
pc->count[PCOUNT_BPATH_SELECTED]++;
+ if (CHECK_FLAG(pi->flags, BGP_PATH_UNSORTED))
+ pc->count[PCOUNT_UNSORTED]++;
if (CHECK_FLAG(pi->flags, BGP_PATH_COUNTED)) {
pc->count[PCOUNT_COUNTED]++;
@@ -15496,9 +15830,8 @@ 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;
- bgp_damp_info_free(
- pi->extra->damp_info,
- 1, afi, safi);
+ bgp_damp_info_free(pi->extra->damp_info,
+ NULL, 1);
pi = pi_temp;
} else
pi = pi->next;
@@ -15509,26 +15842,38 @@ static int bgp_clear_damp_route(struct vty *vty, const char *view_name,
}
} else {
dest = bgp_node_match(bgp->rib[afi][safi], &match);
- if (dest != NULL) {
- const struct prefix *dest_p = bgp_dest_get_prefix(dest);
+ if (!dest)
+ return CMD_SUCCESS;
- if (!prefix_check
- || dest_p->prefixlen == match.prefixlen) {
- pi = bgp_dest_get_bgp_path_info(dest);
- while (pi) {
- if (pi->extra && pi->extra->damp_info) {
- pi_temp = pi->next;
- bgp_damp_info_free(
- pi->extra->damp_info,
- 1, afi, safi);
- pi = pi_temp;
- } else
- pi = pi->next;
- }
+ const struct prefix *dest_p = bgp_dest_get_prefix(dest);
+
+ if (prefix_check || dest_p->prefixlen != match.prefixlen)
+ return CMD_SUCCESS;
+
+ pi = bgp_dest_get_bgp_path_info(dest);
+ while (pi) {
+ if (!(pi->extra && pi->extra->damp_info)) {
+ pi = pi->next;
+ continue;
}
- bgp_dest_unlock_node(dest);
+ pi_temp = pi->next;
+ struct bgp_damp_info *bdi = pi->extra->damp_info;
+
+ if (bdi->lastrecord != BGP_RECORD_UPDATE)
+ continue;
+
+ bgp_aggregate_increment(bgp,
+ bgp_dest_get_prefix(bdi->dest),
+ bdi->path, bdi->afi, bdi->safi);
+ bgp_process(bgp, bdi->dest, bdi->path, bdi->afi,
+ bdi->safi);
+
+ bgp_damp_info_free(pi->extra->damp_info, NULL, 1);
+ pi = pi_temp;
}
+
+ bgp_dest_unlock_node(dest);
}
return CMD_SUCCESS;
@@ -15542,7 +15887,9 @@ DEFUN (clear_ip_bgp_dampening,
BGP_STR
"Clear route flap dampening information\n")
{
- bgp_damp_info_clean(AFI_IP, SAFI_UNICAST);
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bgp_damp_info_clean(bgp, &bgp->damp[AFI_IP][SAFI_UNICAST], AFI_IP,
+ SAFI_UNICAST);
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 2929c75..89449ac 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -59,20 +59,15 @@ enum bgp_show_adj_route_type {
#define BGP_SHOW_SCODE_HEADER \
"Status codes: s suppressed, d damped, " \
- "h history, * valid, > best, = multipath,\n" \
+ "h history, u unsorted, * valid, > best, = multipath,\n" \
" i internal, r RIB-failure, S Stale, R Removed\n"
#define BGP_SHOW_OCODE_HEADER \
"Origin codes: i - IGP, e - EGP, ? - incomplete\n"
#define BGP_SHOW_NCODE_HEADER "Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self\n"
#define BGP_SHOW_RPKI_HEADER \
"RPKI validation codes: V valid, I invalid, N Not found\n\n"
-#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
-#define BGP_SHOW_HEADER_WIDE " Network Next Hop Metric LocPrf Weight Path\n"
-
-/* Maximum number of labels we can process or send with a prefix. We
- * really do only 1 for MPLS (BGP-LU) but we can do 2 for EVPN-VxLAN.
- */
-#define BGP_MAX_LABELS 2
+#define BGP_SHOW_HEADER " Network Next Hop Metric LocPrf Weight Path\n"
+#define BGP_SHOW_HEADER_WIDE " Network Next Hop Metric LocPrf Weight Path\n"
/* Maximum number of sids we can process or send with a prefix. */
#define BGP_MAX_SIDS 6
@@ -237,8 +232,7 @@ struct bgp_path_info_extra {
uint32_t igpmetric;
/* MPLS label(s) - VNI(s) for EVPN-VxLAN */
- mpls_label_t label[BGP_MAX_LABELS];
- uint32_t num_labels;
+ struct bgp_labels *labels;
/* timestamp of the rib installation */
time_t bgp_rib_uptime;
@@ -327,6 +321,7 @@ struct bgp_path_info {
#define BGP_PATH_ACCEPT_OWN (1 << 16)
#define BGP_PATH_MPLSVPN_LABEL_NH (1 << 17)
#define BGP_PATH_MPLSVPN_NH_LABEL_BIND (1 << 18)
+#define BGP_PATH_UNSORTED (1 << 19)
/* BGP route type. This can be static, RIP, OSPF, BGP etc. */
uint8_t type;
@@ -345,6 +340,8 @@ struct bgp_path_info {
unsigned short instance;
+ enum bgp_path_selection_reason reason;
+
/* Addpath identifiers */
uint32_t addpath_rx_id;
struct bgp_addpath_info_data tx_addpath;
@@ -750,12 +747,16 @@ extern void bgp_path_info_delete(struct bgp_dest *dest,
struct bgp_path_info *pi);
extern struct bgp_path_info_extra *
bgp_path_info_extra_get(struct bgp_path_info *path);
+extern bool bgp_path_info_has_valid_label(const struct bgp_path_info *path);
+extern uint8_t bgp_path_info_num_labels(const struct bgp_path_info *pi);
extern void bgp_path_info_set_flag(struct bgp_dest *dest,
struct bgp_path_info *path, uint32_t flag);
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, size_t buf_len);
+extern bool bgp_path_info_labels_same(const struct bgp_path_info *bpi,
+ const mpls_label_t *label, uint32_t n);
extern int bgp_nlri_parse_ip(struct peer *, struct attr *, struct bgp_nlri *);
@@ -792,16 +793,17 @@ extern void bgp_update(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, struct attr *attr, afi_t afi,
safi_t safi, int type, int sub_type,
struct prefix_rd *prd, mpls_label_t *label,
- uint32_t num_labels, int soft_reconfig,
+ uint8_t num_labels, int soft_reconfig,
struct bgp_route_evpn *evpn);
extern void bgp_withdraw(struct peer *peer, const struct prefix *p,
uint32_t addpath_id, afi_t afi, safi_t safi, int type,
int sub_type, struct prefix_rd *prd,
- mpls_label_t *label, uint32_t num_labels,
+ mpls_label_t *label, uint8_t num_labels,
struct bgp_route_evpn *evpn);
/* for bgp_nexthop and bgp_damp */
-extern void bgp_process(struct bgp *, struct bgp_dest *, afi_t, safi_t);
+extern void bgp_process(struct bgp *bgp, struct bgp_dest *dest,
+ struct bgp_path_info *pi, afi_t afi, safi_t safi);
/*
* Add an end-of-initial-update marker to the process queue. This is just a
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index dbc3d64..97ae92c 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1056,7 +1056,7 @@ static enum route_map_cmd_result_t
route_match_vni(void *rule, const struct prefix *prefix, void *object)
{
vni_t vni = 0;
- unsigned int label_cnt = 0;
+ unsigned int label_cnt;
struct bgp_path_info *path = NULL;
struct prefix_evpn *evp = (struct prefix_evpn *) prefix;
@@ -1081,13 +1081,10 @@ route_match_vni(void *rule, const struct prefix *prefix, void *object)
&& evp->prefix.route_type != BGP_EVPN_IP_PREFIX_ROUTE))
return RMAP_NOOP;
- if (path->extra == NULL)
- return RMAP_NOMATCH;
-
- for (;
- label_cnt < BGP_MAX_LABELS && label_cnt < path->extra->num_labels;
+ for (label_cnt = 0; label_cnt < BGP_MAX_LABELS &&
+ label_cnt < bgp_path_info_num_labels(path);
label_cnt++) {
- if (vni == label2vni(&path->extra->label[label_cnt]))
+ if (vni == label2vni(&path->extra->labels->label[label_cnt]))
return RMAP_MATCH;
}
@@ -1944,7 +1941,6 @@ route_set_srte_color(void *rule, const struct prefix *prefix, void *object)
path = object;
path->attr->srte_color = *srte_color;
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
return RMAP_OKAY;
}
@@ -2326,7 +2322,7 @@ static const struct route_map_rule_cmd route_set_aspath_prepend_cmd = {
static void *route_aspath_exclude_compile(const char *arg)
{
struct aspath_exclude *ase;
- struct aspath_exclude_list *ael;
+ struct as_list *aux_aslist;
const char *str = arg;
static const char asp_acl[] = "as-path-access-list";
@@ -2338,44 +2334,37 @@ static void *route_aspath_exclude_compile(const char *arg)
while (*str == ' ')
str++;
ase->exclude_aspath_acl_name = XSTRDUP(MTYPE_TMP, str);
- ase->exclude_aspath_acl = as_list_lookup(str);
+ aux_aslist = as_list_lookup(str);
+ if (!aux_aslist)
+ /* new orphan filter */
+ as_exclude_set_orphan(ase);
+ else
+ as_list_list_add_head(&aux_aslist->exclude_rule, ase);
+
+ ase->exclude_aspath_acl = aux_aslist;
} else
ase->aspath = aspath_str2aspath(str, bgp_get_asnotation(NULL));
- if (ase->exclude_aspath_acl) {
- ael = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
- sizeof(struct aspath_exclude_list));
- ael->bp_as_excl = ase;
- ael->next = ase->exclude_aspath_acl->exclude_list;
- ase->exclude_aspath_acl->exclude_list = ael;
- }
-
return ase;
}
static void route_aspath_exclude_free(void *rule)
{
struct aspath_exclude *ase = rule;
- struct aspath_exclude_list *cur_ael = NULL;
- struct aspath_exclude_list *prev_ael = NULL;
+ struct as_list *acl;
+
+ /* manage references to that rule*/
+ if (ase->exclude_aspath_acl) {
+ acl = ase->exclude_aspath_acl;
+ as_list_list_del(&acl->exclude_rule, ase);
+ } else {
+ /* no ref to acl, this aspath exclude is orphan */
+ as_exclude_remove_orphan(ase);
+ }
aspath_free(ase->aspath);
if (ase->exclude_aspath_acl_name)
XFREE(MTYPE_TMP, ase->exclude_aspath_acl_name);
- if (ase->exclude_aspath_acl)
- cur_ael = ase->exclude_aspath_acl->exclude_list;
- while (cur_ael) {
- if (cur_ael->bp_as_excl == ase) {
- if (prev_ael)
- prev_ael->next = cur_ael->next;
- else
- ase->exclude_aspath_acl->exclude_list = NULL;
- XFREE(MTYPE_ROUTE_MAP_COMPILED, cur_ael);
- break;
- }
- prev_ael = cur_ael;
- cur_ael = cur_ael->next;
- }
XFREE(MTYPE_ROUTE_MAP_COMPILED, ase);
}
@@ -2410,16 +2399,10 @@ route_set_aspath_exclude(void *rule, const struct prefix *dummy, void *object)
else if (ase->exclude_all)
path->attr->aspath = aspath_filter_exclude_all(new_path);
- else if (ase->exclude_aspath_acl_name) {
- if (!ase->exclude_aspath_acl)
- ase->exclude_aspath_acl =
- as_list_lookup(ase->exclude_aspath_acl_name);
- if (ase->exclude_aspath_acl)
- path->attr->aspath =
- aspath_filter_exclude_acl(new_path,
- ase->exclude_aspath_acl);
- }
-
+ else if (ase->exclude_aspath_acl)
+ path->attr->aspath =
+ aspath_filter_exclude_acl(new_path,
+ ase->exclude_aspath_acl);
return RMAP_OKAY;
}
@@ -3196,7 +3179,7 @@ struct rmap_ecomm_lb_set {
#define RMAP_ECOMM_LB_SET_CUMUL 2
#define RMAP_ECOMM_LB_SET_NUM_MPATH 3
bool non_trans;
- uint32_t bw;
+ uint64_t bw;
};
static enum route_map_cmd_result_t
@@ -3206,8 +3189,7 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
struct bgp_path_info *path;
struct peer *peer;
struct ecommunity ecom_lb = {0};
- struct ecommunity_val lb_eval;
- uint32_t bw_bytes = 0;
+ uint64_t bw_bytes = 0;
uint16_t mpath_count = 0;
struct ecommunity *new_ecom;
struct ecommunity *old_ecom;
@@ -3221,13 +3203,13 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
/* Build link bandwidth extended community */
as = (peer->bgp->as > BGP_AS_MAX) ? BGP_AS_TRANS : peer->bgp->as;
if (rels->lb_type == RMAP_ECOMM_LB_SET_VALUE) {
- bw_bytes = ((uint64_t)rels->bw * 1000 * 1000) / 8;
+ bw_bytes = (rels->bw * 1000 * 1000) / 8;
} else if (rels->lb_type == RMAP_ECOMM_LB_SET_CUMUL) {
/* process this only for the best path. */
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
return RMAP_OKAY;
- bw_bytes = (uint32_t)bgp_path_info_mpath_cumbw(path);
+ bw_bytes = bgp_path_info_mpath_cumbw(path);
if (!bw_bytes)
return RMAP_OKAY;
@@ -3237,31 +3219,53 @@ route_set_ecommunity_lb(void *rule, const struct prefix *prefix, void *object)
if (!CHECK_FLAG(path->flags, BGP_PATH_SELECTED))
return RMAP_OKAY;
- bw_bytes = ((uint64_t)peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
+ bw_bytes = (peer->bgp->lb_ref_bw * 1000 * 1000) / 8;
mpath_count = bgp_path_info_mpath_count(path) + 1;
bw_bytes *= mpath_count;
}
- encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
- CHECK_FLAG(peer->flags,
- PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_EXTENDED_LINK_BANDWIDTH)) {
+ struct ecommunity_val_ipv6 lb_eval;
- /* add to route or merge with existing */
- old_ecom = bgp_attr_get_ecommunity(path->attr);
- if (old_ecom) {
- new_ecom = ecommunity_dup(old_ecom);
- ecommunity_add_val(new_ecom, &lb_eval, true, true);
- if (!old_ecom->refcnt)
- ecommunity_free(&old_ecom);
+ encode_lb_extended_extcomm(as, bw_bytes, rels->non_trans,
+ &lb_eval);
+
+ old_ecom = bgp_attr_get_ipv6_ecommunity(path->attr);
+ if (old_ecom) {
+ new_ecom = ecommunity_dup(old_ecom);
+ ecommunity_add_val_ipv6(new_ecom, &lb_eval, true, true);
+ if (!old_ecom->refcnt)
+ ecommunity_free(&old_ecom);
+ } else {
+ ecom_lb.size = 1;
+ ecom_lb.unit_size = IPV6_ECOMMUNITY_SIZE;
+ ecom_lb.val = (uint8_t *)lb_eval.val;
+ new_ecom = ecommunity_dup(&ecom_lb);
+ }
+
+ bgp_attr_set_ipv6_ecommunity(path->attr, new_ecom);
} else {
- ecom_lb.size = 1;
- ecom_lb.unit_size = ECOMMUNITY_SIZE;
- ecom_lb.val = (uint8_t *)lb_eval.val;
- new_ecom = ecommunity_dup(&ecom_lb);
- }
+ struct ecommunity_val lb_eval;
+
+ encode_lb_extcomm(as, bw_bytes, rels->non_trans, &lb_eval,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_DISABLE_LINK_BW_ENCODING_IEEE));
+
+ old_ecom = bgp_attr_get_ecommunity(path->attr);
+ if (old_ecom) {
+ new_ecom = ecommunity_dup(old_ecom);
+ ecommunity_add_val(new_ecom, &lb_eval, true, true);
+ if (!old_ecom->refcnt)
+ ecommunity_free(&old_ecom);
+ } else {
+ ecom_lb.size = 1;
+ ecom_lb.unit_size = ECOMMUNITY_SIZE;
+ ecom_lb.val = (uint8_t *)lb_eval.val;
+ new_ecom = ecommunity_dup(&ecom_lb);
+ }
- /* new_ecom will be intern()'d or attr_flush()'d in call stack */
- bgp_attr_set_ecommunity(path->attr, new_ecom);
+ bgp_attr_set_ecommunity(path->attr, new_ecom);
+ }
/* Mark that route-map has set link bandwidth; used in attribute
* setting decisions.
@@ -3275,7 +3279,7 @@ static void *route_set_ecommunity_lb_compile(const char *arg)
{
struct rmap_ecomm_lb_set *rels;
uint8_t lb_type;
- uint32_t bw = 0;
+ uint64_t bw = 0;
char bw_str[40] = {0};
char *p, *str;
bool non_trans = false;
@@ -3317,13 +3321,8 @@ static enum route_map_cmd_result_t
route_set_ecommunity_color(void *rule, const struct prefix *prefix,
void *object)
{
- struct bgp_path_info *path;
-
- path = object;
-
route_set_ecommunity(rule, prefix, object);
- path->attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR);
return RMAP_OKAY;
}
@@ -3953,11 +3952,11 @@ route_set_ipv6_nexthop_prefer_global(void *rule, const struct prefix *prefix,
if (CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IN)
|| CHECK_FLAG(peer->rmap_type, PEER_RMAP_TYPE_IMPORT)) {
/* Set next hop preference to global */
- path->attr->mp_nexthop_prefer_global = true;
+ SET_FLAG(path->attr->nh_flags, BGP_ATTR_NH_MP_PREFER_GLOBAL);
SET_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
} else {
- path->attr->mp_nexthop_prefer_global = false;
+ UNSET_FLAG(path->attr->nh_flags, BGP_ATTR_NH_MP_PREFER_GLOBAL);
SET_FLAG(path->attr->rmap_change_flags,
BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED);
}
@@ -6880,7 +6879,7 @@ DEFUN_YANG(no_set_ecommunity_none, no_set_ecommunity_none_cmd,
DEFUN_YANG (set_ecommunity_lb,
set_ecommunity_lb_cmd,
- "set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
+ "set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]",
SET_STR
"BGP extended community attribute\n"
"Link bandwidth extended community\n"
@@ -6934,7 +6933,7 @@ DEFUN_YANG (set_ecommunity_lb,
DEFUN_YANG (no_set_ecommunity_lb,
no_set_ecommunity_lb_cmd,
- "no set extcommunity bandwidth <(1-25600)|cumulative|num-multipaths> [non-transitive]",
+ "no set extcommunity bandwidth <(1-4294967295)|cumulative|num-multipaths> [non-transitive]",
NO_STR
SET_STR
"BGP extended community attribute\n"
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index c1d6ee1..15c32ea 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -2937,7 +2937,7 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
struct routemap_hook_context *rhc;
enum ecommunity_lb_type lb_type;
char str[VTY_BUFSIZ];
- uint16_t bandwidth;
+ uint32_t bandwidth;
int ret;
/* Add configuration. */
@@ -2951,8 +2951,8 @@ lib_route_map_entry_set_action_rmap_set_action_extcommunity_lb_finish(
switch (lb_type) {
case EXPLICIT_BANDWIDTH:
- bandwidth = yang_dnode_get_uint16(args->dnode, "bandwidth");
- snprintf(str, sizeof(str), "%d", bandwidth);
+ bandwidth = yang_dnode_get_uint32(args->dnode, "bandwidth");
+ snprintf(str, sizeof(str), "%u", bandwidth);
break;
case CUMULATIVE_BANDWIDTH:
snprintf(str, sizeof(str), "%s", "cumulative");
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index 22f78fb..a487f49 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -29,6 +29,7 @@
#include "bgpd/bgpd.h"
#include "bgpd/bgp_table.h"
#include "bgp_advertise.h"
+#include "bgp_label.h"
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_attr.h"
#include "bgpd/bgp_aspath.h"
@@ -656,17 +657,16 @@ static void revalidate_bgp_node(struct bgp_dest *bgp_dest, afi_t afi,
safi_t safi)
{
struct bgp_adj_in *ain;
+ mpls_label_t *label;
+ uint8_t num_labels;
for (ain = bgp_dest->adj_in; ain; ain = ain->next) {
struct bgp_path_info *path =
bgp_dest_get_bgp_path_info(bgp_dest);
- mpls_label_t *label = NULL;
- uint32_t num_labels = 0;
- if (path && path->extra) {
- label = path->extra->label;
- num_labels = path->extra->num_labels;
- }
+ num_labels = bgp_path_info_num_labels(path);
+ label = num_labels ? path->extra->labels->label : NULL;
+
(void)bgp_update(ain->peer, bgp_dest_get_prefix(bgp_dest),
ain->addpath_rx_id, ain->attr, afi, safi,
ZEBRA_ROUTE_BGP, BGP_ROUTE_NORMAL, NULL, label,
@@ -1082,7 +1082,7 @@ static void print_prefix_table(struct vty *vty, struct rpki_vrf *rpki_vrf,
unsigned int number_of_ipv4_prefixes = 0;
unsigned int number_of_ipv6_prefixes = 0;
- struct rtr_mgr_group *group = get_connected_group(rpki_vrf);
+ struct rtr_mgr_group *group;
json_object *json_records = NULL;
if (!rpki_vrf)
@@ -1621,7 +1621,7 @@ static int bgp_rpki_write_vrf(struct vty *vty, struct vrf *vrf)
#endif
case TCP:
tcp_config = cache->tr_config.tcp_config;
- vty_out(vty, "%s rpki cache %s %s ", sep,
+ vty_out(vty, "%s rpki cache tcp %s %s ", sep,
tcp_config->host, tcp_config->port);
if (tcp_config->bindaddr)
vty_out(vty, "source %s ",
@@ -1630,7 +1630,7 @@ static int bgp_rpki_write_vrf(struct vty *vty, struct vrf *vrf)
#if defined(FOUND_SSH)
case SSH:
ssh_config = cache->tr_config.ssh_config;
- vty_out(vty, "%s rpki cache %s %u %s %s %s ", sep,
+ vty_out(vty, "%s rpki cache ssh %s %u %s %s %s ", sep,
ssh_config->host, ssh_config->port,
ssh_config->username,
ssh_config->client_privkey_path,
@@ -1918,8 +1918,11 @@ DEFUN (no_rpki_retry_interval,
return CMD_SUCCESS;
}
+#if CONFDATE > 20240916
+CPP_NOTICE("Remove rpki_cache_cmd")
+#endif
DEFPY(rpki_cache, rpki_cache_cmd,
- "rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
+ "rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [KNOWN_HOSTS_PATH]> [source <A.B.C.D>$bindaddr] preference (1-255)",
RPKI_OUTPUT_STRING
"Install a cache server to current group\n"
"IP address of cache server\n"
@@ -1928,7 +1931,7 @@ DEFPY(rpki_cache, rpki_cache_cmd,
"SSH port number\n"
"SSH user name\n"
"Path to own SSH private key\n"
- "Path to Public key of cache server\n"
+ "Path to the known hosts file\n"
"Configure source IP address of RPKI connection\n"
"Define a Source IP Address\n"
"Preference of the cache server\n"
@@ -1967,7 +1970,7 @@ DEFPY(rpki_cache, rpki_cache_cmd,
if (ssh_uname) {
#if defined(FOUND_SSH)
return_value = add_ssh_cache(rpki_vrf, cache, sshport, ssh_uname,
- ssh_privkey, server_pubkey,
+ ssh_privkey, known_hosts_path,
preference, bindaddr_str);
#else
return_value = SUCCESS;
@@ -1990,19 +1993,143 @@ DEFPY(rpki_cache, rpki_cache_cmd,
return CMD_SUCCESS;
}
+DEFPY(rpki_cache_tcp, rpki_cache_tcp_cmd,
+ "rpki cache tcp <A.B.C.D|WORD>$cache TCPPORT [source <A.B.C.D>$bindaddr] preference (1-255)",
+ RPKI_OUTPUT_STRING
+ "Install a cache server to current group\n"
+ "Use TCP\n"
+ "IP address of cache server\n"
+ "Hostname of cache server\n"
+ "TCP port number\n"
+ "Configure source IP address of RPKI connection\n"
+ "Define a Source IP Address\n"
+ "Preference of the cache server\n"
+ "Preference value\n")
+{
+ int return_value;
+ struct listnode *cache_node;
+ struct cache *current_cache;
+ struct rpki_vrf *rpki_vrf;
+ bool init;
+
+ if (vty->node == RPKI_VRF_NODE)
+ rpki_vrf = VTY_GET_CONTEXT_SUB(rpki_vrf);
+ else
+ rpki_vrf = VTY_GET_CONTEXT(rpki_vrf);
+
+ if (!rpki_vrf)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!rpki_vrf || !rpki_vrf->cache_list)
+ return CMD_WARNING;
+
+ init = !!list_isempty(rpki_vrf->cache_list);
+
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node,
+ current_cache)) {
+ if (current_cache->preference == preference) {
+ vty_out(vty,
+ "Cache with preference %ld is already configured\n",
+ preference);
+ return CMD_WARNING;
+ }
+ }
+
+ return_value = add_tcp_cache(rpki_vrf, cache, tcpport, preference,
+ bindaddr_str);
+
+ if (return_value == ERROR) {
+ vty_out(vty, "Could not create new rpki cache\n");
+ return CMD_WARNING;
+ }
+
+ if (init)
+ start(rpki_vrf);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY(rpki_cache_ssh, rpki_cache_ssh_cmd,
+ "rpki cache ssh <A.B.C.D|WORD>$cache (1-65535)$sshport SSH_UNAME SSH_PRIVKEY [KNOWN_HOSTS_PATH] [source <A.B.C.D>$bindaddr] preference (1-255)",
+ RPKI_OUTPUT_STRING
+ "Install a cache server to current group\n"
+ "Use SSH\n"
+ "IP address of cache server\n"
+ "Hostname of cache server\n"
+ "SSH port number\n"
+ "SSH user name\n"
+ "Path to own SSH private key\n"
+ "Path to the known hosts file\n"
+ "Configure source IP address of RPKI connection\n"
+ "Define a Source IP Address\n"
+ "Preference of the cache server\n"
+ "Preference value\n")
+{
+ int return_value;
+ struct listnode *cache_node;
+ struct cache *current_cache;
+ struct rpki_vrf *rpki_vrf;
+ bool init;
+
+ if (vty->node == RPKI_VRF_NODE)
+ rpki_vrf = VTY_GET_CONTEXT_SUB(rpki_vrf);
+ else
+ rpki_vrf = VTY_GET_CONTEXT(rpki_vrf);
+
+ if (!rpki_vrf)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (!rpki_vrf || !rpki_vrf->cache_list)
+ return CMD_WARNING;
+
+ init = !!list_isempty(rpki_vrf->cache_list);
+
+ for (ALL_LIST_ELEMENTS_RO(rpki_vrf->cache_list, cache_node,
+ current_cache)) {
+ if (current_cache->preference == preference) {
+ vty_out(vty,
+ "Cache with preference %ld is already configured\n",
+ preference);
+ return CMD_WARNING;
+ }
+ }
+
+#if defined(FOUND_SSH)
+ return_value = add_ssh_cache(rpki_vrf, cache, sshport, ssh_uname,
+ ssh_privkey, known_hosts_path, preference,
+ bindaddr_str);
+#else
+ return_value = SUCCESS;
+ vty_out(vty,
+ "ssh sockets are not supported. Please recompile rtrlib and frr with ssh support. If you want to use it\n");
+#endif
+
+ if (return_value == ERROR) {
+ vty_out(vty, "Could not create new rpki cache\n");
+ return CMD_WARNING;
+ }
+
+ if (init)
+ start(rpki_vrf);
+
+ return CMD_SUCCESS;
+}
+
DEFPY (no_rpki_cache,
no_rpki_cache_cmd,
- "no rpki cache <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [SERVER_PUBKEY]> [source <A.B.C.D>$bindaddr] preference (1-255)",
+ "no rpki cache <tcp|ssh> <A.B.C.D|WORD> <TCPPORT|(1-65535)$sshport SSH_UNAME SSH_PRIVKEY [KNOWN_HOSTS_PATH]> [source <A.B.C.D>$bindaddr] preference (1-255)",
NO_STR
RPKI_OUTPUT_STRING
"Install a cache server to current group\n"
+ "Use TCP\n"
+ "Use SSH\n"
"IP address of cache server\n"
"Hostname of cache server\n"
"TCP port number\n"
"SSH port number\n"
"SSH user name\n"
"Path to own SSH private key\n"
- "Path to Public key of cache server\n"
+ "Path to the known hosts file\n"
"Configure source IP address of RPKI connection\n"
"Define a Source IP Address\n"
"Preference of the cache server\n"
@@ -2088,16 +2215,18 @@ DEFPY (show_rpki_prefix_table,
DEFPY (show_rpki_as_number,
show_rpki_as_number_cmd,
- "show rpki as-number ASNUM$by_asn [vrf NAME$vrfname] [json$uj]",
+ "show rpki as-number <0$zero|ASNUM$by_asn> [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Lookup by ASN in prefix table\n"
+ "AS Number of 0, see RFC-7607\n"
"AS Number\n"
VRF_CMD_HELP_STR
JSON_STR)
{
struct json_object *json = NULL;
struct rpki_vrf *rpki_vrf;
+ as_t as;
if (uj)
json = json_object_new_object();
@@ -2118,18 +2247,24 @@ DEFPY (show_rpki_as_number,
return CMD_WARNING;
}
- print_prefix_table_by_asn(vty, by_asn, rpki_vrf, json);
+ if (zero)
+ as = 0;
+ else
+ as = by_asn;
+
+ print_prefix_table_by_asn(vty, as, rpki_vrf, json);
return CMD_SUCCESS;
}
DEFPY (show_rpki_prefix,
show_rpki_prefix_cmd,
- "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASNUM$asn] [vrf NAME$vrfname] [json$uj]",
+ "show rpki prefix <A.B.C.D/M|X:X::X:X/M> [0$zero|ASNUM$asn] [vrf NAME$vrfname] [json$uj]",
SHOW_STR
RPKI_OUTPUT_STRING
"Lookup IP prefix and optionally ASN in prefix table\n"
"IPv4 prefix\n"
"IPv6 prefix\n"
+ "AS Number of 0, see RFC-7607\n"
"AS Number\n"
VRF_CMD_HELP_STR
JSON_STR)
@@ -2138,6 +2273,7 @@ DEFPY (show_rpki_prefix,
json_object *json_records = NULL;
enum asnotation_mode asnotation;
struct rpki_vrf *rpki_vrf;
+ as_t as;
if (uj)
json = json_object_new_object();
@@ -2153,6 +2289,11 @@ DEFPY (show_rpki_prefix,
return CMD_WARNING;
}
+ if (zero)
+ as = 0;
+ else
+ as = asn;
+
struct lrtr_ip_addr addr;
char addr_str[INET6_ADDRSTRLEN];
size_t addr_len = strchr(prefix_str, '/') - prefix_str;
@@ -2174,7 +2315,7 @@ DEFPY (show_rpki_prefix,
enum pfxv_state result;
if (pfx_table_validate_r(rpki_vrf->rtr_config->pfx_table, &matches,
- &match_count, asn, &addr, prefix->prefixlen,
+ &match_count, as, &addr, prefix->prefixlen,
&result) != PFX_SUCCESS) {
if (json) {
json_object_string_add(json, "error", "Prefix lookup failed.");
@@ -2198,7 +2339,7 @@ DEFPY (show_rpki_prefix,
const struct pfx_record *record = &matches[i];
if (record->max_len >= prefix->prefixlen &&
- ((asn != 0 && (uint32_t)asn == record->asn) || asn == 0)) {
+ ((as != 0 && (uint32_t)as == record->asn) || asn == 0)) {
print_record(&matches[i], vty, json_records,
asnotation);
}
@@ -2243,10 +2384,16 @@ DEFPY (show_rpki_cache_server,
if (cache->type == TCP) {
if (!json) {
vty_out(vty,
- "host: %s port: %s, preference: %hhu\n",
+ "host: %s port: %s, preference: %hhu, protocol: tcp",
cache->tr_config.tcp_config->host,
cache->tr_config.tcp_config->port,
cache->preference);
+ if (cache->tr_config.tcp_config->bindaddr)
+ vty_out(vty, ", source: %s\n",
+ cache->tr_config.tcp_config
+ ->bindaddr);
+ else
+ vty_out(vty, "\n");
} else {
json_server = json_object_new_object();
json_object_string_add(json_server, "mode",
@@ -2259,6 +2406,12 @@ DEFPY (show_rpki_cache_server,
cache->tr_config.tcp_config->port);
json_object_int_add(json_server, "preference",
cache->preference);
+ if (cache->tr_config.tcp_config->bindaddr)
+ json_object_string_add(json_server,
+ "source",
+ cache->tr_config
+ .tcp_config
+ ->bindaddr);
json_object_array_add(json_servers,
json_server);
}
@@ -2267,7 +2420,7 @@ DEFPY (show_rpki_cache_server,
} else if (cache->type == SSH) {
if (!json) {
vty_out(vty,
- "host: %s port: %d username: %s server_hostkey_path: %s client_privkey_path: %s, preference: %hhu\n",
+ "host: %s, port: %d, username: %s, server_hostkey_path: %s, client_privkey_path: %s, preference: %hhu, protocol: ssh",
cache->tr_config.ssh_config->host,
cache->tr_config.ssh_config->port,
cache->tr_config.ssh_config->username,
@@ -2276,6 +2429,12 @@ DEFPY (show_rpki_cache_server,
cache->tr_config.ssh_config
->client_privkey_path,
cache->preference);
+ if (cache->tr_config.ssh_config->bindaddr)
+ vty_out(vty, ", source: %s\n",
+ cache->tr_config.ssh_config
+ ->bindaddr);
+ else
+ vty_out(vty, "\n");
} else {
json_server = json_object_new_object();
json_object_string_add(json_server, "mode",
@@ -2299,6 +2458,12 @@ DEFPY (show_rpki_cache_server,
->client_privkey_path);
json_object_int_add(json_server, "preference",
cache->preference);
+ if (cache->tr_config.ssh_config->bindaddr)
+ json_object_string_add(json_server,
+ "source",
+ cache->tr_config
+ .ssh_config
+ ->bindaddr);
json_object_array_add(json_servers,
json_server);
}
@@ -2651,6 +2816,8 @@ static void install_cli_commands(void)
install_element(RPKI_NODE, &no_rpki_retry_interval_cmd);
/* Install rpki cache commands */
+ install_element(RPKI_NODE, &rpki_cache_tcp_cmd);
+ install_element(RPKI_NODE, &rpki_cache_ssh_cmd);
install_element(RPKI_NODE, &rpki_cache_cmd);
install_element(RPKI_NODE, &no_rpki_cache_cmd);
@@ -2673,6 +2840,8 @@ static void install_cli_commands(void)
install_element(RPKI_VRF_NODE, &no_rpki_retry_interval_cmd);
/* Install rpki cache commands */
+ install_element(RPKI_VRF_NODE, &rpki_cache_tcp_cmd);
+ install_element(RPKI_VRF_NODE, &rpki_cache_ssh_cmd);
install_element(RPKI_VRF_NODE, &rpki_cache_cmd);
install_element(RPKI_VRF_NODE, &no_rpki_cache_cmd);
diff --git a/bgpd/bgp_snmp_bgp4v2.c b/bgpd/bgp_snmp_bgp4v2.c
index 0c8ed33..7036910 100644
--- a/bgpd/bgp_snmp_bgp4v2.c
+++ b/bgpd/bgp_snmp_bgp4v2.c
@@ -853,7 +853,8 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[],
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
return SNMP_INTEGER(2);
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- if (path->attr->mp_nexthop_prefer_global)
+ if (CHECK_FLAG(path->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
return SNMP_INTEGER(2);
else
return SNMP_INTEGER(4);
@@ -867,7 +868,8 @@ static uint8_t *bgp4v2PathAttrTable(struct variable *v, oid name[],
case BGP_ATTR_NHLEN_IPV6_GLOBAL:
return SNMP_IP6ADDRESS(path->attr->mp_nexthop_global);
case BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL:
- if (path->attr->mp_nexthop_prefer_global)
+ if (CHECK_FLAG(path->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL))
return SNMP_IP6ADDRESS(
path->attr->mp_nexthop_global);
else
diff --git a/bgpd/bgp_table.c b/bgpd/bgp_table.c
index 8465ada..781909b 100644
--- a/bgpd/bgp_table.c
+++ b/bgpd/bgp_table.c
@@ -239,7 +239,11 @@ static ssize_t printfrr_bd(struct fbuf *buf, struct printfrr_eargs *ea,
if (!dest)
return bputs(buf, "(null)");
+#if !defined(DEV_BUILD)
/* need to get the real length even if buffer too small */
prefix2str(p, cbuf, sizeof(cbuf));
return bputs(buf, cbuf);
+#else
+ return bprintfrr(buf, "%s(%p)", prefix2str(p, cbuf, sizeof(cbuf)), dest);
+#endif
}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index 5b4c3be..130f5ca 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -76,6 +76,11 @@ struct bgp_dest {
STAILQ_ENTRY(bgp_dest) pq;
+ struct zebra_announce_item zai;
+ struct bgp_path_info *za_bgp_pi;
+ struct bgpevpn *za_vpn;
+ bool za_is_sync;
+
uint64_t version;
mpls_label_t local_label;
@@ -91,12 +96,16 @@ struct bgp_dest {
#define BGP_NODE_LABEL_REQUESTED (1 << 7)
#define BGP_NODE_SOFT_RECONFIG (1 << 8)
#define BGP_NODE_PROCESS_CLEAR (1 << 9)
+#define BGP_NODE_SCHEDULE_FOR_INSTALL (1 << 10)
+#define BGP_NODE_SCHEDULE_FOR_DELETE (1 << 11)
struct bgp_addpath_node_data tx_addpath;
enum bgp_path_selection_reason reason;
};
+DECLARE_LIST(zebra_announce, struct bgp_dest, zai);
+
extern void bgp_delete_listnode(struct bgp_dest *dest);
/*
* bgp_table_iter_t
diff --git a/bgpd/bgp_trace.c b/bgpd/bgp_trace.c
index 02afbeb..af45e7a 100644
--- a/bgpd/bgp_trace.c
+++ b/bgpd/bgp_trace.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index d13515a..124e7a3 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -145,11 +145,12 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
dst->addpath_type[afi][safi] = src->addpath_type[afi][safi];
dst->addpath_best_selected[afi][safi] =
src->addpath_best_selected[afi][safi];
+ dst->addpath_paths_limit[afi][safi] =
+ src->addpath_paths_limit[afi][safi];
dst->local_as = src->local_as;
dst->change_local_as = src->change_local_as;
dst->shared_network = src->shared_network;
dst->local_role = src->local_role;
- dst->as_path_loop_detection = src->as_path_loop_detection;
if (src->soo[afi][safi]) {
ecommunity_free(&dst->soo[afi][safi]);
@@ -348,6 +349,8 @@ static unsigned int updgrp_hash_key_make(const void *p)
key = jhash_1word((flags & PEER_UPDGRP_AF_FLAGS), key);
key = jhash_1word((uint32_t)peer->addpath_type[afi][safi], key);
key = jhash_1word(peer->addpath_best_selected[afi][safi], key);
+ key = jhash_1word(peer->addpath_paths_limit[afi][safi].receive, key);
+ key = jhash_1word(peer->addpath_paths_limit[afi][safi].send, key);
key = jhash_1word((peer->cap & PEER_UPDGRP_CAP_FLAGS), key);
key = jhash_1word((peer->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS),
key);
@@ -356,9 +359,12 @@ static unsigned int updgrp_hash_key_make(const void *p)
key = jhash_1word(peer->max_packet_size, key);
key = jhash_1word(peer->pmax_out[afi][safi], key);
- if (peer->as_path_loop_detection)
- key = jhash_2words(peer->as, peer->as_path_loop_detection, key);
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_AS_LOOP_DETECTION))
+ key = jhash_2words(peer->as,
+ CHECK_FLAG(peer->flags,
+ PEER_FLAG_AS_LOOP_DETECTION),
+ key);
if (peer->group)
key = jhash_1word(jhash(peer->group->name,
strlen(peer->group->name), SEED1),
@@ -439,7 +445,7 @@ static unsigned int updgrp_hash_key_make(const void *p)
key = jhash_1word((peer->flags & PEER_FLAG_AIGP), key);
if (peer->soo[afi][safi]) {
- char *soo_str = ecommunity_str(peer->soo[afi][safi]);
+ const char *soo_str = ecommunity_str(peer->soo[afi][safi]);
key = jhash_1word(jhash(soo_str, strlen(soo_str), SEED1), key);
}
@@ -460,7 +466,11 @@ static unsigned int updgrp_hash_key_make(const void *p)
CHECK_FLAG(peer->af_cap[afi][safi],
PEER_UPDGRP_AF_CAP_FLAGS),
peer->v_routeadv, peer->change_local_as,
- peer->as_path_loop_detection);
+ !!CHECK_FLAG(peer->flags,
+ PEER_FLAG_AS_LOOP_DETECTION));
+ zlog_debug("%pBP Update Group Hash: addpath paths-limit: (send %u, receive %u)",
+ peer, peer->addpath_paths_limit[afi][safi].send,
+ peer->addpath_paths_limit[afi][safi].receive);
zlog_debug(
"%pBP Update Group Hash: max packet size: %u pmax_out: %u Peer Group: %s rmap out: %s",
peer, peer->max_packet_size, peer->pmax_out[afi][safi],
@@ -1722,18 +1732,6 @@ static int update_group_walkcb(struct hash_bucket *bucket, void *arg)
return ret;
}
-static int update_group_periodic_merge_walkcb(struct update_group *updgrp,
- void *arg)
-{
- struct update_subgroup *subgrp;
- struct update_subgroup *tmp_subgrp;
- const char *reason = arg;
-
- UPDGRP_FOREACH_SUBGRP_SAFE (updgrp, subgrp, tmp_subgrp)
- update_subgroup_check_merge(subgrp, reason);
- return UPDWALK_CONTINUE;
-}
-
/********************
* PUBLIC FUNCTIONS
********************/
@@ -2072,14 +2070,6 @@ void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx)
}
}
-void update_group_periodic_merge(struct bgp *bgp)
-{
- char reason[] = "periodic merge check";
-
- update_group_walk(bgp, update_group_periodic_merge_walkcb,
- (void *)reason);
-}
-
static int
update_group_default_originate_route_map_walkcb(struct update_group *updgrp,
void *arg)
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index 5e8b537..d0fd226 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -369,7 +369,6 @@ extern void update_group_policy_update(struct bgp *bgp,
extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
updgrp_walkcb cb, void *ctx);
extern void update_group_walk(struct bgp *bgp, updgrp_walkcb cb, void *ctx);
-extern void update_group_periodic_merge(struct bgp *bgp);
extern void
update_group_refresh_default_originate_route_map(struct event *thread);
extern void update_group_start_advtimer(struct bgp *bgp);
diff --git a/bgpd/bgp_updgrp_adv.c b/bgpd/bgp_updgrp_adv.c
index 9d62265..250378a 100644
--- a/bgpd/bgp_updgrp_adv.c
+++ b/bgpd/bgp_updgrp_adv.c
@@ -78,6 +78,8 @@ static inline struct bgp_adj_out *adj_lookup(struct bgp_dest *dest,
static void adj_free(struct bgp_adj_out *adj)
{
+ bgp_labels_unintern(&adj->labels);
+
TAILQ_REMOVE(&(adj->subgroup->adjq), adj, subgrp_adj_train);
SUBGRP_DECR_STAT(adj->subgroup, adj_count);
@@ -97,13 +99,19 @@ subgrp_announce_addpath_best_selected(struct bgp_dest *dest,
enum bgp_path_selection_reason reason;
char pfx_buf[PREFIX2STR_BUFFER] = {};
int paths_eq = 0;
- int best_path_count = 0;
struct list *list = list_new();
struct bgp_path_info *pi = NULL;
+ uint16_t paths_count = 0;
+ uint16_t paths_limit = peer->addpath_paths_limit[afi][safi].receive;
if (peer->addpath_type[afi][safi] == BGP_ADDPATH_BEST_SELECTED) {
- while (best_path_count++ <
- peer->addpath_best_selected[afi][safi]) {
+ paths_limit =
+ paths_limit
+ ? MIN(paths_limit,
+ peer->addpath_best_selected[afi][safi])
+ : peer->addpath_best_selected[afi][safi];
+
+ while (paths_count++ < paths_limit) {
struct bgp_path_info *exist = NULL;
for (pi = bgp_dest_get_bgp_path_info(dest); pi;
@@ -139,8 +147,26 @@ subgrp_announce_addpath_best_selected(struct bgp_dest *dest,
subgroup_process_announce_selected(
subgrp, NULL, dest, afi, safi, id);
} else {
- subgroup_process_announce_selected(subgrp, pi, dest,
- afi, safi, id);
+ /* No Paths-Limit involved */
+ if (!paths_limit) {
+ subgroup_process_announce_selected(subgrp, pi,
+ dest, afi,
+ safi, id);
+ continue;
+ }
+
+ /* If we have Paths-Limit capability, we MUST
+ * not send more than the number of paths expected
+ * by the peer.
+ */
+ if (paths_count++ < paths_limit)
+ subgroup_process_announce_selected(subgrp, pi,
+ dest, afi,
+ safi, id);
+ else
+ subgroup_process_announce_selected(subgrp, NULL,
+ dest, afi,
+ safi, id);
}
}
@@ -509,7 +535,7 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
struct peer *adv_peer;
struct peer_af *paf;
struct bgp *bgp;
- uint32_t attr_hash = attrhash_key_make(attr);
+ uint32_t attr_hash = 0;
peer = SUBGRP_PEER(subgrp);
afi = SUBGRP_AFI(subgrp);
@@ -544,9 +570,13 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
* the route wasn't changed actually.
* Do not suppress BGP UPDATES for route-refresh.
*/
- if (CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES)
- && !CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES)
- && adj->attr_hash == attr_hash) {
+ if (likely(CHECK_FLAG(bgp->flags, BGP_FLAG_SUPPRESS_DUPLICATES)))
+ attr_hash = attrhash_key_make(attr);
+
+ if (!CHECK_FLAG(subgrp->sflags, SUBGRP_STATUS_FORCE_UPDATES) &&
+ attr_hash && adj->attr_hash == attr_hash &&
+ bgp_labels_cmp(path->extra ? path->extra->labels : NULL,
+ adj->labels)) {
if (BGP_DEBUG(update, UPDATE_OUT)) {
char attr_str[BUFSIZ] = {0};
@@ -588,6 +618,10 @@ bool bgp_adj_out_set_subgroup(struct bgp_dest *dest,
adv->baa = bgp_advertise_attr_intern(subgrp->hash, attr);
adv->adj = adj;
adj->attr_hash = attr_hash;
+ if (path->extra)
+ adj->labels = bgp_labels_intern(path->extra->labels);
+ else
+ adj->labels = NULL;
/* Add new advertisement to advertisement attribute list. */
bgp_advertise_add(adv->baa, adv);
diff --git a/bgpd/bgp_updgrp_packet.c b/bgpd/bgp_updgrp_packet.c
index 7502bf2..6e30d4f 100644
--- a/bgpd/bgp_updgrp_packet.c
+++ b/bgpd/bgp_updgrp_packet.c
@@ -523,11 +523,13 @@ struct stream *bpacket_reformat_for_peer(struct bpacket *pkt,
gnh_modified = 1;
}
- if (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg)) {
- if (peer->nexthop.v4.s_addr != INADDR_ANY) {
- ipv4_to_ipv4_mapped_ipv6(mod_v6nhg,
- peer->nexthop.v4);
- }
+ if (peer->nexthop.v4.s_addr != INADDR_ANY &&
+ (IN6_IS_ADDR_UNSPECIFIED(mod_v6nhg) ||
+ (IN6_IS_ADDR_LINKLOCAL(mod_v6nhg) &&
+ peer->connection->su.sa.sa_family == AF_INET6 &&
+ paf->afi == AFI_IP))) {
+ ipv4_to_ipv4_mapped_ipv6(mod_v6nhg, peer->nexthop.v4);
+ gnh_modified = 1;
}
if (IS_MAPPED_IPV6(&peer->nexthop.v6_global)) {
@@ -665,7 +667,7 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
uint32_t addpath_tx_id = 0;
struct prefix_rd *prd = NULL;
mpls_label_t label = MPLS_INVALID_LABEL, *label_pnt = NULL;
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
if (!subgrp)
return NULL;
@@ -812,9 +814,12 @@ struct bpacket *subgroup_update_packet(struct update_subgroup *subgrp)
path);
label_pnt = &label;
num_labels = 1;
- } else if (path && path->extra) {
- label_pnt = &path->extra->label[0];
- num_labels = path->extra->num_labels;
+ } else {
+ num_labels = bgp_path_info_num_labels(path);
+ label_pnt =
+ num_labels
+ ? &path->extra->labels->label[0]
+ : NULL;
}
if (stream_empty(snlri))
@@ -1081,7 +1086,7 @@ void subgroup_default_update_packet(struct update_subgroup *subgrp,
struct bpacket_attr_vec_arr vecarr;
bool addpath_capable = false;
mpls_label_t label = MPLS_LABEL_IMPLICIT_NULL;
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
if (DISABLE_BGP_ANNOUNCE)
return;
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 9530a66..1a87799 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -126,6 +126,10 @@ FRR_CFG_DEFAULT_BOOL(BGP_SOFT_VERSION_CAPABILITY,
{ .val_bool = true, .match_profile = "datacenter", },
{ .val_bool = false },
);
+FRR_CFG_DEFAULT_BOOL(BGP_DYNAMIC_CAPABILITY,
+ { .val_bool = true, .match_profile = "datacenter", },
+ { .val_bool = false },
+);
FRR_CFG_DEFAULT_BOOL(BGP_ENFORCE_FIRST_AS,
{ .val_bool = false, .match_version = "< 9.1", },
{ .val_bool = true },
@@ -623,6 +627,9 @@ int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
if (DFLT_BGP_SOFT_VERSION_CAPABILITY)
SET_FLAG((*bgp)->flags,
BGP_FLAG_SOFT_VERSION_CAPABILITY);
+ if (DFLT_BGP_DYNAMIC_CAPABILITY)
+ SET_FLAG((*bgp)->flags,
+ BGP_FLAG_DYNAMIC_CAPABILITY);
if (DFLT_BGP_ENFORCE_FIRST_AS)
SET_FLAG((*bgp)->flags, BGP_FLAG_ENFORCE_FIRST_AS);
@@ -1694,6 +1701,10 @@ DEFUN (no_router_bgp,
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, tmp_bgp)) {
if (tmp_bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
continue;
+
+ if (CHECK_FLAG(tmp_bgp->vrf_flags, BGP_VRF_AUTO))
+ bgp_delete(tmp_bgp);
+
if (CHECK_FLAG(
tmp_bgp->af_flags[AFI_IP]
[SAFI_UNICAST],
@@ -1753,10 +1764,10 @@ DEFPY (bgp_session_dscp,
bgp_session_dscp_cmd,
"bgp session-dscp (0-63)$dscp",
BGP_STR
- "Override default (C6) bgp TCP session DSCP value\n"
- "Manually configured dscp parameter\n")
+ "Override default (CS6) DSCP for BGP connections\n"
+ "Manually configured DSCP value\n")
{
- bm->tcp_dscp = dscp << 2;
+ bm->ip_tos = dscp << 2;
return CMD_SUCCESS;
}
@@ -1766,10 +1777,10 @@ DEFPY (no_bgp_session_dscp,
"no bgp session-dscp [(0-63)]",
NO_STR
BGP_STR
- "Override default (C6) bgp TCP session DSCP value\n"
- "Manually configured dscp parameter\n")
+ "Override default (CS6) DSCP for BGP connections\n"
+ "Manually configured DSCP value\n")
{
- bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
+ bm->ip_tos = IPTOS_PREC_INTERNETCONTROL;
return CMD_SUCCESS;
}
@@ -3028,14 +3039,17 @@ DEFUN (bgp_graceful_restart,
VTY_DECLVAR_CONTEXT(bgp, bgp);
ret = bgp_gr_update_all(bgp, GLOBAL_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("[BGP_GR] bgp_graceful_restart_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
+
return bgp_vty_return(vty, ret);
}
@@ -3055,14 +3069,16 @@ DEFUN (no_bgp_graceful_restart,
int ret = BGP_GR_FAILURE;
ret = bgp_gr_update_all(bgp, NO_GLOBAL_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug("[BGP_GR] no_bgp_graceful_restart_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3270,24 +3286,25 @@ DEFUN (bgp_graceful_restart_disable,
VTY_DECLVAR_CONTEXT(bgp, bgp);
ret = bgp_gr_update_all(bgp, GLOBAL_DISABLE_CMD);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
- bgp->peer, ret);
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_RESTART,
+ CAPABILITY_ACTION_UNSET);
+ bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
+ CAPABILITY_CODE_LLGR,
+ CAPABILITY_ACTION_UNSET);
+ }
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
- zlog_debug(
- "[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
-
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_RESTART,
- CAPABILITY_ACTION_UNSET);
- bgp_capability_send(peer, AFI_IP, SAFI_UNICAST,
- CAPABILITY_CODE_LLGR,
- CAPABILITY_ACTION_UNSET);
- }
+ zlog_debug("[BGP_GR] bgp_graceful_restart_disable_cmd : END ");
return bgp_vty_return(vty, ret);
}
@@ -3309,15 +3326,17 @@ DEFUN (no_bgp_graceful_restart_disable,
int ret = BGP_GR_FAILURE;
ret = bgp_gr_update_all(bgp, NO_GLOBAL_DISABLE_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp, bgp->peer,
- ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT_AND_SEND_CAPABILITY_TO_ZEBRA(bgp,
+ bgp->peer,
+ ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset all peers to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_graceful_restart_disable_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset all peers to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3332,7 +3351,7 @@ DEFUN (bgp_neighbor_graceful_restart_set,
{
int idx_peer = 1;
struct peer *peer;
- int ret = BGP_GR_FAILURE;
+ int result = BGP_GR_FAILURE, ret = BGP_GR_SUCCESS;
VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
@@ -3344,18 +3363,23 @@ DEFUN (bgp_neighbor_graceful_restart_set,
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- ret = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ result = bgp_neighbor_graceful_restart(peer, PEER_GR_CMD);
+ if (result == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] bgp_neighbor_graceful_restart_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
- return bgp_vty_return(vty, ret);
+ if (ret != BGP_GR_SUCCESS)
+ vty_out(vty,
+ "As part of configuring graceful-restart, capability send to zebra failed\n");
+
+ return bgp_vty_return(vty, result);
}
DEFUN (no_bgp_neighbor_graceful_restart,
@@ -3368,7 +3392,7 @@ DEFUN (no_bgp_neighbor_graceful_restart,
)
{
int idx_peer = 2;
- int ret = BGP_GR_FAILURE;
+ int result = BGP_GR_FAILURE, ret = BGP_GR_SUCCESS;
struct peer *peer;
VTY_BGP_GR_DEFINE_LOOP_VARIABLE;
@@ -3381,18 +3405,23 @@ DEFUN (no_bgp_neighbor_graceful_restart,
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : START ");
- ret = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ result = bgp_neighbor_graceful_restart(peer, NO_PEER_GR_CMD);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
- return bgp_vty_return(vty, ret);
+ if (ret != BGP_GR_SUCCESS)
+ vty_out(vty,
+ "As part of configuring graceful-restart, capability send to zebra failed\n");
+
+ return bgp_vty_return(vty, result);
}
DEFUN (bgp_neighbor_graceful_restart_helper_set,
@@ -3420,15 +3449,16 @@ DEFUN (bgp_neighbor_graceful_restart_helper_set,
ret = bgp_neighbor_graceful_restart(peer, PEER_HELPER_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] bgp_neighbor_graceful_restart_helper_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3457,15 +3487,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_helper,
"[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_HELPER_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_helper_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3493,18 +3524,19 @@ DEFUN (bgp_neighbor_graceful_restart_disable_set,
return CMD_WARNING_CONFIG_FAILED;
ret = bgp_neighbor_graceful_restart(peer, PEER_DISABLE_CMD);
+ if (ret == BGP_GR_SUCCESS) {
+ if (peer->bgp->t_startup)
+ bgp_peer_gr_flags_update(peer);
- if (peer->bgp->t_startup)
- bgp_peer_gr_flags_update(peer);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR]bgp_neighbor_graceful_restart_disable_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -3533,15 +3565,16 @@ DEFUN (no_bgp_neighbor_graceful_restart_disable,
"[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : START ");
ret = bgp_neighbor_graceful_restart(peer, NO_PEER_DISABLE_CMD);
-
- VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
- VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ if (ret == BGP_GR_SUCCESS) {
+ VTY_BGP_GR_ROUTER_DETECT(bgp, peer, peer->bgp->peer);
+ VTY_SEND_BGP_GR_CAPABILITY_TO_ZEBRA(peer->bgp, ret);
+ vty_out(vty,
+ "Graceful restart configuration changed, reset this peer to take effect\n");
+ }
if (BGP_DEBUG(graceful_restart, GRACEFUL_RESTART))
zlog_debug(
"[BGP_GR] no_bgp_neighbor_graceful_restart_disable_set_cmd : END ");
- vty_out(vty,
- "Graceful restart configuration changed, reset this peer to take effect\n");
return bgp_vty_return(vty, ret);
}
@@ -4298,6 +4331,24 @@ DEFPY (bgp_default_software_version_capability,
return CMD_SUCCESS;
}
+DEFPY (bgp_default_dynamic_capability,
+ bgp_default_dynamic_capability_cmd,
+ "[no] bgp default dynamic-capability",
+ NO_STR
+ BGP_STR
+ "Configure BGP defaults\n"
+ "Advertise dynamic capability for all neighbors\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (no)
+ UNSET_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY);
+ else
+ SET_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY);
+
+ return CMD_SUCCESS;
+}
+
/* "bgp network import-check" configuration. */
DEFUN (bgp_network_import_check,
bgp_network_import_check_cmd,
@@ -4315,6 +4366,9 @@ DEFUN (bgp_network_import_check,
return CMD_SUCCESS;
}
+#if CONFDATE > 20241013
+CPP_NOTICE("Drop `bgp network import-check exact` command")
+#endif
ALIAS_HIDDEN(bgp_network_import_check, bgp_network_import_check_exact_cmd,
"bgp network import-check exact",
BGP_STR
@@ -5077,6 +5131,8 @@ DEFUN (no_neighbor,
struct peer_group *group;
struct peer *peer;
struct peer *other;
+ afi_t afi;
+ int lr_count;
ret = str2sockunion(argv[idx_peer]->arg, &su);
if (ret < 0) {
@@ -5094,6 +5150,15 @@ DEFUN (no_neighbor,
group = peer_group_lookup(bgp, argv[idx_peer]->arg);
if (group) {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ lr_count = listcount(group->listen_range[afi]);
+ if (lr_count) {
+ vty_out(vty,
+ "%%Peer-group %s is attached to %d listen-range(s), delete them first\n",
+ group->name, lr_count);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
peer_group_notify_unconfig(group);
peer_group_delete(group);
} else {
@@ -5171,9 +5236,20 @@ DEFUN (no_neighbor_peer_group,
VTY_DECLVAR_CONTEXT(bgp, bgp);
int idx_word = 2;
struct peer_group *group;
+ afi_t afi;
+ int lr_count;
group = peer_group_lookup(bgp, argv[idx_word]->arg);
if (group) {
+ for (afi = AFI_IP; afi < AFI_MAX; afi++) {
+ lr_count = listcount(group->listen_range[afi]);
+ if (lr_count) {
+ vty_out(vty,
+ "%%Peer-group %s is attached to %d listen-range(s), delete them first\n",
+ group->name, lr_count);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ }
peer_group_notify_unconfig(group);
peer_group_delete(group);
} else {
@@ -7073,6 +7149,26 @@ DEFUN (no_neighbor_disable_connected_check,
PEER_FLAG_DISABLE_CONNECTED_CHECK);
}
+DEFPY(neighbor_extended_link_bw,
+ neighbor_extended_link_bw_cmd,
+ "[no] neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor extended-link-bandwidth",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Send Extended (64-bit) version of encoding for Link-Bandwidth\n")
+{
+ int ret;
+
+ if (no)
+ ret = peer_flag_unset_vty(vty, neighbor,
+ PEER_FLAG_EXTENDED_LINK_BANDWIDTH);
+ else
+ ret = peer_flag_set_vty(vty, neighbor,
+ PEER_FLAG_EXTENDED_LINK_BANDWIDTH);
+
+ return ret;
+}
+
/* disable-link-bw-encoding-ieee */
DEFUN(neighbor_disable_link_bw_encoding_ieee,
neighbor_disable_link_bw_encoding_ieee_cmd,
@@ -9198,15 +9294,64 @@ DEFPY(
NEIGHBOR_ADDR_STR2
"Detect AS loops before sending to neighbor\n")
{
+ return peer_flag_set_vty(vty, neighbor, PEER_FLAG_AS_LOOP_DETECTION);
+}
+
+DEFPY (neighbor_addpath_paths_limit,
+ neighbor_addpath_paths_limit_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor addpath-rx-paths-limit (1-65535)$paths_limit",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Paths Limit for Addpath to receive from the peer\n"
+ "Maximum number of paths\n")
+{
struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ int ret;
peer = peer_and_group_lookup_vty(vty, neighbor);
if (!peer)
return CMD_WARNING_CONFIG_FAILED;
- peer->as_path_loop_detection = true;
+ ret = peer_af_flag_set_vty(vty, neighbor, afi, safi,
+ PEER_FLAG_ADDPATH_RX_PATHS_LIMIT);
- return CMD_SUCCESS;
+ peer->addpath_paths_limit[afi][safi].send = paths_limit;
+
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_PATHS_LIMIT,
+ CAPABILITY_ACTION_SET);
+
+ return ret;
+}
+
+DEFPY (no_neighbor_addpath_paths_limit,
+ no_neighbor_addpath_paths_limit_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor addpath-rx-paths-limit [(1-65535)]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Paths Limit for Addpath to receive from the peer\n"
+ "Maximum number of paths\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ int ret;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ret = peer_af_flag_unset_vty(vty, neighbor, afi, safi,
+ PEER_FLAG_ADDPATH_RX_PATHS_LIMIT);
+
+ peer->addpath_paths_limit[afi][safi].send = 0;
+
+ bgp_capability_send(peer, afi, safi, CAPABILITY_CODE_PATHS_LIMIT,
+ CAPABILITY_ACTION_SET);
+
+ return ret;
}
DEFPY(
@@ -9218,15 +9363,7 @@ DEFPY(
NEIGHBOR_ADDR_STR2
"Detect AS loops before sending to neighbor\n")
{
- struct peer *peer;
-
- peer = peer_and_group_lookup_vty(vty, neighbor);
- if (!peer)
- return CMD_WARNING_CONFIG_FAILED;
-
- peer->as_path_loop_detection = false;
-
- return CMD_SUCCESS;
+ return peer_flag_unset_vty(vty, neighbor, PEER_FLAG_AS_LOOP_DETECTION);
}
DEFPY(neighbor_path_attribute_discard,
@@ -9343,6 +9480,92 @@ DEFPY(no_neighbor_path_attribute_treat_as_withdraw,
return CMD_SUCCESS;
}
+DEFPY(neighbor_damp,
+ neighbor_damp_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [(1-45)$half [(1-20000)$reuse (1-20000)$suppress (1-255)$max]]",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enable neighbor route-flap dampening\n"
+ "Half-life time for the penalty\n"
+ "Value to start reusing a route\n"
+ "Value to start suppressing a route\n"
+ "Maximum duration to suppress a stable route\n")
+{
+ struct peer *peer = peer_and_group_lookup_vty(vty, neighbor);
+
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+ if (!half)
+ half = DEFAULT_HALF_LIFE;
+ if (!reuse) {
+ reuse = DEFAULT_REUSE;
+ suppress = DEFAULT_SUPPRESS;
+ max = half * 4;
+ }
+ if (suppress < reuse) {
+ vty_out(vty, "Suppress value cannot be less than reuse value\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ bgp_peer_damp_enable(peer, bgp_node_afi(vty), bgp_node_safi(vty),
+ half * 60, reuse, suppress, max * 60);
+ return CMD_SUCCESS;
+}
+
+DEFPY(no_neighbor_damp,
+ no_neighbor_damp_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor dampening [HALF [REUSE SUPPRESS MAX]]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Enable neighbor route-flap dampening\n"
+ "Half-life time for the penalty\n"
+ "Value to start reusing a route\n"
+ "Value to start suppressing a route\n"
+ "Maximum duration to suppress a stable route\n")
+{
+ struct peer *peer = peer_and_group_lookup_vty(vty, neighbor);
+
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+ bgp_peer_damp_disable(peer, bgp_node_afi(vty), bgp_node_safi(vty));
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ip_bgp_neighbor_damp_param,
+ show_ip_bgp_neighbor_damp_param_cmd,
+ "show [ip] bgp [<ipv4|ipv6> [unicast]] neighbors <A.B.C.D|X:X::X:X|WORD>$neighbor dampening parameters [json]$json",
+ SHOW_STR
+ IP_STR
+ BGP_STR
+ BGP_AFI_HELP_STR
+ "Address Family modifier\n"
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Neighbor route-flap dampening information\n"
+ "Display detail of configured dampening parameters\n"
+ JSON_STR)
+{
+ bool use_json = false;
+ int idx = 0;
+ afi_t afi = AFI_IP;
+ safi_t safi = SAFI_UNICAST;
+ struct peer *peer;
+
+ if (argv_find(argv, argc, "ip", &idx))
+ afi = AFI_IP;
+ if (argv_find(argv, argc, "ipv4", &idx))
+ afi = AFI_IP;
+ if (argv_find(argv, argc, "ipv6", &idx))
+ afi = AFI_IP6;
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING;
+ if (json)
+ use_json = true;
+ bgp_show_peer_dampening_parameters(vty, peer, afi, safi, use_json);
+ return CMD_SUCCESS;
+}
+
static int set_ecom_list(struct vty *vty, int argc, struct cmd_token **argv,
struct ecommunity **list, bool is_rt6)
{
@@ -9628,8 +9851,6 @@ DEFPY (af_label_vpn_export,
BGP_VPN_POLICY_TOVPN_LABEL_AUTO);
/* fetch a label */
bgp->vpn_policy[afi].tovpn_label = MPLS_LABEL_NONE;
- bgp_lp_get(LP_TYPE_VRF, &bgp->vpn_policy[afi],
- vpn_leak_label_callback);
} else {
bgp->vpn_policy[afi].tovpn_label = label;
UNSET_FLAG(bgp->vpn_policy[afi].flags,
@@ -10218,12 +10439,20 @@ DEFPY(bgp_imexport_vrf, bgp_imexport_vrf_cmd,
vrf_bgp = bgp_lookup_by_name(import_name);
if (!vrf_bgp) {
- if (strcmp(import_name, VRF_DEFAULT_NAME) == 0)
+ if (strcmp(import_name, VRF_DEFAULT_NAME) == 0) {
vrf_bgp = bgp_default;
- else
+ } else {
/* Auto-create assuming the same AS */
ret = bgp_get_vty(&vrf_bgp, &as, import_name, bgp_type,
NULL, ASNOTATION_UNDEFINED);
+
+ /* Auto created VRF instances should be marked
+ * properly, otherwise we have a state after bgpd
+ * restart where VRF instance has default VRF's ASN.
+ */
+ SET_FLAG(vrf_bgp->vrf_flags, BGP_VRF_AUTO);
+ }
+
if (ret) {
vty_out(vty,
"VRF %s is not configured as a bgp instance\n",
@@ -10672,7 +10901,10 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
if (rm_p->prefixlen == match.prefixlen) {
SET_FLAG(rm->flags,
BGP_NODE_USER_CLEAR);
- bgp_process(bgp, rm, afi, safi);
+ bgp_process(bgp, rm,
+ bgp_dest_get_bgp_path_info(
+ rm),
+ afi, safi);
}
bgp_dest_unlock_node(rm);
}
@@ -10684,7 +10916,9 @@ static int bgp_clear_prefix(struct vty *vty, const char *view_name,
if (dest_p->prefixlen == match.prefixlen) {
SET_FLAG(dest->flags, BGP_NODE_USER_CLEAR);
- bgp_process(bgp, dest, afi, safi);
+ bgp_process(bgp, dest,
+ bgp_dest_get_bgp_path_info(dest),
+ afi, safi);
}
bgp_dest_unlock_node(dest);
}
@@ -11439,10 +11673,9 @@ static void bgp_show_peer_reset(struct vty * vty, struct peer *peer,
BGP_NOTIFY_CEASE_HARD_RESET)
: "");
} else {
- vty_out(vty, " %s (%s)\n",
+ vty_out(vty, " %s (%s)\n",
peer_down_str[(int)peer->last_reset],
- peer->soft_version ? peer->soft_version
- : "n/a");
+ peer->soft_version ? peer->soft_version : "n/a");
}
}
}
@@ -12392,6 +12625,9 @@ static void bgp_show_all_instances_summary_vty(struct vty *vty, afi_t afi,
vty_out(vty, "{\n");
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!is_first)
@@ -12684,7 +12920,7 @@ static void bgp_show_neighbor_graceful_restart_remote_mode(struct vty *vty,
if (json)
json_object_string_add(json, "remoteGrMode", mode);
else
- vty_out(vty, "%s\n", mode);
+ vty_out(vty, "%s", mode);
}
static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
@@ -12716,7 +12952,7 @@ static void bgp_show_neighbor_graceful_restart_local_mode(struct vty *vty,
if (json)
json_object_string_add(json, "localGrMode", mode);
else
- vty_out(vty, "%s\n", mode);
+ vty_out(vty, "%s", mode);
}
static void bgp_show_neighbor_graceful_restart_capability_per_afi_safi(
@@ -14070,33 +14306,28 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
CHECK_FLAG(
p->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_TX_RCV)) {
- if (CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_TX_ADV) &&
- CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_TX_RCV))
- json_object_boolean_true_add(
- json_sub,
- "txAdvertisedAndReceived");
- else if (
- CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_TX_ADV))
- json_object_boolean_true_add(
- json_sub,
- "txAdvertised");
- else if (
- CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_TX_RCV))
- json_object_boolean_true_add(
- json_sub,
- "txReceived");
+ json_object_boolean_add(
+ json_sub,
+ "txAdvertisedAndReceived",
+ CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV) &&
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV));
+
+ json_object_boolean_add(
+ json_sub, "txAdvertised",
+ CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_ADV));
+
+ json_object_boolean_add(
+ json_sub, "txReceived",
+ CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_TX_RCV));
}
if (CHECK_FLAG(
@@ -14105,33 +14336,28 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
CHECK_FLAG(
p->af_cap[afi][safi],
PEER_CAP_ADDPATH_AF_RX_RCV)) {
- if (CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_RX_ADV) &&
- CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_RX_RCV))
- json_object_boolean_true_add(
- json_sub,
- "rxAdvertisedAndReceived");
- else if (
- CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_RX_ADV))
- json_object_boolean_true_add(
- json_sub,
- "rxAdvertised");
- else if (
- CHECK_FLAG(
- p->af_cap[afi]
- [safi],
- PEER_CAP_ADDPATH_AF_RX_RCV))
- json_object_boolean_true_add(
- json_sub,
- "rxReceived");
+ json_object_boolean_add(
+ json_sub,
+ "rxAdvertisedAndReceived",
+ CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV) &&
+ CHECK_FLAG(
+ p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV));
+
+ json_object_boolean_add(
+ json_sub, "rxAdvertised",
+ CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_ADV));
+
+ json_object_boolean_add(
+ json_sub, "rxReceived",
+ CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_ADDPATH_AF_RX_RCV));
}
if (CHECK_FLAG(
@@ -14157,6 +14383,86 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
json_add);
}
+ /* Paths-Limit */
+ if (CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_ADV)) {
+ json_object *json_add = NULL;
+ const char *print_store;
+
+ json_add = json_object_new_object();
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ json_object *json_sub = NULL;
+
+ json_sub = json_object_new_object();
+ print_store = get_afi_safi_str(afi, safi,
+ true);
+
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV)) {
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV) &&
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV)) {
+ json_object_boolean_true_add(
+ json_sub,
+ "advertisedAndReceived");
+ json_object_int_add(
+ json_sub,
+ "advertisedPathsLimit",
+ p->addpath_paths_limit
+ [afi][safi]
+ .send);
+ json_object_int_add(
+ json_sub,
+ "receivedPathsLimit",
+ p->addpath_paths_limit
+ [afi][safi]
+ .receive);
+ } else if (CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV)) {
+ json_object_boolean_true_add(
+ json_sub,
+ "advertised");
+ json_object_int_add(
+ json_sub,
+ "advertisedPathsLimit",
+ p->addpath_paths_limit
+ [afi][safi]
+ .send);
+ } else if (CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV)) {
+ json_object_boolean_true_add(
+ json_sub,
+ "received");
+ json_object_int_add(
+ json_sub,
+ "receivedPathsLimit",
+ p->addpath_paths_limit
+ [afi][safi]
+ .receive);
+ }
+ }
+
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV))
+ json_object_object_add(json_add,
+ print_store,
+ json_sub);
+ else
+ json_object_free(json_sub);
+ }
+
+ json_object_object_add(json_cap, "pathsLimit",
+ json_add);
+ }
+
/* Dynamic */
if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
@@ -14610,6 +14916,47 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
}
}
+ /* Paths-Limit */
+ if (CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_RCV) ||
+ CHECK_FLAG(p->cap, PEER_CAP_PATHS_LIMIT_ADV)) {
+ vty_out(vty, " Paths-Limit:\n");
+
+ FOREACH_AFI_SAFI (afi, safi) {
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV) ||
+ CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV)) {
+ vty_out(vty, " %s: ",
+ get_afi_safi_str(afi,
+ safi,
+ false));
+
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV))
+ vty_out(vty,
+ "advertised (%u)",
+ p->addpath_paths_limit
+ [afi][safi]
+ .send);
+
+ if (CHECK_FLAG(p->af_cap[afi][safi],
+ PEER_CAP_PATHS_LIMIT_AF_RCV))
+ vty_out(vty,
+ "%sreceived (%u)",
+ CHECK_FLAG(p->af_cap[afi]
+ [safi],
+ PEER_CAP_PATHS_LIMIT_AF_ADV)
+ ? " and "
+ : "",
+ p->addpath_paths_limit
+ [afi][safi]
+ .receive);
+
+ vty_out(vty, "\n");
+ }
+ }
+ }
+
/* Dynamic */
if (CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_RCV) ||
CHECK_FLAG(p->cap, PEER_CAP_DYNAMIC_ADV)) {
@@ -15662,6 +16009,9 @@ static void bgp_show_all_instances_neighbors_vty(struct vty *vty,
vty_out(vty, "{\n");
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
nbr_output = true;
if (use_json) {
if (!(json = json_object_new_object())) {
@@ -16221,6 +16571,9 @@ static int bgp_show_all_instance_route_leak_vty(struct vty *vty, afi_t afi,
if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT)
vrf_name = bgp->name;
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
if (use_json) {
json_vrf = json_object_new_object();
} else {
@@ -16311,6 +16664,9 @@ static void bgp_show_all_instances_updgrps_vty(struct vty *vty, afi_t afi,
struct bgp *bgp;
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
+
if (!uj)
vty_out(vty, "\nInstance %s:\n",
(bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
@@ -17512,6 +17868,76 @@ DEFUN (bgp_redistribute_ipv6_rmap_metric,
return bgp_redistribute_set(bgp, AFI_IP6, type, 0, changed);
}
+DEFPY(bgp_redistribute_ipv6_table, bgp_redistribute_ipv6_table_cmd,
+ "redistribute table-direct (1-65535)$table_id [{metric$metric (0-4294967295)$metric_val|route-map WORD$rmap}]",
+ "Redistribute information from another routing protocol\n"
+ "Non-main Kernel Routing Table - Direct\n"
+ "Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+ bool changed = false;
+ struct route_map *route_map = NULL;
+ struct bgp_redist *red;
+
+ if (rmap)
+ route_map = route_map_lookup_warn_noexist(vty, rmap);
+
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use 'table-direct'\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (table_id == RT_TABLE_MAIN || table_id == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %lu routing table\n",
+ table_id);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ red = bgp_redist_add(bgp, AFI_IP6, ZEBRA_ROUTE_TABLE_DIRECT, table_id);
+ if (rmap)
+ changed = bgp_redistribute_rmap_set(red, rmap, route_map);
+ if (metric)
+ changed |= bgp_redistribute_metric_set(bgp, red, AFI_IP6,
+ ZEBRA_ROUTE_TABLE_DIRECT,
+ metric_val);
+ return bgp_redistribute_set(bgp, AFI_IP6, ZEBRA_ROUTE_TABLE_DIRECT,
+ table_id, changed);
+}
+
+DEFPY(no_bgp_redistribute_ipv6_table, no_bgp_redistribute_ipv6_table_cmd,
+ "no redistribute table-direct (1-65535)$table_id [{metric (0-4294967295)|route-map WORD}]",
+ NO_STR
+ "Redistribute information from another routing protocol\n"
+ "Non-main Kernel Routing Table - Direct\n"
+ "Table ID\n"
+ "Metric for redistributed routes\n"
+ "Default metric\n"
+ "Route map reference\n"
+ "Pointer to route-map entries\n")
+{
+ VTY_DECLVAR_CONTEXT(bgp, bgp);
+
+ if (bgp->vrf_id != VRF_DEFAULT) {
+ vty_out(vty,
+ "%% Only default BGP instance can use 'table-direct'\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ if (table_id == RT_TABLE_MAIN || table_id == RT_TABLE_LOCAL) {
+ vty_out(vty,
+ "%% 'table-direct', can not use %lu routing table\n",
+ table_id);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ bgp_redistribute_unset(bgp, AFI_IP6, ZEBRA_ROUTE_TABLE_DIRECT, table_id);
+ return CMD_SUCCESS;
+}
+
DEFUN (bgp_redistribute_ipv6_metric_rmap,
bgp_redistribute_ipv6_metric_rmap_cmd,
"redistribute " FRR_IP6_REDIST_STR_BGPD " metric (0-4294967295) route-map RMAP_NAME",
@@ -18172,6 +18598,9 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " neighbor %s disable-link-bw-encoding-ieee\n",
addr);
+ if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_LINK_BANDWIDTH))
+ vty_out(vty, " neighbor %s extended-link-bandwidth\n", addr);
+
/* extended-optional-parameters */
if (peergroup_flag_check(peer, PEER_FLAG_EXTENDED_OPT_PARAMS))
vty_out(vty, " neighbor %s extended-optional-parameters\n",
@@ -18231,9 +18660,15 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " neighbor %s timers delayopen %u\n", addr,
peer->bgp->default_delayopen);
- /* capability dynamic */
- if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
- vty_out(vty, " neighbor %s capability dynamic\n", addr);
+ /* capability software-version */
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY)) {
+ if (!peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
+ vty_out(vty, " no neighbor %s capability dynamic\n",
+ addr);
+ } else {
+ if (peergroup_flag_check(peer, PEER_FLAG_DYNAMIC_CAPABILITY))
+ vty_out(vty, " neighbor %s capability dynamic\n", addr);
+ }
/* capability extended-nexthop */
if (peergroup_flag_check(peer, PEER_FLAG_CAPABILITY_ENHE)) {
@@ -18282,7 +18717,7 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
vty_out(vty, " neighbor %s strict-capability-match\n", addr);
/* Sender side AS path loop detection. */
- if (peer->as_path_loop_detection)
+ if (peergroup_flag_check(peer, PEER_FLAG_AS_LOOP_DETECTION))
vty_out(vty, " neighbor %s sender-as-path-loop-detection\n",
addr);
@@ -18404,6 +18839,11 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
if (CHECK_FLAG(peer->af_flags[afi][safi], PEER_FLAG_DISABLE_ADDPATH_RX))
vty_out(vty, " neighbor %s disable-addpath-rx\n", addr);
+ if (CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_ADDPATH_RX_PATHS_LIMIT))
+ vty_out(vty, " neighbor %s addpath-rx-paths-limit %u\n", addr,
+ peer->addpath_paths_limit[afi][safi].send);
+
/* ORF capability. */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_ORF_PREFIX_SM)
|| peergroup_af_flag_check(peer, afi, safi,
@@ -18679,7 +19119,16 @@ static void bgp_config_write_family(struct vty *vty, struct bgp *bgp, afi_t afi,
/* BGP flag dampening. */
if (CHECK_FLAG(bgp->af_flags[afi][safi], BGP_CONFIG_DAMPENING))
- bgp_config_write_damp(vty, afi, safi);
+ bgp_config_write_damp(vty, bgp, afi, safi);
+ for (ALL_LIST_ELEMENTS_RO(bgp->group, node, group))
+ if (peer_af_flag_check(group->conf, afi, safi,
+ PEER_FLAG_CONFIG_DAMPENING))
+ bgp_config_write_peer_damp(vty, group->conf, afi, safi);
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer))
+ if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE) &&
+ peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_CONFIG_DAMPENING))
+ bgp_config_write_peer_damp(vty, peer, afi, safi);
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group))
bgp_config_write_peer_af(vty, bgp, group->conf, afi, safi);
@@ -18765,9 +19214,9 @@ int bgp_config_write(struct vty *vty)
if (CHECK_FLAG(bm->flags, BM_FLAG_SEND_EXTRA_DATA_TO_ZEBRA))
vty_out(vty, "bgp send-extra-data zebra\n");
- /* BGP session DSCP value */
- if (bm->tcp_dscp != IPTOS_PREC_INTERNETCONTROL)
- vty_out(vty, "bgp session-dscp %u\n", bm->tcp_dscp >> 2);
+ /* DSCP value for outgoing packets in BGP connections */
+ if (bm->ip_tos != IPTOS_PREC_INTERNETCONTROL)
+ vty_out(vty, "bgp session-dscp %u\n", bm->ip_tos >> 2);
/* BGP InQ limit */
if (bm->inq_limit != BM_DEFAULT_Q_LIMIT)
@@ -18919,6 +19368,15 @@ int bgp_config_write(struct vty *vty)
? ""
: "no ");
+ if (!!CHECK_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY) !=
+ SAVE_BGP_DYNAMIC_CAPABILITY)
+ vty_out(vty,
+ " %sbgp default dynamic-capability\n",
+ CHECK_FLAG(bgp->flags,
+ BGP_FLAG_DYNAMIC_CAPABILITY)
+ ? ""
+ : "no ");
+
/* BGP default subgroup-pkt-queue-max. */
if (bgp->default_subgroup_pkt_queue_max
!= BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX)
@@ -19967,6 +20425,9 @@ void bgp_vty_init(void)
/* bgp default software-version-capability */
install_element(BGP_NODE, &bgp_default_software_version_capability_cmd);
+ /* bgp default dynamic-capability */
+ install_element(BGP_NODE, &bgp_default_dynamic_capability_cmd);
+
/* "bgp default subgroup-pkt-queue-max" commands. */
install_element(BGP_NODE, &bgp_default_subgroup_pkt_queue_max_cmd);
install_element(BGP_NODE, &no_bgp_default_subgroup_pkt_queue_max_cmd);
@@ -20565,6 +21026,26 @@ void bgp_vty_init(void)
install_element(BGP_VPNV6_NODE,
&no_neighbor_addpath_tx_bestpath_per_as_cmd);
+ /* "neighbor addpath-rx-paths-limit" commands.*/
+ install_element(BGP_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_addpath_paths_limit_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_addpath_paths_limit_cmd);
+
/* "neighbor sender-as-path-loop-detection" commands. */
install_element(BGP_NODE, &neighbor_aspath_loop_detection_cmd);
install_element(BGP_NODE, &no_neighbor_aspath_loop_detection_cmd);
@@ -20641,6 +21122,9 @@ void bgp_vty_init(void)
install_element(BGP_NODE,
&no_neighbor_disable_link_bw_encoding_ieee_cmd);
+
+ install_element(BGP_NODE, &neighbor_extended_link_bw_cmd);
+
/* "neighbor extended-optional-parameters" commands. */
install_element(BGP_NODE, &neighbor_extended_optional_parameters_cmd);
install_element(BGP_NODE,
@@ -20967,6 +21451,15 @@ void bgp_vty_init(void)
install_element(BGP_VPNV6_NODE,
&neighbor_maximum_prefix_threshold_restart_cmd);
install_element(BGP_VPNV6_NODE, &no_neighbor_maximum_prefix_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_threshold_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_warning_cmd);
+ install_element(BGP_EVPN_NODE,
+ &neighbor_maximum_prefix_threshold_warning_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_maximum_prefix_restart_cmd);
+ install_element(BGP_EVPN_NODE,
+ &neighbor_maximum_prefix_threshold_restart_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_maximum_prefix_cmd);
/* "neighbor allowas-in" */
install_element(BGP_NODE, &neighbor_allowas_in_hidden_cmd);
@@ -21014,6 +21507,23 @@ void bgp_vty_init(void)
install_element(BGP_EVPN_NODE, &neighbor_soo_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_soo_cmd);
+ /* "neighbor dampening" commands. */
+ install_element(BGP_NODE, &neighbor_damp_cmd);
+ install_element(BGP_NODE, &no_neighbor_damp_cmd);
+ install_element(BGP_IPV4_NODE, &neighbor_damp_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_damp_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_damp_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_damp_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_damp_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_damp_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_damp_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_damp_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_damp_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_damp_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_damp_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_damp_cmd);
+ install_element(VIEW_NODE, &show_ip_bgp_neighbor_damp_param_cmd);
+
/* address-family commands. */
install_element(BGP_NODE, &address_family_ipv4_safi_cmd);
install_element(BGP_NODE, &address_family_ipv6_safi_cmd);
@@ -21117,6 +21627,8 @@ void bgp_vty_init(void)
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_cmd);
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_rmap_metric_cmd);
install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_metric_rmap_cmd);
+ install_element(BGP_IPV6_NODE, &bgp_redistribute_ipv6_table_cmd);
+ install_element(BGP_IPV6_NODE, &no_bgp_redistribute_ipv6_table_cmd);
/* import|export vpn [route-map RMAP_NAME] */
install_element(BGP_IPV4_NODE, &bgp_imexport_vpn_cmd);
@@ -21226,9 +21738,6 @@ static const char *community_direct_str(int direct)
static void community_list_perror(struct vty *vty, int ret)
{
switch (ret) {
- case COMMUNITY_LIST_ERR_CANT_FIND_LIST:
- vty_out(vty, "%% Can't find community-list\n");
- break;
case COMMUNITY_LIST_ERR_MALFORMED_VAL:
vty_out(vty, "%% Malformed community-list value\n");
break;
@@ -21338,16 +21847,11 @@ DEFUN (no_community_list_standard_all,
argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
cl_name_or_number = argv[idx]->arg;
- int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq,
- direct, style);
+ community_list_unset(bgp_clist, cl_name_or_number, str, seq, direct,
+ style);
XFREE(MTYPE_TMP, str);
- if (ret < 0) {
- community_list_perror(vty, ret);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
return CMD_SUCCESS;
}
@@ -21451,16 +21955,11 @@ DEFUN (no_community_list_expanded_all,
argv_find(argv, argc, "COMMUNITY_LIST_NAME", &idx);
cl_name_or_number = argv[idx]->arg;
- int ret = community_list_unset(bgp_clist, cl_name_or_number, str, seq,
- direct, style);
+ community_list_unset(bgp_clist, cl_name_or_number, str, seq, direct,
+ style);
XFREE(MTYPE_TMP, str);
- if (ret < 0) {
- community_list_perror(vty, ret);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
return CMD_SUCCESS;
}
@@ -21616,7 +22115,6 @@ static int lcommunity_list_set_vty(struct vty *vty, int argc,
static int lcommunity_list_unset_vty(struct vty *vty, int argc,
struct cmd_token **argv, int style)
{
- int ret;
int direct = 0;
char *str = NULL;
int idx = 0;
@@ -21649,18 +22147,13 @@ static int lcommunity_list_unset_vty(struct vty *vty, int argc,
argv_find(argv, argc, "LCOMMUNITY_LIST_NAME", &idx);
/* Unset community list. */
- ret = lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, seq, direct,
- style);
+ lcommunity_list_unset(bgp_clist, argv[idx]->arg, str, seq, direct,
+ style);
/* Free temporary community list string allocated by
argv_concat(). */
XFREE(MTYPE_TMP, str);
- if (ret < 0) {
- community_list_perror(vty, ret);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
return CMD_SUCCESS;
}
@@ -22057,16 +22550,11 @@ DEFUN (no_extcommunity_list_standard_all,
argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
cl_number_or_name = argv[idx]->arg;
- int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
- seq, direct, style);
+ extcommunity_list_unset(bgp_clist, cl_number_or_name, str, seq, direct,
+ style);
XFREE(MTYPE_TMP, str);
- if (ret < 0) {
- community_list_perror(vty, ret);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
return CMD_SUCCESS;
}
@@ -22122,16 +22610,11 @@ DEFUN (no_extcommunity_list_expanded_all,
argv_find(argv, argc, "EXTCOMMUNITY_LIST_NAME", &idx);
cl_number_or_name = argv[idx]->arg;
- int ret = extcommunity_list_unset(bgp_clist, cl_number_or_name, str,
- seq, direct, style);
+ extcommunity_list_unset(bgp_clist, cl_number_or_name, str, seq, direct,
+ style);
XFREE(MTYPE_TMP, str);
- if (ret < 0) {
- community_list_perror(vty, ret);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
return CMD_SUCCESS;
}
diff --git a/bgpd/bgp_vty.h b/bgpd/bgp_vty.h
index 4955e4c..addd717 100644
--- a/bgpd/bgp_vty.h
+++ b/bgpd/bgp_vty.h
@@ -13,8 +13,6 @@ struct bgp;
#define BGP_INSTANCE_HELP_STR "BGP view\nBGP VRF\nView/VRF name\n"
#define BGP_INSTANCE_ALL_HELP_STR "BGP view\nBGP VRF\nAll Views/VRFs\n"
-#define BGP_AF_STR "Address Family\n"
-#define BGP_AF_MODIFIER_STR "Address Family modifier\n"
#define BGP_AFI_CMD_STR "<ipv4|ipv6>"
#define BGP_AFI_HELP_STR BGP_AF_STR BGP_AF_STR
#define BGP_SAFI_CMD_STR "<unicast|multicast|vpn>"
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index fe29662..5bb177b 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -235,6 +235,14 @@ static int bgp_ifp_up(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_up(ifp);
+ if (bgp_get_default() && if_is_loopback(ifp)) {
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
+ vpn_leak_postchange_all();
+ }
+
return 0;
}
@@ -282,16 +290,25 @@ static int bgp_ifp_down(struct interface *ifp)
hook_call(bgp_vrf_status_changed, bgp, ifp);
bgp_nht_ifp_down(ifp);
+ if (bgp_get_default() && if_is_loopback(ifp)) {
+ vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_label_withdraw(bgp, AFI_IP6);
+ vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_sid_withdraw(bgp, AFI_IP6);
+ vpn_leak_postchange_all();
+ }
+
return 0;
}
static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
{
- struct connected *ifc;
+ struct connected *ifc, *connected;
struct bgp *bgp;
struct peer *peer;
struct prefix *addr;
struct listnode *node, *nnode;
+ bool v6_ll_in_nh_global;
afi_t afi;
safi_t safi;
@@ -309,56 +326,70 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
if (!bgp)
return 0;
- if (if_is_operative(ifc->ifp)) {
- bgp_connected_add(bgp, ifc);
+ if (!if_is_operative(ifc->ifp))
+ return 0;
- /* If we have learnt of any neighbors on this interface,
- * check to kick off any BGP interface-based neighbors,
- * but only if this is a link-local address.
- */
- if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6)
- && !list_isempty(ifc->ifp->nbr_connected))
- bgp_start_interface_nbrs(bgp, ifc->ifp);
- else {
- addr = ifc->address;
+ bgp_connected_add(bgp, ifc);
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- if (addr->family == AF_INET)
- continue;
+ /* If we have learnt of any neighbors on this interface,
+ * check to kick off any BGP interface-based neighbors,
+ * but only if this is a link-local address.
+ */
+ if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6) &&
+ !list_isempty(ifc->ifp->nbr_connected))
+ bgp_start_interface_nbrs(bgp, ifc->ifp);
+ else if (ifc->address->family == AF_INET6 &&
+ !IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6)) {
+ addr = ifc->address;
- /*
- * If the Peer's interface name matches the
- * interface name for which BGP received the
- * update and if the received interface address
- * is a globalV6 and if the peer is currently
- * using a v4-mapped-v6 addr or a link local
- * address, then copy the Rxed global v6 addr
- * into peer's v6_global and send updates out
- * with new nexthop addr.
- */
- if ((peer->conf_if &&
- (strcmp(peer->conf_if, ifc->ifp->name) ==
- 0)) &&
- !IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6) &&
- ((IS_MAPPED_IPV6(
- &peer->nexthop.v6_global)) ||
- IN6_IS_ADDR_LINKLOCAL(
- &peer->nexthop.v6_global))) {
-
- if (bgp_debug_zebra(ifc->address)) {
- zlog_debug(
- "Update peer %pBP's current intf addr %pI6 and send updates",
- peer,
- &peer->nexthop
- .v6_global);
- }
- memcpy(&peer->nexthop.v6_global,
- &addr->u.prefix6,
- IPV6_MAX_BYTELEN);
- FOREACH_AFI_SAFI (afi, safi)
- bgp_announce_route(peer, afi,
- safi, true);
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ v6_ll_in_nh_global = false;
+
+ if (IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_global)) {
+ frr_each (if_connected, ifc->ifp->connected,
+ connected) {
+ if (connected->address->family !=
+ AF_INET6)
+ continue;
+ if (!IPV6_ADDR_SAME(&connected->address
+ ->u.prefix6,
+ &peer->nexthop
+ .v6_global))
+ continue;
+ /* peer->nexthop.v6_global contains a link-local address
+ * that needs to be replaced by the global address.
+ */
+ v6_ll_in_nh_global = true;
+ break;
+ }
+ }
+
+ /*
+ * If the Peer's interface name matches the
+ * interface name for which BGP received the
+ * update and if the received interface address
+ * is a globalV6 and if the peer is currently
+ * using a v4-mapped-v6 addr or a link local
+ * address, then copy the Rxed global v6 addr
+ * into peer's v6_global and send updates out
+ * with new nexthop addr.
+ */
+ if (v6_ll_in_nh_global ||
+ (peer->conf_if &&
+ strcmp(peer->conf_if, ifc->ifp->name) == 0 &&
+ (IS_MAPPED_IPV6(&peer->nexthop.v6_global) ||
+ IN6_IS_ADDR_LINKLOCAL(&peer->nexthop.v6_global)))) {
+ if (bgp_debug_zebra(ifc->address)) {
+ zlog_debug("Update peer %pBP's current intf global addr from %pI6 to %pI6 and send updates",
+ peer,
+ &peer->nexthop.v6_global,
+ &addr->u.prefix6);
}
+ memcpy(&peer->nexthop.v6_global,
+ &addr->u.prefix6, IPV6_MAX_BYTELEN);
+ FOREACH_AFI_SAFI (afi, safi)
+ bgp_announce_route(peer, afi, safi,
+ true);
}
}
}
@@ -369,10 +400,14 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
{
struct listnode *node, *nnode;
- struct connected *ifc;
+ struct connected *ifc, *connected;
struct peer *peer;
struct bgp *bgp;
struct prefix *addr;
+ struct in6_addr *v6_global = NULL;
+ struct in6_addr *v6_local = NULL;
+ afi_t afi;
+ safi_t safi;
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -391,7 +426,18 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
addr = ifc->address;
- if (bgp) {
+ if (bgp && addr->family == AF_INET6 &&
+ !IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6)) {
+ /* find another IPv6 global if possible and find the IPv6 link-local */
+ frr_each (if_connected, ifc->ifp->connected, connected) {
+ if (connected->address->family != AF_INET6)
+ continue;
+ if (IN6_IS_ADDR_LINKLOCAL(&connected->address->u.prefix6))
+ v6_local = &connected->address->u.prefix6;
+ else
+ v6_global = &connected->address->u.prefix6;
+ }
+
/*
* When we are using the v6 global as part of the peering
* nexthops and we are removing it, then we need to
@@ -400,17 +446,17 @@ static int bgp_interface_address_delete(ZAPI_CALLBACK_ARGS)
* we do not want the peering to bounce.
*/
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
- afi_t afi;
- safi_t safi;
-
- if (addr->family == AF_INET)
- continue;
-
- if (!IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6)
- && memcmp(&peer->nexthop.v6_global,
- &addr->u.prefix6, 16)
- == 0) {
- memset(&peer->nexthop.v6_global, 0, 16);
+ if (IPV6_ADDR_SAME(&peer->nexthop.v6_global,
+ &addr->u.prefix6)) {
+ if (v6_global)
+ IPV6_ADDR_COPY(&peer->nexthop.v6_global,
+ v6_global);
+ else if (v6_local)
+ IPV6_ADDR_COPY(&peer->nexthop.v6_global,
+ v6_local);
+ else
+ memset(&peer->nexthop.v6_global, 0,
+ IPV6_MAX_BYTELEN);
FOREACH_AFI_SAFI (afi, safi)
bgp_announce_route(peer, afi, safi,
true);
@@ -927,7 +973,8 @@ bgp_path_info_to_ipv6_nexthop(struct bgp_path_info *path, ifindex_t *ifindex)
|| path->attr->mp_nexthop_len
== BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL) {
/* Check if route-map is set to prefer global over link-local */
- if (path->attr->mp_nexthop_prefer_global) {
+ if (CHECK_FLAG(path->attr->nh_flags,
+ BGP_ATTR_NH_MP_PREFER_GLOBAL)) {
nexthop = &path->attr->mp_nexthop_global;
if (IN6_IS_ADDR_LINKLOCAL(nexthop))
*ifindex = path->attr->nh_ifindex;
@@ -1194,7 +1241,7 @@ static bool update_ipv6nh_for_route_install(int nh_othervrf, struct bgp *nh_bgp,
}
static bool bgp_zebra_use_nhop_weighted(struct bgp *bgp, struct attr *attr,
- uint32_t *nh_weight)
+ uint64_t *nh_weight)
{
/* zero link-bandwidth and link-bandwidth not present are treated
* as the same situation.
@@ -1226,7 +1273,7 @@ static void bgp_zebra_announce_parse_nexthop(
struct bgp_path_info local_info;
struct bgp_path_info *mpinfo_cp = &local_info;
mpls_label_t *labels;
- uint32_t num_labels = 0;
+ uint8_t num_labels = 0;
mpls_label_t nh_label;
int nh_othervrf = 0;
bool nh_updated = false;
@@ -1254,9 +1301,7 @@ static void bgp_zebra_announce_parse_nexthop(
}
for (; mpinfo; mpinfo = bgp_path_info_mpath_next(mpinfo)) {
- labels = NULL;
- num_labels = 0;
- uint32_t nh_weight;
+ uint64_t nh_weight;
bool is_evpn;
bool is_parent_evpn;
@@ -1286,25 +1331,19 @@ static void bgp_zebra_announce_parse_nexthop(
&nh_weight))
continue;
}
- if (CHECK_FLAG(info->flags, BGP_PATH_SELECTED))
- api_nh = &api->nexthops[*valid_nh_count];
- else
- api_nh = &api->backup_nexthops[*valid_nh_count];
+ api_nh = &api->nexthops[*valid_nh_count];
- if (CHECK_FLAG(info->attr->flag,
- ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
- api_nh->srte_color = bgp_attr_get_color(info->attr);
+ api_nh->srte_color = bgp_attr_get_color(info->attr);
if (bgp_debug_zebra(&api->prefix)) {
- if (mpinfo->extra) {
+ if (bgp_path_info_num_labels(mpinfo)) {
zlog_debug("%s: p=%pFX, bgp_is_valid_label: %d",
__func__, p,
bgp_is_valid_label(
- &mpinfo->extra->label[0]));
+ &mpinfo->extra->labels
+ ->label[0]));
} else {
- zlog_debug(
- "%s: p=%pFX, extra is NULL, no label",
- __func__, p);
+ zlog_debug("%s: p=%pFX, no label", __func__, p);
}
}
@@ -1370,13 +1409,10 @@ static void bgp_zebra_announce_parse_nexthop(
mpinfo->peer->sort == BGP_PEER_CONFED))
*allow_recursion = true;
- if (mpinfo->extra) {
- labels = mpinfo->extra->label;
- num_labels = mpinfo->extra->num_labels;
- }
+ num_labels = bgp_path_info_num_labels(mpinfo);
+ labels = num_labels ? mpinfo->extra->labels->label : NULL;
- if (labels && (num_labels > 0) &&
- (is_evpn || bgp_is_valid_label(&labels[0]))) {
+ if (num_labels && (is_evpn || bgp_is_valid_label(&labels[0]))) {
enum lsp_types_t nh_label_type = ZEBRA_LSP_NONE;
if (is_evpn) {
@@ -1501,15 +1537,16 @@ static void bgp_debug_zebra_nh(struct zapi_route *api)
snprintf(eth_buf, sizeof(eth_buf), " RMAC %s",
prefix_mac2str(&api_nh->rmac, buf1,
sizeof(buf1)));
- zlog_debug(" nhop [%d]: %s if %u VRF %u wt %u %s %s %s", i + 1,
- nh_buf, api_nh->ifindex, api_nh->vrf_id,
+ zlog_debug(" nhop [%d]: %s if %u VRF %u wt %" PRIu64
+ " %s %s %s",
+ i + 1, nh_buf, api_nh->ifindex, api_nh->vrf_id,
api_nh->weight, label_buf, segs_buf, eth_buf);
}
}
-void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
- struct bgp_path_info *info, struct bgp *bgp, afi_t afi,
- safi_t safi)
+static enum zclient_send_status
+bgp_zebra_announce_actual(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp)
{
struct bgp_path_info *bpi_ultimate;
struct zapi_route api = { 0 };
@@ -1521,35 +1558,19 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
route_tag_t tag;
bool is_add;
uint32_t nhg_id = 0;
- uint32_t recursion_flag = 0;
-
- /*
- * BGP is installing this route and bgp has been configured
- * to suppress announcements until the route has been installed
- * let's set the fact that we expect this route to be installed
- */
- if (BGP_SUPPRESS_FIB_ENABLED(bgp))
- SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
- /* Don't try to install if we're not connected to Zebra or Zebra doesn't
- * know of this instance.
- */
- if (!bgp_install_info_to_zebra(bgp))
- return;
-
- if (bgp->main_zebra_update_hold)
- return;
+ struct bgp_table *table = bgp_dest_table(dest);
+ const struct prefix *p = bgp_dest_get_prefix(dest);
- if (safi == SAFI_FLOWSPEC) {
- bgp_pbr_update_entry(bgp, bgp_dest_get_prefix(dest), info, afi,
- safi, true);
- return;
+ if (table->safi == SAFI_FLOWSPEC) {
+ bgp_pbr_update_entry(bgp, p, info, table->afi, table->safi,
+ true);
+ return ZCLIENT_SEND_SUCCESS;
}
/* Make Zebra API structure. */
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
- api.safi = safi;
+ api.safi = table->safi;
api.prefix = *p;
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
@@ -1579,15 +1600,15 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api.tableid = info->attr->rmap_table_id;
}
- if (CHECK_FLAG(info->attr->flag, ATTR_FLAG_BIT(BGP_ATTR_SRTE_COLOR)))
+ if (info->attr->srte_color)
SET_FLAG(api.message, ZAPI_MESSAGE_SRTE);
/* Metric is currently based on the best-path only */
metric = info->attr->med;
bgp_zebra_announce_parse_nexthop(info, p, bgp, &api, &valid_nh_count,
- afi, safi, &nhg_id, &metric, &tag,
- &allow_recursion);
+ table->afi, table->safi, &nhg_id,
+ &metric, &tag, &allow_recursion);
is_add = (valid_nh_count || nhg_id) ? true : false;
@@ -1640,7 +1661,7 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api.tag = tag;
}
- distance = bgp_distance_apply(p, info, afi, safi, bgp);
+ distance = bgp_distance_apply(p, info, table->afi, table->safi, bgp);
if (distance) {
SET_FLAG(api.message, ZAPI_MESSAGE_DISTANCE);
api.distance = distance;
@@ -1654,16 +1675,14 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
api.metric, api.tag, api.nexthop_num, nhg_id);
bgp_debug_zebra_nh(&api);
- if (CHECK_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION))
- recursion_flag = 1;
-
zlog_debug("%s: %pFX: announcing to zebra (recursion %sset)",
- __func__, p, (recursion_flag ? "" : "NOT "));
+ __func__, p, (allow_recursion ? "" : "NOT "));
}
- zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
- zclient, &api);
+ return zclient_route_send(is_add ? ZEBRA_ROUTE_ADD : ZEBRA_ROUTE_DELETE,
+ zclient, &api);
}
+
/* Announce all routes of a table to zebra */
void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
{
@@ -1684,14 +1703,11 @@ void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi)
for (dest = bgp_table_top(table); dest; dest = bgp_route_next(dest))
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
-
(pi->type == ZEBRA_ROUTE_BGP
&& (pi->sub_type == BGP_ROUTE_NORMAL
|| pi->sub_type == BGP_ROUTE_IMPORTED)))
-
- bgp_zebra_announce(dest,
- bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, true,
+ NULL, false);
}
/* Announce routes of any bgp subtype of a table to zebra */
@@ -1713,39 +1729,30 @@ void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next)
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED) &&
pi->type == ZEBRA_ROUTE_BGP)
- bgp_zebra_announce(dest,
- bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, true,
+ NULL, false);
}
-void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
- struct bgp *bgp, afi_t afi, safi_t safi)
+enum zclient_send_status bgp_zebra_withdraw_actual(struct bgp_dest *dest,
+ struct bgp_path_info *info,
+ struct bgp *bgp)
{
struct zapi_route api;
struct peer *peer;
+ struct bgp_table *table = bgp_dest_table(dest);
+ const struct prefix *p = bgp_dest_get_prefix(dest);
- /*
- * If we are withdrawing the route, we don't need to have this
- * flag set. So unset it.
- */
- UNSET_FLAG(info->net->flags, BGP_NODE_FIB_INSTALL_PENDING);
-
- /* Don't try to install if we're not connected to Zebra or Zebra doesn't
- * know of this instance.
- */
- if (!bgp_install_info_to_zebra(bgp))
- return;
-
- if (safi == SAFI_FLOWSPEC) {
+ if (table->safi == SAFI_FLOWSPEC) {
peer = info->peer;
- bgp_pbr_update_entry(peer->bgp, p, info, afi, safi, false);
- return;
+ bgp_pbr_update_entry(peer->bgp, p, info, table->afi,
+ table->safi, false);
+ return ZCLIENT_SEND_SUCCESS;
}
memset(&api, 0, sizeof(api));
api.vrf_id = bgp->vrf_id;
api.type = ZEBRA_ROUTE_BGP;
- api.safi = safi;
+ api.safi = table->safi;
api.prefix = *p;
if (info->attr->rmap_table_id) {
@@ -1757,7 +1764,218 @@ void bgp_zebra_withdraw(const struct prefix *p, struct bgp_path_info *info,
zlog_debug("Tx route delete VRF %u %pFX", bgp->vrf_id,
&api.prefix);
- zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+ return zclient_route_send(ZEBRA_ROUTE_DELETE, zclient, &api);
+}
+
+/*
+ * Walk the new Fifo list one by one and invoke bgp_zebra_announce/withdraw
+ * to install/withdraw the routes to zebra.
+ *
+ * If status = ZCLIENT_SEND_SUCCESS (Buffer empt)y i.e. Zebra is free to
+ * receive more incoming data, then pick the next item on the list and
+ * continue processing.
+ *
+ * If status = ZCLIENT_SEND_BUFFERED (Buffer pending) i.e. Zebra is busy,
+ * break and bail out of the function because once at some point when zebra
+ * is free, a callback is triggered which inturn call this same function and
+ * continue processing items on list.
+ */
+#define ZEBRA_ANNOUNCEMENTS_LIMIT 1000
+static void bgp_handle_route_announcements_to_zebra(struct event *e)
+{
+ bool is_evpn = false;
+ uint32_t count = 0;
+ struct bgp_dest *dest = NULL;
+ struct bgp_table *table = NULL;
+ enum zclient_send_status status = ZCLIENT_SEND_SUCCESS;
+ bool install;
+ const struct prefix_evpn *evp = NULL;
+
+ while (count < ZEBRA_ANNOUNCEMENTS_LIMIT) {
+ is_evpn = false;
+
+ dest = zebra_announce_pop(&bm->zebra_announce_head);
+
+ if (!dest)
+ break;
+
+ table = bgp_dest_table(dest);
+ install = CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ if (table->afi == AFI_L2VPN && table->safi == SAFI_EVPN) {
+ is_evpn = true;
+ evp = (const struct prefix_evpn *)bgp_dest_get_prefix(
+ dest);
+ }
+
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("BGP %s route %pBD(%s) with dest %p and flags 0x%x to zebra",
+ install ? "announcing" : "withdrawing", dest,
+ table->bgp->name_pretty, dest, dest->flags);
+
+ if (install) {
+ if (is_evpn)
+ status =
+ evpn_zebra_install(table->bgp,
+ dest->za_vpn,
+ (const struct prefix_evpn
+ *)
+ bgp_dest_get_prefix(
+ dest),
+ dest->za_bgp_pi);
+ else
+ status = bgp_zebra_announce_actual(dest,
+ dest->za_bgp_pi,
+ table->bgp);
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ } else {
+ if (is_evpn)
+ status = evpn_zebra_uninstall(
+ table->bgp, dest->za_vpn,
+ (const struct prefix_evpn *)
+ bgp_dest_get_prefix(dest),
+ dest->za_bgp_pi, false);
+ else
+ status = bgp_zebra_withdraw_actual(dest,
+ dest->za_bgp_pi,
+ table->bgp);
+
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ }
+
+ if (is_evpn && status == ZCLIENT_SEND_FAILURE)
+ flog_err(EC_BGP_EVPN_FAIL,
+ "%s (%u): Failed to %s EVPN %pFX %s route in VNI %u",
+ vrf_id_to_name(table->bgp->vrf_id),
+ table->bgp->vrf_id,
+ install ? "install" : "uninstall", evp,
+ evp->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
+ ? "MACIP"
+ : "IMET",
+ dest->za_vpn->vni);
+
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ dest->za_bgp_pi = NULL;
+ dest->za_vpn = NULL;
+ bgp_dest_unlock_node(dest);
+
+ if (status == ZCLIENT_SEND_BUFFERED)
+ break;
+
+ count++;
+ }
+
+ if (status != ZCLIENT_SEND_BUFFERED &&
+ zebra_announce_count(&bm->zebra_announce_head))
+ event_add_event(bm->master,
+ bgp_handle_route_announcements_to_zebra, NULL,
+ 0, &bm->t_bgp_zebra_route);
+}
+
+/*
+ * Callback function invoked when zclient_flush_data() receives a BUFFER_EMPTY
+ * i.e. zebra is free to receive more incoming data.
+ */
+static void bgp_zebra_buffer_write_ready(void)
+{
+ bgp_handle_route_announcements_to_zebra(NULL);
+}
+
+/*
+ * BGP is now keeping a list of dests with the dest having a pointer
+ * to the bgp_path_info that it will be working on.
+ * Here is the sequence of events that should happen:
+ *
+ * Current State New State Action
+ * ------------- --------- ------
+ * ---- Install Place dest on list, save pi, mark
+ * as going to be installed
+ * ---- Withdrawal Place dest on list, save pi, mark
+ * as going to be deleted
+ *
+ * Install Install Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * Installed
+ * Install Withdrawal Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * withdrawan, remove install flag
+ *
+ * Withdrawal Install Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * installed.
+ * Withdrawal Withdrawal Leave dest on list, release old pi,
+ * save new pi, mark as going to be
+ * withdrawn.
+ */
+void bgp_zebra_route_install(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp, bool install, struct bgpevpn *vpn,
+ bool is_sync)
+{
+ bool is_evpn = false;
+ struct bgp_table *table = NULL;
+
+ table = bgp_dest_table(dest);
+ if (table && table->afi == AFI_L2VPN && table->safi == SAFI_EVPN)
+ is_evpn = true;
+
+ /*
+ * BGP is installing this route and bgp has been configured
+ * to suppress announcements until the route has been installed
+ * let's set the fact that we expect this route to be installed
+ */
+ if (install) {
+ if (BGP_SUPPRESS_FIB_ENABLED(bgp))
+ SET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+
+ if (bgp->main_zebra_update_hold && !is_evpn)
+ return;
+ } else {
+ UNSET_FLAG(dest->flags, BGP_NODE_FIB_INSTALL_PENDING);
+ }
+
+ /*
+ * Don't try to install if we're not connected to Zebra or Zebra doesn't
+ * know of this instance.
+ */
+ if (!bgp_install_info_to_zebra(bgp) && !is_evpn)
+ return;
+
+ if (!CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL) &&
+ !CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
+ zebra_announce_add_tail(&bm->zebra_announce_head, dest);
+ /*
+ * If neither flag is set and za_bgp_pi is not set then it is a bug
+ */
+ assert(!dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ bgp_dest_lock_node(dest);
+ dest->za_bgp_pi = info;
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL)) {
+ assert(dest->za_bgp_pi);
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ dest->za_bgp_pi = info;
+ } else if (CHECK_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE)) {
+ assert(dest->za_bgp_pi);
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_path_info_lock(info);
+ dest->za_bgp_pi = info;
+ }
+
+ if (is_evpn) {
+ dest->za_vpn = vpn;
+ dest->za_is_sync = is_sync;
+ }
+
+ if (install) {
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ } else {
+ UNSET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_INSTALL);
+ SET_FLAG(dest->flags, BGP_NODE_SCHEDULE_FOR_DELETE);
+ }
+
+ event_add_event(bm->master, bgp_handle_route_announcements_to_zebra,
+ NULL, 0, &bm->t_bgp_zebra_route);
}
/* Withdraw all entries in a BGP instances RIB table from Zebra */
@@ -1778,8 +1996,8 @@ void bgp_zebra_withdraw_table_all_subtypes(struct bgp *bgp, afi_t afi, safi_t sa
for (pi = bgp_dest_get_bgp_path_info(dest); pi; pi = pi->next) {
if (CHECK_FLAG(pi->flags, BGP_PATH_SELECTED)
&& (pi->type == ZEBRA_ROUTE_BGP))
- bgp_zebra_withdraw(bgp_dest_get_prefix(dest),
- pi, bgp, afi, safi);
+ bgp_zebra_route_install(dest, pi, bgp, false,
+ NULL, false);
}
}
}
@@ -1964,7 +2182,7 @@ bool bgp_redistribute_metric_set(struct bgp *bgp, struct bgp_redist *red,
bgp_path_info_set_flag(dest, pi,
BGP_PATH_ATTR_CHANGED);
- bgp_process(bgp, dest, afi, SAFI_UNICAST);
+ bgp_process(bgp, dest, pi, afi, SAFI_UNICAST);
}
}
}
@@ -3148,6 +3366,15 @@ static int bgp_ifp_create(struct interface *ifp)
bgp_update_interface_nbrs(bgp, ifp, ifp);
hook_call(bgp_vrf_status_changed, bgp, ifp);
+
+ if (bgp_get_default() && if_is_loopback(ifp)) {
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_label_update(bgp, AFI_IP6);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP);
+ vpn_leak_zebra_vrf_sid_update(bgp, AFI_IP6);
+ vpn_leak_postchange_all();
+ }
+
return 0;
}
@@ -3452,6 +3679,7 @@ void bgp_zebra_init(struct event_loop *master, unsigned short instance)
zclient = zclient_new(master, &zclient_options_default, bgp_handlers,
array_size(bgp_handlers));
zclient_init(zclient, ZEBRA_ROUTE_BGP, 0, &bgpd_privs);
+ zclient->zebra_buffer_write_ready = bgp_zebra_buffer_write_ready;
zclient->zebra_connected = bgp_zebra_connected;
zclient->zebra_capabilities = bgp_zebra_capabilities;
zclient->nexthop_update = bgp_nexthop_update;
@@ -3892,8 +4120,7 @@ int bgp_zebra_srv6_manager_release_locator_chunk(const char *name)
void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t ifindex, vrf_id_t vrf_id,
enum lsp_types_t ltype, struct prefix *p,
- uint32_t num_labels,
- mpls_label_t out_labels[])
+ uint8_t num_labels, mpls_label_t out_labels[])
{
struct zapi_labels zl = {};
struct zapi_nexthop *znh;
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 396c833..55a4185 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -28,13 +28,11 @@ extern void bgp_zebra_destroy(void);
extern int bgp_zebra_get_table_range(struct zclient *zc, uint32_t chunk_size,
uint32_t *start, uint32_t *end);
extern int bgp_if_update_all(void);
-extern void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
- struct bgp_path_info *path, struct bgp *bgp,
- afi_t afi, safi_t safi);
+extern void bgp_zebra_route_install(struct bgp_dest *dest,
+ struct bgp_path_info *path, struct bgp *bgp,
+ bool install, struct bgpevpn *vpn,
+ bool is_sync);
extern void bgp_zebra_announce_table(struct bgp *bgp, afi_t afi, safi_t safi);
-extern void bgp_zebra_withdraw(const struct prefix *p,
- struct bgp_path_info *path, struct bgp *bgp,
- afi_t afi, safi_t safi);
/* Announce routes of any bgp subtype of a table to zebra */
extern void bgp_zebra_announce_table_all_subtypes(struct bgp *bgp, afi_t afi,
@@ -122,9 +120,12 @@ extern int bgp_zebra_srv6_manager_release_locator_chunk(const char *name);
extern void bgp_zebra_send_nexthop_label(int cmd, mpls_label_t label,
ifindex_t index, vrf_id_t vrfid,
enum lsp_types_t ltype,
- struct prefix *p, uint32_t num_labels,
+ struct prefix *p, uint8_t num_labels,
mpls_label_t out_labels[]);
extern bool bgp_zebra_request_label_range(uint32_t base, uint32_t chunk_size,
bool label_auto);
extern void bgp_zebra_release_label_range(uint32_t start, uint32_t end);
+extern enum zclient_send_status
+bgp_zebra_withdraw_actual(struct bgp_dest *dest, struct bgp_path_info *info,
+ struct bgp *bgp);
#endif /* _QUAGGA_BGP_ZEBRA_H */
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index d6d874b..894226a 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -1377,7 +1377,7 @@ int bgp_global_gr_init(struct bgp *bgp)
/*GLOBAL_GR_cmd */ /*no_Global_GR_cmd*/
GLOBAL_GR, GLOBAL_INVALID,
/*GLOBAL_DISABLE_cmd*//*no_Global_Disable_cmd*/
- GLOBAL_INVALID, GLOBAL_HELPER
+ GLOBAL_DISABLE, GLOBAL_HELPER
},
/* GLOBAL_INVALID Mode */
{
@@ -1411,13 +1411,13 @@ int bgp_peer_gr_init(struct peer *peer)
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
{PEER_DISABLE, bgp_peer_gr_action }, {PEER_INVALID, NULL },
/* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
- { PEER_INVALID, NULL }, {PEER_GLOBAL_INHERIT,
+ { PEER_HELPER, NULL }, {PEER_GLOBAL_INHERIT,
bgp_peer_gr_action }
},
{
/* PEER_GR Mode */
/* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
- { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
+ { PEER_GR, NULL }, { PEER_GLOBAL_INHERIT,
bgp_peer_gr_action },
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
{PEER_DISABLE, bgp_peer_gr_action }, { PEER_INVALID, NULL },
@@ -1429,7 +1429,7 @@ int bgp_peer_gr_init(struct peer *peer)
/* Event-> */ /* PEER_GR_CMD */ /* NO_PEER_GR_CMD */
{ PEER_GR, bgp_peer_gr_action }, { PEER_INVALID, NULL },
/* Event-> */ /* PEER_DISABLE_CMD */ /* NO_PEER_DISABLE_CMD */
- { PEER_INVALID, NULL }, { PEER_GLOBAL_INHERIT,
+ { PEER_DISABLE, NULL }, { PEER_GLOBAL_INHERIT,
bgp_peer_gr_action },
/* Event-> */ /* PEER_HELPER_cmd */ /* NO_PEER_HELPER_CMD */
{ PEER_HELPER, bgp_peer_gr_action }, { PEER_INVALID, NULL }
@@ -1550,6 +1550,8 @@ struct peer *peer_new(struct bgp *bgp)
PEER_FLAG_SEND_LARGE_COMMUNITY);
peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
peer->addpath_best_selected[afi][safi] = 0;
+ peer->addpath_paths_limit[afi][safi].receive = 0;
+ peer->addpath_paths_limit[afi][safi].send = 0;
peer->soo[afi][safi] = NULL;
}
@@ -1565,6 +1567,9 @@ struct peer *peer_new(struct bgp *bgp)
if (CHECK_FLAG(bgp->flags, BGP_FLAG_SOFT_VERSION_CAPABILITY))
peer_flag_set(peer, PEER_FLAG_CAPABILITY_SOFT_VERSION);
+ if (CHECK_FLAG(bgp->flags, BGP_FLAG_DYNAMIC_CAPABILITY))
+ peer_flag_set(peer, PEER_FLAG_DYNAMIC_CAPABILITY);
+
SET_FLAG(peer->flags_invert, PEER_FLAG_CAPABILITY_FQDN);
SET_FLAG(peer->flags, PEER_FLAG_CAPABILITY_FQDN);
@@ -1646,6 +1651,8 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
peer_dst->weight[afi][safi] = peer_src->weight[afi][safi];
peer_dst->addpath_type[afi][safi] =
peer_src->addpath_type[afi][safi];
+ peer_dst->addpath_paths_limit[afi][safi] =
+ peer_src->addpath_paths_limit[afi][safi];
}
for (afidx = BGP_AF_START; afidx < BGP_AF_MAX; afidx++) {
@@ -1869,21 +1876,31 @@ void bgp_peer_conf_if_to_su_update(struct peer_connection *connection)
void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct bgp_dest *dest, *ndest;
+ struct bgp_path_info *pi, *next;
struct bgp_table *table;
for (dest = bgp_table_top(bgp->rib[afi][safi]); dest;
dest = bgp_route_next(dest)) {
table = bgp_dest_get_bgp_table_info(dest);
- if (table != NULL) {
- /* Special handling for 2-level routing
- * tables. */
- if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
- || safi == SAFI_EVPN) {
- for (ndest = bgp_table_top(table); ndest;
- ndest = bgp_route_next(ndest))
- bgp_process(bgp, ndest, afi, safi);
- } else
- bgp_process(bgp, dest, afi, safi);
+
+ if (!table)
+ continue;
+
+ /* Special handling for 2-level routing
+ * tables. */
+ if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
+ || safi == SAFI_EVPN) {
+ for (ndest = bgp_table_top(table); ndest;
+ ndest = bgp_route_next(ndest)) {
+ for (pi = bgp_dest_get_bgp_path_info(ndest);
+ (pi != NULL) && (next = pi->next, 1);
+ pi = next)
+ bgp_process(bgp, ndest, pi, afi, safi);
+ }
+ } else {
+ for (pi = bgp_dest_get_bgp_path_info(dest);
+ (pi != NULL) && (next = pi->next, 1); pi = next)
+ bgp_process(bgp, dest, pi, afi, safi);
}
}
}
@@ -2691,6 +2708,14 @@ int peer_delete(struct peer *peer)
if (peer->bfd_config)
bgp_peer_remove_bfd_config(peer);
+ /* Delete peer route flap dampening configuration. This needs to happen
+ * before removing the peer from peer groups.
+ */
+ FOREACH_AFI_SAFI (afi, safi)
+ if (peer_af_flag_check(peer, afi, safi,
+ PEER_FLAG_CONFIG_DAMPENING))
+ bgp_peer_damp_disable(peer, afi, safi);
+
/* If this peer belongs to peer group, clear up the
relationship. */
if (peer->group) {
@@ -2938,6 +2963,13 @@ static void peer_group2peer_config_copy(struct peer_group *group,
SET_FLAG(peer->flags,
PEER_FLAG_CAPABILITY_SOFT_VERSION);
+ /* capability dynamic apply */
+ if (!CHECK_FLAG(peer->flags_override,
+ PEER_FLAG_DYNAMIC_CAPABILITY))
+ if (CHECK_FLAG(conf->flags, PEER_FLAG_DYNAMIC_CAPABILITY))
+ SET_FLAG(peer->flags,
+ PEER_FLAG_DYNAMIC_CAPABILITY);
+
/* password apply */
if (!CHECK_FLAG(peer->flags_override, PEER_FLAG_PASSWORD))
PEER_STR_ATTR_INHERIT(peer, group, password,
@@ -2992,9 +3024,21 @@ int peer_group_remote_as(struct bgp *bgp, const char *group_name, as_t *as,
peer_as_change(group->conf, *as, as_type, as_str);
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- if (((peer->as_type == AS_SPECIFIED) && peer->as != *as)
- || (peer->as_type != as_type))
+ if (((peer->as_type == AS_SPECIFIED) && peer->as != *as) ||
+ (peer->as_type != as_type)) {
peer_as_change(peer, *as, as_type, as_str);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug("%s peer %s set to as_type %u curr status %s trigger BGP_Start",
+ __func__, peer->host, peer->as_type,
+ lookup_msg(bgp_status_msg,
+ peer->connection->status, NULL));
+ /* Start Peer FSM to form neighbor using new as,
+ * NOTE: the connection is triggered upon start
+ * timer expiry.
+ */
+ if (!BGP_PEER_START_SUPPRESSED(peer))
+ BGP_EVENT_ADD(peer->connection, BGP_Start);
+ }
}
return 0;
@@ -3089,7 +3133,7 @@ int peer_group_delete(struct peer_group *group)
int peer_group_remote_as_delete(struct peer_group *group)
{
- struct peer *peer, *other;
+ struct peer *peer;
struct listnode *node, *nnode;
if ((group->conf->as_type == AS_UNSPECIFIED)
@@ -3097,19 +3141,12 @@ int peer_group_remote_as_delete(struct peer_group *group)
return 0;
for (ALL_LIST_ELEMENTS(group->peer, node, nnode, peer)) {
- other = peer->doppelganger;
-
if (CHECK_FLAG(peer->flags, PEER_FLAG_CAPABILITY_ENHE))
bgp_zebra_terminate_radv(peer->bgp, peer);
- peer_delete(peer);
-
- if (other && other->connection->status != Deleted) {
- other->group = NULL;
- peer_delete(other);
- }
+ /* reset existing peer connection */
+ peer_as_change(peer, 0, AS_UNSPECIFIED, NULL);
}
- list_delete_all_node(group->peer);
group->conf->as = 0;
group->conf->as_type = AS_UNSPECIFIED;
@@ -3583,10 +3620,13 @@ struct bgp *bgp_lookup_by_name(const char *name)
struct bgp *bgp;
struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
+ for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
+ if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_AUTO))
+ continue;
if ((bgp->name == NULL && name == NULL)
|| (bgp->name && name && strcmp(bgp->name, name) == 0))
return bgp;
+ }
return NULL;
}
@@ -3835,6 +3875,9 @@ void bgp_instance_down(struct bgp *bgp)
struct listnode *node;
struct listnode *next;
+ /* Cleanup evpn instance state */
+ bgp_evpn_instance_down(bgp);
+
/* Stop timers. */
if (bgp->t_rmap_def_originate_eval)
EVENT_OFF(bgp->t_rmap_def_originate_eval);
@@ -3869,10 +3912,35 @@ int bgp_delete(struct bgp *bgp)
afi_t afi;
safi_t safi;
int i;
+ struct bgp_dest *dest = NULL;
+ struct bgp_dest *dest_next = NULL;
+ struct bgp_table *dest_table = NULL;
struct graceful_restart_info *gr_info;
+ uint32_t cnt_before, cnt_after;
assert(bgp);
+ /*
+ * Iterate the pending dest list and remove all the dest pertaininig to
+ * the bgp under delete.
+ */
+ cnt_before = zebra_announce_count(&bm->zebra_announce_head);
+ for (dest = zebra_announce_first(&bm->zebra_announce_head); dest;
+ dest = dest_next) {
+ dest_next = zebra_announce_next(&bm->zebra_announce_head, dest);
+ dest_table = bgp_dest_table(dest);
+ if (dest_table->bgp == bgp) {
+ zebra_announce_del(&bm->zebra_announce_head, dest);
+ bgp_path_info_unlock(dest->za_bgp_pi);
+ bgp_dest_unlock_node(dest);
+ }
+ }
+
+ cnt_after = zebra_announce_count(&bm->zebra_announce_head);
+ if (BGP_DEBUG(zebra, ZEBRA))
+ zlog_debug("Zebra Announce Fifo cleanup count before %u and after %u during BGP %s deletion",
+ cnt_before, cnt_after, bgp->name_pretty);
+
bgp_soft_reconfig_table_task_cancel(bgp, NULL, NULL);
/* make sure we withdraw any exported routes */
@@ -3921,6 +3989,11 @@ int bgp_delete(struct bgp *bgp)
EVENT_OFF(gr_info->t_route_select);
}
+ /* Delete route flap dampening configuration */
+ FOREACH_AFI_SAFI (afi, safi) {
+ bgp_damp_disable(bgp, afi, safi);
+ }
+
if (BGP_DEBUG(zebra, ZEBRA)) {
if (bgp->inst_type == BGP_INSTANCE_TYPE_DEFAULT)
zlog_debug("Deleting Default VRF");
@@ -4385,6 +4458,11 @@ struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
zlog_debug("%s Dynamic Neighbor added, group %s count %d",
peer->host, group->name, dncount);
+ if (dncount == gbgp->dynamic_neighbors_limit) {
+ zlog_warn("Dynamic Neighbor %s added as last connection. Peer-group %s reached maximum listen limit %d",
+ peer->host, group->name,
+ gbgp->dynamic_neighbors_limit);
+ }
return peer;
}
@@ -4571,7 +4649,7 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_DONT_CAPABILITY, 0, peer_change_none},
{PEER_FLAG_OVERRIDE_CAPABILITY, 0, peer_change_none},
{PEER_FLAG_STRICT_CAP_MATCH, 0, peer_change_none},
- {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_reset},
+ {PEER_FLAG_DYNAMIC_CAPABILITY, 0, peer_change_none},
{PEER_FLAG_DISABLE_CONNECTED_CHECK, 0, peer_change_reset},
{PEER_FLAG_CAPABILITY_ENHE, 0, peer_change_reset},
{PEER_FLAG_ENFORCE_FIRST_AS, 0, peer_change_reset_in},
@@ -4594,6 +4672,8 @@ static const struct peer_flag_action peer_flag_action_list[] = {
{PEER_FLAG_GRACEFUL_SHUTDOWN, 0, peer_change_none},
{PEER_FLAG_CAPABILITY_SOFT_VERSION, 0, peer_change_none},
{PEER_FLAG_CAPABILITY_FQDN, 0, peer_change_none},
+ {PEER_FLAG_AS_LOOP_DETECTION, 0, peer_change_none},
+ {PEER_FLAG_EXTENDED_LINK_BANDWIDTH, 0, peer_change_none},
{0, 0, 0}};
static const struct peer_flag_action peer_af_flag_action_list[] = {
@@ -4628,6 +4708,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_SOO, 0, peer_change_reset},
{PEER_FLAG_ACCEPT_OWN, 0, peer_change_reset},
{PEER_FLAG_SEND_EXT_COMMUNITY_RPKI, 1, peer_change_reset_out},
+ {PEER_FLAG_ADDPATH_RX_PATHS_LIMIT, 0, peer_change_none},
{0, 0, 0}};
/* Proper action set. */
@@ -4758,6 +4839,8 @@ void bgp_shutdown_enable(struct bgp *bgp, const char *msg)
/* iterate through peers of BGP instance */
for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
+ peer->last_reset = PEER_DOWN_USER_SHUTDOWN;
+
/* continue, if peer is already in administrative shutdown. */
if (CHECK_FLAG(peer->flags, PEER_FLAG_SHUTDOWN))
continue;
@@ -4812,8 +4895,10 @@ void bgp_shutdown_disable(struct bgp *bgp)
/* clear the BGP instances shutdown flag */
UNSET_FLAG(bgp->flags, BGP_FLAG_SHUTDOWN);
- for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer))
+ for (ALL_LIST_ELEMENTS_RO(bgp->peer, node, peer)) {
bgp_timer_set(peer->connection);
+ peer->last_reset = PEER_DOWN_WAITING_OPEN;
+ }
}
/* Change specified peer flag. */
@@ -4885,6 +4970,10 @@ static int peer_flag_modify(struct peer *peer, uint64_t flag, int set)
bgp_zebra_terminate_radv(peer->bgp, peer);
}
+ if (flag == PEER_FLAG_SHUTDOWN)
+ peer->last_reset = set ? PEER_DOWN_USER_SHUTDOWN
+ : PEER_DOWN_WAITING_OPEN;
+
/* Execute flag action on peer. */
if (action.type == peer_change_reset)
peer_flag_modify_action(peer, flag);
@@ -4920,6 +5009,10 @@ static int peer_flag_modify(struct peer *peer, uint64_t flag, int set)
set ? bgp_zebra_initiate_radv(member->bgp, member)
: bgp_zebra_terminate_radv(member->bgp, member);
+ if (flag == PEER_FLAG_SHUTDOWN)
+ member->last_reset = set ? PEER_DOWN_USER_SHUTDOWN
+ : PEER_DOWN_WAITING_OPEN;
+
/* Execute flag action on peer-group member. */
if (action.type == peer_change_reset)
peer_flag_modify_action(member, flag);
@@ -8298,6 +8391,8 @@ void bgp_master_init(struct event_loop *master, const int buffer_size,
memset(&bgp_master, 0, sizeof(bgp_master));
bm = &bgp_master;
+
+ zebra_announce_init(&bm->zebra_announce_head);
bm->bgp = list_new();
bm->listen_sockets = list_new();
bm->port = BGP_PORT_DEFAULT;
@@ -8311,11 +8406,12 @@ void bgp_master_init(struct event_loop *master, const int buffer_size,
bm->terminating = false;
bm->socket_buffer = buffer_size;
bm->wait_for_fib = false;
- bm->tcp_dscp = IPTOS_PREC_INTERNETCONTROL;
+ bm->ip_tos = IPTOS_PREC_INTERNETCONTROL;
bm->inq_limit = BM_DEFAULT_Q_LIMIT;
bm->outq_limit = BM_DEFAULT_Q_LIMIT;
bm->t_bgp_sync_label_manager = NULL;
bm->t_bgp_start_label_manager = NULL;
+ bm->t_bgp_zebra_route = NULL;
bgp_mac_init();
/* init the rd id space.
@@ -8482,6 +8578,7 @@ void bgp_init(unsigned short instance)
/* BGP inits. */
bgp_attr_init();
+ bgp_labels_init();
bgp_debug_init();
bgp_community_alias_init();
bgp_dump_init();
@@ -8566,6 +8663,7 @@ void bgp_terminate(void)
EVENT_OFF(bm->t_rmap_update);
EVENT_OFF(bm->t_bgp_sync_label_manager);
EVENT_OFF(bm->t_bgp_start_label_manager);
+ EVENT_OFF(bm->t_bgp_zebra_route);
bgp_mac_finish();
}
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 0f69095..1f8cc53 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -18,6 +18,8 @@
#include "iana_afi.h"
#include "asn.h"
+PREDECL_LIST(zebra_announce);
+
/* For union sockunion. */
#include "queue.h"
#include "sockunion.h"
@@ -31,6 +33,7 @@
#include "bgp_addpath_types.h"
#include "bgp_nexthop.h"
#include "bgp_io.h"
+#include "bgp_damp.h"
#include "lib/bfd.h"
@@ -163,8 +166,8 @@ struct bgp_master {
bool terminating; /* global flag that sigint terminate seen */
- /* DSCP value for TCP sessions */
- uint8_t tcp_dscp;
+ /* TOS value for outgoing packets in BGP connections */
+ uint8_t ip_tos;
#define BM_DEFAULT_Q_LIMIT 10000
uint32_t inq_limit;
@@ -173,8 +176,13 @@ struct bgp_master {
struct event *t_bgp_sync_label_manager;
struct event *t_bgp_start_label_manager;
+ struct event *t_bgp_zebra_route;
+
bool v6_with_v4_nexthops;
+ /* To preserve ordering of installations into zebra across all Vrfs */
+ struct zebra_announce_head zebra_announce_head;
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp_master);
@@ -471,7 +479,7 @@ struct bgp {
* factor (e.g., number of multipaths for the prefix)
* Value is in Mbps
*/
- uint32_t lb_ref_bw;
+ uint64_t lb_ref_bw;
#define BGP_LINK_BW_REF_BW 1
/* BGP flags. */
@@ -522,6 +530,8 @@ struct bgp {
#define BGP_FLAG_LU_IPV6_EXPLICIT_NULL (1ULL << 34)
#define BGP_FLAG_SOFT_VERSION_CAPABILITY (1ULL << 35)
#define BGP_FLAG_ENFORCE_FIRST_AS (1ULL << 36)
+#define BGP_FLAG_DYNAMIC_CAPABILITY (1ULL << 37)
+#define BGP_FLAG_VNI_DOWN (1ULL << 38)
/* BGP default address-families.
* New peers inherit enabled afi/safis from bgp instance.
@@ -825,6 +835,9 @@ struct bgp {
enum asnotation_mode asnotation;
+ /* BGP route flap dampening configuration */
+ struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(bgp);
@@ -1140,6 +1153,11 @@ struct llgr_info {
uint8_t flags;
};
+struct addpath_paths_limit {
+ uint16_t send;
+ uint16_t receive;
+};
+
struct peer_connection {
struct peer *peer;
@@ -1333,6 +1351,8 @@ struct peer {
#define PEER_CAP_ROLE_RCV (1ULL << 26) /* role received */
#define PEER_CAP_SOFT_VERSION_ADV (1ULL << 27)
#define PEER_CAP_SOFT_VERSION_RCV (1ULL << 28)
+#define PEER_CAP_PATHS_LIMIT_ADV (1U << 29)
+#define PEER_CAP_PATHS_LIMIT_RCV (1U << 30)
/* Capability flags (reset in bgp_stop) */
uint32_t af_cap[AFI_MAX][SAFI_MAX];
@@ -1351,6 +1371,8 @@ struct peer {
#define PEER_CAP_ENHE_AF_NEGO (1U << 14) /* Extended nexthop afi/safi negotiated */
#define PEER_CAP_LLGR_AF_ADV (1U << 15)
#define PEER_CAP_LLGR_AF_RCV (1U << 16)
+#define PEER_CAP_PATHS_LIMIT_AF_ADV (1U << 17)
+#define PEER_CAP_PATHS_LIMIT_AF_RCV (1U << 18)
/* Global configuration flags. */
/*
@@ -1461,6 +1483,8 @@ struct peer {
#define PEER_FLAG_GRACEFUL_SHUTDOWN (1ULL << 35)
#define PEER_FLAG_CAPABILITY_SOFT_VERSION (1ULL << 36)
#define PEER_FLAG_CAPABILITY_FQDN (1ULL << 37) /* fqdn capability */
+#define PEER_FLAG_AS_LOOP_DETECTION (1ULL << 38) /* as path loop detection */
+#define PEER_FLAG_EXTENDED_LINK_BANDWIDTH (1ULL << 39)
/*
*GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
@@ -1488,6 +1512,9 @@ struct peer {
/* Last update packet sent time */
time_t pkt_stime[AFI_MAX][SAFI_MAX];
+ /* Peer / peer group route flap dampening configuration */
+ struct bgp_damp_config damp[AFI_MAX][SAFI_MAX];
+
/* Peer Per AF flags */
/*
* Please consult the comments for *flags_override*, *flags_invert* and
@@ -1528,6 +1555,8 @@ struct peer {
#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 27)
#define PEER_FLAG_SOO (1ULL << 28)
#define PEER_FLAG_SEND_EXT_COMMUNITY_RPKI (1ULL << 29)
+#define PEER_FLAG_ADDPATH_RX_PATHS_LIMIT (1ULL << 30)
+#define PEER_FLAG_CONFIG_DAMPENING (1U << 31)
#define PEER_FLAG_ACCEPT_OWN (1ULL << 63)
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
@@ -1647,6 +1676,8 @@ struct peer {
uint32_t stat_pfx_nh_invalid;
uint32_t stat_pfx_dup_withdraw;
uint32_t stat_upd_7606; /* RFC7606: treat-as-withdraw */
+ uint64_t stat_pfx_loc_rib; /* RFC7854 : Number of routes in Loc-RIB */
+ uint64_t stat_pfx_adj_rib_in; /* RFC7854 : Number of routes in Adj-RIBs-In */
/* BGP state count */
uint32_t established; /* Established */
@@ -1813,9 +1844,6 @@ struct peer {
char *hostname;
char *domainname;
- /* Sender side AS path loop detection. */
- bool as_path_loop_detection;
-
/* Extended Message Support */
uint16_t max_packet_size;
@@ -1845,6 +1873,9 @@ struct peer {
/* Add-Path Best selected paths number to advertise */
uint8_t addpath_best_selected[AFI_MAX][SAFI_MAX];
+ /* Add-Path Paths-Limit */
+ struct addpath_paths_limit addpath_paths_limit[AFI_MAX][SAFI_MAX];
+
QOBJ_FIELDS;
};
DECLARE_QOBJ_TYPE(peer);
@@ -1951,7 +1982,6 @@ struct bgp_nlri {
#define BGP_ATTR_LARGE_COMMUNITIES 32
#define BGP_ATTR_OTC 35
#define BGP_ATTR_PREFIX_SID 40
-#define BGP_ATTR_SRTE_COLOR 51
#ifdef ENABLE_BGP_VNC_ATTR
#define BGP_ATTR_VNC 255
#endif
@@ -1970,6 +2000,7 @@ struct bgp_nlri {
#define BGP_NOTIFY_FSM_ERR 5
#define BGP_NOTIFY_CEASE 6
#define BGP_NOTIFY_ROUTE_REFRESH_ERR 7
+#define BGP_NOTIFY_SEND_HOLD_ERR 8
/* Subcodes for BGP Finite State Machine Error */
#define BGP_NOTIFY_FSM_ERR_SUBCODE_UNSPECIFIC 0
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 382af05..23e3eb4 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -463,7 +463,7 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_path_info_delete(bn, bpi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
} else {
vnc_zlog_debug_verbose(
"%s: Couldn't find route (safi=%d) at prefix %pFX",
@@ -549,6 +549,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
int flags)
{
afi_t afi; /* of the VN address */
+ struct bgp_labels bgp_labels = {};
struct bgp_path_info *new;
struct bgp_path_info *bpi;
struct bgp_dest *bn;
@@ -592,7 +593,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
}
}
- if (label)
+ if (label && *label != MPLS_INVALID_LABEL)
label_val = *label;
else
label_val = MPLS_LABEL_IMPLICIT_NULL;
@@ -1001,7 +1002,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
/* Process change. */
bgp_aggregate_increment(bgp, p, bpi, afi, safi);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, bpi, afi, safi);
bgp_dest_unlock_node(bn);
vnc_zlog_debug_any(
@@ -1020,7 +1021,10 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
new->extra->vnc = XCALLOC(MTYPE_BGP_ROUTE_EXTRA_VNC,
sizeof(struct bgp_path_info_extra_vnc));
new->extra->vnc->vnc.export.rfapi_handle = (void *)rfd;
- encode_label(label_val, &new->extra->label[0]);
+
+ encode_label(label_val, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
/* debug */
@@ -1046,7 +1050,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
}
bgp_dest_unlock_node(bn);
- bgp_process(bgp, bn, afi, safi);
+ bgp_process(bgp, bn, new, afi, safi);
vnc_zlog_debug_any(
"%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRDP)",
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 168b8e4..2afcb2f 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -442,6 +442,7 @@ static struct bgp_path_info *rfapiBgpInfoCreate(struct attr *attr,
uint32_t *label)
{
struct bgp_path_info *new;
+ struct bgp_labels bgp_labels = {};
new = info_make(type, sub_type, 0, peer, attr, NULL);
@@ -454,8 +455,11 @@ static struct bgp_path_info *rfapiBgpInfoCreate(struct attr *attr,
new->extra->vnc->vnc.import.rd = *prd;
new->extra->vnc->vnc.import.create_time = monotime(NULL);
}
- if (label)
- encode_label(*label, &new->extra->label[0]);
+ if (label && *label != MPLS_INVALID_LABEL) {
+ encode_label(*label, &bgp_labels.label[0]);
+ bgp_labels.num_labels = 1;
+ new->extra->labels = bgp_labels_intern(&bgp_labels);
+ }
peer_lock(peer);
@@ -1267,7 +1271,10 @@ rfapiRouteInfo2NextHopEntry(struct rfapi_ip_prefix *rprefix,
bpi->extra->vnc->vnc.import.rd.val[1];
/* label comes from MP_REACH_NLRI label */
- vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
+ vo->v.l2addr.label =
+ bgp_path_info_num_labels(bpi)
+ ? decode_label(&bpi->extra->labels->label[0])
+ : MPLS_INVALID_LABEL;
new->vn_options = vo;
@@ -4154,15 +4161,16 @@ static void rfapiBgpTableFilteredImport(struct bgp *bgp,
for (bpi = bgp_dest_get_bgp_path_info(dest2);
bpi; bpi = bpi->next) {
- uint32_t label = 0;
+ uint32_t label = MPLS_INVALID_LABEL;
if (CHECK_FLAG(bpi->flags,
BGP_PATH_REMOVED))
continue;
- if (bpi->extra)
+ if (bgp_path_info_num_labels(bpi))
label = decode_label(
- &bpi->extra->label[0]);
+ &bpi->extra->labels
+ ->label[0]);
(*rfapiBgpInfoFilteredImportFunction(
safi))(
it, /* which import table */
diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c
index 316904e..a0bdf49 100644
--- a/bgpd/rfapi/rfapi_rib.c
+++ b/bgpd/rfapi/rfapi_rib.c
@@ -691,7 +691,10 @@ static void rfapiRibBi2Ri(struct bgp_path_info *bpi, struct rfapi_info *ri,
bpi->extra->vnc->vnc.import.rd.val[1];
/* label comes from MP_REACH_NLRI label */
- vo->v.l2addr.label = decode_label(&bpi->extra->label[0]);
+ vo->v.l2addr.label =
+ bgp_path_info_num_labels(bpi)
+ ? decode_label(&bpi->extra->labels->label[0])
+ : MPLS_INVALID_LABEL;
rfapi_vn_options_free(
ri->vn_options); /* maybe free old version */
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index 5da99db..9bfb6c4 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -413,12 +413,12 @@ void rfapi_vty_out_vncinfo(struct vty *vty, const struct prefix *p,
XFREE(MTYPE_ECOMMUNITY_STR, s);
}
- if (bpi->extra != NULL) {
- if (bpi->extra->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
+ if (bgp_path_info_num_labels(bpi)) {
+ if (bpi->extra->labels->label[0] == BGP_PREVENT_VRF_2_VRF_LEAK)
vty_out(vty, " label=VRF2VRF");
else
vty_out(vty, " label=%u",
- decode_label(&bpi->extra->label[0]));
+ decode_label(&bpi->extra->labels->label[0]));
}
if (bpi->attr->srv6_l3vpn || bpi->attr->srv6_vpn) {
@@ -1052,8 +1052,8 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
snprintf(buf_un, sizeof(buf_un), "%s",
inet_ntop(pfx_vn.family, &pfx_vn.u.prefix, buf_ntop,
sizeof(buf_ntop)));
- if (bpi->extra) {
- uint32_t l = decode_label(&bpi->extra->label[0]);
+ if (bgp_path_info_num_labels(bpi)) {
+ uint32_t l = decode_label(&bpi->extra->labels->label[0]);
snprintf(buf_vn, sizeof(buf_vn), "Label: %d", l);
} else /* should never happen */
{
@@ -1161,8 +1161,8 @@ static int rfapiPrintRemoteRegBi(struct bgp *bgp, void *stream,
}
}
}
- if (tun_type != BGP_ENCAP_TYPE_MPLS && bpi->extra) {
- uint32_t l = decode_label(&bpi->extra->label[0]);
+ if (tun_type != BGP_ENCAP_TYPE_MPLS && bgp_path_info_num_labels(bpi)) {
+ uint32_t l = decode_label(&bpi->extra->labels->label[0]);
if (!MPLS_LABEL_IS_NULL(l)) {
fp(out, " Label: %d", l);
diff --git a/bgpd/rfapi/vnc_import_bgp.c b/bgpd/rfapi/vnc_import_bgp.c
index c067b7a..2bb7c1b 100644
--- a/bgpd/rfapi/vnc_import_bgp.c
+++ b/bgpd/rfapi/vnc_import_bgp.c
@@ -414,7 +414,7 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
uint32_t lifetime;
uint32_t *plifetime;
struct bgp_attr_encap_subtlv *encaptlvs;
- uint32_t label = 0;
+ uint32_t label;
struct rfapi_un_option optary[3];
struct rfapi_un_option *opt = NULL;
@@ -470,16 +470,19 @@ static void vnc_import_bgp_add_route_mode_resolve_nve_one_bi(
if (bgp_attr_get_ecommunity(bpi->attr))
ecommunity_merge(new_ecom, bgp_attr_get_ecommunity(bpi->attr));
- if (bpi->extra)
- label = decode_label(&bpi->extra->label[0]);
+ if (bgp_path_info_num_labels(bpi))
+ label = decode_label(&bpi->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
add_vnc_route(&vncHDResolveNve, bgp, SAFI_MPLS_VPN,
- prefix, /* unicast route prefix */
+ prefix, /* unicast route prefix */
prd, &nexthop_h, /* new nexthop */
local_pref, plifetime,
(struct bgp_tea_options *)encaptlvs, /* RFP options */
opt, NULL, new_ecom, med, /* NULL => don't set med */
- (label ? &label : NULL), /* NULL= default */
+ ((label != MPLS_INVALID_LABEL) ? &label
+ : NULL), /* NULL= default */
ZEBRA_ROUTE_BGP_DIRECT, BGP_ROUTE_REDISTRIBUTE,
RFAPI_AHR_RFPOPT_IS_VNCTLV); /* flags */
@@ -1678,7 +1681,7 @@ static void vnc_import_bgp_exterior_add_route_it(
bpi_interior = bpi_interior->next) {
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
if (!is_usable_interior_route(bpi_interior))
continue;
@@ -1695,14 +1698,19 @@ static void vnc_import_bgp_exterior_add_route_it(
*/
have_usable_route = 1;
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(new_attr));
new_attr = *bpi_interior->attr;
@@ -1851,7 +1859,7 @@ void vnc_import_bgp_exterior_del_route(
for (bpi_interior = rn->info; bpi_interior;
bpi_interior = bpi_interior->next) {
struct prefix_rd *prd;
- uint32_t label = 0;
+ uint32_t label;
if (!is_usable_interior_route(bpi_interior))
continue;
@@ -1864,14 +1872,19 @@ void vnc_import_bgp_exterior_del_route(
*/
have_usable_route = 1;
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
rfapiBgpInfoFilteredImportVPN(
it, FIF_ACTION_KILL, bpi_interior->peer,
NULL, /* rfd */
@@ -2007,18 +2020,22 @@ void vnc_import_bgp_exterior_add_route_interior(
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
assert(bpi_exterior);
assert(pfx_exterior);
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(struct attr));
new_attr = *bpi_interior->attr;
@@ -2097,7 +2114,7 @@ void vnc_import_bgp_exterior_add_route_interior(
struct bgp_path_info *bpi;
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
/* do pull-down */
@@ -2124,15 +2141,19 @@ void vnc_import_bgp_exterior_add_route_interior(
* parent routes.
*/
for (bpi = par->info; bpi; bpi = bpi->next) {
-
- if (bpi->extra) {
+ if (bpi->extra)
prd = &bpi->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi))
+ label = decode_label(
+ &bpi->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
rfapiBgpInfoFilteredImportVPN(
it, FIF_ACTION_KILL, bpi->peer,
NULL, /* rfd */
@@ -2147,14 +2168,19 @@ void vnc_import_bgp_exterior_add_route_interior(
* Add constructed exterior routes based on
* the new interior route at longer prefix.
*/
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc
.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels
+ ->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(struct attr));
new_attr = *bpi_interior->attr;
@@ -2237,7 +2263,7 @@ void vnc_import_bgp_exterior_add_route_interior(
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
/* do pull-down */
@@ -2266,13 +2292,17 @@ void vnc_import_bgp_exterior_add_route_interior(
* Add constructed exterior routes based on the
* new interior route at the longer prefix.
*/
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc.import.rd;
- label = decode_label(
- &bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(struct attr));
new_attr = *bpi_interior->attr;
@@ -2372,14 +2402,19 @@ void vnc_import_bgp_exterior_del_route_interior(
&cursor)) {
struct prefix_rd *prd;
- uint32_t label = 0;
+ uint32_t label;
- if (bpi_interior->extra) {
+ if (bpi_interior->extra)
prd = &bpi_interior->extra->vnc->vnc.import.rd;
- label = decode_label(&bpi_interior->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi_interior))
+ label = decode_label(
+ &bpi_interior->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
rfapiBgpInfoFilteredImportVPN(
it, FIF_ACTION_KILL, bpi_interior->peer, NULL, /* rfd */
pfx_exterior, NULL, afi, prd, bpi_interior->attr,
@@ -2446,18 +2481,22 @@ void vnc_import_bgp_exterior_del_route_interior(
struct prefix_rd *prd;
struct attr new_attr;
- uint32_t label = 0;
+ uint32_t label;
if (bpi->type == ZEBRA_ROUTE_BGP_DIRECT_EXT)
continue;
- if (bpi->extra) {
+ if (bpi->extra)
prd = &bpi->extra->vnc->vnc.import.rd;
- label = decode_label(
- &bpi->extra->label[0]);
- } else
+ else
prd = NULL;
+ if (bgp_path_info_num_labels(bpi))
+ label = decode_label(
+ &bpi->extra->labels->label[0]);
+ else
+ label = MPLS_INVALID_LABEL;
+
/* use local_pref from unicast route */
memset(&new_attr, 0, sizeof(new_attr));
new_attr = *bpi->attr;
diff --git a/configure.ac b/configure.ac
index 4762306..7a9b804 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ([2.69])
-AC_INIT([frr], [10.0.1], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [10.1], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
@@ -275,7 +275,16 @@ AC_DEFUN([AC_C_FLAG], [{
AC_CACHE_CHECK([[whether $CC supports $1]], cachename, [
AC_LANG_PUSH([C])
ac_c_flag_save="$CFLAGS"
- CFLAGS="$CFLAGS $1"
+ dnl GCC ignores unknown -Wno-whatever flags, but errors on -Wwhatever
+ dnl except when it ignores them it prints:
+ dnl cc1: note: unrecognized command-line option ‘-Wno-whatever’ may have been intended to silence earlier diagnostics
+ dnl which is annoying as hell. So check for the positive flag instead.
+ flag_add="$1"
+ if test "$flag_add" != "${flag_add#-Wno-}"; then
+ CFLAGS="$CFLAGS -W${flag_add#-Wno-}"
+ else
+ CFLAGS="$CFLAGS $flag_add"
+ fi
AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[$4]])],
[
@@ -453,6 +462,7 @@ fi
AC_C_FLAG([-Wno-unused-parameter])
AC_C_FLAG([-Wno-missing-field-initializers])
AC_C_FLAG([-Wno-microsoft-anon-tag])
+AC_C_FLAG([-Wno-error=deprecated-declarations])
AC_C_FLAG([-Wc++-compat], [], [CXX_COMPAT_CFLAGS="-Wc++-compat"])
AC_SUBST([CXX_COMPAT_CFLAGS])
@@ -703,6 +713,8 @@ AC_ARG_ENABLE([mgmtd_local_validations],
AS_HELP_STRING([--enable-mgmtd-local-validations], [dev: unimplemented local validation]))
AC_ARG_ENABLE([mgmtd_test_be_client],
AS_HELP_STRING([--enable-mgmtd-test-be-client], [build test backend client]))
+AC_ARG_ENABLE([fpm_listener],
+ AS_HELP_STRING([--enable-fpm-listener], [build fpm listener test program]))
AC_ARG_ENABLE([ripd],
AS_HELP_STRING([--disable-ripd], [do not build ripd]))
AC_ARG_ENABLE([ripngd],
@@ -749,8 +761,6 @@ AC_ARG_ENABLE([snmp],
AS_HELP_STRING([--enable-snmp], [enable SNMP support for agentx]))
AC_ARG_ENABLE([config_rollbacks],
AS_HELP_STRING([--enable-config-rollbacks], [enable configuration rollbacks (requires sqlite3)]))
-AC_ARG_ENABLE([confd],
- AS_HELP_STRING([--enable-confd=ARG], [enable confd integration]))
AC_ARG_ENABLE([sysrepo],
AS_HELP_STRING([--enable-sysrepo], [enable sysrepo integration]))
AC_ARG_ENABLE([grpc],
@@ -784,8 +794,6 @@ AC_ARG_ENABLE([configfile_mask],
AS_HELP_STRING([--enable-configfile-mask=ARG], [set mask for config files]))
AC_ARG_ENABLE([logfile_mask],
AS_HELP_STRING([--enable-logfile-mask=ARG], [set mask for log files]))
-AC_ARG_ENABLE([shell_access],
- AS_HELP_STRING([--enable-shell-access], [Allow users to access shell/telnet/ssh]))
AC_ARG_ENABLE([realms],
AS_HELP_STRING([--enable-realms], [enable REALMS support under Linux]))
AC_ARG_ENABLE([rtadv],
@@ -897,10 +905,6 @@ fi
AC_SUBST([DFLT_NAME])
AC_DEFINE_UNQUOTED([DFLT_NAME], ["$DFLT_NAME"], [Name of the configuration default set])
-if test "$enable_shell_access" = "yes"; then
- AC_DEFINE([HAVE_SHELL_ACCESS], [1], [Allow user to use ssh/telnet/bash, be aware this is considered insecure])
-fi
-
#
# Python for clippy
#
@@ -1101,6 +1105,8 @@ dnl -------------------------
AC_CHECK_HEADERS([stropts.h sys/ksym.h \
linux/version.h asm/types.h endian.h sys/endian.h])
+AC_CHECK_LIB([atomic], [main], [LIBS="$LIBS -latomic"], [], [])
+
ac_stdatomic_ok=false
AC_DEFINE([FRR_AUTOCONF_ATOMIC], [1], [did autoconf checks for atomic funcs])
AC_CHECK_HEADER([stdatomic.h],[
@@ -1832,6 +1838,10 @@ AS_IF([test "$enable_mgmtd_test_be_client" = "yes"], [
AC_DEFINE([HAVE_MGMTD_TESTC], [1], [mgmtd_testc])
])
+AS_IF([test "$enable_fpm_listener" = "yes"], [
+ AC_DEFINE([HAVE_FPM_LISTENER], [1], [fpm_listener])
+])
+
AS_IF([test "$enable_ripd" != "no"], [
AC_DEFINE([HAVE_RIPD], [1], [ripd])
])
@@ -2049,7 +2059,7 @@ dnl libyang
dnl ---------------
PKG_CHECK_MODULES([LIBYANG], [libyang >= 2.1.128], , [
AC_MSG_ERROR([m4_normalize([libyang >= 2.1.128 is required, and was not found on your system.
-Pleaes consult doc/developer/building-libyang.rst for instructions on installing or building libyang.])])])
+Please consult doc/developer/building-libyang.rst for instructions on installing or building libyang.])])])
ac_cflags_save="$CFLAGS"
CFLAGS="$CFLAGS $LIBYANG_CFLAGS"
AC_CHECK_MEMBER([struct lyd_node.priv], [], [
@@ -2082,22 +2092,6 @@ if test "$enable_config_rollbacks" = "yes"; then
fi
dnl ---------------
-dnl confd
-dnl ---------------
-if test "$enable_confd" != "" -a "$enable_confd" != "no"; then
- AC_CHECK_PROG([CONFD], [confd], [confd], [/bin/false], "${enable_confd}/bin")
- if test "$CONFD" = "/bin/false"; then
- AC_MSG_ERROR([confd was not found on your system.])]
- fi
- AC_CHECK_PROG([CONFDC], [confdc], [confdc], [/bin/false], "${enable_confd}/bin")
- CONFD_CFLAGS="-I${enable_confd}/include -L${enable_confd}/lib"
- AC_SUBST([CONFD_CFLAGS])
- CONFD_LIBS="-lconfd"
- AC_SUBST([CONFD_LIBS])
- AC_DEFINE([HAVE_CONFD], [1], [Enable confd integration])
-fi
-
-dnl ---------------
dnl sysrepo
dnl ---------------
if test "$enable_sysrepo" = "yes"; then
@@ -2766,7 +2760,6 @@ AM_CONDITIONAL([ENABLE_BGP_VNC], [test "$enable_bgp_vnc" != "no"])
AM_CONDITIONAL([BGP_BMP], [$bgpd_bmp])
dnl northbound
AM_CONDITIONAL([SQLITE3], [$SQLITE3])
-AM_CONDITIONAL([CONFD], [test "$enable_confd" != ""])
AM_CONDITIONAL([SYSREPO], [test "$enable_sysrepo" = "yes"])
AM_CONDITIONAL([GRPC], [test "$enable_grpc" = "yes"])
AM_CONDITIONAL([ZEROMQ], [test "$ZEROMQ" = "true"])
@@ -2794,6 +2787,7 @@ AM_CONDITIONAL([ZEBRA], [test "$enable_zebra" != "no"])
AM_CONDITIONAL([BGPD], [test "$enable_bgpd" != "no"])
AM_CONDITIONAL([MGMTD], [test "$enable_mgmtd" != "no"])
AM_CONDITIONAL([MGMTD_TESTC], [test "$enable_mgmtd_test_be_client" = "yes"])
+AM_CONDITIONAL([FPM_LISTENER], [test "enable_fpm_listener" = "yes"])
AM_CONDITIONAL([RIPD], [test "$enable_ripd" != "no"])
AM_CONDITIONAL([OSPFD], [test "$enable_ospfd" != "no"])
AM_CONDITIONAL([LDPD], [test "$enable_ldpd" != "no"])
diff --git a/doc/developer/building-libyang.rst b/doc/developer/building-libyang.rst
index a46c793..8d9876c 100644
--- a/doc/developer/building-libyang.rst
+++ b/doc/developer/building-libyang.rst
@@ -41,7 +41,7 @@ DEB packages are available as CI artifacts `here
cd libyang
git checkout v2.1.128
mkdir build; cd build
- cmake -D CMAKE_INSTALL_PREFIX:PATH=/usr \
+ cmake --install-prefix /usr \
-D CMAKE_BUILD_TYPE:String="Release" ..
make
sudo make install
diff --git a/doc/developer/checkpatch.rst b/doc/developer/checkpatch.rst
index d8fe007..4ef261b 100644
--- a/doc/developer/checkpatch.rst
+++ b/doc/developer/checkpatch.rst
@@ -761,15 +761,6 @@ Indentation and Line Breaks
Macros, Attributes and Symbols
------------------------------
- **ARRAY_SIZE**
- The ARRAY_SIZE(foo) macro should be preferred over
- sizeof(foo)/sizeof(foo[0]) for finding number of elements in an
- array.
-
- The macro is defined in include/linux/kernel.h::
-
- #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
-
**AVOID_EXTERNS**
Function prototypes don't need to be declared extern in .h
files. It's assumed by the compiler and is unnecessary.
diff --git a/doc/developer/cross-compiling.rst b/doc/developer/cross-compiling.rst
index af99262..c503487 100644
--- a/doc/developer/cross-compiling.rst
+++ b/doc/developer/cross-compiling.rst
@@ -148,7 +148,7 @@ be built and installed generally like:
CC=${HOST_ARCH}-gcc \
CXX=${HOST_ARCH}-g++ \
cmake \
- -DCMAKE_INSTALL_PREFIX=/usr/${HOST_ARCH} \
+ --install-prefix /usr/${HOST_ARCH} \
..
make
make install
diff --git a/doc/developer/logging.rst b/doc/developer/logging.rst
index 52653d3..82cc8b2 100644
--- a/doc/developer/logging.rst
+++ b/doc/developer/logging.rst
@@ -77,7 +77,14 @@ are available:
.. note::
- ``printfrr()`` does not support the ``%n`` format.
+ ``printfrr()`` does not support the ``%n`` format. It does support ISO C23
+ ``%b``, ``%w99d`` and ``%wf99d`` additions, but the latter two are not
+ supported by the ``frr-format`` plugin yet, and all 3 aren't supported by
+ the older compilers still in use on some supported platforms.
+
+ ``%b`` can be used with ``FMT_NSTD``, but ``%w99d`` and ``%wf99d`` require
+ work in the ``frr-format`` plugin before they are really usable.
+
AS-Safety
^^^^^^^^^
@@ -376,7 +383,8 @@ bgpd
.. frrfmt:: %pBD (struct bgp_dest *)
- Print prefix for a BGP destination.
+ Print prefix for a BGP destination. When using ``--enable-dev-build`` include
+ the pointer value for the bgp_dest.
:frrfmtout:`fe80::1234/64`
@@ -557,8 +565,9 @@ Integer formats
cause compiler warnings when used without the plugin. Use with
:c:macro:`FMT_NSTD` if necessary.
- It is possible ISO C23 may introduce another format for these, possibly
- ``%w64d`` discussed in `JTC 1/SC 22/WG 14/N2680 <http://www.open-std.org/jtc1/sc22/wg14/www/docs/n2680.pdf>`_.
+ As anticipated, ISO C23 has introduced new modifiers for this, specifically
+ ``%w64d`` (= ``%Ld``) and ``%w64u`` (= ``%Lu``). Unfortunately, these new
+ modifiers are not supported by ``frr-format`` yet.
.. frrfmt:: %Lu (uint64_t)
diff --git a/doc/developer/mgmtd-dev.rst b/doc/developer/mgmtd-dev.rst
index 2404ffe..b979af0 100644
--- a/doc/developer/mgmtd-dev.rst
+++ b/doc/developer/mgmtd-dev.rst
@@ -317,12 +317,25 @@ Likewise the client should be cleaned up in the daemon cleanup routine.
Back-End XPATH mappings
^^^^^^^^^^^^^^^^^^^^^^^
-In order for ``mgmtd`` to direct configuration to your daemon you need to add
+In order for ``mgmtd`` to direct YANG modeled data to your daemon you should add
some XPATH mappings to ``mgmtd/mgmt_be_adapter.c``. These XPATHs determine which
-configuration changes get sent over the *back-end* interface to your daemon.
-There are 2 arrays to update the first for config support and the second for
-operational state.
-
+YANG modeled data (e.g., config changes) get sent over the *back-end* interface
+to your daemon. There are 4 arrays to possibly update: configuration,
+operational, notification, and RPC. You only need to add entries to the array
+that you require mapping for.
+
+Additionally the back-end client can specify these XPATH mappings when it
+first connects to mgmtd using it's initial ``SUBSCRIBE`` message.
+
+NOTE: the notif array (``be_client_notif_xpaths``), is a slightly different from
+the other 3 types (config, oper and rpc) in that it maps xpaths the back-end
+client wishes to *receive* notifications for, not the ones it may generate.
+Normally a back-end client is generating notifications; however, mgmtd supports
+back-end clients also "subscribing" to receive these notifications as well from
+other back-end clients through notif_xpath maps.
+
+Config Map Example
+""""""""""""""""""
Below are the strings added for staticd config support:
.. code-block:: c
@@ -342,6 +355,9 @@ Below are the strings added for staticd config support:
#endif
};
+
+Operational Map Example
+"""""""""""""""""""""""
Below are the strings added for zebra operational state support (note zebra is
not conditionalized b/c it should always be present):
@@ -358,6 +374,33 @@ not conditionalized b/c it should always be present):
[MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths,
};
+
+RPC Map Example
+"""""""""""""""
+Below is the string added for ripd RPC support:
+
+.. code-block:: c
+
+ static const char *const ripd_rpc_xpaths[] = {
+ "/frr-ripd",
+ NULL,
+ };
+
+ static const char *const *be_client_rpc_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
+ #ifdef HAVE_RIPD
+ [MGMTD_BE_CLIENT_ID_RIPD] = ripd_rpc_xpaths,
+ #endif
+ };
+
+
+Notification Map Example
+""""""""""""""""""""""""
+There are no current back-end daemons that wish to receive other back-end
+notifications so the array is empty. This may change in the future, and of
+course any back-end daemon can utilize the connect (``BeSubscribeReq``) messages
+as well.
+
+
MGMTD Internals
---------------
diff --git a/doc/developer/northbound/advanced-topics.rst b/doc/developer/northbound/advanced-topics.rst
index edfc10b..eb75602 100644
--- a/doc/developer/northbound/advanced-topics.rst
+++ b/doc/developer/northbound/advanced-topics.rst
@@ -12,8 +12,7 @@ Auto-generated CLI commands
In order to have less code to maintain, it should be possible to write a
tool that auto-generates CLI commands based on the FRR YANG models. As a
matter of fact, there are already a number of NETCONF-based CLIs that do
-exactly that (e.g. `Clixon <https://github.com/clicon/clixon>`__,
-ConfD’s CLI).
+exactly that (e.g. `Clixon <https://github.com/clicon/clixon>`__).
The problem however is that there isn’t an exact one-to-one mapping
between the existing CLI commands and the corresponding YANG nodes from
@@ -27,11 +26,6 @@ command for each YANG leaf, (leaf-)list and presence-container. The
ripd’s ``timers basic`` command, for instance, would become three
different commands, which would be undesirable.
- This Tail-f’s®
- `document <http://info.tail-f.com/hubfs/Whitepapers/Tail-f_ConfD-CLI__Cfg_Mode_App_Note_Rev%20C.pdf>`__
- shows how to customize ConfD auto-generated CLI commands using YANG
- annotations.
-
The good news is that *libyang* allows users to create plugins to
implement their own YANG extensions, which can be used to implement CLI
annotations. If done properly, a CLI generator can save FRR developers
@@ -76,8 +70,8 @@ Example of how this feature could be provided in the CLI:
``commit confirmed [minutes <1-60>]``. The ability to do confirmed
commits should also be exposed in the northbound API so that the
northbound plugins can also take advantage of it (in the case of the
-Sysrepo and ConfD plugins, confirmed commits are implemented externally
-in the *netopeer2-server* and *confd* daemons, respectively).
+Sysrepo plugin, confirmed commit is implemented externally in the
+*netopeer2-server* daemon).
Proposed feature: enable/disable configuration commands/sections
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/doc/developer/northbound/architecture.rst b/doc/developer/northbound/architecture.rst
index 5fd89c3..4e84f1d 100644
--- a/doc/developer/northbound/architecture.rst
+++ b/doc/developer/northbound/architecture.rst
@@ -116,7 +116,7 @@ multitude of different management APIs, all of them connected to the
northbound layer of the FRR daemons. By default, only the CLI interface
is compiled built-in in the FRR daemons. The other management interfaces
are provided as optional plugins and need to be loaded during the daemon
-initialization (e.g. *zebra -M confd*). This design makes it possible to
+initialization (e.g. *zebra -M grpc*). This design makes it possible to
integrate FRR with different NETCONF solutions without introducing
vendor lock-in. The [[Plugins - Writing Your Own]] page explains how to
write custom northbound plugins that can be tailored to all needs
diff --git a/doc/developer/northbound/demos.rst b/doc/developer/northbound/demos.rst
index 8a0f6ad..7c5ae0c 100644
--- a/doc/developer/northbound/demos.rst
+++ b/doc/developer/northbound/demos.rst
@@ -8,23 +8,3 @@ This short demo shows some of the capabilities of the new transactional
CLI:
|asciicast1|
-
-ConfD + NETCONF + Cisco YDK
----------------------------
-
-This is a very simple demo of *ripd* being configured by a python
-script. The script uses NETCONF to communicate with *ripd*, which has
-the ConfD plugin loaded. The most interesting part, however, is the fact
-that the python script is not using handcrafted XML payloads to
-configure *ripd*. Instead, the script is using python bindings generated
-using Cisco’s YANG Development Kit (YDK).
-
-- Script used in the demo:
- https://gist.github.com/rwestphal/defa9bd1ccf216ab082d4711ae402f95
-
-|asciicast2|
-
-.. |asciicast1| image:: https://asciinema.org/a/jL0BS5HfP2kS6N1HfgsZvfZk1.png
- :target: https://asciinema.org/a/jL0BS5HfP2kS6N1HfgsZvfZk1
-.. |asciicast2| image:: https://asciinema.org/a/VfMElNxsjLcdvV7484E6ChxWv.png
- :target: https://asciinema.org/a/VfMElNxsjLcdvV7484E6ChxWv
diff --git a/doc/developer/northbound/links.rst b/doc/developer/northbound/links.rst
index 6cec176..e8fb327 100644
--- a/doc/developer/northbound/links.rst
+++ b/doc/developer/northbound/links.rst
@@ -195,14 +195,6 @@ pyangbind
- GitHub page: https://github.com/robshakir/pyangbind
- Documentation: http://pynms.io/pyangbind/
-ConfD
-^^^^^
-
-- Official webpage (for ConfD Basic):
- http://www.tail-f.com/confd-basic/
-- Training Videos: http://www.tail-f.com/confd-training-videos/
-- Forum: http://discuss.tail-f.com/
-
Sysrepo
^^^^^^^
diff --git a/doc/developer/northbound/operational-data-rpcs-and-notifications.rst b/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
index 5cb70ca..07f92c2 100644
--- a/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
+++ b/doc/developer/northbound/operational-data-rpcs-and-notifications.rst
@@ -10,10 +10,10 @@ Operational data
~~~~~~~~~~~~~~~~
Writing API-agnostic code for YANG-modeled operational data is
-challenging. ConfD and Sysrepo, for instance, have completely different
-APIs to fetch operational data. So how can we write API-agnostic
-callbacks that can be used by both the ConfD and Sysrepo plugins, and
-any other northbound client that might be written in the future?
+challenging. Sysrepo, for instance, has completely different API to
+fetch operational data. So how can we write API-agnostic callbacks
+that can be used by both the Sysrepo plugin, and any other northbound
+client that might be written in the future?
As an additional requirement, the callbacks must be designed in a way
that makes in-place XPath filtering possible. As an example, a
@@ -94,27 +94,18 @@ in the northbound architecture:
*/
void *(*lookup_entry)(struct yang_list_keys *keys);
-These callbacks were designed to provide maximum flexibility, and borrow
-a lot of ideas from the ConfD API. Each callback does one and only one
-task, they are indivisible primitives that can be combined in several
-different ways to iterate over operational data. The extra flexibility
-certainly has a performance cost, but it’s the price to pay if we want
-to expose FRR operational data using several different management
-interfaces (e.g. NETCONF via either ConfD or Sysrepo+Netopeer2). In the
+These callbacks were designed to provide maximum flexibility. Each
+callback does one and only one task, they are indivisible primitives
+that can be combined in several different ways to iterate over operational
+data. The extra flexibility certainly has a performance cost, but it’s the
+price to pay if we want to expose FRR operational data using several
+different management interfaces (e.g. Sysrepo+Netopeer2). In the
future it might be possible to introduce optional callbacks that do
things like returning multiple objects at once. They would provide
enhanced performance when iterating over large lists, but their use
would be limited by the northbound plugins that can be integrated with
them.
- NOTE: using the northbound callbacks as a base, the ConfD plugin can
- provide up to 100 objects between each round trip between FRR and the
- *confd* daemon. Preliminary tests showed FRR taking ~7 seconds
- (asynchronously, without blocking the main pthread) to return a RIP
- table containing 100k routes to a NETCONF client connected to *confd*
- (JSON was used as the encoding format). Work needs to be done to find
- the bottlenecks and optimize this operation.
-
The [[Plugins - Writing Your Own]] page explains how the northbound
plugins can fetch operational data using the aforementioned northbound
callbacks, and how in-place XPath filtering can be implemented.
@@ -351,10 +342,10 @@ are being iterated over. If that is not done, the list entry returned by
this callback can become a dangling pointer when used in another
callback.
-Currently the ConfD and Sysrepo plugins run only in the main pthread.
-The plan in the short-term is to introduce a separate pthread only for
-handling operational data, and use the main pthread only for handling
-configuration changes, RPCs and notifications.
+Currently the Sysrepo plugin runs only in the main pthread. The plan in the
+short-term is to introduce a separate pthread only for handling operational
+data, and use the main pthread only for handling configuration changes,
+RPCs and notifications.
RPCs and Actions
~~~~~~~~~~~~~~~~
@@ -396,8 +387,8 @@ some EXEC-level commands using YANG so that their functionality is
exposed to other management interfaces other than the CLI. As an
example, if the ``clear bgp`` command is modeled using a YANG RPC, and a
corresponding ``rpc`` callback is written, then it should be possible to
-clear BGP neighbors using NETCONF and RESTCONF with that RPC (the ConfD
-and Sysrepo plugins have full support for YANG RPCs and actions).
+clear BGP neighbors using NETCONF and RESTCONF with that RPC (the Sysrepo
+plugin has full support for YANG RPCs and actions).
Here’s an example of a very simple RPC modeled using YANG:
@@ -568,8 +559,7 @@ Now sending the *authentication-failure* YANG notification should be as
simple as calling the above function and provide the appropriate
interface name. The notification will be processed by all northbound
plugins that subscribed a callback to the ``nb_notification_send`` hook.
-The ConfD and Sysrepo plugins, for instance, use this hook to relay the
-notifications to the *confd*/*sysrepod* daemons, which can generate
-NETCONF notifications to subscribed clients. When no northbound plugin
-is loaded, ``nb_notification_send()`` doesn’t do anything and the
-notifications are ignored.
+The Sysrepo plugin, for instance, uses this hook to relay the notifications
+to the *sysrepod* daemon, which can generate NETCONF notifications to subscribed
+clients. When no northbound plugin is loaded, ``nb_notification_send()`` doesn’t
+do anything and the notifications are ignored.
diff --git a/doc/developer/northbound/plugins-sysrepo.rst b/doc/developer/northbound/plugins-sysrepo.rst
index 0cfdb82..f4df68c 100644
--- a/doc/developer/northbound/plugins-sysrepo.rst
+++ b/doc/developer/northbound/plugins-sysrepo.rst
@@ -32,7 +32,7 @@ libyang
cd libyang
git checkout v2.1.148
mkdir build; cd build
- cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ cmake --install-prefix /usr \
-DCMAKE_BUILD_TYPE:String="Release" ..
make
sudo make install
@@ -51,7 +51,7 @@ Sysrepo
cd sysrepo/
git checkout v2.2.150
mkdir build; cd build
- cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ cmake --install-prefix /usr \
-DCMAKE_BUILD_TYPE:String="Release" ..
make
sudo make install
diff --git a/doc/developer/static-linking.rst b/doc/developer/static-linking.rst
index 5342fbf..e9bb928 100644
--- a/doc/developer/static-linking.rst
+++ b/doc/developer/static-linking.rst
@@ -44,7 +44,7 @@ when building libyang statically.
The resultant cmake command is::
cmake -DENABLE_STATIC=ON -DENABLE_LYD_PRIV=ON \
- -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+ --install-prefix /usr \
-DCMAKE_POSITION_INDEPENDENT_CODE=TRUE \
-DCMAKE_BUILD_TYPE:String="Release" ..
diff --git a/doc/developer/topotests-markers.rst b/doc/developer/topotests-markers.rst
index 9f92412..670bf0d 100644
--- a/doc/developer/topotests-markers.rst
+++ b/doc/developer/topotests-markers.rst
@@ -12,6 +12,7 @@ systems, all tests must be marked with at least one of the following markers:
* eigrpd
* isisd
* ldpd
+* mgmtd
* nhrpd
* ospf6d
* ospfd
@@ -64,12 +65,12 @@ Adding a single marker:
import pytest
...
-
+
# add after imports, before defining classes or functions:
pytestmark = pytest.mark.bfdd
-
+
...
-
+
def test_using_bfdd():
@@ -79,16 +80,16 @@ Adding multiple markers:
import pytest
...
-
+
# add after imports, before defining classes or functions:
pytestmark = [
pytest.mark.bgpd,
pytest.mark.ospfd,
pytest.mark.ospf6d
]
-
+
...
-
+
def test_using_bgpd_ospfd_ospf6d():
diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst
index 9b9058b..e1702c4 100644
--- a/doc/developer/topotests.rst
+++ b/doc/developer/topotests.rst
@@ -46,6 +46,7 @@ The version of protobuf package that is installed on your system will determine
which versions of the python protobuf packages you need to install.
.. code:: shell
+
# - Either - For protobuf version <= 3.12
python3 -m pip install 'protobuf<4'
@@ -712,6 +713,44 @@ Here's an example of collecting ``rr`` execution state from ``mgmtd`` on router
To specify additional arguments for ``rr record``, one can use the
``--rr-options``.
+.. _code_coverage:
+
+Code coverage
+"""""""""""""
+Code coverage reporting requires installation of the ``gcov`` and ``lcov``
+packages.
+
+Code coverage can automatically be gathered for any topotest run. To support
+this FRR must first be compiled with the ``--enable-gcov`` configure option.
+This will cause *.gnco files to be created during the build. When topotests are
+run the statistics are generated and stored in *.gcda files. Topotest
+infrastructure will gather these files, capture the information into a
+``coverage.info`` ``lcov`` file and also report the coverage summary.
+
+To enable code coverage support pass the ``--cov-topotest`` argument to pytest.
+If you build your FRR in a directory outside of the FRR source directory you
+will also need to pass the ``--cov-frr-build-dir`` argument specifying the build
+directory location.
+
+During the topotest run the *.gcda files are generated into a ``gcda``
+sub-directory of the top-level run directory (i.e., normally
+``/tmp/topotests/gcda``). These files will then be copied at the end of the
+topotest run into the FRR build directory where the ``gcov`` and ``lcov``
+utilities expect to find them. This is done to deal with the various different
+file ownership and permissions.
+
+At the end of the run ``lcov`` will be run to capture all of the coverage data
+into a ``coverage.info`` file. This file will be located in the top-level run
+directory (i.e., normally ``/tmp/topotests/coverage.info``).
+
+The ``coverage.info`` file can then be used to generate coverage reports or file
+markup (e.g., using the ``genhtml`` utility) or enable markup within your
+IDE/editor if supported (e.g., the emacs ``cov-mode`` package)
+
+NOTE: the *.gcda files in ``/tmp/topotests/gcda`` are cumulative so if you do
+not remove them they will aggregate data across multiple topotest runs.
+
+
.. _topotests_docker:
Running Tests with Docker
diff --git a/doc/developer/workflow.rst b/doc/developer/workflow.rst
index 68834ed..f720f62 100644
--- a/doc/developer/workflow.rst
+++ b/doc/developer/workflow.rst
@@ -167,13 +167,13 @@ as early as possible, i.e. the first 2-week window.
For reference, the expected release schedule according to the above is:
+---------+------------+------------+------------+
-| Release | 2023-11-07 | 2024-03-05 | 2024-07-02 |
+| Release | 2024-03-12 | 2024-07-02 | 2024-11-05 |
+---------+------------+------------+------------+
-| RC | 2023-10-24 | 2024-02-20 | 2024-06-18 |
+| RC | 2024-02-27 | 2024-06-18 | 2024-10-22 |
+---------+------------+------------+------------+
-| dev/X.Y | 2023-10-10 | 2024-02-06 | 2024-06-04 |
+| dev/X.Y | 2024-02-13 | 2024-06-04 | 2024-10-08 |
+---------+------------+------------+------------+
-| freeze | 2023-09-26 | 2024-01-23 | 2024-05-21 |
+| freeze | 2024-01-30 | 2024-05-21 | 2024-09-24 |
+---------+------------+------------+------------+
Here is the hint on how to get the dates easily:
diff --git a/doc/developer/zebra.rst b/doc/developer/zebra.rst
index be2952e..482df96 100644
--- a/doc/developer/zebra.rst
+++ b/doc/developer/zebra.rst
@@ -161,6 +161,21 @@ Zebra Protocol Commands
The definitions of zebra protocol commands can be found at ``lib/zclient.h``.
+
+Zebra Dataplane
+===============
+
+The zebra dataplane subsystem provides a framework for FIB
+programming. Zebra uses the dataplane to program the local kernel as
+it makes changes to objects such as IP routes, MPLS LSPs, and
+interface IP addresses. The dataplane runs in its own pthread, in
+order to off-load work from the main zebra pthread.
+
+The zebra dataplane API is versioned; the version number must be
+updated along with API changes. Plugins can test the current version
+number and confirm that they are compatible with the current version.
+
+
Dataplane batching
==================
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 99d2a8c..150a915 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -589,26 +589,52 @@ Route Flap Dampening
.. clicmd:: bgp dampening (1-45) (1-20000) (1-50000) (1-255)
- This command enables BGP route-flap dampening and specifies dampening parameters.
+ This command enables (with optionally specified dampening parameters) or
+ disables route-flap dampening for all routes of a BGP instance.
+
+.. 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.
+
+.. 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
+ group.
half-life
- Half-life time for the penalty
+ Half-life time for the penalty in minutes (default value: 15).
reuse-threshold
- Value to start reusing a route
+ Value to start reusing a route (default value: 750).
suppress-threshold
- Value to start suppressing a route
+ Value to start suppressing a route (default value: 2000).
max-suppress
- Maximum duration to suppress a stable route
+ Maximum duration to suppress a stable route in minutes (default value:
+ 60).
The route-flap damping algorithm is compatible with :rfc:`2439`. The use of
- this command is not recommended nowadays.
+ these commands is not recommended nowadays.
At the moment, route-flap dampening is not working per VRF and is working only
for IPv4 unicast and multicast.
+ With different parameter sets configurable for BGP instances, peer groups and
+ peers, the active dampening profile for a route is chosen on the fly,
+ allowing for various changes in configuration (i.e. peer group memberships)
+ during runtime. The parameter sets are taking precedence in the following
+ order:
+
+ 1. Peer
+ 2. Peer group
+ 3. BGP instance
+
+ The negating commands do not allow to exclude a peer/peer group from a peer
+ group/BGP instances configuration.
+
.. seealso::
https://www.ripe.net/publications/docs/ripe-378
@@ -1064,7 +1090,7 @@ BGP GR Global Mode Commands
This command will enable BGP graceful restart functionality at the global
level.
-.. clicmd:: bgp graceful-restart disable
+.. clicmd:: bgp graceful-restart-disable
This command will disable both the functionality graceful restart and helper
mode.
@@ -1334,7 +1360,14 @@ OSPFv3 into ``address-family ipv4 unicast`` as OSPFv3 supports IPv6.
.. clicmd:: redistribute <babel|connected|eigrp|isis|kernel|openfabric|ospf|ospf6|rip|ripng|sharp|static> [metric (0-4294967295)] [route-map WORD]
-Redistribute routes from other protocols into BGP.
+ Redistribute routes from other protocols into BGP.
+
+ Note - When redistributing a static route, or any better Admin Distance route,
+ into BGP for which the same path is learned dynamically from another BGP
+ speaker, if the redistribute path is more preferred from a BGP Best Path
+ standpoint than the dynamically learned path, then BGP will not export
+ the best path to Zebra(RIB) for installation into the routing table,
+ unless BGP receives the path before the static route is created.
.. clicmd:: redistribute <table|table-direct> (1-65535)] [metric (0-4294967295)] [route-map WORD]
@@ -1565,6 +1598,15 @@ Configuring Peers
value is carried encoded as uint32. To enable backward compatibility we
need to disable IEEE floating-point encoding option per-peer.
+.. clicmd:: neighbor PEER extended-link-bandwidth
+
+ By default bandwidth in extended communities is carried encoded as IEEE
+ floating-point format, and is limited to maximum of 25 Gbps.
+
+ Enabling this parameter, you can use the bandwidth of to 4294967295 Mbps.
+
+ This is disabled by default.
+
.. clicmd:: neighbor PEER enforce-first-as
Discard updates received from the specified (eBGP) peer if the AS_PATH
@@ -1785,6 +1827,17 @@ Configuring Peers
Do not accept additional paths from this neighbor.
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> addpath-rx-paths-limit (1-65535)
+
+ Limit the maximum number of paths a BGP speaker can receive from a peer, optimizing
+ the transmission of BGP routes by selectively relaying pertinent routes instead of
+ the entire set.
+
+ If this command is configured, the sender will only send the number of paths specified
+ in PATHS-LIMIT capability.
+
+ To exchange this limit, both peers must support the PATHS-LIMIT capability.
+
.. clicmd:: neighbor PEER ttl-security hops NUMBER
This command enforces Generalized TTL Security Mechanism (GTSM), as
@@ -1810,7 +1863,7 @@ Configuring Peers
This includes changing graceful-restart (LLGR also) timers,
enabling/disabling add-path, and other supported capabilities.
-.. clicmd:: neighbor PEER capability fqdn
+.. clicmd:: neighbor PEER capability fqdn
Allow BGP to negotiate the FQDN Capability with its peers.
@@ -1819,7 +1872,7 @@ Configuring Peers
This capability is activated by default. The ``no neighbor PEER capability
fqdn`` avoid negotiation of that capability. This is useful for peers who
- are not supporting this capability or supporting BGP Capabilities
+ are not supporting this capability or supporting BGP Capabilities
Negotiation RFC 2842.
.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> accept-own
@@ -1943,6 +1996,13 @@ Configuring Peers
outputs. It's easier to troubleshoot if you have a number of BGP peers
and a number of routes to check.
+.. clicmd:: bgp default dynamic-capability
+
+ This command enables dynamic capability advertisement by default
+ for all the neighbors.
+
+ For ``datacenter`` profile, this is enabled by default.
+
.. clicmd:: bgp default software-version-capability
This command enables software version capability advertisement by default
@@ -3201,6 +3261,31 @@ L3VPN SRv6
Specify the SRv6 locator to be used for SRv6 L3VPN. The Locator name must
be set in zebra, but user can set it in any order.
+L3VPN SRv6 SID reachability
+---------------------------
+
+In the context of IPv4 L3VPN over SRv6 specific usecase, 2001:db8:12::2
+is the peer IPv6 address of r2, and 2001:db8:2:2:: is the SRv6 SID
+advertised by router r2 for prefix P. On r1, the SID reachability is
+checked in order to install the prefix P. The below output indicates
+that the 2001:db8:2:2:: prefix is valid.
+
+
+.. code-block:: frr
+
+ r1# show bgp nexthop detail
+ Current BGP nexthop cache:
+ 2001:db8:2:2:: valid [IGP metric 0], #paths 4
+ gate 2001:db8:12::2, if eth0
+ Last update: Tue Nov 14 10:36:28 2023
+ Paths:
+ 1/1 192.168.2.0/24 VRF vrf10 flags 0x4018
+ 1/3 192.168.2.0/24 RD 65002:10 VRF default flags 0x418
+ 2001:db8:12::2 valid [IGP metric 0], #paths 0, peer 2001:db8:12::2
+ if eth0
+ Last update: Tue Nov 14 10:36:26 2023
+ Paths:
+
General configuration
^^^^^^^^^^^^^^^^^^^^^
@@ -4017,6 +4102,10 @@ The following are available in the top level *enable* mode:
Clear all peers.
+.. clicmd:: clear bgp ipv4|ipv6 ASNUM
+
+ Clear peers with the AS number in plain or dotted format.
+
.. clicmd:: clear bgp ipv4|ipv6 \*
Clear all peers with this address-family activated.
@@ -4848,8 +4937,8 @@ setting.
.. clicmd:: bgp session-dscp (0-63)
-This command allows bgp to control, at a global level, the TCP dscp values
-in the TCP header.
+This command allows the BGP daemon to control, at a global level, the DSCP value
+used in outgoing packets for each BGP connection.
.. _bgp-suppress-fib:
diff --git a/doc/user/bmp.rst b/doc/user/bmp.rst
index 0f46832..14d0849 100644
--- a/doc/user/bmp.rst
+++ b/doc/user/bmp.rst
@@ -23,6 +23,8 @@ The `BMP` implementation in FRR has the following properties:
- 3: count of **prefixes** with loop in cluster id
- 4: count of **prefixes** with loop in AS-path
- 5: count of **prefixes** with loop in originator
+ - 7: count of **routes** in adj-rib-in
+ - 8: count of **routes** in Loc-RIB
- 11: count of updates subjected to :rfc:`7607` "treat as withdrawal"
handling due to errors
- 65531: *experimental* count of prefixes rejected due to invalid next-hop
@@ -146,6 +148,11 @@ associated with a particular ``bmp targets``:
Send BMP Statistics (counter) messages at the specified interval (in
milliseconds.)
+.. clicmd:: bmp stats send-experimental
+
+ Send BMP Statistics (counter) messages whose code is defined as
+ experimental (in the [65531-65534] range).
+
.. clicmd:: bmp monitor AFI SAFI <pre-policy|post-policy|loc-rib>
Perform Route Monitoring for the specified AFI and SAFI. Only IPv4 and
diff --git a/doc/user/installation.rst b/doc/user/installation.rst
index fb9e23d..e49f104 100644
--- a/doc/user/installation.rst
+++ b/doc/user/installation.rst
@@ -274,6 +274,10 @@ options from the list below.
Build with FPM module support.
+.. option:: --enable-fpm-listener
+
+ Build a small fpm listener for testing.
+
.. option:: --with-service-timeout=X
Set timeout value for FRR service. The time of restarting or reloading FRR
@@ -309,13 +313,6 @@ options from the list below.
make these arrays at build time. Additionally if this parameter is
not passed in FRR will default to 16 ECMP.
-.. option:: --enable-shell-access
-
- Turn on the ability of FRR to access some shell options( telnet/ssh/bash/etc. )
- from vtysh itself. This option is considered extremely unsecure and should only
- be considered for usage if you really really know what you are doing. This
- option is deprecated and will be removed on Feb 1, 2024.
-
.. option:: --enable-gcov
Code coverage reports from gcov require adjustments to the C and LD flags.
@@ -329,11 +326,6 @@ options from the list below.
Build with configuration rollback support. Requires SQLite3.
-.. option:: --enable-confd=<dir>
-
- Build the ConfD northbound plugin. Look for the libconfd libs and headers
- in `dir`.
-
.. option:: --enable-sysrepo
Build the Sysrepo northbound plugin.
@@ -430,7 +422,12 @@ options to the configuration script.
Python dependency, documentation and tests
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-FRR's documentation and basic unit tests heavily use code written in Python.
+FRR uses Python for these components:
+
+* configuration reloading (see :ref:`FRR-RELOAD <frr-reload>` for details),
+* documentation,
+* unit tests.
+
Additionally, FRR ships Python extensions written in C which are used during
its build process.
diff --git a/doc/user/isisd.rst b/doc/user/isisd.rst
index d37dfa6..7412611 100644
--- a/doc/user/isisd.rst
+++ b/doc/user/isisd.rst
@@ -123,7 +123,7 @@ ISIS Timer
Set LSP refresh interval in seconds, globally, for an area (level-1) or a
domain (level-2).
-.. clicmd:: max-lsp-lifetime [level-1 | level-2] (360-65535)
+.. clicmd:: max-lsp-lifetime [level-1 | level-2] (350-65535)
Set LSP maximum LSP lifetime in seconds, globally, for an area (level-1) or
a domain (level-2).
@@ -224,17 +224,17 @@ ISIS interface
Add padding to IS-IS hello packets during adjacency formation only.
-.. clicmd:: isis hello-interval (1-600) [level-1 | level-2]
+.. clicmd:: isis hello-interval [level-1 | level-2] (1-600)
Set Hello interval in seconds globally, for an area (level-1) or a domain
(level-2).
-.. clicmd:: isis hello-multiplier (2-100) [level-1 | level-2]
+.. clicmd:: isis hello-multiplier [level-1 | level-2] (2-100)
Set multiplier for Hello holding time globally, for an area (level-1) or a
domain (level-2).
-.. clicmd:: isis metric [(0-255) | (0-16777215)] [level-1 | level-2]
+.. clicmd:: isis metric [level-1 | level-2] [(0-255) | (0-16777215)]
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
@@ -301,7 +301,7 @@ Showing ISIS information
Show summary information about ISIS.
-.. clicmd:: show isis hostname
+.. clicmd:: show isis [vrf <NAME|all>] hostname
Show information about ISIS node.
@@ -320,17 +320,17 @@ Showing ISIS information
Show the ISIS database globally, for a specific LSP id without or with
details.
-.. clicmd:: show isis topology [level-1|level-2] [algorithm (128-255)]
+.. clicmd:: show isis [vrf <NAME|all>] topology [level-1|level-2] [algorithm [(128-255)]]
Show topology IS-IS paths to Intermediate Systems, globally, in area
(level-1) or domain (level-2).
-.. clicmd:: show isis route [level-1|level-2] [prefix-sid|backup] [algorithm (128-255)]
+.. clicmd:: show isis [vrf <NAME|all>] route [level-1|level-2] [prefix-sid|backup] [algorithm [(128-255)]]
Show the ISIS routing table, as determined by the most recent SPF
calculation.
-.. clicmd:: show isis fast-reroute summary [level-1|level-2]
+.. clicmd:: show isis [vrf <NAME|all>] fast-reroute summary [level-1|level-2]
Show information about the number of prefixes having LFA protection,
and network-wide LFA coverage.
@@ -435,7 +435,7 @@ 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.
-.. clicmd:: show isis segment-routing node [algorithm (128-255)]
+.. clicmd:: show isis segment-routing node [algorithm [(128-255)]]
Show detailed information about all learned Segment Routing Nodes.
@@ -462,10 +462,14 @@ To do so, it defines a set of Flex-Algo Definitions (FAD) which
have the following characteristics:
- a numeric identifier (ID) between 128 and 255 inclusive
+
- a set of constraints (basically, include or exclude a certain given set of
links, designated by a admin-group)
+
- the calculation type (only the `Shortest-Path-First` is currently supported)
+
- the metric type (only the IGP inherited metric type is currently supported)
+
- some additional flags (not supported for the moment).
A subset of routers advertises the Flex-Algo Definitions (FAD) to the other
@@ -475,13 +479,18 @@ rules:
- If a locally configured FAD is not advertised to the area, the router does not
participate in the particular flex algorithm.
+
- If a given flex algorithm is running, the participation in this particular
flex algorithm stops when its advertisements are over.
+
- A router includes its own FAD in the election process if and only if it is
advertised to the other routers.
+
- If only one router advertises the FAD, the FAD is elected.
+
- If several FADs are advertised with different priorities, the one with the
highest priority value is selected.
+
- If there are multiple advertisements of the FAD with the same highest
priority, the FAD of the router with the highest IS-IS system-ID is
selected.
@@ -497,15 +506,11 @@ which flex algorithm they must use for a given packet.
The following commands configure Flex-Algo at the 'router isis' configuration
level. Segment-Routing prefixes must be configured for the Flex-Algo.
-.. clicmd:: flexible-algorithm (128-255)
+.. clicmd:: flex-algo (128-255)
Add a Flex-Algo Definition (FAD) and enter the FAD configuration
level. The algorithm ID value is in the range of 128 to 255 inclusive.
-.. clicmd:: no flexible-algorithm (128-255)
-
- Unconfigure a Flex-Algo Definition.
-
.. clicmd:: affinity-map NAME bit-position (0-255)
Add the specified 'affinity-map'. Affinity-map definitions are used in
@@ -517,7 +522,7 @@ level. Segment-Routing prefixes must be configured for the Flex-Algo.
admin-group 'bit-position' is set 1, else it is set to 0.
The following commands configure Flex-Algo at the 'router isis' and
-'flexible-algorithm (128-255)' configuration level.
+'flex-algo (128-255)' configuration level.
.. clicmd:: advertise-definition
@@ -634,26 +639,14 @@ Debugging ISIS
IS-IS Adjacency related packets.
-.. clicmd:: debug isis checksum-errors
-
- IS-IS LSP checksum errors.
-
.. clicmd:: debug isis events
IS-IS Events.
-.. clicmd:: debug isis local-updates
-
- IS-IS local update packets.
-
.. clicmd:: debug isis packet-dump
IS-IS packet dump.
-.. clicmd:: debug isis protocol-errors
-
- IS-IS LSP protocol errors.
-
.. clicmd:: debug isis route-events
IS-IS Route related events.
@@ -663,11 +656,8 @@ Debugging ISIS
IS-IS CSNP/PSNP packets.
.. clicmd:: debug isis spf-events
-.. clicmd:: debug isis spf-statistics
-.. clicmd:: debug isis spf-triggers
- IS-IS Shortest Path First Events, Timing and Statistic Data and triggering
- events.
+ IS-IS Shortest Path First Events.
.. clicmd:: debug isis update-packets
@@ -846,7 +836,7 @@ A simple vrf example:
!
interface eth0 vrf RED
- ip router isis FOO vrf RED
+ ip router isis FOO
isis network point-to-point
isis circuit-type level-2-only
!
diff --git a/doc/user/mgmtd.rst b/doc/user/mgmtd.rst
index aa7ccaa..8b197bb 100644
--- a/doc/user/mgmtd.rst
+++ b/doc/user/mgmtd.rst
@@ -97,6 +97,8 @@ Following are some of the management operations supported:
- Currently committing configurations from Candidate to Running database
is only allowed, and not vice versa.
+Front-End Native Protobuf API
+"""""""""""""""""""""""""""""
The exact set of message-based APIs are represented as Google Protobuf
messages and can be found in the following file distributed with FRR codebase.
@@ -104,6 +106,14 @@ messages and can be found in the following file distributed with FRR codebase.
lib/mgmt.proto
+Front-End Native (non-protobuf) API
+"""""""""""""""""""""""""""""""""""
+Additionally there exists a "native" API that does not utilize ``protobuf``s
+this native API and the front-end messages and structures it supports are
+documented in the header file ``lib/mgmt_msg_native.h``.
+
+Connecting to MGMTd
+"""""""""""""""""""
The MGMT daemon implements a MGMT Frontend Server that opens a UNIX
socket-based IPC channel on the following path to listen for incoming
connections from all possible Frontend clients:
@@ -124,7 +134,9 @@ specification of this library can be found at:
lib/mgmt_fe_client.h
-Following is a list of message types supported on the MGMT Frontend Interface:
+Following is a list of protobuf message types supported on the MGMT Frontend
+Interface:
+
- SESSION_REQ<Client-Connection-Id, Destroy>
- SESSION_REPLY<Client-Connection-Id, Destroy, Session-Id>
- LOCK_DB_REQ <Session-Id, Database-Id>
@@ -139,8 +151,21 @@ Following is a list of message types supported on the MGMT Frontend Interface:
- COMMIT_CONFIG_REPLY <Session-Id, Source-Db-id, Dest-Db-Id, Status>
- GET_DATA_REQ <Session-Id, Database-Id, Base-Yang-Xpath>
- GET_DATA_REPLY <Session-Id, Database-id, Base-Yang-Xpath, Yang-Data-Set>
- - REGISTER_NOTIFY_REQ <Session-Id, Database-Id, Base-Yang-Xpath>
- - DATA_NOTIFY_REQ <Database-Id, Base-Yang-Xpath, Yang-Data-Set>
+
+Following is a list of native messages types supported by the MGMTd Front-End
+API:
+
+ - ERROR (receive) - received in response to any sent native message.
+ - TREE_DATA (receive) - returned data from a datastore
+ - GET_DATA (send) - get a tree of data
+ - NOTIFY (receive) - a notification received from mgmtd
+ - EDIT (send) - edit configuration datastore
+ - EDIT_REPLY (receive) - reply for an edit operation
+ - RPC (send) - sending (invoking) an RPC.
+ - RPC_REPLY (receive) - reply from invoking an RPC
+ - NOTIFY_SELECT (send) - specify the sub-set of notifications the front-end
+ wishes to receive, rather than the default of receiving all.
+
Please refer to the MGMT Frontend Client Developers Reference and Guide
(coming soon) for more details.
diff --git a/doc/user/ospf6d.rst b/doc/user/ospf6d.rst
index ad58610..ea41ba5 100644
--- a/doc/user/ospf6d.rst
+++ b/doc/user/ospf6d.rst
@@ -494,11 +494,11 @@ Graceful Restart
Configure Graceful Restart (RFC 5187) helper support.
- By default, helper support is disabled for all neighbours.
+ By default, helper support is disabled for all neighbors.
This config enables/disables helper support on this router
- for all neighbours.
+ for all neighbors.
To enable/disable helper support for a specific
- neighbour, the router-id (A.B.C.D) has to be specified.
+ neighbor, the router-id (A.B.C.D) has to be specified.
.. clicmd:: graceful-restart helper strict-lsa-checking
diff --git a/doc/user/ospf_fundamentals.rst b/doc/user/ospf_fundamentals.rst
index c566059..3032d27 100644
--- a/doc/user/ospf_fundamentals.rst
+++ b/doc/user/ospf_fundamentals.rst
@@ -12,7 +12,7 @@ OSPF Fundamentals
:term:`distance-vector` protocols, such as :abbr:`RIP` or :abbr:`BGP`, where
routers describe available `paths` (i.e. routes) to each other, in
:term:`link-state` protocols routers instead describe the state of their links
-to their immediate neighbouring routers.
+to their immediate neighboring routers.
.. index::
single: Link State Announcement
@@ -127,7 +127,7 @@ LSA Flooding
""""""""""""
OSPF defines several related mechanisms, used to manage synchronisation of
-:abbr:`LSDB` s between neighbours as neighbours form adjacencies and the
+:abbr:`LSDB` s between neighbors as neighbors form adjacencies and the
propagation, or `flooding` of new or updated :abbr:`LSA` s.
@@ -259,7 +259,7 @@ called `intra-area routes`.
LSA is originated for such a link.
Stub
- A link with no adjacent neighbours, or a host route.
+ A link with no adjacent neighbors, or a host route.
- Link ID and Data
@@ -339,8 +339,8 @@ The example below shows two :abbr:`LSA` s, both originated by the same router
of different LSA types.
The first LSA being the router LSA describing 192.168.0.49's links: 2 links
-to multi-access networks with fully-adjacent neighbours (i.e. Transit
-links) and 1 being a Stub link (no adjacent neighbours).
+to multi-access networks with fully-adjacent neighbors (i.e. Transit
+links) and 1 being a Stub link (no adjacent neighbors).
The second LSA being a Network LSA, for which 192.168.0.49 is the
:abbr:`DR`, listing the Router IDs of 4 routers on that network which
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 3bc4487..70c15e7 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -28,6 +28,12 @@ Configuring OSPF
Enable the OSPF API server. This is required to use ``ospfclient``.
+.. option:: -l, --apiserver_addr <address>
+
+ Specify the local IPv4 address to which to bind the OSPF API server socket.
+ If unspecified, connections are accepted to any address. Specification of
+ 127.0.0.1 can be used to limit socket access to local applications.
+
*ospfd* must acquire interface information from *zebra* in order to function.
Therefore *zebra* must be running before invoking *ospfd*. Also, if *zebra* is
restarted then *ospfd* must be too.
@@ -239,6 +245,17 @@ To start OSPF process you have to specify the OSPF router.
This configuration setting MUST be consistent across all routers within the
OSPF domain.
+.. clicmd:: neighbor A.B.C.D [poll-interval (1-65535)] [priority (0-255)]
+
+
+ Configures OSPF neighbors for non-broadcast multi-access (NBMA) networks
+ and point-to-multipoint non-broadcast networks. The `poll-interval`
+ specifies the rate for sending hello packets to neighbors that are not
+ active. When the configured neighbor is discovered, hello packets will be
+ sent at the rate of the hello-interval. The default `poll-interval` is 60
+ seconds. The `priority` is used to for the Designated Router (DR) election
+ on non-broadcast multi-access networks.
+
.. clicmd:: network A.B.C.D/M area A.B.C.D
.. clicmd:: network A.B.C.D/M area (0-4294967295)
@@ -580,7 +597,7 @@ Interfaces
Note that OSPF MD5 authentication requires that time never go backwards
(correct time is NOT important, only that it never goes backwards), even
across resets, if ospfd is to be able to promptly reestablish adjacencies
- with its neighbours after restarts/reboots. The host should have system time
+ with its neighbors after restarts/reboots. The host should have system time
be set at boot from an external or non-volatile source (e.g. battery backed
clock, NTP, etc.) or else the system clock should be periodically saved to
non-volatile storage and restored at boot if MD5 authentication is to be
@@ -612,7 +629,7 @@ Interfaces
Note that OSPF HMAC cryptographic authentication requires that time never go backwards
(correct time is NOT important, only that it never goes backwards), even
across resets, if ospfd is to be able to promptly reestablish adjacencies
- with its neighbours after restarts/reboots. The host should have system time
+ with its neighbors after restarts/reboots. The host should have system time
be set at boot from an external or non-volatile source (e.g. battery backed
clock, NTP, etc.) or else the system clock should be periodically saved to
non-volatile storage and restored at boot if HMAC cryptographic authentication is to be
@@ -679,7 +696,7 @@ Interfaces
it's recommended to set the hello delay and hello interval with the same values.
The default value is 10 seconds.
-.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint [delay-reflood]|point-to-point [dmvpn])
+.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint [delay-reflood|non-broadcast]|point-to-point [dmvpn])
When configuring a point-to-point network on an interface and the interface
has a /32 address associated with then OSPF will treat the interface
@@ -691,6 +708,13 @@ Interfaces
point-to-point, but the HUB will be a point-to-multipoint. To make this
topology work, specify the optional 'dmvpn' parameter at the spoke.
+ When the network is configured as point-to-multipoint and `non-broadcast`
+ is specified, the network doesn't support broadcast or multicast delivery
+ and neighbors cannot be discovered from OSPF hello received from the
+ OSPFAllRouters (224.0.0.5). Rather, they must be explicitly configured
+ using the :clicmd:`neighbor A.B.C.D` configuration command as they are
+ on non-broadcast networks.
+
When the network is configured as point-to-multipoint and `delay-reflood`
is specified, LSAs received on the interface from neighbors on the
interface will not be flooded back out on the interface immediately.
@@ -739,6 +763,32 @@ Interfaces
optional IPv4 address is specified, the prefix suppression will apply
to the OSPF interface associated with the specified interface address.
+.. clicmd:: ip ospf neighbor-filter NAME [A.B.C.D]
+
+ Configure an IP prefix-list to use to filter packets received from
+ OSPF neighbors on the OSPF interface. The prefix-list should include rules
+ to permit or deny OSPF neighbors by IP source address. This is useful for
+ multi-access interfaces where adjacencies with only a subset of the
+ reachable neighbors are desired. Applications include testing partially
+ meshed topologies, OSPF Denial of Sevice (DoS) mitigation, and avoidance
+ of adjacencies with OSPF neighbors not meeting traffic engineering criteria.
+
+ Example:
+
+.. code-block:: frr
+
+ !
+ ! Prefix-list to block neighbor with source address 10.1.0.2
+ !
+ ip prefix-list nbr-filter seq 10 deny 10.1.0.2/32
+ ip prefix-list nbr-filter seq 200 permit any
+ !
+ ! Configure the neighbor filter prefix-list on interface eth0
+ !
+ interface eth0
+ ip ospf neighbor-filter nbr-filter
+ !
+
.. clicmd:: ip ospf area (A.B.C.D|(0-4294967295))
@@ -838,11 +888,11 @@ Graceful Restart
Configure Graceful Restart (RFC 3623) helper support.
- By default, helper support is disabled for all neighbours.
+ By default, helper support is disabled for all neighbors.
This config enables/disables helper support on this router
- for all neighbours.
+ for all neighbors.
To enable/disable helper support for a specific
- neighbour, the router-id (A.B.C.D) has to be specified.
+ neighbor, the router-id (A.B.C.D) has to be specified.
.. clicmd:: graceful-restart helper strict-lsa-checking
@@ -937,7 +987,7 @@ Showing Information
User can get that information as JSON format when ``json`` keyword
at the end of cli is presented.
-.. clicmd:: show ip ospf graceful-restart helper [detail] [json]
+.. clicmd:: show ip ospf [{(1-65535)|vrf <NAME|all>}] graceful-restart helper [detail] [json]
Displays the Graceful Restart Helper details including helper
config changes.
@@ -1082,7 +1132,7 @@ Router Information
respectively the PCE IP address, Autonomous System (AS) numbers of
controlled domains, neighbor ASs, flag and scope. For flag and scope, please
refer to :rfc`5088` for the BITPATTERN recognition. Multiple 'pce neighbor'
- command could be specified in order to specify all PCE neighbours.
+ command could be specified in order to specify all PCE neighbors.
.. clicmd:: show ip ospf router-info
diff --git a/doc/user/ripngd.rst b/doc/user/ripngd.rst
index f898bed..f55ee39 100644
--- a/doc/user/ripngd.rst
+++ b/doc/user/ripngd.rst
@@ -136,7 +136,7 @@ functionality.
range is very large for compatibility with other protocols. For RIPng, valid
metric values are from 1 to 16.
-.. clicmd:: set tag (1-4294967295)
+.. clicmd:: set tag <untagged|(1-4294967295)>
Set a tag on the matched route.
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 791762a..1d2f4e3 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -176,10 +176,9 @@ Route Map Match Command
Matches the specified `metric`.
-.. clicmd:: match tag TAG
+.. clicmd:: match tag <untagged|(1-4294967295)>
- Matches the specified tag value associated with the route. This tag value
- can be in the range of (1-4294967295).
+ Matches the specified tag (or untagged) value associated with the route.
.. clicmd:: match local-preference METRIC
@@ -241,9 +240,10 @@ Route Map Set Command
.. program:: configure
-.. clicmd:: set tag TAG
+.. clicmd:: set tag <untagged|(1-4294967295)>
+
+ Set a tag on the matched route.
- Set a tag on the matched route. This tag value can be from (1-4294967295).
Additionally if you have compiled with the :option:`--enable-realms`
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. As
diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst
index 76910ee..98f9b10 100644
--- a/doc/user/rpki.rst
+++ b/doc/user/rpki.rst
@@ -131,19 +131,13 @@ The following commands are available for independent of a specific cache server.
The default value is 600 seconds.
-.. clicmd:: rpki cache (A.B.C.D|WORD) PORT [SSH_USERNAME] [SSH_PRIVKEY_PATH] [KNOWN_HOSTS_PATH] [source A.B.C.D] preference (1-255)
+.. clicmd:: rpki cache tcp HOST PORT [source A.B.C.D] preference (1-255)
+ Add a TCP cache server to the socket.
- 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
- router and cache server by SSH is optional. Deleting a socket removes the
- associated cache server and terminates the existing connection.
+.. clicmd:: rpki cache ssh HOST PORT SSH_USERNAME SSH_PRIVKEY_PATH [KNOWN_HOSTS_PATH] [source A.B.C.D] preference (1-255)
- A.B.C.D|WORD
- Address of the cache server.
-
- PORT
- Port number to connect to the cache server
+ Add a SSH cache server to the socket.
SSH_USERNAME
SSH username to establish an SSH connection to the cache server.
@@ -159,7 +153,6 @@ The following commands are available for independent of a specific cache server.
source A.B.C.D
Source address of the RPKI connection to access cache server.
-
.. _validating-bgp-updates:
Validating BGP Updates
@@ -215,15 +208,18 @@ Displaying RPKI
Display RPKI configuration state including timers values.
-.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [(1-4294967295)] [vrf NAME] [json]
+.. clicmd:: show rpki prefix <A.B.C.D/M|X:X::X:X/M> [ASN] [vrf NAME] [json]
Display validated prefixes received from the cache servers filtered
- by the specified prefix.
+ by the specified prefix. The AS number space has been increased
+ to allow the choice of using AS 0 because RFC-7607 specifically
+ calls out the usage of 0 in a special case.
.. clicmd:: show rpki as-number ASN [vrf NAME] [json]
Display validated prefixes received from the cache servers filtered
- by ASN.
+ by ASN. The usage of AS 0 is allowed because RFC-76067 specifically
+ calls out the usage of 0 in a special case.
.. clicmd:: show rpki prefix-table [vrf NAME] [json]
@@ -264,9 +260,9 @@ RPKI Configuration Example
rpki polling_period 1000
rpki timeout 10
! SSH Example:
- rpki cache example.com 22 rtr-ssh ./ssh_key/id_rsa preference 1
+ rpki cache ssh example.com 22 rtr-ssh ./ssh_key/id_rsa preference 1
! TCP Example:
- rpki cache rpki-validator.realmv6.org 8282 preference 2
+ rpki cache tcp rpki-validator.realmv6.org 8282 preference 2
exit
!
exit-vrf
@@ -275,9 +271,9 @@ RPKI Configuration Example
rpki polling_period 1000
rpki timeout 10
! SSH Example:
- rpki cache example.com source 198.51.100.223 22 rtr-ssh ./ssh_key/id_rsa preference 1
+ rpki cache ssh example.com source 198.51.100.223 22 rtr-ssh ./ssh_key/id_rsa preference 1
! TCP Example:
- rpki cache rpki-validator.realmv6.org 8282 preference 2
+ rpki cache tcp rpki-validator.realmv6.org 8282 preference 2
exit
!
router bgp 65001
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index 30b0204..37644dc 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -1356,6 +1356,9 @@ FPM Commands
User FPM configurations: 1
User FPM disable requests: 0
+.. clicmd:: show fpm status [json]
+
+ Show the FPM status.
.. clicmd:: clear fpm counters
@@ -1450,29 +1453,41 @@ To program the PBR rules as rte_flows you additionally need to configure
zebra Terminal Mode Commands
============================
-.. clicmd:: show ip route
+.. clicmd:: show [ip|ipv6] route
Display current routes which zebra holds in its database.
::
Router# show ip route
- Codes: K - kernel route, C - connected, S - static, R - RIP,
- B - BGP * - FIB route.
-
- K* 0.0.0.0/0 203.181.89.241
- S 0.0.0.0/0 203.181.89.1
- C* 127.0.0.0/8 lo
- C* 203.181.89.240/28 eth0
+ Codes: K - kernel route, C - connected, L - local, S - static,
+ R - RIP, O - OSPF, I - IS-IS, B - BGP, E - EIGRP, N - NHRP,
+ T - Table, v - VNC, V - VNC-Direct, A - Babel, D - SHARP,
+ F - PBR, f - OpenFabric, t - Table-Direct,
+ > - selected route, * - FIB route, q - queued, r - rejected, b - backup
+ t - trapped, o - offload failure
+ K>* 0.0.0.0/0 [0/100] via 192.168.119.1, enp13s0, 00:30:22
+ S> 4.5.6.7/32 [1/0] via 192.168.119.1 (recursive), weight 1, 00:30:22
+ * via 192.168.119.1, enp13s0, weight 1, 00:30:22
+ K>* 169.254.0.0/16 [0/1000] is directly connected, virbr2 linkdown, 00:30:22
+ L>* 192.168.119.205/32 is directly connected, enp13s0, 00:30:22
-.. clicmd:: show ipv6 route
.. 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.
+.. clicmd:: show [ip|ipv6] route summary
+
+ Display summary information about routes received from each protocol.
+ This command displays the entries received from each route and as such
+ this total can be more than the actual number of FIB routes. Finally
+ due to the way that linux supports local and connected routes the FIB
+ total may not be exactly what is shown in the equivalent `ip route show`
+ command to see the state of the linux kernel.
+
.. clicmd:: show interface [NAME] [{vrf VRF|brief}] [json]
.. clicmd:: show interface [NAME] [{vrf all|brief}] [json]
diff --git a/docker/debian/Dockerfile b/docker/debian/Dockerfile
index d136538..b317b05 100644
--- a/docker/debian/Dockerfile
+++ b/docker/debian/Dockerfile
@@ -24,5 +24,5 @@ RUN chown -R frr:frr /etc/frr /var/run/frr
ENTRYPOINT ["/usr/bin/tini", "--"]
# Default CMD starts watchfrr
-COPY docker-start /usr/lib/frr/docker-start
+COPY --chmod=0755 docker-start /usr/lib/frr/docker-start
CMD ["/usr/lib/frr/docker-start"]
diff --git a/docker/ubuntu-ci/Dockerfile b/docker/ubuntu-ci/Dockerfile
index 5a49806..5c4649d 100644
--- a/docker/ubuntu-ci/Dockerfile
+++ b/docker/ubuntu-ci/Dockerfile
@@ -23,13 +23,17 @@ RUN apt update && apt upgrade -y && \
libreadline-dev \
libsnmp-dev \
libsqlite3-dev \
+ lsb-release \
libtool \
+ lcov \
make \
perl \
pkg-config \
python3-dev \
python3-sphinx \
+ screen \
texinfo \
+ tmux \
&& \
# Protobuf build requirements
apt-get install -y \
@@ -89,18 +93,14 @@ RUN groupadd -r -g 92 frr && \
echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \
mkdir -p /home/frr && chown frr.frr /home/frr
-USER frr:frr
+# Install FRR built packages
+RUN mkdir -p /etc/apt/keyrings && \
+ curl -s -o /etc/apt/keyrings/frrouting.gpg https://deb.frrouting.org/frr/keys.gpg && \
+ echo deb '[signed-by=/etc/apt/keyrings/frrouting.gpg]' https://deb.frrouting.org/frr \
+ $(lsb_release -s -c) "frr-stable" > /etc/apt/sources.list.d/frr.list && \
+ apt-get update && apt-get install -y librtr-dev libyang2-dev libyang2-tools
-# build and install libyang2
-RUN cd && pwd && ls -al && \
- git clone https://github.com/CESNET/libyang.git && \
- cd libyang && \
- git checkout v2.1.128 && \
- mkdir build; cd build && \
- cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr \
- -DCMAKE_BUILD_TYPE:String="Release" .. && \
- make -j $(nproc) && \
- sudo make install
+USER frr:frr
COPY --chown=frr:frr . /home/frr/frr/
@@ -111,6 +111,10 @@ RUN cd ~/frr && \
--sysconfdir=/etc \
--localstatedir=/var \
--sbindir=/usr/lib/frr \
+ --enable-gcov \
+ --enable-dev-build \
+ --enable-mgmtd-test-be-client \
+ --enable-rpki \
--enable-sharpd \
--enable-multipath=64 \
--enable-user=frr \
diff --git a/docker/ubuntu-ci/docker-start b/docker/ubuntu-ci/docker-start
index 9a45c72..c383ea8 100755
--- a/docker/ubuntu-ci/docker-start
+++ b/docker/ubuntu-ci/docker-start
@@ -1,8 +1,5 @@
#!/bin/bash
-
if [ $(uname -a | grep -ci Ubuntu) -ge 1 ]; then
- #for topotests under ubuntu host
- sudo modprobe mpls-router mpls-iptunnel
- sudo /etc/init.d/openvswitch-switch start
+ sudo modprobe mpls-router mpls-iptunnel vrf
fi
while true ; do sleep 365d ; done
diff --git a/docker/ubuntu22-ci/README.md b/docker/ubuntu22-ci/README.md
index 73f4a10..617192e 100644
--- a/docker/ubuntu22-ci/README.md
+++ b/docker/ubuntu22-ci/README.md
@@ -8,10 +8,18 @@ This builds an ubuntu 22.04 container for dev / test
docker build -t frr-ubuntu22:latest -f docker/ubuntu-ci/Dockerfile .
```
-# Running Full Topotest
+# Run
```
-docker run --init -it --privileged --name frr-ubuntu22 -v /lib/modules:/lib/modules frr-ubuntu22:latest bash -c 'cd ~/frr/tests/topotests ; sudo pytest -nauto --dist=loadfile'
+docker run -d --init --privileged --name frr-ubuntu22 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu22:latest
+```
+
+# Running full topotest (container stops at end)
+
+```
+docker run --init -it --privileged --name frr-ubuntu22 \
+ -v /lib/modules:/lib/modules frr-ubuntu22:latest \
+ bash -c 'cd /home/frr/frr/tests/topotests; sudo pytest -nauto --dist=loadfile'
```
# Extract results from the above run into `run-results` dir and analyze
@@ -20,10 +28,11 @@ docker run --init -it --privileged --name frr-ubuntu22 -v /lib/modules:/lib/modu
tests/topotests/analyze.py -C frr-ubuntu22 -Ar run-results
```
-# Running
+# Extract coverage from a stopped container into host FRR source tree
```
-docker run -d --init --privileged --name frr-ubuntu22 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu22:latest
+docker export frr-ubuntu22 | tar --strip=3 --wildcards -vx '*.gc??'
+lcov -b $(pwd) --capture --directory . --output-file=coverage.info
```
# make check
@@ -38,10 +47,10 @@ docker exec frr-ubuntu22 bash -c 'cd ~/frr ; make check'
docker exec -it frr-ubuntu22 bash
```
-# topotest -- when Host O/S is Ubuntu only
+# Run a specific topotest
```
-docker exec frr-ubuntu22 bash -c 'cd ~/frr/tests/topotests/ospf_topo1 ; sudo pytest test_ospf_topo1.py'
+docker exec frr-ubuntu22 bash -c 'cd ~/frr/tests/topotests ; sudo pytest ospf_topo1/test_ospf_topo1.py'
```
# stop & remove container
diff --git a/eigrpd/eigrp_main.c b/eigrpd/eigrp_main.c
index 552ba7c..319ac92 100644
--- a/eigrpd/eigrp_main.c
+++ b/eigrpd/eigrp_main.c
@@ -36,6 +36,7 @@
#include "distribute.h"
#include "libfrr.h"
#include "routemap.h"
+#include "libagentx.h"
//#include "if_rmap.h"
#include "eigrpd/eigrp_structs.h"
@@ -94,10 +95,11 @@ static void sighup(void)
static void sigint(void)
{
zlog_notice("Terminating on signal");
- eigrp_terminate();
keychain_terminate();
+ eigrp_terminate();
+
exit(0);
}
@@ -132,6 +134,8 @@ static const struct frr_yang_module_info *const eigrpd_yang_modules[] = {
&frr_interface_info,
&frr_route_map_info,
&frr_vrf_info,
+ &ietf_key_chain_info,
+ &ietf_key_chain_deviation_info,
};
/* clang-format off */
@@ -175,9 +179,11 @@ int main(int argc, char **argv, char **envp)
/* EIGRP master init. */
eigrp_master_init();
+
eigrp_om->master = frr_init();
master = eigrp_om->master;
+ libagentx_init();
eigrp_error_init();
eigrp_vrf_init();
vrf_init(NULL, NULL, NULL, NULL);
diff --git a/eigrpd/eigrp_routemap.h b/eigrpd/eigrp_routemap.h
index c471679..c797d10 100644
--- a/eigrpd/eigrp_routemap.h
+++ b/eigrpd/eigrp_routemap.h
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
/*
* eigrp_routemap.h
*
diff --git a/fpm/fpm.proto b/fpm/fpm.proto
index 9f0917f..beaa5d6 100644
--- a/fpm/fpm.proto
+++ b/fpm/fpm.proto
@@ -6,6 +6,9 @@
//
// @author Avneesh Sachdev <avneesh@sproute.com>
//
+// Portions:
+// Copyright (C) 2024 Carmine Scarpitta (for SRv6)
+//
// 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
@@ -72,6 +75,141 @@ message AddRoute {
required int32 metric = 8;
repeated Nexthop nexthops = 9;
+
+ /* Source Address of outer encapsulating IPv6 header */
+ optional qpb.Ipv6Address srv6_encap_source_address = 10;
+ /* SRv6 SID for VPN use cases */
+ optional qpb.Ipv6Address srv6_vpn_sid = 11;
+}
+
+/* SID Format - as per RFC 8986 section #3.1 */
+message SRv6SIDFormat
+{
+ /* Locator block length */
+ required uint32 locator_block_length = 1;
+ /* Locator node length */
+ required uint32 locator_node_length = 2;
+ /* Function length */
+ required uint32 function_length = 3;
+ /* Argument length */
+ required uint32 argument_length = 4;
+}
+
+/* SRv6 Local SID */
+message SRv6LocalSID
+{
+ /* SRv6 SID value */
+ required qpb.Ipv6Address sid = 1;
+
+ /* SID Format - as per RFC 8986 section #3.1 */
+ optional SRv6SIDFormat sid_format = 2;
+
+ /* SRv6 Endpoint Behavior associated with the SID */
+ oneof end_behavior
+ {
+ /* Endpoint */
+ End end = 3;
+ /* Endpoint with L3 cross-connect */
+ EndX end_x = 4;
+ /* Endpoint with specific IPv6 table lookup */
+ EndT end_t = 5;
+ /* Endpoint with decapsulation and IPv6 cross-connect */
+ EndDX6 end_dx6 = 7;
+ /* Endpoint with decapsulation and IPv4 cross-connect */
+ EndDX4 end_dx4 = 8;
+ /* Endpoint with decapsulation and specific IPv6 table lookup */
+ EndDT6 end_dt6 = 9;
+ /* Endpoint with decapsulation and specific IPv4 table lookup */
+ EndDT4 end_dt4 = 10;
+ /* Endpoint with decapsulation and specific IP table lookup */
+ EndDT46 end_dt46 = 11;
+ /* Endpoint behavior with NEXT-CSID, PSP and USD flavors */
+ UN un = 12;
+ /* End.X behavior with NEXT-CSID, PSP and USD flavors */
+ UA ua = 13;
+ /* End.DT6 behavior with NEXT-CSID flavor */
+ UDT6 udt6 = 14;
+ /* End.DT4 behavior with NEXT-CSID flavor */
+ UDT4 udt4 = 15;
+ /* End.DT46 behavior with NEXT-CSID flavor */
+ UDT46 udt46 = 16;
+ }
+
+ /* Endpoint */
+ message End
+ {
+ }
+
+ /* Endpoint with L3 cross-connect */
+ message EndX
+ {
+ required Nexthop nexthop = 1;
+ }
+
+ /* Endpoint with specific IPv6 table lookup */
+ message EndT
+ {
+ required uint32 vrf_id = 1;
+ }
+
+ /* Endpoint with decapsulation and IPv6 cross-connect */
+ message EndDX6
+ {
+ required Nexthop nexthop = 1;
+ }
+
+ /* Endpoint with decapsulation and IPv4 cross-connect */
+ message EndDX4
+ {
+ required Nexthop nexthop = 1;
+ }
+
+ /* Endpoint with decapsulation and specific IPv6 table lookup */
+ message EndDT6
+ {
+ required uint32 vrf_id = 1;
+ }
+
+ /* Endpoint with decapsulation and specific IPv4 table lookup */
+ message EndDT4
+ {
+ required uint32 vrf_id = 1;
+ }
+
+ /* Endpoint with decapsulation and specific IP table lookup */
+ message EndDT46
+ {
+ required uint32 vrf_id = 1;
+ }
+
+ /* Endpoint behavior with NEXT-CSID, PSP and USD flavors */
+ message UN
+ {
+ }
+
+ /* End.X behavior with NEXT-CSID, PSP and USD flavors */
+ message UA
+ {
+ required Nexthop nexthop = 1;
+ }
+
+ /* End.DT6 behavior with NEXT-CSID flavor */
+ message UDT6
+ {
+ required uint32 vrf_id = 1;
+ }
+
+ /* End.DT4 behavior with NEXT-CSID flavor */
+ message UDT4
+ {
+ required uint32 vrf_id = 1;
+ }
+
+ /* End.DT46 behavior with NEXT-CSID flavor */
+ message UDT46
+ {
+ required uint32 vrf_id = 1;
+ }
}
//
@@ -82,10 +220,17 @@ message Message {
UNKNOWN_MSG = 0;
ADD_ROUTE = 1;
DELETE_ROUTE = 2;
+ /* Install an SRv6 Local SID */
+ ADD_SRV6_LOCALSID = 3;
+ /* Remove an SRv6 Local SID */
+ DELETE_SRV6_LOCALSID = 4;
};
optional Type type = 1;
optional AddRoute add_route = 2;
optional DeleteRoute delete_route = 3;
+
+ /* SRv6 Local SID */
+ optional SRv6LocalSID srv6_localsid = 4;
}
diff --git a/fpm/fpm_pb.c b/fpm/fpm_pb.c
index e4c9395..0e8f618 100644
--- a/fpm/fpm_pb.c
+++ b/fpm/fpm_pb.c
@@ -10,3 +10,8 @@
/*
* Main file for the fpm_pb library.
*/
+
+#include "config.h"
+#include "xref.h"
+
+XREF_SETUP();
diff --git a/fpm/fpm_pb.h b/fpm/fpm_pb.h
index 7e39054..23d7e43 100644
--- a/fpm/fpm_pb.h
+++ b/fpm/fpm_pb.h
@@ -5,6 +5,9 @@
* @copyright Copyright (C) 2016 Sproute Networks, Inc.
*
* @author Avneesh Sachdev <avneesh@sproute.com>
+ *
+ * Portions:
+ * Copyright (C) 2024 Carmine Scarpitta (for SRv6)
*/
/*
@@ -15,6 +18,7 @@
#define _FPM_PB_H
#include "lib/route_types.h"
+#include "lib/vrf.h"
#include "qpb/qpb.h"
#include "fpm/fpm.pb-c.h"
@@ -42,4 +46,400 @@ static inline Fpm__RouteKey *fpm__route_key__create(qpb_allocator_t *allocator,
return key;
}
+/*
+ * fpm__nexthop__create
+ */
+#define fpm_nexthop_create fpm__nexthop__create
+static inline Fpm__Nexthop *
+fpm__nexthop__create(qpb_allocator_t *allocator, struct nexthop *nh)
+{
+ Fpm__Nexthop *nexthop;
+ uint8_t family;
+
+ nexthop = QPB_ALLOC(allocator, typeof(*nexthop));
+ if (!nexthop)
+ return NULL;
+
+ fpm__nexthop__init(nexthop);
+
+ if (nh->type == NEXTHOP_TYPE_IPV4 ||
+ nh->type == NEXTHOP_TYPE_IPV4_IFINDEX)
+ family = AF_INET;
+ else if (nh->type == NEXTHOP_TYPE_IPV6 ||
+ nh->type == NEXTHOP_TYPE_IPV6_IFINDEX)
+ family = AF_INET6;
+ else
+ return NULL;
+
+ nexthop->if_id = qpb__if_identifier__create(allocator, nh->ifindex);
+ if (!nexthop->if_id)
+ return NULL;
+
+ nexthop->address = qpb__l3_address__create(allocator, &nh->gate, family);
+ if (!nexthop->address)
+ return NULL;
+
+
+ return nexthop;
+}
+
+/*
+ * fpm__nexthop__get
+ *
+ * Read out information from a protobuf nexthop structure.
+ */
+#define fpm_nexthop_get fpm__nexthop__get
+static inline int fpm__nexthop__get(const Fpm__Nexthop *nh,
+ struct nexthop *nexthop)
+{
+ struct in_addr ipv4;
+ struct in6_addr ipv6;
+ uint32_t ifindex;
+ char *ifname;
+
+ if (!nh)
+ return 0;
+
+ if (!qpb_if_identifier_get(nh->if_id, &ifindex, &ifname))
+ return 0;
+
+ if (nh->address) {
+ if (nh->address->v4) {
+ memset(&ipv4, 0, sizeof(ipv4));
+ if (!qpb__ipv4_address__get(nh->address->v4, &ipv4))
+ return 0;
+
+ nexthop->vrf_id = VRF_DEFAULT;
+ nexthop->type = NEXTHOP_TYPE_IPV4;
+ nexthop->gate.ipv4 = ipv4;
+ if (ifindex) {
+ nexthop->type = NEXTHOP_TYPE_IPV4_IFINDEX;
+ nexthop->ifindex = ifindex;
+ }
+ return 1;
+ }
+
+ if (nh->address->v6) {
+ memset(&ipv6, 0, sizeof(ipv6));
+ if (!qpb__ipv6_address__get(nh->address->v6, &ipv6))
+ return 0;
+ nexthop->vrf_id = VRF_DEFAULT;
+ nexthop->type = NEXTHOP_TYPE_IPV6;
+ nexthop->gate.ipv6 = ipv6;
+ if (ifindex) {
+ nexthop->type = NEXTHOP_TYPE_IPV6_IFINDEX;
+ nexthop->ifindex = ifindex;
+ }
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * fpm__srv6_sid_format__create
+ */
+#define fpm_srv6_sid_format_create fpm__srv6_sid_format__create
+static inline Fpm__SRv6SIDFormat *
+fpm__srv6_sid_format__create(qpb_allocator_t *allocator,
+ uint8_t locator_block_length,
+ uint8_t locator_node_length,
+ uint8_t function_length, uint8_t argument_length)
+{
+ Fpm__SRv6SIDFormat *sid_format;
+
+ sid_format = QPB_ALLOC(allocator, typeof(*sid_format));
+ if (!sid_format)
+ return NULL;
+ fpm__srv6_sidformat__init(sid_format);
+
+ sid_format->locator_block_length = locator_block_length;
+ sid_format->locator_node_length = locator_node_length;
+ sid_format->function_length = function_length;
+ sid_format->argument_length = argument_length;
+
+ return sid_format;
+}
+
+/*
+ * fpm__srv6_local_sid_end_behavior__create
+ */
+#define fpm_srv6_local_sid_end_behavior_create \
+ fpm__srv6_local_sid_end_behavior__create
+static inline Fpm__SRv6LocalSID__End *
+fpm__srv6_local_sid_end_behavior__create(qpb_allocator_t *allocator)
+{
+ Fpm__SRv6LocalSID__End *end;
+
+ end = QPB_ALLOC(allocator, typeof(*end));
+ if (!end)
+ return NULL;
+
+ fpm__srv6_local_sid__end__init(end);
+
+ return end;
+}
+
+/*
+ * fpm__srv6_local_sid_end_x_behavior__create
+ */
+#define fpm_srv6_local_sid_end_x_behavior_create \
+ fpm__srv6_local_sid_end_x_behavior__create
+static inline Fpm__SRv6LocalSID__EndX *
+fpm__srv6_local_sid_end_x_behavior__create(qpb_allocator_t *allocator,
+ struct nexthop *nexthop)
+{
+ Fpm__SRv6LocalSID__EndX *end_x;
+
+ end_x = QPB_ALLOC(allocator, typeof(*end_x));
+ if (!end_x)
+ return NULL;
+
+ fpm__srv6_local_sid__end_x__init(end_x);
+
+ end_x->nexthop = fpm_nexthop_create(allocator, nexthop);
+
+ return end_x;
+}
+
+/*
+ * fpm__srv6_local_sid_end_t_behavior__create
+ */
+#define fpm_srv6_local_sid_end_t_behavior_create \
+ fpm__srv6_local_sid_end_t_behavior__create
+static inline Fpm__SRv6LocalSID__EndT *
+fpm__srv6_local_sid_end_t_behavior__create(qpb_allocator_t *allocator,
+ vrf_id_t vrf_id)
+{
+ Fpm__SRv6LocalSID__EndT *end_t;
+
+ end_t = QPB_ALLOC(allocator, typeof(*end_t));
+ if (!end_t)
+ return NULL;
+
+ fpm__srv6_local_sid__end_t__init(end_t);
+
+ end_t->vrf_id = vrf_id;
+
+ return end_t;
+}
+
+/*
+ * fpm__srv6_local_sid_end_dx6_behavior__create
+ */
+#define fpm_srv6_local_sid_end_dx6_behavior_create \
+ fpm__srv6_local_sid_end_dx6_behavior__create
+static inline Fpm__SRv6LocalSID__EndDX6 *
+fpm__srv6_local_sid_end_dx6_behavior__create(qpb_allocator_t *allocator,
+ struct nexthop *nexthop)
+{
+ Fpm__SRv6LocalSID__EndDX6 *end_dx6;
+
+ end_dx6 = QPB_ALLOC(allocator, typeof(*end_dx6));
+ if (!end_dx6)
+ return NULL;
+
+ fpm__srv6_local_sid__end_dx6__init(end_dx6);
+
+ end_dx6->nexthop = fpm_nexthop_create(allocator, nexthop);
+
+ return end_dx6;
+}
+
+/*
+ * fpm__srv6_local_sid_end_dx4_behavior__create
+ */
+#define fpm_srv6_local_sid_end_dx4_behavior_create \
+ fpm__srv6_local_sid_end_dx4_behavior__create
+static inline Fpm__SRv6LocalSID__EndDX4 *
+fpm__srv6_local_sid_end_dx4_behavior__create(qpb_allocator_t *allocator,
+ struct nexthop *nexthop)
+{
+ Fpm__SRv6LocalSID__EndDX4 *end_dx4;
+
+ end_dx4 = QPB_ALLOC(allocator, typeof(*end_dx4));
+ if (!end_dx4)
+ return NULL;
+
+ fpm__srv6_local_sid__end_dx4__init(end_dx4);
+
+ end_dx4->nexthop = fpm_nexthop_create(allocator, nexthop);
+
+ return end_dx4;
+}
+
+/*
+ * fpm__srv6_local_sid_end_dt6_behavior__create
+ */
+#define fpm_srv6_local_sid_end_dt6_behavior_create \
+ fpm__srv6_local_sid_end_dt6_behavior__create
+static inline Fpm__SRv6LocalSID__EndDT6 *
+fpm__srv6_local_sid_end_dt6_behavior__create(qpb_allocator_t *allocator,
+ vrf_id_t vrf_id)
+{
+ Fpm__SRv6LocalSID__EndDT6 *end_dt6;
+
+ end_dt6 = QPB_ALLOC(allocator, typeof(*end_dt6));
+ if (!end_dt6)
+ return NULL;
+
+ fpm__srv6_local_sid__end_dt6__init(end_dt6);
+
+ end_dt6->vrf_id = vrf_id;
+
+ return end_dt6;
+}
+
+/*
+ * fpm__srv6_local_sid_end_dt4_behavior__create
+ */
+#define fpm_srv6_local_sid_end_dt4_behavior_create \
+ fpm__srv6_local_sid_end_dt4_behavior__create
+static inline Fpm__SRv6LocalSID__EndDT4 *
+fpm__srv6_local_sid_end_dt4_behavior__create(qpb_allocator_t *allocator,
+ vrf_id_t vrf_id)
+{
+ Fpm__SRv6LocalSID__EndDT4 *end_dt4;
+
+ end_dt4 = QPB_ALLOC(allocator, typeof(*end_dt4));
+ if (!end_dt4)
+ return NULL;
+
+ fpm__srv6_local_sid__end_dt4__init(end_dt4);
+
+ end_dt4->vrf_id = vrf_id;
+
+ return end_dt4;
+}
+
+/*
+ * fpm__srv6_local_sid_end_dt46_behavior__create
+ */
+#define fpm_srv6_local_sid_end_dt46_behavior_create \
+ fpm__srv6_local_sid_end_dt46_behavior__create
+static inline Fpm__SRv6LocalSID__EndDT46 *
+fpm__srv6_local_sid_end_dt46_behavior__create(qpb_allocator_t *allocator,
+ vrf_id_t vrf_id)
+{
+ Fpm__SRv6LocalSID__EndDT46 *end_dt46;
+
+ end_dt46 = QPB_ALLOC(allocator, typeof(*end_dt46));
+ if (!end_dt46)
+ return NULL;
+
+ fpm__srv6_local_sid__end_dt46__init(end_dt46);
+
+ end_dt46->vrf_id = vrf_id;
+
+ return end_dt46;
+}
+
+/*
+ * fpm__srv6_local_sid_un_behavior__create
+ */
+#define fpm_srv6_local_sid_un_behavior_create \
+ fpm__srv6_local_sid_un_behavior__create
+static inline Fpm__SRv6LocalSID__UN *
+fpm__srv6_local_sid_un_behavior__create(qpb_allocator_t *allocator)
+{
+ Fpm__SRv6LocalSID__UN *un;
+
+ un = QPB_ALLOC(allocator, typeof(*un));
+ if (!un)
+ return NULL;
+
+ fpm__srv6_local_sid__un__init(un);
+
+ return un;
+}
+
+/*
+ * fpm__srv6_local_sid_ua_behavior__create
+ */
+#define fpm_srv6_local_sid_ua_behavior_create \
+ fpm__srv6_local_sid_ua_behavior__create
+static inline Fpm__SRv6LocalSID__UA *
+fpm__srv6_local_sid_ua_behavior__create(qpb_allocator_t *allocator,
+ struct nexthop *nexthop)
+{
+ Fpm__SRv6LocalSID__UA *ua;
+
+ ua = QPB_ALLOC(allocator, typeof(*ua));
+ if (!ua)
+ return NULL;
+
+ fpm__srv6_local_sid__ua__init(ua);
+
+ ua->nexthop = fpm_nexthop_create(allocator, nexthop);
+
+ return ua;
+}
+
+/*
+ * fpm__srv6_local_sid_udt6_behavior__create
+ */
+#define fpm_srv6_local_sid_udt6_behavior_create \
+ fpm__srv6_local_sid_udt6_behavior__create
+static inline Fpm__SRv6LocalSID__UDT6 *
+fpm__srv6_local_sid_udt6_behavior__create(qpb_allocator_t *allocator,
+ vrf_id_t vrf_id)
+{
+ Fpm__SRv6LocalSID__UDT6 *udt6;
+
+ udt6 = QPB_ALLOC(allocator, typeof(*udt6));
+ if (!udt6)
+ return NULL;
+
+ fpm__srv6_local_sid__udt6__init(udt6);
+
+ udt6->vrf_id = vrf_id;
+
+ return udt6;
+}
+
+/*
+ * fpm__srv6_local_sid_udt4_behavior__create
+ */
+#define fpm_srv6_local_sid_udt4_behavior_create \
+ fpm__srv6_local_sid_udt4_behavior__create
+static inline Fpm__SRv6LocalSID__UDT4 *
+fpm__srv6_local_sid_udt4_behavior__create(qpb_allocator_t *allocator,
+ vrf_id_t vrf_id)
+{
+ Fpm__SRv6LocalSID__UDT4 *udt4;
+
+ udt4 = QPB_ALLOC(allocator, typeof(*udt4));
+ if (!udt4)
+ return NULL;
+
+ fpm__srv6_local_sid__udt4__init(udt4);
+
+ udt4->vrf_id = vrf_id;
+
+ return udt4;
+}
+
+/*
+ * fpm__srv6_local_sid_udt46_behavior__create
+ */
+#define fpm_srv6_local_sid_udt46_behavior_create \
+ fpm__srv6_local_sid_udt46_behavior__create
+static inline Fpm__SRv6LocalSID__UDT46 *
+fpm__srv6_local_sid_udt46_behavior__create(qpb_allocator_t *allocator,
+ vrf_id_t vrf_id)
+{
+ Fpm__SRv6LocalSID__UDT46 *udt46;
+
+ udt46 = QPB_ALLOC(allocator, typeof(*udt46));
+ if (!udt46)
+ return NULL;
+
+ fpm__srv6_local_sid__udt46__init(udt46);
+
+ udt46->vrf_id = vrf_id;
+
+ return udt46;
+}
+
#endif
diff --git a/grpc/frrgrpc_pb.c b/grpc/frrgrpc_pb.c
new file mode 100644
index 0000000..938d777
--- /dev/null
+++ b/grpc/frrgrpc_pb.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: ISC
+/*
+ * libfrrgrpc_pb library stub source
+ */
+
+#include "config.h"
+#include "xref.h"
+
+XREF_SETUP();
diff --git a/grpc/subdir.am b/grpc/subdir.am
index 06b37f9..a464edc 100644
--- a/grpc/subdir.am
+++ b/grpc/subdir.am
@@ -10,6 +10,10 @@ nodist_grpc_libfrrgrpc_pb_la_SOURCES = \
grpc/frr-northbound.pb.cc \
grpc/frr-northbound.grpc.pb.cc \
# end
+
+grpc_libfrrgrpc_pb_la_SOURCES = \
+ grpc/frrgrpc_pb.c \
+ # end
endif
CLEANFILES += \
diff --git a/include/linux/compiler_types.h b/include/linux/compiler_types.h
new file mode 100644
index 0000000..72393a8
--- /dev/null
+++ b/include/linux/compiler_types.h
@@ -0,0 +1,246 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __LINUX_COMPILER_TYPES_H
+#define __LINUX_COMPILER_TYPES_H
+
+#ifndef __ASSEMBLY__
+
+#ifdef __CHECKER__
+# define __user __attribute__((noderef, address_space(1)))
+# define __kernel __attribute__((address_space(0)))
+# define __safe __attribute__((safe))
+# define __force __attribute__((force))
+# define __nocast __attribute__((nocast))
+# define __iomem __attribute__((noderef, address_space(2)))
+# define __must_hold(x) __attribute__((context(x,1,1)))
+# define __acquires(x) __attribute__((context(x,0,1)))
+# define __releases(x) __attribute__((context(x,1,0)))
+# define __acquire(x) __context__(x,1)
+# define __release(x) __context__(x,-1)
+# define __cond_lock(x,c) ((c) ? ({ __acquire(x); 1; }) : 0)
+# define __percpu __attribute__((noderef, address_space(3)))
+# define __rcu __attribute__((noderef, address_space(4)))
+# define __private __attribute__((noderef))
+extern void __chk_user_ptr(const volatile void __user *);
+extern void __chk_io_ptr(const volatile void __iomem *);
+# define ACCESS_PRIVATE(p, member) (*((typeof((p)->member) __force *) &(p)->member))
+#else /* __CHECKER__ */
+# ifdef STRUCTLEAK_PLUGIN
+# define __user __attribute__((user))
+# else
+# define __user
+# endif
+# define __kernel
+# define __safe
+# define __force
+# define __nocast
+# define __iomem
+# define __chk_user_ptr(x) (void)0
+# define __chk_io_ptr(x) (void)0
+# define __builtin_warning(x, y...) (1)
+# define __must_hold(x)
+# define __acquires(x)
+# define __releases(x)
+# define __acquire(x) (void)0
+# define __release(x) (void)0
+# define __cond_lock(x,c) (c)
+# define __percpu
+# define __rcu
+# define __private
+# define ACCESS_PRIVATE(p, member) ((p)->member)
+#endif /* __CHECKER__ */
+
+/* Indirect macros required for expanded argument pasting, eg. __LINE__. */
+#define ___PASTE(a,b) a##b
+#define __PASTE(a,b) ___PASTE(a,b)
+
+#ifdef __KERNEL__
+
+/* Attributes */
+#include <linux/compiler_attributes.h>
+
+/* Compiler specific macros. */
+#ifdef __clang__
+#include <linux/compiler-clang.h>
+#elif defined(__INTEL_COMPILER)
+#include <linux/compiler-intel.h>
+#elif defined(__GNUC__)
+/* The above compilers also define __GNUC__, so order is important here. */
+#include <linux/compiler-gcc.h>
+#else
+#error "Unknown compiler"
+#endif
+
+/*
+ * Some architectures need to provide custom definitions of macros provided
+ * by linux/compiler-*.h, and can do so using asm/compiler.h. We include that
+ * conditionally rather than using an asm-generic wrapper in order to avoid
+ * build failures if any C compilation, which will include this file via an
+ * -include argument in c_flags, occurs prior to the asm-generic wrappers being
+ * generated.
+ */
+#ifdef CONFIG_HAVE_ARCH_COMPILER_H
+#include <asm/compiler.h>
+#endif
+
+struct ftrace_branch_data {
+ const char *func;
+ const char *file;
+ unsigned line;
+ union {
+ struct {
+ unsigned long correct;
+ unsigned long incorrect;
+ };
+ struct {
+ unsigned long miss;
+ unsigned long hit;
+ };
+ unsigned long miss_hit[2];
+ };
+};
+
+struct ftrace_likely_data {
+ struct ftrace_branch_data data;
+ unsigned long constant;
+};
+
+#ifdef CONFIG_ENABLE_MUST_CHECK
+#define __must_check __attribute__((__warn_unused_result__))
+#else
+#define __must_check
+#endif
+
+#if defined(CC_USING_HOTPATCH)
+#define notrace __attribute__((hotpatch(0, 0)))
+#elif defined(CC_USING_PATCHABLE_FUNCTION_ENTRY)
+#define notrace __attribute__((patchable_function_entry(0, 0)))
+#else
+#define notrace __attribute__((__no_instrument_function__))
+#endif
+
+/*
+ * it doesn't make sense on ARM (currently the only user of __naked)
+ * to trace naked functions because then mcount is called without
+ * stack and frame pointer being set up and there is no chance to
+ * restore the lr register to the value before mcount was called.
+ */
+#define __naked __attribute__((__naked__)) notrace
+
+#define __compiler_offsetof(a, b) __builtin_offsetof(a, b)
+
+/*
+ * Force always-inline if the user requests it so via the .config.
+ * Prefer gnu_inline, so that extern inline functions do not emit an
+ * externally visible function. This makes extern inline behave as per gnu89
+ * semantics rather than c99. This prevents multiple symbol definition errors
+ * of extern inline functions at link time.
+ * A lot of inline functions can cause havoc with function tracing.
+ * Do not use __always_inline here, since currently it expands to inline again
+ * (which would break users of __always_inline).
+ */
+#if !defined(CONFIG_OPTIMIZE_INLINING)
+#define inline inline __attribute__((__always_inline__)) __gnu_inline \
+ __inline_maybe_unused notrace
+#else
+#define inline inline __gnu_inline \
+ __inline_maybe_unused notrace
+#endif
+
+/*
+ * gcc provides both __inline__ and __inline as alternate spellings of
+ * the inline keyword, though the latter is undocumented. New kernel
+ * code should only use the inline spelling, but some existing code
+ * uses __inline__. Since we #define inline above, to ensure
+ * __inline__ has the same semantics, we need this #define.
+ *
+ * However, the spelling __inline is strictly reserved for referring
+ * to the bare keyword.
+ */
+#define __inline__ inline
+
+/*
+ * GCC does not warn about unused static inline functions for -Wunused-function.
+ * Suppress the warning in clang as well by using __maybe_unused, but enable it
+ * for W=1 build. This will allow clang to find unused functions. Remove the
+ * __inline_maybe_unused entirely after fixing most of -Wunused-function warnings.
+ */
+#ifdef KBUILD_EXTRA_WARN1
+#define __inline_maybe_unused
+#else
+#define __inline_maybe_unused __maybe_unused
+#endif
+
+/*
+ * Rather then using noinline to prevent stack consumption, use
+ * noinline_for_stack instead. For documentation reasons.
+ */
+#define noinline_for_stack noinline
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The below symbols may be defined for one or more, but not ALL, of the above
+ * compilers. We don't consider that to be an error, so set them to nothing.
+ * For example, some of them are for compiler specific plugins.
+ */
+#ifndef __latent_entropy
+# define __latent_entropy
+#endif
+
+#ifndef __randomize_layout
+# define __randomize_layout __designated_init
+#endif
+
+#ifndef __no_randomize_layout
+# define __no_randomize_layout
+#endif
+
+#ifndef randomized_struct_fields_start
+# define randomized_struct_fields_start
+# define randomized_struct_fields_end
+#endif
+
+#ifndef asm_volatile_goto
+#define asm_volatile_goto(x...) asm goto(x)
+#endif
+
+#ifdef CONFIG_CC_HAS_ASM_INLINE
+#define asm_inline asm __inline
+#else
+#define asm_inline asm
+#endif
+
+#ifndef __no_fgcse
+# define __no_fgcse
+#endif
+
+/* Are two types/vars the same type (ignoring qualifiers)? */
+#define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
+
+/* Is this type a native word size -- useful for atomic operations */
+#define __native_word(t) \
+ (sizeof(t) == sizeof(char) || sizeof(t) == sizeof(short) || \
+ sizeof(t) == sizeof(int) || sizeof(t) == sizeof(long))
+
+/* Helpers for emitting diagnostics in pragmas. */
+#ifndef __diag
+#define __diag(string)
+#endif
+
+#ifndef __diag_GCC
+#define __diag_GCC(version, severity, string)
+#endif
+
+#define __diag_push() __diag(push)
+#define __diag_pop() __diag(pop)
+
+#define __diag_ignore(compiler, version, option, comment) \
+ __diag_ ## compiler(version, ignore, option)
+#define __diag_warn(compiler, version, option, comment) \
+ __diag_ ## compiler(version, warn, option)
+#define __diag_error(compiler, version, option, comment) \
+ __diag_ ## compiler(version, error, option)
+
+#endif /* __LINUX_COMPILER_TYPES_H */
diff --git a/include/linux/if.h b/include/linux/if.h
new file mode 100644
index 0000000..a8ccf6d
--- /dev/null
+++ b/include/linux/if.h
@@ -0,0 +1,296 @@
+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the INET interface module.
+ *
+ * Version: @(#)if.h 1.0.2 04/18/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
+ * Ross Biro
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * 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.
+ */
+#ifndef _LINUX_IF_H
+#define _LINUX_IF_H
+
+#include <linux/libc-compat.h> /* for compatibility with glibc */
+#include <linux/types.h> /* for "__kernel_caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+#include <linux/compiler_types.h> /* for "__user" et al */
+
+#ifndef __KERNEL__
+#include <sys/socket.h> /* for struct sockaddr. */
+#endif
+
+#if __UAPI_DEF_IF_IFNAMSIZ
+#define IFNAMSIZ 16
+#endif /* __UAPI_DEF_IF_IFNAMSIZ */
+#define IFALIASZ 256
+#define ALTIFNAMSIZ 128
+#include <linux/hdlc/ioctl.h>
+
+/* For glibc compatibility. An empty enum does not compile. */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || \
+ __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0
+/**
+ * enum net_device_flags - &struct net_device flags
+ *
+ * These are the &struct net_device flags, they can be set by drivers, the
+ * kernel and some can be triggered by userspace. Userspace can query and
+ * set these flags using userspace utilities but there is also a sysfs
+ * entry available for all dev flags which can be queried and set. These flags
+ * are shared for all types of net_devices. The sysfs entries are available
+ * via /sys/class/net/<dev>/flags. Flags which can be toggled through sysfs
+ * are annotated below, note that only a few flags can be toggled and some
+ * other flags are always preserved from the original net_device flags
+ * even if you try to set them via sysfs. Flags which are always preserved
+ * are kept under the flag grouping @IFF_VOLATILE. Flags which are volatile
+ * are annotated below as such.
+ *
+ * You should have a pretty good reason to be extending these flags.
+ *
+ * @IFF_UP: interface is up. Can be toggled through sysfs.
+ * @IFF_BROADCAST: broadcast address valid. Volatile.
+ * @IFF_DEBUG: turn on debugging. Can be toggled through sysfs.
+ * @IFF_LOOPBACK: is a loopback net. Volatile.
+ * @IFF_POINTOPOINT: interface is has p-p link. Volatile.
+ * @IFF_NOTRAILERS: avoid use of trailers. Can be toggled through sysfs.
+ * Volatile.
+ * @IFF_RUNNING: interface RFC2863 OPER_UP. Volatile.
+ * @IFF_NOARP: no ARP protocol. Can be toggled through sysfs. Volatile.
+ * @IFF_PROMISC: receive all packets. Can be toggled through sysfs.
+ * @IFF_ALLMULTI: receive all multicast packets. Can be toggled through
+ * sysfs.
+ * @IFF_MASTER: master of a load balancer. Volatile.
+ * @IFF_SLAVE: slave of a load balancer. Volatile.
+ * @IFF_MULTICAST: Supports multicast. Can be toggled through sysfs.
+ * @IFF_PORTSEL: can set media type. Can be toggled through sysfs.
+ * @IFF_AUTOMEDIA: auto media select active. Can be toggled through sysfs.
+ * @IFF_DYNAMIC: dialup device with changing addresses. Can be toggled
+ * through sysfs.
+ * @IFF_LOWER_UP: driver signals L1 up. Volatile.
+ * @IFF_DORMANT: driver signals dormant. Volatile.
+ * @IFF_ECHO: echo sent packets. Volatile.
+ */
+enum net_device_flags {
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
+ IFF_UP = 1<<0, /* sysfs */
+ IFF_BROADCAST = 1<<1, /* volatile */
+ IFF_DEBUG = 1<<2, /* sysfs */
+ IFF_LOOPBACK = 1<<3, /* volatile */
+ IFF_POINTOPOINT = 1<<4, /* volatile */
+ IFF_NOTRAILERS = 1<<5, /* sysfs */
+ IFF_RUNNING = 1<<6, /* volatile */
+ IFF_NOARP = 1<<7, /* sysfs */
+ IFF_PROMISC = 1<<8, /* sysfs */
+ IFF_ALLMULTI = 1<<9, /* sysfs */
+ IFF_MASTER = 1<<10, /* volatile */
+ IFF_SLAVE = 1<<11, /* volatile */
+ IFF_MULTICAST = 1<<12, /* sysfs */
+ IFF_PORTSEL = 1<<13, /* sysfs */
+ IFF_AUTOMEDIA = 1<<14, /* sysfs */
+ IFF_DYNAMIC = 1<<15, /* sysfs */
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+ IFF_LOWER_UP = 1<<16, /* volatile */
+ IFF_DORMANT = 1<<17, /* volatile */
+ IFF_ECHO = 1<<18, /* volatile */
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+};
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO != 0 || __UAPI_DEF_IF_NET_DEVICE_FLAGS != 0 */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS
+#define IFF_UP IFF_UP
+#define IFF_BROADCAST IFF_BROADCAST
+#define IFF_DEBUG IFF_DEBUG
+#define IFF_LOOPBACK IFF_LOOPBACK
+#define IFF_POINTOPOINT IFF_POINTOPOINT
+#define IFF_NOTRAILERS IFF_NOTRAILERS
+#define IFF_RUNNING IFF_RUNNING
+#define IFF_NOARP IFF_NOARP
+#define IFF_PROMISC IFF_PROMISC
+#define IFF_ALLMULTI IFF_ALLMULTI
+#define IFF_MASTER IFF_MASTER
+#define IFF_SLAVE IFF_SLAVE
+#define IFF_MULTICAST IFF_MULTICAST
+#define IFF_PORTSEL IFF_PORTSEL
+#define IFF_AUTOMEDIA IFF_AUTOMEDIA
+#define IFF_DYNAMIC IFF_DYNAMIC
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS */
+
+#if __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define IFF_LOWER_UP IFF_LOWER_UP
+#define IFF_DORMANT IFF_DORMANT
+#define IFF_ECHO IFF_ECHO
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+
+#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|\
+ IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
+
+#define IF_GET_IFACE 0x0001 /* for querying only */
+#define IF_GET_PROTO 0x0002
+
+/* For definitions see hdlc.h */
+#define IF_IFACE_V35 0x1000 /* V.35 serial interface */
+#define IF_IFACE_V24 0x1001 /* V.24 serial interface */
+#define IF_IFACE_X21 0x1002 /* X.21 serial interface */
+#define IF_IFACE_T1 0x1003 /* T1 telco serial interface */
+#define IF_IFACE_E1 0x1004 /* E1 telco serial interface */
+#define IF_IFACE_SYNC_SERIAL 0x1005 /* can't be set by software */
+#define IF_IFACE_X21D 0x1006 /* X.21 Dual Clocking (FarSite) */
+
+/* For definitions see hdlc.h */
+#define IF_PROTO_HDLC 0x2000 /* raw HDLC protocol */
+#define IF_PROTO_PPP 0x2001 /* PPP protocol */
+#define IF_PROTO_CISCO 0x2002 /* Cisco HDLC protocol */
+#define IF_PROTO_FR 0x2003 /* Frame Relay protocol */
+#define IF_PROTO_FR_ADD_PVC 0x2004 /* Create FR PVC */
+#define IF_PROTO_FR_DEL_PVC 0x2005 /* Delete FR PVC */
+#define IF_PROTO_X25 0x2006 /* X.25 */
+#define IF_PROTO_HDLC_ETH 0x2007 /* raw HDLC, Ethernet emulation */
+#define IF_PROTO_FR_ADD_ETH_PVC 0x2008 /* Create FR Ethernet-bridged PVC */
+#define IF_PROTO_FR_DEL_ETH_PVC 0x2009 /* Delete FR Ethernet-bridged PVC */
+#define IF_PROTO_FR_PVC 0x200A /* for reading PVC status */
+#define IF_PROTO_FR_ETH_PVC 0x200B
+#define IF_PROTO_RAW 0x200C /* RAW Socket */
+
+/* RFC 2863 operational status */
+enum {
+ IF_OPER_UNKNOWN,
+ IF_OPER_NOTPRESENT,
+ IF_OPER_DOWN,
+ IF_OPER_LOWERLAYERDOWN,
+ IF_OPER_TESTING,
+ IF_OPER_DORMANT,
+ IF_OPER_UP,
+};
+
+/* link modes */
+enum {
+ IF_LINK_MODE_DEFAULT,
+ IF_LINK_MODE_DORMANT, /* limit upward transition to dormant */
+};
+
+/*
+ * Device mapping structure. I'd just gone off and designed a
+ * beautiful scheme using only loadable modules with arguments
+ * for driver options and along come the PCMCIA people 8)
+ *
+ * Ah well. The get() side of this is good for WDSETUP, and it'll
+ * be handy for debugging things. The set side is fine for now and
+ * being very small might be worth keeping for clean configuration.
+ */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFMAP
+struct ifmap {
+ unsigned long mem_start;
+ unsigned long mem_end;
+ unsigned short base_addr;
+ unsigned char irq;
+ unsigned char dma;
+ unsigned char port;
+ /* 3 bytes spare */
+};
+#endif /* __UAPI_DEF_IF_IFMAP */
+
+struct if_settings {
+ unsigned int type; /* Type of physical device or protocol */
+ unsigned int size; /* Size of the data allocated by the caller */
+ union {
+ /* {atm/eth/dsl}_settings anyone ? */
+ raw_hdlc_proto __user *raw_hdlc;
+ cisco_proto __user *cisco;
+ fr_proto __user *fr;
+ fr_proto_pvc __user *fr_pvc;
+ fr_proto_pvc_info __user *fr_pvc_info;
+
+ /* interface settings */
+ sync_serial_settings __user *sync;
+ te1_settings __user *te1;
+ } ifs_ifsu;
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's. All interface ioctl's must have parameter
+ * definitions which begin with ifr_name. The
+ * remainder may be interface specific.
+ */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFREQ
+struct ifreq {
+#define IFHWADDRLEN 6
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ } ifr_ifrn;
+
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short ifru_flags;
+ int ifru_ivalue;
+ int ifru_mtu;
+ struct ifmap ifru_map;
+ char ifru_slave[IFNAMSIZ]; /* Just fits the size */
+ char ifru_newname[IFNAMSIZ];
+ void __user * ifru_data;
+ struct if_settings ifru_settings;
+ } ifr_ifru;
+};
+#endif /* __UAPI_DEF_IF_IFREQ */
+
+#define ifr_name ifr_ifrn.ifrn_name /* interface name */
+#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_metric ifr_ifru.ifru_ivalue /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+#define ifr_map ifr_ifru.ifru_map /* device map */
+#define ifr_slave ifr_ifru.ifru_slave /* slave device */
+#define ifr_data ifr_ifru.ifru_data /* for use by interface */
+#define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
+#define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
+#define ifr_qlen ifr_ifru.ifru_ivalue /* Queue length */
+#define ifr_newname ifr_ifru.ifru_newname /* New name */
+#define ifr_settings ifr_ifru.ifru_settings /* Device/proto settings*/
+
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+
+/* for compatibility with glibc net/if.h */
+#if __UAPI_DEF_IF_IFCONF
+struct ifconf {
+ int ifc_len; /* size of buffer */
+ union {
+ char __user *ifcu_buf;
+ struct ifreq __user *ifcu_req;
+ } ifc_ifcu;
+};
+#endif /* __UAPI_DEF_IF_IFCONF */
+
+#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
+#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
+
+#endif /* _LINUX_IF_H */
diff --git a/include/linux/libc-compat.h b/include/linux/libc-compat.h
new file mode 100644
index 0000000..8254c93
--- /dev/null
+++ b/include/linux/libc-compat.h
@@ -0,0 +1,267 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Compatibility interface for userspace libc header coordination:
+ *
+ * Define compatibility macros that are used to control the inclusion or
+ * exclusion of UAPI structures and definitions in coordination with another
+ * userspace C library.
+ *
+ * This header is intended to solve the problem of UAPI definitions that
+ * conflict with userspace definitions. If a UAPI header has such conflicting
+ * definitions then the solution is as follows:
+ *
+ * * Synchronize the UAPI header and the libc headers so either one can be
+ * used and such that the ABI is preserved. If this is not possible then
+ * no simple compatibility interface exists (you need to write translating
+ * wrappers and rename things) and you can't use this interface.
+ *
+ * Then follow this process:
+ *
+ * (a) Include libc-compat.h in the UAPI header.
+ * e.g. #include <linux/libc-compat.h>
+ * This include must be as early as possible.
+ *
+ * (b) In libc-compat.h add enough code to detect that the comflicting
+ * userspace libc header has been included first.
+ *
+ * (c) If the userspace libc header has been included first define a set of
+ * guard macros of the form __UAPI_DEF_FOO and set their values to 1, else
+ * set their values to 0.
+ *
+ * (d) Back in the UAPI header with the conflicting definitions, guard the
+ * definitions with:
+ * #if __UAPI_DEF_FOO
+ * ...
+ * #endif
+ *
+ * This fixes the situation where the linux headers are included *after* the
+ * libc headers. To fix the problem with the inclusion in the other order the
+ * userspace libc headers must be fixed like this:
+ *
+ * * For all definitions that conflict with kernel definitions wrap those
+ * defines in the following:
+ * #if !__UAPI_DEF_FOO
+ * ...
+ * #endif
+ *
+ * This prevents the redefinition of a construct already defined by the kernel.
+ */
+#ifndef _UAPI_LIBC_COMPAT_H
+#define _UAPI_LIBC_COMPAT_H
+
+/* We have included glibc headers... */
+#if defined(__GLIBC__)
+
+/* Coordinate with glibc net/if.h header. */
+#if defined(_NET_IF_H) && defined(__USE_MISC)
+
+/* GLIBC headers included first so don't define anything
+ * that would already be defined. */
+
+#define __UAPI_DEF_IF_IFCONF 0
+#define __UAPI_DEF_IF_IFMAP 0
+#define __UAPI_DEF_IF_IFNAMSIZ 0
+#define __UAPI_DEF_IF_IFREQ 0
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 0
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+#endif /* __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO */
+
+#else /* _NET_IF_H */
+
+/* Linux headers included first, and we must define everything
+ * we need. The expectation is that glibc will check the
+ * __UAPI_DEF_* defines and adjust appropriately. */
+
+#define __UAPI_DEF_IF_IFCONF 1
+#define __UAPI_DEF_IF_IFMAP 1
+#define __UAPI_DEF_IF_IFNAMSIZ 1
+#define __UAPI_DEF_IF_IFREQ 1
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+
+#endif /* _NET_IF_H */
+
+/* Coordinate with glibc netinet/in.h header. */
+#if defined(_NETINET_IN_H)
+
+/* GLIBC headers included first so don't define anything
+ * that would already be defined. */
+#define __UAPI_DEF_IN_ADDR 0
+#define __UAPI_DEF_IN_IPPROTO 0
+#define __UAPI_DEF_IN_PKTINFO 0
+#define __UAPI_DEF_IP_MREQ 0
+#define __UAPI_DEF_SOCKADDR_IN 0
+#define __UAPI_DEF_IN_CLASS 0
+
+#define __UAPI_DEF_IN6_ADDR 0
+/* The exception is the in6_addr macros which must be defined
+ * if the glibc code didn't define them. This guard matches
+ * the guard in glibc/inet/netinet/in.h which defines the
+ * additional in6_addr macros e.g. s6_addr16, and s6_addr32. */
+#if defined(__USE_MISC) || defined (__USE_GNU)
+#define __UAPI_DEF_IN6_ADDR_ALT 0
+#else
+#define __UAPI_DEF_IN6_ADDR_ALT 1
+#endif
+#define __UAPI_DEF_SOCKADDR_IN6 0
+#define __UAPI_DEF_IPV6_MREQ 0
+#define __UAPI_DEF_IPPROTO_V6 0
+#define __UAPI_DEF_IPV6_OPTIONS 0
+#define __UAPI_DEF_IN6_PKTINFO 0
+#define __UAPI_DEF_IP6_MTUINFO 0
+
+#else
+
+/* Linux headers included first, and we must define everything
+ * we need. The expectation is that glibc will check the
+ * __UAPI_DEF_* defines and adjust appropriately. */
+#define __UAPI_DEF_IN_ADDR 1
+#define __UAPI_DEF_IN_IPPROTO 1
+#define __UAPI_DEF_IN_PKTINFO 1
+#define __UAPI_DEF_IP_MREQ 1
+#define __UAPI_DEF_SOCKADDR_IN 1
+#define __UAPI_DEF_IN_CLASS 1
+
+#define __UAPI_DEF_IN6_ADDR 1
+/* We unconditionally define the in6_addr macros and glibc must
+ * coordinate. */
+#define __UAPI_DEF_IN6_ADDR_ALT 1
+#define __UAPI_DEF_SOCKADDR_IN6 1
+#define __UAPI_DEF_IPV6_MREQ 1
+#define __UAPI_DEF_IPPROTO_V6 1
+#define __UAPI_DEF_IPV6_OPTIONS 1
+#define __UAPI_DEF_IN6_PKTINFO 1
+#define __UAPI_DEF_IP6_MTUINFO 1
+
+#endif /* _NETINET_IN_H */
+
+/* Coordinate with glibc netipx/ipx.h header. */
+#if defined(__NETIPX_IPX_H)
+
+#define __UAPI_DEF_SOCKADDR_IPX 0
+#define __UAPI_DEF_IPX_ROUTE_DEFINITION 0
+#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 0
+#define __UAPI_DEF_IPX_CONFIG_DATA 0
+#define __UAPI_DEF_IPX_ROUTE_DEF 0
+
+#else /* defined(__NETIPX_IPX_H) */
+
+#define __UAPI_DEF_SOCKADDR_IPX 1
+#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1
+#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1
+#define __UAPI_DEF_IPX_CONFIG_DATA 1
+#define __UAPI_DEF_IPX_ROUTE_DEF 1
+
+#endif /* defined(__NETIPX_IPX_H) */
+
+/* Definitions for xattr.h */
+#if defined(_SYS_XATTR_H)
+#define __UAPI_DEF_XATTR 0
+#else
+#define __UAPI_DEF_XATTR 1
+#endif
+
+/* If we did not see any headers from any supported C libraries,
+ * or we are being included in the kernel, then define everything
+ * that we need. Check for previous __UAPI_* definitions to give
+ * unsupported C libraries a way to opt out of any kernel definition. */
+#else /* !defined(__GLIBC__) */
+
+/* Definitions for if.h */
+#ifndef __UAPI_DEF_IF_IFCONF
+#define __UAPI_DEF_IF_IFCONF 1
+#endif
+#ifndef __UAPI_DEF_IF_IFMAP
+#define __UAPI_DEF_IF_IFMAP 1
+#endif
+#ifndef __UAPI_DEF_IF_IFNAMSIZ
+#define __UAPI_DEF_IF_IFNAMSIZ 1
+#endif
+#ifndef __UAPI_DEF_IF_IFREQ
+#define __UAPI_DEF_IF_IFREQ 1
+#endif
+/* Everything up to IFF_DYNAMIC, matches net/if.h until glibc 2.23 */
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS 1
+#endif
+/* For the future if glibc adds IFF_LOWER_UP, IFF_DORMANT and IFF_ECHO */
+#ifndef __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO
+#define __UAPI_DEF_IF_NET_DEVICE_FLAGS_LOWER_UP_DORMANT_ECHO 1
+#endif
+
+/* Definitions for in.h */
+#ifndef __UAPI_DEF_IN_ADDR
+#define __UAPI_DEF_IN_ADDR 1
+#endif
+#ifndef __UAPI_DEF_IN_IPPROTO
+#define __UAPI_DEF_IN_IPPROTO 1
+#endif
+#ifndef __UAPI_DEF_IN_PKTINFO
+#define __UAPI_DEF_IN_PKTINFO 1
+#endif
+#ifndef __UAPI_DEF_IP_MREQ
+#define __UAPI_DEF_IP_MREQ 1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN
+#define __UAPI_DEF_SOCKADDR_IN 1
+#endif
+#ifndef __UAPI_DEF_IN_CLASS
+#define __UAPI_DEF_IN_CLASS 1
+#endif
+
+/* Definitions for in6.h */
+#ifndef __UAPI_DEF_IN6_ADDR
+#define __UAPI_DEF_IN6_ADDR 1
+#endif
+#ifndef __UAPI_DEF_IN6_ADDR_ALT
+#define __UAPI_DEF_IN6_ADDR_ALT 1
+#endif
+#ifndef __UAPI_DEF_SOCKADDR_IN6
+#define __UAPI_DEF_SOCKADDR_IN6 1
+#endif
+#ifndef __UAPI_DEF_IPV6_MREQ
+#define __UAPI_DEF_IPV6_MREQ 1
+#endif
+#ifndef __UAPI_DEF_IPPROTO_V6
+#define __UAPI_DEF_IPPROTO_V6 1
+#endif
+#ifndef __UAPI_DEF_IPV6_OPTIONS
+#define __UAPI_DEF_IPV6_OPTIONS 1
+#endif
+#ifndef __UAPI_DEF_IN6_PKTINFO
+#define __UAPI_DEF_IN6_PKTINFO 1
+#endif
+#ifndef __UAPI_DEF_IP6_MTUINFO
+#define __UAPI_DEF_IP6_MTUINFO 1
+#endif
+
+/* Definitions for ipx.h */
+#ifndef __UAPI_DEF_SOCKADDR_IPX
+#define __UAPI_DEF_SOCKADDR_IPX 1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEFINITION
+#define __UAPI_DEF_IPX_ROUTE_DEFINITION 1
+#endif
+#ifndef __UAPI_DEF_IPX_INTERFACE_DEFINITION
+#define __UAPI_DEF_IPX_INTERFACE_DEFINITION 1
+#endif
+#ifndef __UAPI_DEF_IPX_CONFIG_DATA
+#define __UAPI_DEF_IPX_CONFIG_DATA 1
+#endif
+#ifndef __UAPI_DEF_IPX_ROUTE_DEF
+#define __UAPI_DEF_IPX_ROUTE_DEF 1
+#endif
+
+/* Definitions for xattr.h */
+#ifndef __UAPI_DEF_XATTR
+#define __UAPI_DEF_XATTR 1
+#endif
+
+#endif /* __GLIBC__ */
+
+#endif /* _UAPI_LIBC_COMPAT_H */
diff --git a/include/subdir.am b/include/subdir.am
index 6f07b6b..bcf3ef7 100644
--- a/include/subdir.am
+++ b/include/subdir.am
@@ -1,4 +1,7 @@
noinst_HEADERS += \
+ include/linux/compiler_types.h \
+ include/linux/libc-compat.h \
+ include/linux/if.h \
include/linux/if_addr.h \
include/linux/if_bridge.h \
include/linux/if_link.h \
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index cba1b91..430bee9 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -687,7 +687,7 @@ void isis_adj_print_json(struct isis_adjacency *adj, struct json_object *json,
default:
continue;
}
- backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
+ backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)"
: "";
json_object_string_add(adj_sid_json, "nexthop",
@@ -726,13 +726,13 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
now = time(NULL);
if (adj->last_upd) {
if (adj->last_upd + adj->hold_time < now)
- vty_out(vty, " Expiring");
+ vty_out(vty, " Expiring ");
else
vty_out(vty, " %-9llu",
(unsigned long long)adj->last_upd
+ adj->hold_time - now);
} else
- vty_out(vty, "- ");
+ vty_out(vty, " - ");
vty_out(vty, "%-10pSY", adj->snpa);
vty_out(vty, "\n");
}
@@ -862,7 +862,7 @@ void isis_adj_print_vty(struct isis_adjacency *adj, struct vty *vty,
default:
continue;
}
- backup = (sra->type == ISIS_SR_LAN_BACKUP) ? " (backup)"
+ backup = (sra->type == ISIS_SR_ADJ_BACKUP) ? " (backup)"
: "";
vty_out(vty, " %s %s%s: %u\n",
diff --git a/isisd/isis_lfa.c b/isisd/isis_lfa.c
index 6f21f4c..dc8f0b9 100644
--- a/isisd/isis_lfa.c
+++ b/isisd/isis_lfa.c
@@ -916,9 +916,8 @@ int isis_tilfa_check(struct isis_spftree *spftree_pc,
adj = isis_adj_find(spftree_pc->area, spftree_pc->level,
vertex->N.id);
- if (adj
- && isis_sr_adj_sid_find(adj, spftree_pc->family,
- ISIS_SR_LAN_BACKUP)) {
+ if (adj && isis_sr_adj_sid_find(adj, spftree_pc->family,
+ ISIS_SR_ADJ_BACKUP)) {
if (IS_DEBUG_LFA)
zlog_debug(
"ISIS-LFA: %s %s already covered by node protection",
@@ -2127,9 +2126,16 @@ void isis_lfa_compute(struct isis_area *area, struct isis_circuit *circuit,
}
vadj_primary = listnode_head(vertex->Adj_N);
+ if (!vadj_primary) {
+ if (IS_DEBUG_LFA)
+ zlog_debug(
+ "ISIS-LFA: skipping computing LFAs due to no adjacencies");
+ continue;
+ }
sadj_primary = vadj_primary->sadj;
parent_vertex = listnode_head(vertex->parents);
+ assert(parent_vertex);
prefix_metric = vertex->d_N - parent_vertex->d_N;
/*
diff --git a/isisd/isis_lsp.c b/isisd/isis_lsp.c
index 77573cd..c98cee0 100644
--- a/isisd/isis_lsp.c
+++ b/isisd/isis_lsp.c
@@ -442,47 +442,6 @@ void set_overload_on_start_timer(struct event *thread)
isis_area_overload_bit_set(area, false);
}
-static void isis_reset_attach_bit(struct isis_adjacency *adj)
-{
- struct isis_area *area = adj->circuit->area;
- struct lspdb_head *head;
- struct isis_lsp *lsp;
- uint8_t lspid[ISIS_SYS_ID_LEN + 2];
-
- /*
- * If an L2 adjacency changed its state in L-1-2 area, we have to:
- * - set the attached bit in L1 LSPs if it's the first L2 adjacency
- * - remove the attached bit in L1 LSPs if it's the last L2 adjacency
- */
-
- if (area->is_type != IS_LEVEL_1_AND_2 || adj->level == ISIS_ADJ_LEVEL1)
- return;
-
- if (!area->attached_bit_send)
- return;
-
- head = &area->lspdb[IS_LEVEL_1 - 1];
- memset(lspid, 0, ISIS_SYS_ID_LEN + 2);
- memcpy(lspid, area->isis->sysid, ISIS_SYS_ID_LEN);
-
- lsp = lsp_search(head, lspid);
- if (!lsp)
- return;
-
- if (adj->adj_state == ISIS_ADJ_UP
- && !(lsp->hdr.lsp_bits & LSPBIT_ATT)) {
- sched_debug("ISIS (%s): adj going up regenerate lsp-bits",
- area->area_tag);
- lsp_regenerate_schedule(area, IS_LEVEL_1, 0);
- } else if (adj->adj_state == ISIS_ADJ_DOWN
- && (lsp->hdr.lsp_bits & LSPBIT_ATT)
- && !isis_level2_adj_up(area)) {
- sched_debug("ISIS (%s): adj going down regenerate lsp-bits",
- area->area_tag);
- lsp_regenerate_schedule(area, IS_LEVEL_1, 0);
- }
-}
-
static uint8_t lsp_bits_generate(int level, int overload_bit, int attached_bit,
struct isis_area *area)
{
@@ -746,6 +705,10 @@ void lsp_print_common(struct isis_lsp *lsp, struct vty *vty, struct json_object
}
}
+#if CONFDATE > 20240916
+CPP_NOTICE("Remove JSON in '-' format")
+#endif
+
void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
char dynhost, struct isis *isis)
{
@@ -759,10 +722,20 @@ void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
own_json = json_object_new_object();
json_object_object_add(json, "lsp", own_json);
json_object_string_add(own_json, "id", LSPid);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove own key")
+#endif
json_object_string_add(own_json, "own", lsp->own_lsp ? "*" : " ");
+ if (lsp->own_lsp)
+ json_object_boolean_add(own_json, "ownLSP", true);
json_object_int_add(json, "pdu-len", lsp->hdr.pdu_len);
+ json_object_int_add(json, "pduLen", lsp->hdr.pdu_len);
snprintfrr(buf, sizeof(buf), "0x%08x", lsp->hdr.seqno);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove seq-number key")
+#endif
json_object_string_add(json, "seq-number", buf);
+ json_object_string_add(json, "seqNumber", buf);
snprintfrr(buf, sizeof(buf), "0x%04hx", lsp->hdr.checksum);
json_object_string_add(json, "chksum", buf);
if (lsp->hdr.rem_lifetime == 0) {
@@ -772,8 +745,13 @@ void lsp_print_json(struct isis_lsp *lsp, struct json_object *json,
} else {
json_object_int_add(json, "holdtime", lsp->hdr.rem_lifetime);
}
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove att-p-ol key")
+#endif
json_object_string_add(
json, "att-p-ol", lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
+ json_object_string_add(json, "attPOl",
+ lsp_bits2string(lsp->hdr.lsp_bits, b, sizeof(b)));
}
void lsp_print_vty(struct isis_lsp *lsp, struct vty *vty,
@@ -822,15 +800,24 @@ int lsp_print_all(struct vty *vty, struct json_object *json,
{
struct isis_lsp *lsp;
int lsp_count = 0;
+ struct json_object *lsp_json = NULL;
if (detail == ISIS_UI_LEVEL_BRIEF) {
frr_each (lspdb, head, lsp) {
- lsp_print_common(lsp, vty, json, dynhost, isis);
+ if (json) {
+ lsp_json = json_object_new_object();
+ json_object_array_add(json, lsp_json);
+ }
+ lsp_print_common(lsp, vty, lsp_json, dynhost, isis);
lsp_count++;
}
} else if (detail == ISIS_UI_LEVEL_DETAIL) {
frr_each (lspdb, head, lsp) {
- lsp_print_detail(lsp, vty, json, dynhost, isis);
+ if (json) {
+ lsp_json = json_object_new_object();
+ json_object_array_add(json, lsp_json);
+ }
+ lsp_print_detail(lsp, vty, lsp_json, dynhost, isis);
lsp_count++;
}
}
@@ -2345,11 +2332,6 @@ static int lsp_handle_adj_state_change(struct isis_adjacency *adj)
{
lsp_regenerate_schedule(adj->circuit->area, IS_LEVEL_1 | IS_LEVEL_2, 0);
- /* when an adjacency state changes determine if we need to
- * change attach_bits in other area's LSPs
- */
- isis_reset_attach_bit(adj);
-
return 0;
}
diff --git a/isisd/isis_main.c b/isisd/isis_main.c
index 60ec8cd..8dd3a97 100644
--- a/isisd/isis_main.c
+++ b/isisd/isis_main.c
@@ -28,6 +28,7 @@
#include "libfrr.h"
#include "routemap.h"
#include "affinitymap.h"
+#include "libagentx.h"
#include "isisd/isis_affinitymap.h"
#include "isisd/isis_constants.h"
@@ -307,6 +308,7 @@ int main(int argc, char **argv, char **envp)
/*
* initializations
*/
+ libagentx_init();
cmd_init_config_callbacks(isis_config_start, isis_config_end);
isis_error_init();
access_list_init();
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 5794e16..763b8b7 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -3821,7 +3821,8 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args)
case NB_EV_APPLY:
circuit = nb_running_get_entry(args->dnode, NULL, true);
circuit->is_type_config = circ_type;
- isis_circuit_is_type_set(circuit, circ_type);
+ if (!circuit->area || circuit->area->is_type == IS_LEVEL_1_AND_2)
+ isis_circuit_is_type_set(circuit, circ_type);
break;
}
diff --git a/isisd/isis_pdu.c b/isisd/isis_pdu.c
index 6f410d3..5be3170 100644
--- a/isisd/isis_pdu.c
+++ b/isisd/isis_pdu.c
@@ -2082,7 +2082,7 @@ static void send_hello_cb(struct event *thread)
circuit->u.p2p.t_send_p2p_hello = NULL;
send_hello(circuit, 1);
send_hello_sched(circuit, ISIS_LEVEL1,
- 1000 * circuit->hello_interval[1]);
+ 1000 * circuit->hello_interval[0]);
return;
}
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 3b3e1fd..1197f8c 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -873,6 +873,9 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
|| (mt_router_info && !mt_router_info->overload));
lspfragloop:
+ if (!lsp->tlvs)
+ return ISIS_OK;
+
if (lsp->hdr.seqno == 0) {
zlog_warn("%s: lsp with 0 seq_num - ignore", __func__);
return ISIS_WARNING;
@@ -2345,9 +2348,6 @@ static void show_isis_topology_common(struct vty *vty, int levels,
return;
for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
- vty_out(vty,
- "Area %s:", area->area_tag ? area->area_tag : "null");
-
#ifndef FABRICD
/*
* The shapes of the flex algo spftree 2-dimensional array
@@ -2362,7 +2362,12 @@ static void show_isis_topology_common(struct vty *vty, int levels,
fa_data = (struct isis_flex_algo_data *)fa->data;
} else
fa_data = NULL;
+#endif /* ifndef FABRICD */
+ vty_out(vty,
+ "Area %s:", area->area_tag ? area->area_tag : "null");
+
+#ifndef FABRICD
if (algo != SR_ALGORITHM_SPF)
vty_out(vty, " Algorithm %hhu\n", algo);
else
@@ -2426,7 +2431,7 @@ DEFUN(show_isis_topology, show_isis_topology_cmd,
" [vrf <NAME|all>] topology"
#ifndef FABRICD
" [<level-1|level-2>]"
- " [algorithm (128-255)]"
+ " [algorithm [(128-255)]]"
#endif /* ifndef FABRICD */
,
SHOW_STR PROTO_HELP VRF_CMD_HELP_STR
@@ -2445,8 +2450,10 @@ DEFUN(show_isis_topology, show_isis_topology_cmd,
struct isis *isis = NULL;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
+ bool all_algorithm = false;
int idx_vrf = 0;
- uint8_t algorithm = SR_ALGORITHM_SPF;
+ uint16_t algorithm = SR_ALGORITHM_SPF;
+
#ifndef FABRICD
int idx = 0;
@@ -2455,8 +2462,12 @@ DEFUN(show_isis_topology, show_isis_topology_cmd,
levels = ISIS_LEVEL1;
if (argv_find(argv, argc, "level-2", &idx))
levels = ISIS_LEVEL2;
- if (argv_find(argv, argc, "algorithm", &idx))
- algorithm = (uint8_t)strtoul(argv[idx + 1]->arg, NULL, 10);
+ if (argv_find(argv, argc, "algorithm", &idx)) {
+ if (argv_find(argv, argc, "(128-255)", &idx))
+ algorithm = (uint16_t)strtoul(argv[idx]->arg, NULL, 10);
+ else
+ all_algorithm = true;
+ }
#endif /* ifndef FABRICD */
if (!im) {
@@ -2465,17 +2476,33 @@ DEFUN(show_isis_topology, show_isis_topology_cmd,
}
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
+ if (all_algorithm) {
+ for (algorithm = SR_ALGORITHM_FLEX_MIN;
+ algorithm <= SR_ALGORITHM_FLEX_MAX;
+ algorithm++)
+ show_isis_topology_common(
+ vty, levels, isis,
+ (uint8_t)algorithm);
+ } else {
show_isis_topology_common(vty, levels, isis,
- algorithm);
- return CMD_SUCCESS;
+ (uint8_t)algorithm);
+ }
}
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL)
- show_isis_topology_common(vty, levels, isis, algorithm);
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis == NULL)
+ return CMD_SUCCESS;
+ if (all_algorithm) {
+ for (algorithm = SR_ALGORITHM_FLEX_MIN;
+ algorithm <= SR_ALGORITHM_FLEX_MAX; algorithm++) {
+ show_isis_topology_common(vty, levels, isis,
+ (uint8_t)algorithm);
+ }
+ } else
+ show_isis_topology_common(vty, levels, isis, (uint8_t)algorithm);
return CMD_SUCCESS;
}
@@ -2648,17 +2675,14 @@ DEFUN(show_isis_flex_algo, show_isis_flex_algo_cmd,
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- show_isis_flex_algo_common(vty, isis,
- flex_algo);
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL)
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
show_isis_flex_algo_common(vty, isis, flex_algo);
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL)
+ show_isis_flex_algo_common(vty, isis, flex_algo);
return CMD_SUCCESS;
}
@@ -2884,7 +2908,7 @@ static void show_isis_route_common(struct vty *vty, int levels,
struct isis_spftree *spftree;
struct listnode *node;
struct isis_area *area;
- char key[8];
+ char key[18];
if (!isis->area_list || isis->area_list->count == 0)
return;
@@ -2914,6 +2938,7 @@ static void show_isis_route_common(struct vty *vty, int levels,
jstr = json_object_new_string(
area->area_tag ? area->area_tag : "null");
json_object_object_add(*json, "area", jstr);
+ json_object_int_add(*json, "algorithm", algo);
} else {
vty_out(vty, "Area %s:",
area->area_tag ? area->area_tag : "null");
@@ -3013,6 +3038,39 @@ static void show_isis_route_common(struct vty *vty, int levels,
}
}
+static void show_isis_route_all_algos(struct vty *vty, int levels,
+ struct isis *isis, bool prefix_sid,
+ bool backup, json_object **json)
+{
+ uint16_t algo;
+
+ json_object *json_algo = NULL, *json_algos = NULL;
+
+ if (json) {
+ *json = json_object_new_object();
+ json_algos = json_object_new_array();
+ }
+
+ for (algo = SR_ALGORITHM_FLEX_MIN; algo <= SR_ALGORITHM_FLEX_MAX;
+ algo++) {
+ show_isis_route_common(vty, levels, isis, prefix_sid, backup,
+ (uint8_t)algo, json ? &json_algo : NULL);
+ if (!json)
+ continue;
+ if (json_object_object_length(json_algo) == 0) {
+ json_object_free(json_algo);
+ continue;
+ }
+ json_object_object_add(json_algo, "algorithm",
+ json_object_new_int(algo));
+ json_object_array_add(json_algos, json_algo);
+ }
+
+ if (json)
+ json_object_object_add(*json, "algorithms", json_algos);
+}
+
+
DEFUN(show_isis_route, show_isis_route_cmd,
"show " PROTO_NAME
" [vrf <NAME|all>] route"
@@ -3021,7 +3079,7 @@ DEFUN(show_isis_route, show_isis_route_cmd,
#endif /* ifndef FABRICD */
" [<prefix-sid|backup>]"
#ifndef FABRICD
- " [algorithm (128-255)]"
+ " [algorithm [(128-255)]]"
#endif /* ifndef FABRICD */
" [json$uj]",
SHOW_STR PROTO_HELP VRF_FULL_CMD_HELP_STR
@@ -3043,6 +3101,7 @@ DEFUN(show_isis_route, show_isis_route_cmd,
struct listnode *node;
const char *vrf_name = VRF_DEFAULT_NAME;
bool all_vrf = false;
+ bool all_algorithm = false;
bool prefix_sid = false;
bool backup = false;
bool uj = use_json(argc, argv);
@@ -3069,40 +3128,50 @@ DEFUN(show_isis_route, show_isis_route_cmd,
backup = true;
#ifndef FABRICD
- if (argv_find(argv, argc, "algorithm", &idx))
- algorithm = (uint8_t)strtoul(argv[idx + 1]->arg, NULL, 10);
+ if (argv_find(argv, argc, "algorithm", &idx)) {
+ if (argv_find(argv, argc, "(128-255)", &idx))
+ algorithm = (uint8_t)strtoul(argv[idx]->arg, NULL, 10);
+ else
+ all_algorithm = true;
+ }
#endif /* ifndef FABRICD */
if (uj)
json = json_object_new_array();
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
- show_isis_route_common(
- vty, levels, isis, prefix_sid, backup,
- algorithm, uj ? &json_vrf : NULL);
- if (uj) {
- json_object_object_add(
- json_vrf, "vrf_id",
- json_object_new_int(
- isis->vrf_id));
- json_object_array_add(json, json_vrf);
- }
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
+ if (all_algorithm)
+ show_isis_route_all_algos(vty, levels, isis,
+ prefix_sid, backup,
+ uj ? &json_vrf : NULL);
+ else
+ show_isis_route_common(vty, levels, isis,
+ prefix_sid, backup,
+ algorithm,
+ uj ? &json_vrf : NULL);
+ if (uj) {
+ json_object_object_add(json_vrf, "vrf_id",
+ json_object_new_int(
+ isis->vrf_id));
+ json_object_array_add(json, json_vrf);
}
- goto out;
}
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL) {
+ goto out;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL) {
+ if (all_algorithm)
+ show_isis_route_all_algos(vty, levels, isis, prefix_sid,
+ backup, uj ? &json_vrf : NULL);
+ else
show_isis_route_common(vty, levels, isis, prefix_sid,
backup, algorithm,
uj ? &json_vrf : NULL);
- if (uj) {
- json_object_object_add(
- json_vrf, "vrf_id",
- json_object_new_int(isis->vrf_id));
- json_object_array_add(json, json_vrf);
- }
+ if (uj) {
+ json_object_object_add(json_vrf, "vrf_id",
+ json_object_new_int(isis->vrf_id));
+ json_object_array_add(json, json_vrf);
}
}
@@ -3315,16 +3384,14 @@ DEFUN(show_isis_frr_summary, show_isis_frr_summary_cmd,
}
ISIS_FIND_VRF_ARGS(argv, argc, idx, vrf_name, all_vrf);
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- show_isis_frr_summary_common(vty, levels, isis);
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL)
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
show_isis_frr_summary_common(vty, levels, isis);
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL)
+ show_isis_frr_summary_common(vty, levels, isis);
return CMD_SUCCESS;
}
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index 1d69dbb..f783038 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -462,8 +462,7 @@ void isis_area_delete_backup_adj_sids(struct isis_area *area, int level)
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(area->srdb.adj_sids, node, nnode, sra))
- if (sra->type == ISIS_SR_LAN_BACKUP
- && (sra->adj->level & level))
+ if (sra->type == ISIS_SR_ADJ_BACKUP && (sra->adj->level & level))
sr_adj_sid_del(sra);
}
@@ -689,7 +688,7 @@ void sr_adj_sid_add_single(struct isis_adjacency *adj, int family, bool backup,
circuit->ext = isis_alloc_ext_subtlvs();
sra = XCALLOC(MTYPE_ISIS_SR_INFO, sizeof(*sra));
- sra->type = backup ? ISIS_SR_LAN_BACKUP : ISIS_SR_ADJ_NORMAL;
+ sra->type = backup ? ISIS_SR_ADJ_BACKUP : ISIS_SR_ADJ_NORMAL;
sra->input_label = input_label;
sra->nexthop.family = family;
sra->nexthop.address = nexthop;
@@ -819,7 +818,7 @@ static void sr_adj_sid_del(struct sr_adjacency *sra)
exit(1);
}
- if (sra->type == ISIS_SR_LAN_BACKUP && sra->backup_nexthops) {
+ if (sra->type == ISIS_SR_ADJ_BACKUP && sra->backup_nexthops) {
sra->backup_nexthops->del =
(void (*)(void *))isis_nexthop_delete;
list_delete(&sra->backup_nexthops);
@@ -1021,8 +1020,6 @@ static void show_node(struct vty *vty, struct isis_area *area, int level,
struct ttable *tt;
char buf[128];
- vty_out(vty, " IS-IS %s SR-Nodes:\n\n", circuit_t2string(level));
-
/* Prepare table. */
tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
ttable_add_row(tt, "System ID|SRGB|SRLB|Algorithm|MSD");
@@ -1063,6 +1060,8 @@ static void show_node(struct vty *vty, struct isis_area *area, int level,
if (tt->nrows > 1) {
char *table;
+ vty_out(vty, " IS-IS %s SR-Nodes:\n\n", circuit_t2string(level));
+
table = ttable_dump(tt, "\n");
vty_out(vty, "%s\n", table);
XFREE(MTYPE_TMP, table);
@@ -1074,7 +1073,7 @@ DEFUN(show_sr_node, show_sr_node_cmd,
"show " PROTO_NAME
" segment-routing node"
#ifndef FABRICD
- " [algorithm (128-255)]"
+ " [algorithm [(128-255)]]"
#endif /* ifndef FABRICD */
,
SHOW_STR PROTO_HELP
@@ -1088,13 +1087,18 @@ DEFUN(show_sr_node, show_sr_node_cmd,
{
struct listnode *node, *inode;
struct isis_area *area;
- uint8_t algorithm = SR_ALGORITHM_SPF;
+ uint16_t algorithm = SR_ALGORITHM_SPF;
+ bool all_algorithm = false;
struct isis *isis;
#ifndef FABRICD
int idx = 0;
- if (argv_find(argv, argc, "algorithm", &idx))
- algorithm = (uint8_t)strtoul(argv[idx + 1]->arg, NULL, 10);
+ if (argv_find(argv, argc, "algorithm", &idx)) {
+ if (argv_find(argv, argc, "(128-255)", &idx))
+ algorithm = (uint16_t)strtoul(argv[idx]->arg, NULL, 10);
+ else
+ all_algorithm = true;
+ }
#endif /* ifndef FABRICD */
for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
@@ -1106,8 +1110,17 @@ DEFUN(show_sr_node, show_sr_node_cmd,
continue;
}
for (int level = ISIS_LEVEL1; level <= ISIS_LEVELS;
- level++)
- show_node(vty, area, level, algorithm);
+ level++) {
+ if (all_algorithm) {
+ for (algorithm = SR_ALGORITHM_FLEX_MIN;
+ algorithm <= SR_ALGORITHM_FLEX_MAX;
+ algorithm++)
+ show_node(vty, area, level,
+ (uint8_t)algorithm);
+ } else
+ show_node(vty, area, level,
+ (uint8_t)algorithm);
+ }
}
}
diff --git a/isisd/isis_sr.h b/isisd/isis_sr.h
index 4378760..76f7768 100644
--- a/isisd/isis_sr.h
+++ b/isisd/isis_sr.h
@@ -82,7 +82,7 @@ struct sr_local_block {
/* Segment Routing Adjacency-SID type. */
enum sr_adj_type {
ISIS_SR_ADJ_NORMAL = 0,
- ISIS_SR_LAN_BACKUP,
+ ISIS_SR_ADJ_BACKUP,
};
/* Segment Routing Adjacency. */
diff --git a/isisd/isis_srv6.c b/isisd/isis_srv6.c
index 1b0c706..44fd599 100644
--- a/isisd/isis_srv6.c
+++ b/isisd/isis_srv6.c
@@ -363,7 +363,7 @@ void isis_area_delete_backup_srv6_endx_sids(struct isis_area *area, int level)
struct listnode *node, *nnode;
for (ALL_LIST_ELEMENTS(area->srv6db.srv6_endx_sids, node, nnode, sra))
- if (sra->type == ISIS_SRV6_LAN_BACKUP &&
+ if (sra->type == ISIS_SRV6_ADJ_BACKUP &&
(sra->adj->level & level))
srv6_endx_sid_del(sra);
}
@@ -420,7 +420,7 @@ void srv6_endx_sid_add_single(struct isis_adjacency *adj, bool backup,
: SRV6_ENDPOINT_BEHAVIOR_END_X;
sra = XCALLOC(MTYPE_ISIS_SRV6_INFO, sizeof(*sra));
- sra->type = backup ? ISIS_SRV6_LAN_BACKUP : ISIS_SRV6_ADJ_NORMAL;
+ sra->type = backup ? ISIS_SRV6_ADJ_BACKUP : ISIS_SRV6_ADJ_NORMAL;
sra->behavior = behavior;
sra->locator = chunk;
sra->structure.loc_block_len = chunk->block_bits_length;
@@ -538,7 +538,7 @@ void srv6_endx_sid_del(struct srv6_adjacency *sra)
exit(1);
}
- if (sra->type == ISIS_SRV6_LAN_BACKUP && sra->backup_nexthops) {
+ if (sra->type == ISIS_SRV6_ADJ_BACKUP && sra->backup_nexthops) {
sra->backup_nexthops->del =
(void (*)(void *))isis_nexthop_delete;
list_delete(&sra->backup_nexthops);
diff --git a/isisd/isis_srv6.h b/isisd/isis_srv6.h
index 3386436..7f16712 100644
--- a/isisd/isis_srv6.h
+++ b/isisd/isis_srv6.h
@@ -68,7 +68,7 @@ struct isis_srv6_locator {
/* SRv6 Adjacency-SID type */
enum srv6_adj_type {
ISIS_SRV6_ADJ_NORMAL = 0,
- ISIS_SRV6_LAN_BACKUP,
+ ISIS_SRV6_ADJ_BACKUP,
};
/* SRv6 Adjacency. */
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 90b53c5..3683f74 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -488,6 +488,10 @@ void isis_link_params_update(struct isis_circuit *circuit,
ext->status = EXT_ADJ_SID;
else if (IS_SUBTLV(ext, EXT_LAN_ADJ_SID))
ext->status = EXT_LAN_ADJ_SID;
+ else if (IS_SUBTLV(ext, EXT_SRV6_LAN_ENDX_SID))
+ ext->status = EXT_SRV6_LAN_ENDX_SID;
+ else if (IS_SUBTLV(ext, EXT_SRV6_ENDX_SID))
+ ext->status = EXT_SRV6_ENDX_SID;
else
ext->status = 0;
}
@@ -793,6 +797,12 @@ static struct ls_vertex *lsp_to_vertex(struct ls_ted *ted, struct isis_lsp *lsp)
lnode.msd = cap->msd;
SET_FLAG(lnode.flags, LS_NODE_MSD);
}
+ if (cap->srv6_cap.is_srv6_capable) {
+ SET_FLAG(lnode.flags, LS_NODE_SRV6);
+ lnode.srv6_cap_flags = cap->srv6_cap.flags;
+ memcpy(&lnode.srv6_msd, &cap->srv6_msd,
+ sizeof(struct isis_srv6_msd));
+ }
}
}
@@ -1048,7 +1058,51 @@ static struct ls_attributes *get_attributes(struct ls_node_id adv,
}
}
}
+ if (CHECK_FLAG(tlvs->status, EXT_SRV6_ENDX_SID)) {
+ struct isis_srv6_endx_sid_subtlv *endx =
+ (struct isis_srv6_endx_sid_subtlv *)
+ tlvs->srv6_endx_sid.head;
+ int i;
+
+ for (; endx; endx = endx->next) {
+ if (endx->flags & EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG) {
+ i = 1;
+ SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID);
+ } else {
+ i = 0;
+ SET_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID);
+ }
+ attr->adj_srv6_sid[i].flags = endx->flags;
+ attr->adj_srv6_sid[i].weight = endx->weight;
+ memcpy(&attr->adj_srv6_sid[i].sid, &endx->sid,
+ sizeof(struct in6_addr));
+ attr->adj_srv6_sid[i].endpoint_behavior = endx->behavior;
+ }
+ }
+ if (CHECK_FLAG(tlvs->status, EXT_SRV6_LAN_ENDX_SID)) {
+ struct isis_srv6_lan_endx_sid_subtlv *lendx =
+ (struct isis_srv6_lan_endx_sid_subtlv *)
+ tlvs->srv6_lan_endx_sid.head;
+ int i;
+ for (; lendx; lendx = lendx->next) {
+ if (lendx->flags & EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG) {
+ i = 1;
+ SET_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID);
+ } else {
+ i = 0;
+ SET_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID);
+ }
+ memcpy(&attr->adj_srv6_sid[i].neighbor.sysid,
+ &lendx->neighbor_id, ISIS_SYS_ID_LEN);
+ attr->adj_srv6_sid[i].flags = lendx->flags;
+ attr->adj_srv6_sid[i].weight = lendx->weight;
+ memcpy(&attr->adj_srv6_sid[i].sid, &lendx->sid,
+ sizeof(struct in6_addr));
+ attr->adj_srv6_sid[i].endpoint_behavior =
+ lendx->behavior;
+ }
+ }
return attr;
}
@@ -1636,30 +1690,26 @@ DEFUN(show_isis_mpls_te_router,
return CMD_SUCCESS;
}
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
- for (ALL_LIST_ELEMENTS_RO(isis->area_list,
- anode, area)) {
- if (!IS_MPLS_TE(area->mta))
- continue;
-
- show_router_id(vty, area);
- }
- }
- return 0;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL) {
- for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode,
- area)) {
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
if (!IS_MPLS_TE(area->mta))
continue;
show_router_id(vty, area);
}
}
+ return 0;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
+ if (!IS_MPLS_TE(area->mta))
+ continue;
+
+ show_router_id(vty, area);
+ }
}
return CMD_SUCCESS;
@@ -2108,19 +2158,18 @@ DEFUN(show_isis_mpls_te_db,
int rc = CMD_WARNING;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
- rc = show_isis_ted(vty, argv, argc, isis);
- if (rc != CMD_SUCCESS)
- return rc;
- }
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis)
+
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
rc = show_isis_ted(vty, argv, argc, isis);
+ if (rc != CMD_SUCCESS)
+ return rc;
+ }
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis)
+ rc = show_isis_ted(vty, argv, argc, isis);
return rc;
}
diff --git a/isisd/isis_te.h b/isisd/isis_te.h
index 5087cda..bf1dc2b 100644
--- a/isisd/isis_te.h
+++ b/isisd/isis_te.h
@@ -69,9 +69,10 @@ typedef enum _status_t { disable, enable, learn } status_t;
/* Mode for Inter-AS LSP */ /* TODO: Check how if LSP is flooded in RFC5316 */
typedef enum _interas_mode_t { off, region, as, emulate } interas_mode_t;
-#define IS_EXT_TE(e) (e && e->status != 0 \
- && e->status != EXT_ADJ_SID \
- && e->status != EXT_LAN_ADJ_SID)
+#define IS_EXT_TE(e) \
+ (e && e->status != 0 && e->status != EXT_ADJ_SID && \
+ e->status != EXT_LAN_ADJ_SID && e->status != EXT_SRV6_ENDX_SID && \
+ e->status != EXT_SRV6_LAN_ENDX_SID)
#define IS_MPLS_TE(a) (a && a->status == enable)
#define IS_EXPORT_TE(a) (a->export)
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index 93ae8c6..3bb8a48 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -348,9 +348,120 @@ copy_item_ext_subtlvs(struct isis_ext_subtlvs *exts, uint16_t mtid)
}
static void format_item_asla_subtlvs(struct isis_asla_subtlvs *asla,
+ struct json_object *ext_json,
struct sbuf *buf, int indent)
{
char admin_group_buf[ADMIN_GROUP_PRINT_MAX_SIZE];
+ struct json_object *json;
+ char cnt_buf[255];
+ size_t i;
+ int j;
+
+ if (ext_json) {
+ json = json_object_new_object();
+ json_object_object_add(ext_json, "asla", json);
+ json_object_boolean_add(json, "legacyFlag", asla->legacy);
+ json_object_string_addf(json, "standardApp", "0x%02x",
+ asla->standard_apps);
+ if (IS_SUBTLV(asla, EXT_ADM_GRP))
+ json_object_string_addf(json, "adminGroup", "0x%x",
+ asla->admin_group);
+ if (IS_SUBTLV(asla, EXT_EXTEND_ADM_GRP) &&
+ admin_group_nb_words(&asla->ext_admin_group) != 0) {
+ struct json_object *ext_adm_grp_json;
+
+ ext_adm_grp_json = json_object_new_object();
+ json_object_object_add(json, "extendedAdminGroup",
+ ext_adm_grp_json);
+ for (i = 0;
+ i < admin_group_nb_words(&asla->ext_admin_group);
+ i++) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%lu",
+ (unsigned long)i);
+ json_object_string_addf(ext_adm_grp_json,
+ cnt_buf, "0x%x",
+ asla->ext_admin_group
+ .bitmap.data[i]);
+ }
+ }
+ if (IS_SUBTLV(asla, EXT_MAX_BW))
+ json_object_string_addf(json, "maxBandwithBytesSec",
+ "%g", asla->max_bw);
+ if (IS_SUBTLV(asla, EXT_MAX_RSV_BW))
+ json_object_string_addf(json, "maxResBandwithBytesSec",
+ "%g", asla->max_rsv_bw);
+ if (IS_SUBTLV(asla, EXT_UNRSV_BW)) {
+ struct json_object *unrsv_json =
+ json_object_new_object();
+
+ json_object_object_add(json, "unrsvBandwithBytesSec",
+ unrsv_json);
+ for (j = 0; j < MAX_CLASS_TYPE; j += 1) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d", j);
+ json_object_string_addf(unrsv_json, cnt_buf,
+ "%g", asla->unrsv_bw[j]);
+ }
+ }
+ if (IS_SUBTLV(asla, EXT_TE_METRIC))
+ json_object_int_add(json, "teMetric", asla->te_metric);
+
+ /* Extended metrics */
+ if (IS_SUBTLV(asla, EXT_DELAY)) {
+ struct json_object *avg_json;
+
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "avgDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(asla->delay)
+ ? "Anomalous"
+ : "Normal");
+ json_object_int_add(avg_json, "microSec", asla->delay);
+ }
+ if (IS_SUBTLV(asla, EXT_MM_DELAY)) {
+ struct json_object *avg_json;
+
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "maxMinDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(asla->min_delay)
+ ? "Anomalous"
+ : "Normal");
+ json_object_string_addf(avg_json, "microSec", "%u / %u",
+ asla->min_delay & TE_EXT_MASK,
+ asla->max_delay & TE_EXT_MASK);
+ }
+ if (IS_SUBTLV(asla, EXT_DELAY_VAR))
+ json_object_int_add(json, "delayVariationMicroSec",
+ asla->delay_var & TE_EXT_MASK);
+ if (IS_SUBTLV(asla, EXT_PKT_LOSS)) {
+ struct json_object *link_json;
+
+ link_json = json_object_new_object();
+ json_object_object_add(json, "linkPacketLoss",
+ link_json);
+ json_object_string_add(link_json, "loss",
+ IS_ANORMAL(asla->pkt_loss)
+ ? "Anomalous"
+ : "Normal");
+ json_object_string_addf(link_json, "percentage", "%g",
+ (float)((asla->pkt_loss &
+ TE_EXT_MASK) *
+ LOSS_PRECISION));
+ }
+ if (IS_SUBTLV(asla, EXT_RES_BW))
+ json_object_string_addf(json,
+ "unidirResidualBandBytesSec",
+ "%g", (asla->res_bw));
+ if (IS_SUBTLV(asla, EXT_AVA_BW))
+ json_object_string_addf(json,
+ "unidirAvailableBandBytesSec",
+ "%g", (asla->ava_bw));
+ if (IS_SUBTLV(asla, EXT_USE_BW))
+ json_object_string_addf(json,
+ "unidirUtilizedBandBytesSec",
+ "%g", (asla->use_bw));
+ return;
+ }
sbuf_push(buf, indent, "Application Specific Link Attributes:\n");
sbuf_push(buf, indent + 2,
@@ -454,6 +565,10 @@ static void format_item_asla_subtlvs(struct isis_asla_subtlvs *asla,
asla->use_bw);
}
+#if CONFDATE > 20240916
+CPP_NOTICE("Remove JSON in '-' format")
+#endif
+
/* mtid parameter is used to manage multi-topology i.e. IPv4 / IPv6 */
static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
struct sbuf *buf, struct json_object *json,
@@ -470,7 +585,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "0x%x",
exts->adm_group);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "adm-group", aux_buf);
+ json_object_string_add(json, "admGroup", aux_buf);
} else {
sbuf_push(buf, indent, "Admin Group: 0x%08x\n",
exts->adm_group);
@@ -484,8 +603,23 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (IS_SUBTLV(exts, EXT_EXTEND_ADM_GRP) &&
admin_group_nb_words(&exts->ext_admin_group) != 0) {
- if (!json) {
- /* TODO json after fix show database detail json */
+ if (json) {
+ struct json_object *ext_adm_grp_json;
+ size_t i;
+ ext_adm_grp_json = json_object_new_object();
+ json_object_object_add(json, "extendedAdminGroup",
+ ext_adm_grp_json);
+ for (i = 0;
+ i < admin_group_nb_words(&exts->ext_admin_group);
+ i++) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%lu",
+ (unsigned long)i);
+ json_object_string_addf(ext_adm_grp_json,
+ cnt_buf, "0x%x",
+ exts->ext_admin_group
+ .bitmap.data[i]);
+ }
+ } else {
sbuf_push(buf, indent, "Ext Admin Group: %s\n",
admin_group_string(
admin_group_buf,
@@ -505,10 +639,17 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_LLRI)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "link-local-id",
exts->local_llri);
json_object_int_add(json, "link-remote-id",
exts->remote_llri);
+ json_object_int_add(json, "linkLocalId",
+ exts->local_llri);
+ json_object_int_add(json, "linkRemoteId",
+ exts->remote_llri);
} else {
sbuf_push(buf, indent, "Link Local ID: %u\n",
exts->local_llri);
@@ -520,7 +661,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET, &exts->local_addr, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "local-iface-ip", aux_buf);
+ json_object_string_add(json, "localIfaceIp", aux_buf);
} else
sbuf_push(buf, indent,
"Local Interface IP Address(es): %pI4\n",
@@ -530,8 +675,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET, &exts->neigh_addr, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "remote-iface-ip",
aux_buf);
+ json_object_string_add(json, "remoteIfaceIp", aux_buf);
} else
sbuf_push(buf, indent,
"Remote Interface IP Address(es): %pI4\n",
@@ -541,8 +690,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET6, &exts->local_addr6, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "local-iface-ipv6",
aux_buf);
+ json_object_string_add(json, "localIfaceIpv6", aux_buf);
} else
sbuf_push(buf, indent,
"Local Interface IPv6 Address(es): %pI6\n",
@@ -552,8 +705,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET6, &exts->neigh_addr6, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "remote-iface-ipv6",
aux_buf);
+ json_object_string_add(json, "remoteIfaceIpv6", aux_buf);
} else
sbuf_push(buf, indent,
"Remote Interface IPv6 Address(es): %pI6\n",
@@ -563,8 +720,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
exts->max_bw);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "max-bandwith-bytes-sec",
aux_buf);
+ json_object_string_add(json, "maxBandwithBytesSec",
+ aux_buf);
} else
sbuf_push(buf, indent,
"Maximum Bandwidth: %g (Bytes/sec)\n",
@@ -574,8 +736,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
exts->max_rsv_bw);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(
json, "max-res-bandwith-bytes-sec", aux_buf);
+ json_object_string_add(json, "maxResBandwithBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -585,6 +752,22 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (IS_SUBTLV(exts, EXT_UNRSV_BW)) {
if (json) {
struct json_object *unrsv_json;
+
+ unrsv_json = json_object_new_object();
+ json_object_object_add(json, "unrsvBandwithBytesSec",
+ unrsv_json);
+ for (int j = 0; j < MAX_CLASS_TYPE; j += 1) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d", j);
+ snprintfrr(aux_buf, sizeof(aux_buf), "%g",
+ exts->unrsv_bw[j]);
+ json_object_string_add(unrsv_json, cnt_buf,
+ aux_buf);
+ }
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
unrsv_json = json_object_new_object();
json_object_object_add(json, "unrsv-bandwith-bytes-sec",
unrsv_json);
@@ -595,6 +778,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_string_add(unrsv_json, cnt_buf,
aux_buf);
}
+ /* end old deprecated key format */
} else {
sbuf_push(buf, indent, "Unreserved Bandwidth:\n");
for (int j = 0; j < MAX_CLASS_TYPE; j += 2) {
@@ -608,7 +792,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_TE_METRIC)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "te-metric", exts->te_metric);
+ json_object_int_add(json, "teMetric", exts->te_metric);
} else
sbuf_push(buf, indent,
"Traffic Engineering Metric: %u\n",
@@ -616,8 +804,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_RMT_AS)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "inter-as-te-remote-as",
exts->remote_as);
+ json_object_int_add(json, "interAsTeRemoteAs",
+ exts->remote_as);
} else
sbuf_push(buf, indent,
"Inter-AS TE Remote AS number: %u\n",
@@ -627,8 +820,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
inet_ntop(AF_INET6, &exts->remote_ip, aux_buf,
sizeof(aux_buf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(
json, "inter-as-te-remote-asbr-ip", aux_buf);
+ json_object_string_add(json, "interAsTeRemoteAsbrIp",
+ aux_buf);
} else
sbuf_push(buf, indent,
"Inter-AS TE Remote ASBR IP address: %pI4\n",
@@ -639,12 +837,23 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *avg_json;
avg_json = json_object_new_object();
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_object_add(json, "avg-delay", avg_json);
json_object_string_add(avg_json, "delay",
IS_ANORMAL(exts->delay)
? "Anomalous"
: "Normal");
json_object_int_add(avg_json, "micro-sec", exts->delay);
+
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "avgDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(exts->delay)
+ ? "Anomalous"
+ : "Normal");
+ json_object_int_add(avg_json, "microSec", exts->delay);
} else
sbuf_push(buf, indent,
"%s Average Link Delay: %u (micro-sec)\n",
@@ -656,6 +865,9 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *avg_json;
avg_json = json_object_new_object();
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_object_add(json, "max-min-delay", avg_json);
json_object_string_add(avg_json, "delay",
IS_ANORMAL(exts->min_delay)
@@ -666,6 +878,17 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
exts->max_delay & TE_EXT_MASK);
json_object_string_add(avg_json, "micro-sec", aux_buf);
+ avg_json = json_object_new_object();
+ json_object_object_add(json, "maxMinDelay", avg_json);
+ json_object_string_add(avg_json, "delay",
+ IS_ANORMAL(exts->min_delay)
+ ? "Anomalous"
+ : "Normal");
+ snprintfrr(aux_buf, sizeof(aux_buf), "%u / %u",
+ exts->min_delay & TE_EXT_MASK,
+ exts->max_delay & TE_EXT_MASK);
+ json_object_string_add(avg_json, "microSec", aux_buf);
+
} else
sbuf_push(
buf, indent,
@@ -677,8 +900,13 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
if (IS_SUBTLV(exts, EXT_DELAY_VAR)) {
if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "delay-variation-micro-sec",
exts->delay_var & TE_EXT_MASK);
+ json_object_int_add(json, "delayVariationMicroSec",
+ exts->delay_var & TE_EXT_MASK);
} else
sbuf_push(buf, indent,
"Delay Variation: %u (micro-sec)\n",
@@ -690,6 +918,10 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
(float)((exts->pkt_loss & TE_EXT_MASK) *
LOSS_PRECISION));
struct json_object *link_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
link_json = json_object_new_object();
json_object_object_add(json, "link-packet-loss",
link_json);
@@ -697,8 +929,18 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
IS_ANORMAL(exts->pkt_loss)
? "Anomalous"
: "Normal");
+ /* typo */
json_object_string_add(link_json, "percentaje",
aux_buf);
+
+ link_json = json_object_new_object();
+ json_object_object_add(json, "linkPacketLoss",
+ link_json);
+ json_object_string_add(link_json, "loss",
+ IS_ANORMAL(exts->pkt_loss)
+ ? "Anomalous"
+ : "Normal");
+ json_object_string_add(link_json, "percentage", aux_buf);
} else
sbuf_push(buf, indent, "%s Link Packet Loss: %g (%%)\n",
IS_ANORMAL(exts->pkt_loss) ? "Anomalous"
@@ -710,9 +952,15 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
(exts->res_bw));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json,
"unidir-residual-band-bytes-sec",
aux_buf);
+ json_object_string_add(json,
+ "unidirResidualBandBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -723,9 +971,15 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
snprintfrr(aux_buf, sizeof(aux_buf), "%g",
(exts->ava_bw));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(
json, "unidir-available-band-bytes-sec",
aux_buf);
+ json_object_string_add(json,
+ "unidirAvailableBandBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -739,6 +993,12 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_string_add(json,
"unidir-utilized-band-bytes-sec",
aux_buf);
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ json_object_string_add(json,
+ "unidirUtilizedBandBytesSec",
+ aux_buf);
} else
sbuf_push(
buf, indent,
@@ -751,6 +1011,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "adj-sid", arr_adj_json);
for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
@@ -794,6 +1059,44 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
: "0");
json_object_array_add(arr_adj_json, flags_json);
}
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "adjSid", arr_adj_json);
+ for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
+ adj; adj = adj->next) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d",
+ adj->sid);
+ flags_json = json_object_new_object();
+ json_object_int_add(flags_json, "sid", adj->sid);
+ json_object_int_add(flags_json, "weight",
+ adj->weight);
+ json_object_boolean_add(flags_json, "flagF",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagB",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagV",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagL",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagS",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagP",
+ adj->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? true
+ : false);
+ json_object_array_add(arr_adj_json, flags_json);
+ }
} else
for (adj = (struct isis_adj_sid *)exts->adj_sid.head;
adj; adj = adj->next) {
@@ -826,6 +1129,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
struct isis_lan_adj_sid *lan;
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "lan-adj-sid",
arr_adj_json);
@@ -876,6 +1184,49 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
: "0");
json_object_array_add(arr_adj_json, flags_json);
}
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "lanAdjSid", arr_adj_json);
+ for (lan = (struct isis_lan_adj_sid *)exts->adj_sid.head;
+ lan; lan = lan->next) {
+ if (((mtid == ISIS_MT_IPV4_UNICAST) &&
+ (lan->family != AF_INET)) ||
+ ((mtid == ISIS_MT_IPV6_UNICAST) &&
+ (lan->family != AF_INET6)))
+ continue;
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%d",
+ lan->sid);
+ flags_json = json_object_new_object();
+ json_object_int_add(flags_json, "sid", lan->sid);
+ json_object_int_add(flags_json, "weight",
+ lan->weight);
+ json_object_boolean_add(flags_json, "flagF",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_FFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagB",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_BFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagV",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_VFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagL",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_LFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagS",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_SFLG
+ ? true
+ : false);
+ json_object_boolean_add(flags_json, "flagP",
+ lan->flags & EXT_SUBTLV_LINK_ADJ_SID_PFLG
+ ? true
+ : false);
+ json_object_array_add(arr_adj_json, flags_json);
+ }
} else
for (lan = (struct isis_lan_adj_sid *)
@@ -918,6 +1269,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "srv6-endx-sid",
arr_adj_json);
@@ -955,7 +1311,47 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_array_add(arr_adj_json, flags_json);
if (adj->subsubtlvs)
isis_format_subsubtlvs(adj->subsubtlvs,
- NULL, json,
+ NULL,
+ arr_adj_json,
+ indent + 4);
+ }
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "srv6EndSID", arr_adj_json);
+ for (adj = (struct isis_srv6_endx_sid_subtlv *)
+ exts->srv6_endx_sid.head;
+ adj; adj = adj->next) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%pI6",
+ &adj->sid);
+ flags_json = json_object_new_object();
+ json_object_string_addf(flags_json, "sid",
+ "%pI6", &adj->sid);
+ json_object_string_add(flags_json, "algorithm",
+ sr_algorithm_string(
+ adj->algorithm));
+ json_object_int_add(flags_json, "weight",
+ adj->weight);
+ json_object_string_add(flags_json, "behavior",
+ seg6local_action2str(
+ adj->behavior));
+ json_object_boolean_add(
+ flags_json, "flagB",
+ !!(adj->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG));
+ json_object_boolean_add(
+ flags_json, "flagS",
+ !!(adj->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_SFLG));
+ json_object_boolean_add(
+ flags_json, "flagP",
+ !!(adj->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_PFLG));
+ json_object_array_add(arr_adj_json, flags_json);
+ if (adj->subsubtlvs)
+ isis_format_subsubtlvs(adj->subsubtlvs,
+ NULL,
+ arr_adj_json,
indent + 4);
}
} else
@@ -989,6 +1385,11 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
struct isis_srv6_lan_endx_sid_subtlv *lan;
if (json) {
struct json_object *arr_adj_json, *flags_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
arr_adj_json = json_object_new_array();
json_object_object_add(json, "srv6-lan-endx-sid",
arr_adj_json);
@@ -1031,7 +1432,53 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
json_object_array_add(arr_adj_json, flags_json);
if (lan->subsubtlvs)
isis_format_subsubtlvs(lan->subsubtlvs,
- NULL, json,
+ NULL,
+ arr_adj_json,
+ indent + 4);
+ }
+ /* end old deprecated key format */
+
+ arr_adj_json = json_object_new_array();
+ json_object_object_add(json, "srv6LanEndxSID",
+ arr_adj_json);
+ for (lan = (struct isis_srv6_lan_endx_sid_subtlv *)
+ exts->srv6_lan_endx_sid.head;
+ lan; lan = lan->next) {
+ snprintfrr(cnt_buf, sizeof(cnt_buf), "%pI6",
+ &lan->sid);
+ flags_json = json_object_new_object();
+ json_object_string_addf(flags_json, "sid",
+ "%pI6", &lan->sid);
+ json_object_int_add(flags_json, "weight",
+ lan->weight);
+ json_object_string_add(flags_json, "algorithm",
+ sr_algorithm_string(
+ lan->algorithm));
+ json_object_int_add(flags_json, "weight",
+ lan->weight);
+ json_object_string_add(flags_json, "behavior",
+ seg6local_action2str(
+ lan->behavior));
+ json_object_boolean_add(
+ flags_json, "flagB",
+ !!(lan->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_BFLG));
+ json_object_boolean_add(
+ flags_json, "flagS",
+ !!(lan->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_SFLG));
+ json_object_boolean_add(
+ flags_json, "flagP",
+ !!(lan->flags &
+ EXT_SUBTLV_LINK_SRV6_ENDX_SID_PFLG));
+ json_object_string_addf(flags_json,
+ "neighbor-id", "%pSY",
+ lan->neighbor_id);
+ json_object_array_add(arr_adj_json, flags_json);
+ if (lan->subsubtlvs)
+ isis_format_subsubtlvs(lan->subsubtlvs,
+ NULL,
+ arr_adj_json,
indent + 4);
}
} else
@@ -1063,7 +1510,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
}
}
for (ALL_LIST_ELEMENTS_RO(exts->aslas, node, asla))
- format_item_asla_subtlvs(asla, buf, indent);
+ format_item_asla_subtlvs(asla, json, buf, indent);
}
static void free_item_ext_subtlvs(struct isis_ext_subtlvs *exts)
@@ -2127,15 +2574,26 @@ static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i,
struct isis_prefix_sid *sid = (struct isis_prefix_sid *)i;
if (json) {
- struct json_object *sr_json;
+ struct json_object *sr_json, *array_json;
+
sr_json = json_object_new_object();
- json_object_object_add(json, "sr", sr_json);
+ json_object_object_get_ex(json, "sr", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "sr", array_json);
+ }
+ json_object_array_add(array_json, sr_json);
if (sid->flags & ISIS_PREFIX_SID_VALUE) {
json_object_int_add(sr_json, "label", sid->value);
} else {
json_object_int_add(sr_json, "index", sid->value);
}
json_object_int_add(sr_json, "alg", sid->algorithm);
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated non boolean json")
+#endif
+ /* old deprecated keys (no booleans) */
json_object_string_add(
sr_json, "readvertised",
((sid->flags & ISIS_PREFIX_SID_READVERTISED) ? "yes"
@@ -2157,6 +2615,27 @@ static void format_item_prefix_sid(uint16_t mtid, struct isis_item *i,
json_object_string_add(
sr_json, "local",
((sid->flags & ISIS_PREFIX_SID_LOCAL) ? "yes" : ""));
+ /* end deprecated keys (no booleans) */
+
+ struct json_object *flags_json;
+
+ flags_json = json_object_new_object();
+ json_object_object_add(sr_json, "flags", flags_json);
+
+ json_object_boolean_add(flags_json, "readvertised",
+ !!(sid->flags &
+ ISIS_PREFIX_SID_READVERTISED));
+ json_object_boolean_add(flags_json, "node",
+ !!(sid->flags & ISIS_PREFIX_SID_NODE));
+ json_object_boolean_add(flags_json, "noPHP",
+ !!(sid->flags & ISIS_PREFIX_SID_NO_PHP));
+ json_object_boolean_add(flags_json, "explicitNull",
+ !!(sid->flags &
+ ISIS_PREFIX_SID_EXPLICIT_NULL));
+ json_object_boolean_add(flags_json, "value",
+ !!(sid->flags & ISIS_PREFIX_SID_VALUE));
+ json_object_boolean_add(flags_json, "local",
+ !!(sid->flags & ISIS_PREFIX_SID_LOCAL));
} else {
sbuf_push(buf, indent, "SR Prefix-SID ");
@@ -2286,7 +2765,11 @@ static void format_subtlv_ipv6_source_prefix(struct prefix_ipv6 *p,
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
prefix2str(p, prefixbuf, sizeof(prefixbuf));
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "ipv6-src-prefix", prefixbuf);
+ json_object_string_add(json, "ipv6SrcPrefix", prefixbuf);
} else {
sbuf_push(buf, indent, "IPv6 Source Prefix: %s\n",
prefix2str(p, prefixbuf, sizeof(prefixbuf)));
@@ -2388,6 +2871,11 @@ static void format_subsubtlv_srv6_sid_structure(
if (json) {
struct json_object *sid_struct_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
sid_struct_json = json_object_new_object();
json_object_object_add(json, "srv6-sid-structure",
sid_struct_json);
@@ -2399,6 +2887,19 @@ static void format_subsubtlv_srv6_sid_structure(
sid_struct->func_len);
json_object_int_add(sid_struct_json, "arg-len",
sid_struct->arg_len);
+ /* end old deprecated key format */
+
+ sid_struct_json = json_object_new_object();
+ json_object_object_add(json, "srv6SidStructure",
+ sid_struct_json);
+ json_object_int_add(sid_struct_json, "locBlockLen",
+ sid_struct->loc_block_len);
+ json_object_int_add(sid_struct_json, "locNodeLen",
+ sid_struct->loc_node_len);
+ json_object_int_add(sid_struct_json, "funcLen",
+ sid_struct->func_len);
+ json_object_int_add(sid_struct_json, "argLen",
+ sid_struct->arg_len);
} else {
sbuf_push(buf, indent, "SRv6 SID Structure ");
sbuf_push(buf, 0, "Locator Block length: %hhu, ",
@@ -2680,6 +3181,11 @@ static void format_item_srv6_end_sid(uint16_t mtid, struct isis_item *i,
if (json) {
struct json_object *sid_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
sid_json = json_object_new_object();
json_object_object_add(json, "srv6-end-sid", sid_json);
json_object_string_add(sid_json, "endpoint-behavior",
@@ -2694,6 +3200,21 @@ static void format_item_srv6_end_sid(uint16_t mtid, struct isis_item *i,
isis_format_subsubtlvs(sid->subsubtlvs, NULL,
subtlvs_json, 0);
}
+ /* end old deprecated key format */
+
+ sid_json = json_object_new_object();
+ json_object_object_add(json, "srv6EndSid", sid_json);
+ json_object_string_add(sid_json, "endpointBehavior",
+ seg6local_action2str(sid->behavior));
+ json_object_string_addf(sid_json, "sidValue", "%pI6", &sid->sid);
+ if (sid->subsubtlvs) {
+ struct json_object *subtlvs_json;
+ subtlvs_json = json_object_new_object();
+ json_object_object_add(sid_json, "subsubtlvs",
+ subtlvs_json);
+ isis_format_subsubtlvs(sid->subsubtlvs, NULL,
+ subtlvs_json, 0);
+ }
} else {
sbuf_push(buf, indent, "SRv6 End SID ");
sbuf_push(buf, 0, "Endpoint Behavior: %s, ",
@@ -2841,9 +3362,13 @@ static void format_item_area_address(uint16_t mtid, struct isis_item *i,
memcpy(iso_addr.area_addr, addr->addr, ISO_ADDR_SIZE);
iso_addr.addr_len = addr->len;
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_addf(json, "area-addr", "%pIS", &iso_addr);
- else
+ json_object_string_addf(json, "areaAddr", "%pIS", &iso_addr);
+ } else
sbuf_push(buf, indent, "Area Address: %pIS\n", &iso_addr);
}
@@ -2929,11 +3454,34 @@ static void format_item_oldstyle_reach(uint16_t mtid, struct isis_item *i,
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id);
if (json) {
- struct json_object *old_json;
+ struct json_object *old_json, *array_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
old_json = json_object_new_object();
- json_object_object_add(json, "old-reach-style", old_json);
+ json_object_object_get_ex(json, "old-reach-style", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "old-reach-style",
+ array_json);
+ }
+ json_object_array_add(array_json, old_json);
json_object_string_add(old_json, "is-reach", sys_id);
json_object_int_add(old_json, "metric", r->metric);
+ /* end old deprecated key format */
+
+ old_json = json_object_new_object();
+ json_object_object_get_ex(json, "oldReachStyle", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "oldReachStyle",
+ array_json);
+ }
+ json_object_array_add(array_json, old_json);
+ json_object_string_add(old_json, "isReach", sys_id);
+ json_object_int_add(old_json, "metric", r->metric);
} else
sbuf_push(buf, indent, "IS Reachability: %s (Metric: %hhu)\n",
sys_id, r->metric);
@@ -3011,9 +3559,13 @@ static void format_item_lan_neighbor(uint16_t mtid, struct isis_item *i,
char sys_id[ISO_SYSID_STRLEN];
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", n->mac);
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "lan-neighbor", sys_id);
- else
+ json_object_string_add(json, "lanNeighbor", sys_id);
+ } else
sbuf_push(buf, indent, "LAN Neighbor: %s\n", sys_id);
}
@@ -3086,6 +3638,9 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
char buf[255];
struct json_object *lsp_json;
lsp_json = json_object_new_object();
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_object_add(json, "lsp-entry", lsp_json);
json_object_string_add(lsp_json, "id", sys_id);
snprintfrr(buf,sizeof(buf),"0x%08x",e->seqno);
@@ -3093,6 +3648,15 @@ static void format_item_lsp_entry(uint16_t mtid, struct isis_item *i,
snprintfrr(buf,sizeof(buf),"0x%04hx",e->checksum);
json_object_string_add(lsp_json, "chksum", buf);
json_object_int_add(lsp_json, "lifetime", e->checksum);
+
+ lsp_json = json_object_new_object();
+ json_object_object_add(json, "lspEntry", lsp_json);
+ json_object_string_add(lsp_json, "id", sys_id);
+ snprintfrr(buf, sizeof(buf), "0x%08x", e->seqno);
+ json_object_string_add(lsp_json, "seq", buf);
+ snprintfrr(buf, sizeof(buf), "0x%04hx", e->checksum);
+ json_object_string_add(lsp_json, "chksum", buf);
+ json_object_int_add(lsp_json, "lifetime", e->checksum);
} else
sbuf_push(
buf, indent,
@@ -3173,9 +3737,19 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pPN", r->id);
if (json) {
- struct json_object *reach_json;
+ struct json_object *reach_json, *array_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
reach_json = json_object_new_object();
- json_object_object_add(json, "ext-reach", reach_json);
+ json_object_object_get_ex(json, "ext-reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ext-reach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
json_object_string_add(
reach_json, "mt-id",
(mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT");
@@ -3186,7 +3760,29 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
isis_mtid2str(mtid));
if (r->subtlvs)
- format_item_ext_subtlvs(r->subtlvs, NULL, json,
+ format_item_ext_subtlvs(r->subtlvs, NULL, reach_json,
+ indent + 2, mtid);
+ /* end old deprecated key format */
+
+ reach_json = json_object_new_object();
+ json_object_object_get_ex(json, "extReach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "extReach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
+ json_object_string_add(reach_json, "mtId",
+ (mtid == ISIS_MT_IPV4_UNICAST)
+ ? "Extended"
+ : "MT");
+ json_object_string_add(reach_json, "id", sys_id);
+ json_object_int_add(reach_json, "metric", r->metric);
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ json_object_string_add(reach_json, "mtName",
+ isis_mtid2str(mtid));
+
+ if (r->subtlvs)
+ format_item_ext_subtlvs(r->subtlvs, NULL, reach_json,
indent + 2, mtid);
} else {
sbuf_push(buf, indent, "%s Reachability: %s (Metric: %u)",
@@ -3314,13 +3910,40 @@ static void format_item_oldstyle_ip_reach(uint16_t mtid, struct isis_item *i,
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
- struct json_object *old_json;
+ struct json_object *old_json, *array_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
old_json = json_object_new_object();
- json_object_object_add(json, "old-ip-reach-style", old_json);
+ json_object_object_get_ex(json, "old-ip-reach-style",
+ &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "old-ip-reach-style",
+ old_json);
+ }
+ json_object_array_add(array_json, old_json);
json_object_string_add(old_json, "prefix",
prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)));
json_object_int_add(old_json, "metric", r->metric);
- } else
+ /* end old deprecated key format */
+
+ old_json = json_object_new_object();
+ json_object_object_get_ex(json, "oldIpReachStyle", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "oldIpReachStyle",
+ old_json);
+ }
+ json_object_array_add(array_json, old_json);
+ json_object_string_add(old_json, "prefix",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(old_json, "metric", r->metric);
+ return;
+ }
sbuf_push(buf, indent, "IP Reachability: %s (Metric: %hhu)\n",
prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)),
r->metric);
@@ -3412,6 +4035,10 @@ static void format_tlv_protocols_supported(struct isis_protocols_supported *p,
struct json_object *protocol_json;
char buf[255];
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
protocol_json = json_object_new_object();
json_object_object_add(json, "protocols-supported",
protocol_json);
@@ -3420,6 +4047,16 @@ static void format_tlv_protocols_supported(struct isis_protocols_supported *p,
json_object_string_add(protocol_json, buf,
nlpid2str(p->protocols[i]));
}
+
+ protocol_json = json_object_new_object();
+ json_object_object_add(json, "supportedProtocols",
+ protocol_json);
+ for (uint8_t i = 0; i < p->count; i++) {
+ snprintfrr(buf, sizeof(buf), "%d", i);
+ json_object_string_add(protocol_json, buf,
+ nlpid2str(p->protocols[i]));
+ }
+ /* end old deprecated key format */
} else {
sbuf_push(buf, indent, "Protocols Supported: ");
for (uint8_t i = 0; i < p->count; i++) {
@@ -3635,9 +4272,13 @@ static void format_item_global_ipv6_address(uint16_t mtid, struct isis_item *i,
char addrbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &a->addr, addrbuf, sizeof(addrbuf));
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "global-ipv6", addrbuf);
- else
+ json_object_string_add(json, "globalIpv6", addrbuf);
+ } else
sbuf_push(buf, indent, "Global IPv6 Interface Address: %s\n",
addrbuf);
}
@@ -3705,12 +4346,30 @@ static void format_item_mt_router_info(uint16_t mtid, struct isis_item *i,
struct isis_mt_router_info *info = (struct isis_mt_router_info *)i;
if (json) {
- struct json_object *mt_json;
+ struct json_object *mt_json, *array_json;
mt_json = json_object_new_object();
- json_object_object_add(json, "mt", mt_json);
+ json_object_object_get_ex(json, "mt", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "mt", array_json);
+ }
+ json_object_array_add(array_json, mt_json);
json_object_int_add(mt_json, "mtid", info->mtid);
+ json_object_string_add(mt_json, "mt-description",
+ isis_mtid2str_fake(info->mtid));
+ json_object_string_add(mt_json, "mtDescription",
+ isis_mtid2str(mtid));
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated non boolean format")
+#endif
json_object_string_add(mt_json, "overload", info->overload?"true":"false");
json_object_string_add(mt_json, "attached", info->attached?"true":"false");
+
+ json_object_boolean_add(mt_json, "overloadBit",
+ !!info->overload);
+ json_object_boolean_add(mt_json, "attachedbit",
+ !!info->attached);
} else
sbuf_push(buf, indent, "MT Router Info: %s%s%s\n",
isis_mtid2str_fake(info->mtid),
@@ -3793,9 +4452,13 @@ static void format_tlv_te_router_id(const struct in_addr *id, struct sbuf *buf,
char addrbuf[INET_ADDRSTRLEN];
inet_ntop(AF_INET, id, addrbuf, sizeof(addrbuf));
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "te-router-id", addrbuf);
- else
+ json_object_string_add(json, "teRouterId", addrbuf);
+ } else
sbuf_push(buf, indent, "TE Router ID: %s\n", addrbuf);
}
@@ -3866,27 +4529,64 @@ static void format_item_extended_ip_reach(uint16_t mtid, struct isis_item *i,
struct json_object *json, int indent)
{
struct isis_extended_ip_reach *r = (struct isis_extended_ip_reach *)i;
+ struct json_object *ext_json, *array_json;
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
- struct json_object *ext_json;
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
ext_json = json_object_new_object();
- json_object_object_add(json, "ext-ip-reach", ext_json);
- json_object_string_add(
- json, "mt-id",
- (mtid == ISIS_MT_IPV4_UNICAST) ? "Extended" : "MT");
- json_object_string_add(
- json, "ip-reach",
- prefix2str(&r->prefix, prefixbuf, sizeof(prefixbuf)));
- json_object_int_add(json, "ip-reach-metric", r->metric);
- json_object_string_add(json, "down", r->down ? "yes" : "");
+ json_object_object_get_ex(json, "ext-ip-reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ext-ip-reach", array_json);
+ }
+ json_object_array_add(array_json, ext_json);
+ json_object_string_add(ext_json, "mt-id",
+ (mtid == ISIS_MT_IPV4_UNICAST)
+ ? "Extended"
+ : "MT");
+ json_object_string_add(ext_json, "ip-reach",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(ext_json, "ip-reach-metric", r->metric);
+ json_object_string_add(ext_json, "down", r->down ? "yes" : "");
if (mtid != ISIS_MT_IPV4_UNICAST)
- json_object_string_add(json, "mt-name",
+ json_object_string_add(ext_json, "mt-name",
isis_mtid2str(mtid));
if (r->subtlvs) {
struct json_object *subtlv_json;
subtlv_json = json_object_new_object();
- json_object_object_add(json, "subtlvs", subtlv_json);
+ json_object_object_add(ext_json, "subtlvs", subtlv_json);
+ format_subtlvs(r->subtlvs, NULL, subtlv_json, 0);
+ }
+ /* end old deprecated key format */
+
+ ext_json = json_object_new_object();
+ json_object_object_get_ex(json, "extIpReach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "extIpReach", array_json);
+ }
+ json_object_array_add(array_json, ext_json);
+ json_object_string_add(ext_json, "mtId",
+ (mtid == ISIS_MT_IPV4_UNICAST)
+ ? "Extended"
+ : "MT");
+ json_object_string_add(ext_json, "ipReach",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(ext_json, "ipReachMetric", r->metric);
+ json_object_boolean_add(ext_json, "down", !!r->down);
+ if (mtid != ISIS_MT_IPV4_UNICAST)
+ json_object_string_add(ext_json, "mtName",
+ isis_mtid2str(mtid));
+ if (r->subtlvs) {
+ struct json_object *subtlv_json;
+ subtlv_json = json_object_new_object();
+ json_object_object_add(ext_json, "subtlvs", subtlv_json);
format_subtlvs(r->subtlvs, NULL, subtlv_json, 0);
}
} else {
@@ -4146,9 +4846,13 @@ static void format_tlv_te_router_id_ipv6(const struct in6_addr *id,
char addrbuf[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, id, addrbuf, sizeof(addrbuf));
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "ipv6-te-router-id", addrbuf);
- else
+ json_object_string_add(json, "ipv6TeRouterId", addrbuf);
+ } else
sbuf_push(buf, indent, "IPv6 TE Router ID: %s\n", addrbuf);
}
@@ -4225,6 +4929,11 @@ static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
if (json) {
struct json_object *spine_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated format */
spine_json = json_object_new_object();
json_object_object_add(json, "spine-leaf-extension",
spine_json);
@@ -4243,6 +4952,25 @@ static void format_tlv_spine_leaf(const struct isis_spine_leaf *spine_leaf,
spine_leaf->is_spine ? "yes" : "");
json_object_string_add(spine_json, "flag-backup",
spine_leaf->is_backup ? "yes" : "");
+ /* end old deprecated format */
+
+ spine_json = json_object_new_object();
+ json_object_object_add(json, "spineLeafExtension", spine_json);
+ if (spine_leaf->has_tier) {
+ snprintfrr(aux_buf, sizeof(aux_buf), "%hhu",
+ spine_leaf->tier);
+ json_object_string_add(spine_json, "tier",
+ (spine_leaf->tier ==
+ ISIS_TIER_UNDEFINED)
+ ? "undefined"
+ : aux_buf);
+ }
+ json_object_boolean_add(spine_json, "flagLeaf",
+ spine_leaf->is_leaf ? true : false);
+ json_object_boolean_add(spine_json, "flagSpine",
+ spine_leaf->is_spine ? true : false);
+ json_object_boolean_add(spine_json, "flagBackup",
+ spine_leaf->is_backup ? true : false);
} else {
sbuf_push(buf, indent, "Spine-Leaf-Extension:\n");
if (spine_leaf->has_tier) {
@@ -4384,6 +5112,11 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
snprintfrr(sys_id, ISO_SYSID_STRLEN, "%pSY", threeway_adj->neighbor_id);
if (json) {
struct json_object *three_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
three_json = json_object_new_object();
json_object_object_add(json, "p2p-three-way-adj", three_json);
json_object_string_add(
@@ -4392,11 +5125,28 @@ format_tlv_threeway_adj(const struct isis_threeway_adj *threeway_adj,
json_object_int_add(three_json, "state", threeway_adj->state);
json_object_int_add(three_json, "ext-local-circuit-id",
threeway_adj->local_circuit_id);
- if (!threeway_adj->neighbor_set)
- return;
- json_object_string_add(three_json, "neigh-system-id", sys_id);
- json_object_int_add(three_json, "neigh-ext-circuit-id",
- threeway_adj->neighbor_circuit_id);
+ if (threeway_adj->neighbor_set) {
+ json_object_string_add(three_json, "neigh-system-id",
+ sys_id);
+ json_object_int_add(three_json, "neigh-ext-circuit-id",
+ threeway_adj->neighbor_circuit_id);
+ }
+ /* end old deprecated key format */
+
+ three_json = json_object_new_object();
+ json_object_object_add(json, "p2pThreeWayAdj", three_json);
+ json_object_string_add(three_json, "stateName",
+ isis_threeway_state_name(
+ threeway_adj->state));
+ json_object_int_add(three_json, "state", threeway_adj->state);
+ json_object_int_add(three_json, "extLocalCircuitId",
+ threeway_adj->local_circuit_id);
+ if (threeway_adj->neighbor_set) {
+ json_object_string_add(three_json, "neighSystemId",
+ sys_id);
+ json_object_int_add(three_json, "neighExtCircuitId",
+ threeway_adj->neighbor_circuit_id);
+ }
} else {
sbuf_push(buf, indent, "P2P Three-Way Adjacency:\n");
sbuf_push(buf, indent, " State: %s (%d)\n",
@@ -4500,9 +5250,51 @@ static void format_item_ipv6_reach(uint16_t mtid, struct isis_item *i,
char prefixbuf[PREFIX2STR_BUFFER];
if (json) {
- struct json_object *reach_json;
+ struct json_object *reach_json, *array_json;
+
+ reach_json = json_object_new_object();
+ json_object_object_get_ex(json, "ipv6Reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ipv6Reach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
+ json_object_string_add(reach_json, "mtId",
+ (mtid == ISIS_MT_IPV4_UNICAST) ? ""
+ : "mt");
+ json_object_string_add(reach_json, "prefix",
+ prefix2str(&r->prefix, prefixbuf,
+ sizeof(prefixbuf)));
+ json_object_int_add(reach_json, "metric", r->metric);
+ json_object_boolean_add(reach_json, "down",
+ r->down ? true : false);
+ json_object_boolean_add(reach_json, "external",
+ r->external ? true : false);
+ if (mtid != ISIS_MT_IPV4_UNICAST) {
+ json_object_string_add(reach_json, "mt-name",
+ isis_mtid2str(mtid));
+ json_object_string_add(reach_json, "mtName",
+ isis_mtid2str(mtid));
+ }
+ if (r->subtlvs) {
+ struct json_object *subtlvs_json;
+ subtlvs_json = json_object_new_object();
+ json_object_object_add(reach_json, "subtlvs",
+ subtlvs_json);
+ format_subtlvs(r->subtlvs, NULL, subtlvs_json, 0);
+ }
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated JSON key format */
reach_json = json_object_new_object();
- json_object_object_add(json, "ipv6-reach", reach_json);
+ json_object_object_get_ex(json, "ipv6-reach", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "ipv6-reach", array_json);
+ }
+ json_object_array_add(array_json, reach_json);
json_object_string_add(reach_json, "mt-id",
(mtid == ISIS_MT_IPV4_UNICAST) ? ""
: "mt");
@@ -4520,9 +5312,11 @@ static void format_item_ipv6_reach(uint16_t mtid, struct isis_item *i,
if (r->subtlvs) {
struct json_object *subtlvs_json;
subtlvs_json = json_object_new_object();
- json_object_object_add(json, "subtlvs", subtlvs_json);
+ json_object_object_add(reach_json, "subtlvs",
+ subtlvs_json);
format_subtlvs(r->subtlvs, NULL, subtlvs_json, 0);
}
+ /* end deprecated key format */
} else {
sbuf_push(buf, indent,
"%sIPv6 Reachability: %s (Metric: %u)%s%s",
@@ -4734,6 +5528,11 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
/* Router ID and Flags */
struct json_object *cap_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* deprecated JSON key format */
cap_json = json_object_new_object();
json_object_object_add(json, "router-capability", cap_json);
inet_ntop(AF_INET, &router_cap->router_id, addrbuf, sizeof(addrbuf));
@@ -4744,10 +5543,26 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
json_object_string_add(
cap_json, "flag-s",
router_cap->flags & ISIS_ROUTER_CAP_FLAG_S ? "1" : "0");
+ /* end deprecated JSON key format */
+
+ cap_json = json_object_new_object();
+ json_object_object_add(json, "routerCapability", cap_json);
+ inet_ntop(AF_INET, &router_cap->router_id, addrbuf, sizeof(addrbuf));
+ json_object_string_add(cap_json, "id", addrbuf);
+ json_object_boolean_add(cap_json, "flagD",
+ !!(router_cap->flags & ISIS_ROUTER_CAP_FLAG_D));
+ json_object_boolean_add(cap_json, "flagS",
+ !!(router_cap->flags & ISIS_ROUTER_CAP_FLAG_S));
+
/* Segment Routing Global Block as per RFC8667 section #3.1 */
if (router_cap->srgb.range_size != 0) {
struct json_object *gb_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* deprecated old key format */
gb_json = json_object_new_object();
json_object_object_add(json, "segment-routing-gb", gb_json);
json_object_string_add(gb_json, "ipv4",
@@ -4760,23 +5575,52 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
router_cap->srgb.lower_bound);
json_object_int_add(gb_json, "global-block-range",
router_cap->srgb.range_size);
+
+ gb_json = json_object_new_object();
+ json_object_object_add(json, "segmentRoutingGb", gb_json);
+ json_object_boolean_add(gb_json, "ipv4",
+ !!IS_SR_IPV4(&router_cap->srgb));
+ json_object_boolean_add(gb_json, "ipv6",
+ !!IS_SR_IPV6(&router_cap->srgb));
+ json_object_int_add(gb_json, "globalBlockBase",
+ router_cap->srgb.lower_bound);
+ json_object_int_add(gb_json, "globalBlockRange",
+ router_cap->srgb.range_size);
}
/* Segment Routing Local Block as per RFC8667 section #3.3 */
if (router_cap->srlb.range_size != 0) {
struct json_object *lb_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
lb_json = json_object_new_object();
json_object_object_add(json, "segment-routing-lb", lb_json);
json_object_int_add(lb_json, "global-block-base",
router_cap->srlb.lower_bound);
json_object_int_add(lb_json, "global-block-range",
router_cap->srlb.range_size);
+ /* end old deprecated key format */
+
+ lb_json = json_object_new_object();
+ json_object_object_add(json, "segmentRoutingLb", lb_json);
+ json_object_int_add(lb_json, "globalBlockBase",
+ router_cap->srlb.lower_bound);
+ json_object_int_add(lb_json, "globalBlockRange",
+ router_cap->srlb.range_size);
}
/* Segment Routing Algorithms as per RFC8667 section #3.2 */
if (router_cap->algo[0] != SR_ALGORITHM_UNSET) {
char buf[255];
struct json_object *alg_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
alg_json = json_object_new_object();
json_object_object_add(json, "segment-routing-algorithm",
alg_json);
@@ -4788,6 +5632,20 @@ static void format_tlv_router_cap_json(const struct isis_router_cap *router_cap,
? "SPF"
: "Strict SPF");
}
+ /* end old deprecated key format */
+
+ alg_json = json_object_new_object();
+ json_object_object_add(json, "segmentRoutingAlgorithm",
+ alg_json);
+ for (int i = 0; i < SR_ALGORITHM_COUNT; i++) {
+ if (router_cap->algo[i] != SR_ALGORITHM_UNSET) {
+ snprintfrr(buf, sizeof(buf), "%d", i);
+ json_object_string_add(alg_json, buf,
+ router_cap->algo[i] == 0
+ ? "SPF"
+ : "Strict SPF");
+ }
+ }
}
/* Segment Routing Node MSD as per RFC8491 section #2 */
@@ -5631,16 +6489,24 @@ static void format_item_auth(uint16_t mtid, struct isis_item *i,
struct isis_auth *auth = (struct isis_auth *)i;
char obuf[768];
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "test-auth", "ok");
- else
+ json_object_string_add(json, "testAuth", "ok");
+ } else
sbuf_push(buf, indent, "Authentication:\n");
switch (auth->type) {
case ISIS_PASSWD_TYPE_CLEARTXT:
zlog_sanitize(obuf, sizeof(obuf), auth->value, auth->length);
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "auth-pass", obuf);
- else
+ json_object_string_add(json, "authPass", obuf);
+ } else
sbuf_push(buf, indent, " Password: %s\n", obuf);
break;
case ISIS_PASSWD_TYPE_HMAC_MD5:
@@ -5648,15 +6514,23 @@ static void format_item_auth(uint16_t mtid, struct isis_item *i,
snprintf(obuf + 2 * j, sizeof(obuf) - 2 * j, "%02hhx",
auth->value[j]);
}
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "auth-hmac-md5", obuf);
- else
+ json_object_string_add(json, "authHmacMd5", obuf);
+ } else
sbuf_push(buf, indent, " HMAC-MD5: %s\n", obuf);
break;
default:
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_int_add(json, "auth-unknown", auth->type);
- else
+ json_object_int_add(json, "authUnknown", auth->type);
+ } else
sbuf_push(buf, indent, " Unknown (%hhu)\n",
auth->type);
break;
@@ -5771,12 +6645,25 @@ static void format_tlv_purge_originator(struct isis_purge_originator *poi,
if (json) {
struct json_object *purge_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old deprecated key format */
purge_json = json_object_new_object();
json_object_object_add(json, "purge_originator", purge_json);
json_object_string_add(purge_json, "id", gen_id);
if (poi->sender_set)
json_object_string_add(purge_json, "rec-from", sen_id);
+ /* end old deprecated key format */
+
+ purge_json = json_object_new_object();
+ json_object_object_add(json, "purgeOriginator", purge_json);
+
+ json_object_string_add(purge_json, "id", gen_id);
+ if (poi->sender_set)
+ json_object_string_add(purge_json, "recFrom", sen_id);
} else {
sbuf_push(buf, indent, "Purge Originator Identification:\n");
sbuf_push(buf, indent, " Generator: %s\n", gen_id);
@@ -6319,6 +7206,11 @@ static void format_item_srv6_locator(uint16_t mtid, struct isis_item *i,
if (json) {
struct json_object *loc_json;
+
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
+ /* old json key format */
loc_json = json_object_new_object();
json_object_object_add(json, "srv6-locator", loc_json);
json_object_int_add(loc_json, "mt-id", mtid);
@@ -6340,6 +7232,26 @@ static void format_item_srv6_locator(uint16_t mtid, struct isis_item *i,
subtlvs_json);
format_subtlvs(loc->subtlvs, NULL, subtlvs_json, 0);
}
+ /* old deprecated key format */
+
+ loc_json = json_object_new_object();
+ json_object_object_add(json, "srv6Locator", loc_json);
+ json_object_int_add(loc_json, "mtId", mtid);
+ json_object_string_addf(loc_json, "prefix", "%pFX",
+ &loc->prefix);
+ json_object_int_add(loc_json, "metric", loc->metric);
+ json_object_boolean_add(loc_json, "flagD",
+ !!CHECK_FLAG(loc->flags,
+ ISIS_TLV_SRV6_LOCATOR_FLAG_D));
+ json_object_int_add(loc_json, "algorithm", loc->algorithm);
+ json_object_string_add(loc_json, "MTName", isis_mtid2str(mtid));
+ if (loc->subtlvs) {
+ struct json_object *subtlvs_json;
+ subtlvs_json = json_object_new_object();
+ json_object_object_add(loc_json, "subtlvs",
+ subtlvs_json);
+ format_subtlvs(loc->subtlvs, NULL, subtlvs_json, 0);
+ }
} else {
sbuf_push(buf, indent, "SRv6 Locator: %pFX (Metric: %u)%s",
&loc->prefix, loc->metric,
@@ -6623,9 +7535,13 @@ static void format_tlvs(struct isis_tlvs *tlvs, struct sbuf *buf, struct json_ob
&tlvs->area_addresses, buf, json, indent);
if (tlvs->mt_router_info_empty) {
- if (json)
+ if (json) {
+#if CONFDATE > 20240916
+ CPP_NOTICE("remove deprecated key format with -")
+#endif
json_object_string_add(json, "mt-router-info", "none");
- else
+ json_object_object_add(json, "mtRouterInfo", NULL);
+ } else
sbuf_push(buf, indent, "MT Router Info: None\n");
} else {
format_items(ISIS_CONTEXT_LSP, ISIS_TLV_MT_ROUTER_INFO,
diff --git a/isisd/isis_zebra.c b/isisd/isis_zebra.c
index 18a0c49..2412ec5 100644
--- a/isisd/isis_zebra.c
+++ b/isisd/isis_zebra.c
@@ -454,7 +454,7 @@ void isis_zebra_send_adjacency_sid(int cmd, const struct sr_adjacency *sra)
znh->labels[0] = MPLS_LABEL_IMPLICIT_NULL;
/* Set backup nexthops. */
- if (sra->type == ISIS_SR_LAN_BACKUP) {
+ if (sra->type == ISIS_SR_ADJ_BACKUP) {
int count;
count = isis_zebra_add_nexthops(isis, sra->backup_nexthops,
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 772eb97..982df08 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -988,63 +988,17 @@ int show_isis_interface_common_json(struct json_object *json,
"no");
return CMD_SUCCESS;
}
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
- areas_json = json_object_new_array();
- json_object_object_add(json, "areas",
- areas_json);
- for (ALL_LIST_ELEMENTS_RO(isis->area_list,
- anode, area)) {
- area_json = json_object_new_object();
- json_object_string_add(
- area_json, "area",
- area->area_tag ? area->area_tag
- : "null");
- circuits_json = json_object_new_array();
- json_object_object_add(area_json,
- "circuits",
- circuits_json);
- for (ALL_LIST_ELEMENTS_RO(
- area->circuit_list, cnode,
- circuit)) {
- circuit_json =
- json_object_new_object();
- json_object_int_add(
- circuit_json, "circuit",
- circuit->circuit_id);
- if (!ifname)
- isis_circuit_print_json(
- circuit,
- circuit_json,
- detail);
- else if (strcmp(circuit->interface->name, ifname) == 0)
- isis_circuit_print_json(
- circuit,
- circuit_json,
- detail);
- json_object_array_add(
- circuits_json,
- circuit_json);
- }
- json_object_array_add(areas_json,
- area_json);
- }
- }
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL) {
+
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
areas_json = json_object_new_array();
json_object_object_add(json, "areas", areas_json);
- for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode,
- area)) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
area_json = json_object_new_object();
json_object_string_add(area_json, "area",
area->area_tag
? area->area_tag
: "null");
-
circuits_json = json_object_new_array();
json_object_object_add(area_json, "circuits",
circuits_json);
@@ -1055,22 +1009,56 @@ int show_isis_interface_common_json(struct json_object *json,
circuit_json, "circuit",
circuit->circuit_id);
if (!ifname)
- isis_circuit_print_json(
- circuit, circuit_json,
- detail);
- else if (
- strcmp(circuit->interface->name,
- ifname) == 0)
- isis_circuit_print_json(
- circuit, circuit_json,
- detail);
+ isis_circuit_print_json(circuit,
+ circuit_json,
+ detail);
+ else if (strcmp(circuit->interface->name,
+ ifname) == 0)
+ isis_circuit_print_json(circuit,
+ circuit_json,
+ detail);
json_object_array_add(circuits_json,
circuit_json);
}
json_object_array_add(areas_json, area_json);
}
}
+ return CMD_SUCCESS;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL) {
+ areas_json = json_object_new_array();
+ json_object_object_add(json, "areas", areas_json);
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
+ area_json = json_object_new_object();
+ json_object_string_add(area_json, "area",
+ area->area_tag ? area->area_tag
+ : "null");
+
+ circuits_json = json_object_new_array();
+ json_object_object_add(area_json, "circuits",
+ circuits_json);
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode,
+ circuit)) {
+ circuit_json = json_object_new_object();
+ json_object_int_add(circuit_json, "circuit",
+ circuit->circuit_id);
+ if (!ifname)
+ isis_circuit_print_json(circuit,
+ circuit_json,
+ detail);
+ else if (strcmp(circuit->interface->name,
+ ifname) == 0)
+ isis_circuit_print_json(circuit,
+ circuit_json,
+ detail);
+ json_object_array_add(circuits_json,
+ circuit_json);
+ }
+ json_object_array_add(areas_json, area_json);
+ }
}
+
return CMD_SUCCESS;
}
@@ -1087,37 +1075,10 @@ int show_isis_interface_common_vty(struct vty *vty, const char *ifname,
vty_out(vty, "IS-IS Routing Process not enabled\n");
return CMD_SUCCESS;
}
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
- for (ALL_LIST_ELEMENTS_RO(isis->area_list,
- anode, area)) {
- vty_out(vty, "Area %s:\n",
- area->area_tag);
- if (detail == ISIS_UI_LEVEL_BRIEF)
- vty_out(vty,
- " Interface CircId State Type Level\n");
-
- for (ALL_LIST_ELEMENTS_RO(
- area->circuit_list, cnode,
- circuit))
- if (!ifname)
- isis_circuit_print_vty(
- circuit, vty,
- detail);
- else if (strcmp(circuit->interface->name, ifname) == 0)
- isis_circuit_print_vty(
- circuit, vty,
- detail);
- }
- }
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL) {
- for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode,
- area)) {
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, inode, isis)) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
vty_out(vty, "Area %s:\n", area->area_tag);
if (detail == ISIS_UI_LEVEL_BRIEF)
@@ -1127,15 +1088,37 @@ int show_isis_interface_common_vty(struct vty *vty, const char *ifname,
for (ALL_LIST_ELEMENTS_RO(area->circuit_list,
cnode, circuit))
if (!ifname)
- isis_circuit_print_vty(
- circuit, vty, detail);
- else if (
- strcmp(circuit->interface->name,
- ifname) == 0)
- isis_circuit_print_vty(
- circuit, vty, detail);
+ isis_circuit_print_vty(circuit,
+ vty,
+ detail);
+ else if (strcmp(circuit->interface->name,
+ ifname) == 0)
+ isis_circuit_print_vty(circuit,
+ vty,
+ detail);
}
}
+ return CMD_SUCCESS;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL) {
+ for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
+ vty_out(vty, "Area %s:\n", area->area_tag);
+
+ if (detail == ISIS_UI_LEVEL_BRIEF)
+ vty_out(vty,
+ " Interface CircId State Type Level\n");
+
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode,
+ circuit))
+ if (!ifname)
+ isis_circuit_print_vty(circuit, vty,
+ detail);
+ else if (strcmp(circuit->interface->name,
+ ifname) == 0)
+ isis_circuit_print_vty(circuit, vty,
+ detail);
+ }
}
return CMD_SUCCESS;
@@ -1318,7 +1301,7 @@ static void isis_neighbor_common_vty(struct vty *vty, const char *id,
if (detail == ISIS_UI_LEVEL_BRIEF)
vty_out(vty,
- " System Id Interface L State Holdtime SNPA\n");
+ " System Id Interface L State Holdtime SNPA\n");
for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit)) {
if (circuit->circ_type == CIRCUIT_T_BROADCAST) {
@@ -1376,28 +1359,23 @@ int show_isis_neighbor_common(struct vty *vty, struct json_object *json,
return CMD_SUCCESS;
}
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
- if (id_to_sysid(isis, id, sysid)) {
- vty_out(vty, "Invalid system id %s\n",
- id);
- return CMD_SUCCESS;
- }
- isis_neighbor_common(vty, json, id, detail,
- isis, sysid);
- }
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL) {
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
if (id_to_sysid(isis, id, sysid)) {
vty_out(vty, "Invalid system id %s\n", id);
return CMD_SUCCESS;
}
- isis_neighbor_common(vty, json, id, detail, isis,
- sysid);
+ isis_neighbor_common(vty, json, id, detail, isis, sysid);
+ }
+ return CMD_SUCCESS;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL) {
+ if (id_to_sysid(isis, id, sysid)) {
+ vty_out(vty, "Invalid system id %s\n", id);
+ return CMD_SUCCESS;
}
+ isis_neighbor_common(vty, json, id, detail, isis, sysid);
}
return CMD_SUCCESS;
@@ -1461,27 +1439,23 @@ int clear_isis_neighbor_common(struct vty *vty, const char *id, const char *vrf_
return CMD_SUCCESS;
}
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
- if (id_to_sysid(isis, id, sysid)) {
- vty_out(vty, "Invalid system id %s\n",
- id);
- return CMD_SUCCESS;
- }
- isis_neighbor_common_clear(vty, id, sysid,
- isis);
- }
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL) {
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis)) {
if (id_to_sysid(isis, id, sysid)) {
vty_out(vty, "Invalid system id %s\n", id);
return CMD_SUCCESS;
}
isis_neighbor_common_clear(vty, id, sysid, isis);
}
+ return CMD_SUCCESS;
+ }
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL) {
+ if (id_to_sysid(isis, id, sysid)) {
+ vty_out(vty, "Invalid system id %s\n", id);
+ return CMD_SUCCESS;
+ }
+ isis_neighbor_common_clear(vty, id, sysid, isis);
}
return CMD_SUCCESS;
@@ -2234,17 +2208,16 @@ DEFUN (show_hostname,
struct isis *isis;
ISIS_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- dynhn_print_all(vty, isis);
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL)
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
dynhn_print_all(vty, isis);
+
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL)
+ dynhn_print_all(vty, isis);
return CMD_SUCCESS;
}
@@ -2307,17 +2280,15 @@ DEFUN(show_isis_spf_ietf, show_isis_spf_ietf_cmd,
return CMD_SUCCESS;
}
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- isis_spf_ietf_common(vty, isis);
-
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL)
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
isis_spf_ietf_common(vty, isis);
+
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL)
+ isis_spf_ietf_common(vty, isis);
return CMD_SUCCESS;
}
@@ -2596,17 +2567,16 @@ DEFUN(show_isis_summary, show_isis_summary_cmd,
}
if (uj)
json = json_object_new_object();
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- common_isis_summary(vty, json, isis);
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis != NULL)
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
common_isis_summary(vty, json, isis);
+
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis != NULL)
+ common_isis_summary(vty, json, isis);
if (uj)
vty_json(vty, json);
@@ -2679,8 +2649,10 @@ void show_isis_database_lspdb_json(struct json_object *json,
struct lspdb_head *lspdb,
const char *sysid_str, int ui_level)
{
+ struct json_object *array_json, *lsp_json;
struct isis_lsp *lsp;
int lsp_count;
+ struct json_object *lsp_arr_json;
if (lspdb_count(lspdb) > 0) {
lsp = lsp_for_sysid(lspdb, sysid_str, area->isis);
@@ -2690,16 +2662,27 @@ void show_isis_database_lspdb_json(struct json_object *json,
}
if (lsp) {
+ json_object_object_get_ex(json, "lsps", &array_json);
+ if (!array_json) {
+ array_json = json_object_new_array();
+ json_object_object_add(json, "lsps", array_json);
+ }
+ lsp_json = json_object_new_object();
+ json_object_array_add(array_json, lsp_json);
+
if (ui_level == ISIS_UI_LEVEL_DETAIL)
- lsp_print_detail(lsp, NULL, json,
+ lsp_print_detail(lsp, NULL, lsp_json,
area->dynhostname, area->isis);
else
- lsp_print_json(lsp, json, area->dynhostname,
+ lsp_print_json(lsp, lsp_json, area->dynhostname,
area->isis);
} else if (sysid_str == NULL) {
- lsp_count =
- lsp_print_all(NULL, json, lspdb, ui_level,
- area->dynhostname, area->isis);
+ lsp_arr_json = json_object_new_array();
+ json_object_object_add(json, "lsps", lsp_arr_json);
+
+ lsp_count = lsp_print_all(NULL, lsp_arr_json, lspdb,
+ ui_level, area->dynhostname,
+ area->isis);
json_object_int_add(json, "count", lsp_count);
}
@@ -2765,6 +2748,8 @@ static void show_isis_database_json(struct json_object *json, const char *sysid_
json_object_object_add(area_json,"area",tag_area_json);
json_object_object_add(area_json,"levels",arr_json);
for (level = 0; level < ISIS_LEVELS; level++) {
+ if (lspdb_count(&area->lspdb[level]) == 0)
+ continue;
lsp_json = json_object_new_object();
show_isis_database_lspdb_json(lsp_json, area, level,
&area->lspdb[level],
@@ -2828,19 +2813,16 @@ static int show_isis_database(struct vty *vty, struct json_object *json, const c
struct listnode *node;
struct isis *isis;
- if (vrf_name) {
- if (all_vrf) {
- for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
- show_isis_database_common(vty, json, sysid_str,
- ui_level, isis);
-
- return CMD_SUCCESS;
- }
- isis = isis_lookup_by_vrfname(vrf_name);
- if (isis)
+ if (all_vrf) {
+ for (ALL_LIST_ELEMENTS_RO(im->isis, node, isis))
show_isis_database_common(vty, json, sysid_str,
ui_level, isis);
+
+ return CMD_SUCCESS;
}
+ isis = isis_lookup_by_vrfname(vrf_name);
+ if (isis)
+ show_isis_database_common(vty, json, sysid_str, ui_level, isis);
return CMD_SUCCESS;
}
diff --git a/ldpd/lde.c b/ldpd/lde.c
index ef4aeca..876dd41 100644
--- a/ldpd/lde.c
+++ b/ldpd/lde.c
@@ -28,6 +28,7 @@
#include "stream.h"
#include "network.h"
#include "libfrr.h"
+#include "zlog_live.h"
static void lde_shutdown(void);
static void lde_dispatch_imsg(struct event *thread);
@@ -116,6 +117,8 @@ static struct frr_signal_t lde_signals[] =
void
lde(void)
{
+ static struct zlog_live_cfg child_log;
+
#ifdef HAVE_SETPROCTITLE
setproctitle("label decision engine");
#endif
@@ -123,6 +126,8 @@ lde(void)
log_procname = log_procnames[PROC_LDE_ENGINE];
master = frr_init();
+ zlog_live_open_fd(&child_log, LOG_DEBUG, LDPD_FD_LOG);
+
/* no frr_config_fork() here, allow frr_pthread to create threads */
frr_is_after_fork = true;
diff --git a/ldpd/ldpd.c b/ldpd/ldpd.c
index da29a4f..4d38fdc 100644
--- a/ldpd/ldpd.c
+++ b/ldpd/ldpd.c
@@ -35,9 +35,11 @@
#include "qobj.h"
#include "libfrr.h"
#include "lib_errors.h"
+#include "zlog_recirculate.h"
+#include "libagentx.h"
static void ldpd_shutdown(void);
-static pid_t start_child(enum ldpd_process, char *, int, int);
+static pid_t start_child(enum ldpd_process, char *, int, int, int);
static void main_dispatch_ldpe(struct event *thread);
static void main_dispatch_lde(struct event *thread);
static int main_imsg_send_ipc_sockets(struct imsgbuf *,
@@ -69,6 +71,8 @@ DEFINE_QOBJ_TYPE(l2vpn_pw);
DEFINE_QOBJ_TYPE(l2vpn);
DEFINE_QOBJ_TYPE(ldpd_conf);
+const char *log_procname;
+
struct ldpd_global global;
struct ldpd_init init;
struct ldpd_conf *ldpd_conf, *vty_conf;
@@ -231,8 +235,12 @@ main(int argc, char *argv[])
{
char *saved_argv0;
int lflag = 0, eflag = 0;
- int pipe_parent2ldpe[2], pipe_parent2ldpe_sync[2];
- int pipe_parent2lde[2], pipe_parent2lde_sync[2];
+ int pipe_parent2ldpe[2];
+ int pipe_parent2ldpe_sync[2];
+ int pipe_ldpe_log[2];
+ int pipe_parent2lde[2];
+ int pipe_parent2lde_sync[2];
+ int pipe_lde_log[2];
bool ctl_sock_used = false;
ldpd_process = PROC_MAIN;
@@ -300,15 +308,6 @@ main(int argc, char *argv[])
exit(1);
}
- if (lflag || eflag) {
- struct zprivs_ids_t ids;
-
- zprivs_preinit(&ldpd_privs);
- zprivs_get_ids(&ids);
-
- zlog_init(ldpd_di.progname, "LDP", 0,
- ids.uid_normal, ids.gid_normal);
- }
if (lflag)
lde();
else if (eflag)
@@ -321,6 +320,9 @@ main(int argc, char *argv[])
pipe_parent2ldpe_sync) == -1)
fatal("socketpair");
+ if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, pipe_ldpe_log) == -1)
+ fatal("socketpair");
+
if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, pipe_parent2lde) == -1)
fatal("socketpair");
@@ -328,6 +330,9 @@ main(int argc, char *argv[])
pipe_parent2lde_sync) == -1)
fatal("socketpair");
+ if (socketpair(AF_UNIX, SOCK_DGRAM, PF_UNSPEC, pipe_lde_log) == -1)
+ fatal("socketpair");
+
sock_set_nonblock(pipe_parent2ldpe[0]);
sock_set_cloexec(pipe_parent2ldpe[0]);
sock_set_nonblock(pipe_parent2ldpe[1]);
@@ -335,6 +340,11 @@ main(int argc, char *argv[])
sock_set_nonblock(pipe_parent2ldpe_sync[0]);
sock_set_cloexec(pipe_parent2ldpe_sync[0]);
sock_set_cloexec(pipe_parent2ldpe_sync[1]);
+ sock_set_nonblock(pipe_ldpe_log[0]);
+ sock_set_cloexec(pipe_ldpe_log[0]);
+ sock_set_nonblock(pipe_ldpe_log[1]);
+ sock_set_cloexec(pipe_ldpe_log[1]);
+
sock_set_nonblock(pipe_parent2lde[0]);
sock_set_cloexec(pipe_parent2lde[0]);
sock_set_nonblock(pipe_parent2lde[1]);
@@ -342,15 +352,26 @@ main(int argc, char *argv[])
sock_set_nonblock(pipe_parent2lde_sync[0]);
sock_set_cloexec(pipe_parent2lde_sync[0]);
sock_set_cloexec(pipe_parent2lde_sync[1]);
+ sock_set_nonblock(pipe_lde_log[0]);
+ sock_set_cloexec(pipe_lde_log[0]);
+ sock_set_nonblock(pipe_lde_log[1]);
+ sock_set_cloexec(pipe_lde_log[1]);
/* start children */
lde_pid = start_child(PROC_LDE_ENGINE, saved_argv0,
- pipe_parent2lde[1], pipe_parent2lde_sync[1]);
+ pipe_parent2lde[1], pipe_parent2lde_sync[1], pipe_lde_log[1]);
ldpe_pid = start_child(PROC_LDP_ENGINE, saved_argv0,
- pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1]);
+ pipe_parent2ldpe[1], pipe_parent2ldpe_sync[1], pipe_ldpe_log[1]);
master = frr_init();
+ /* The two child processes use the zlog_live backend to send their
+ * messages here, where the actual logging config is then applied.
+ * Look for zlog_live_open_fd() to find the other end of this.
+ */
+ zlog_recirculate_subscribe(master, pipe_lde_log[0]);
+ zlog_recirculate_subscribe(master, pipe_ldpe_log[0]);
+ libagentx_init();
vrf_init(NULL, NULL, NULL, NULL);
access_list_init();
ldp_vty_init();
@@ -484,7 +505,8 @@ ldpd_shutdown(void)
}
static pid_t
-start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync)
+start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync,
+ int fd_log)
{
char *argv[7];
int argc = 0, nullfd;
@@ -499,6 +521,7 @@ start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync)
default:
close(fd_async);
close(fd_sync);
+ close(fd_log);
return (pid);
}
@@ -520,6 +543,9 @@ start_child(enum ldpd_process p, char *argv0, int fd_async, int fd_sync)
if (dup2(fd_sync, LDPD_FD_SYNC) == -1)
fatal("cannot setup imsg sync fd");
+ if (dup2(fd_log, LDPD_FD_LOG) == -1)
+ fatal("cannot setup zlog fd");
+
argv[argc++] = argv0;
switch (p) {
case PROC_MAIN:
@@ -569,9 +595,6 @@ static void main_dispatch_ldpe(struct event *thread)
break;
switch (imsg.hdr.type) {
- case IMSG_LOG:
- logit(imsg.hdr.pid, "%s", (const char *)imsg.data);
- break;
case IMSG_REQUEST_SOCKETS:
af = imsg.hdr.pid;
main_imsg_send_net_sockets(af);
@@ -637,9 +660,6 @@ static void main_dispatch_lde(struct event *thread)
break;
switch (imsg.hdr.type) {
- case IMSG_LOG:
- logit(imsg.hdr.pid, "%s", (const char *)imsg.data);
- break;
case IMSG_KLABEL_CHANGE:
if (imsg.hdr.len - IMSG_HEADER_SIZE !=
sizeof(struct kroute))
diff --git a/ldpd/ldpd.h b/ldpd/ldpd.h
index 81c6ba3..ad831a6 100644
--- a/ldpd/ldpd.h
+++ b/ldpd/ldpd.h
@@ -30,6 +30,7 @@
#define LDPD_FD_ASYNC 3
#define LDPD_FD_SYNC 4
+#define LDPD_FD_LOG 5
#define LDPD_OPT_VERBOSE 0x00000001
#define LDPD_OPT_VERBOSE2 0x00000002
@@ -139,7 +140,6 @@ enum imsg_type {
IMSG_RECONF_L2VPN_IPW,
IMSG_RECONF_END,
IMSG_DEBUG_UPDATE,
- IMSG_LOG,
IMSG_ACL_CHECK,
IMSG_INIT,
IMSG_PW_UPDATE,
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index e66b9e9..6e844c0 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -23,6 +23,7 @@
#include "privs.h"
#include "sigevent.h"
#include "libfrr.h"
+#include "zlog_live.h"
static void ldpe_shutdown(void);
static void ldpe_dispatch_main(struct event *thread);
@@ -93,6 +94,8 @@ char *pkt_ptr; /* packet buffer */
void
ldpe(void)
{
+ static struct zlog_live_cfg child_log;
+
#ifdef HAVE_SETPROCTITLE
setproctitle("ldp engine");
#endif
@@ -100,6 +103,8 @@ ldpe(void)
log_procname = log_procnames[ldpd_process];
master = frr_init();
+ zlog_live_open_fd(&child_log, LOG_DEBUG, LDPD_FD_LOG);
+
/* no frr_config_fork() here, allow frr_pthread to create threads */
frr_is_after_fork = true;
diff --git a/ldpd/log.c b/ldpd/log.c
deleted file mode 100644
index 7c4d782..0000000
--- a/ldpd/log.c
+++ /dev/null
@@ -1,138 +0,0 @@
-// SPDX-License-Identifier: ISC
-/* $OpenBSD$ */
-
-/*
- * Copyright (c) 2003, 2004 Henning Brauer <henning@openbsd.org>
- */
-
-#include <zebra.h>
-
-#include "ldpd.h"
-#include "ldpe.h"
-#include "lde.h"
-#include "log.h"
-#include "printfrr.h"
-
-#include <lib/log.h>
-
-const char *log_procname;
-
-void
-logit(int pri, const char *fmt, ...)
-{
- va_list ap;
-
- va_start(ap, fmt);
- vlog(pri, fmt, ap);
- va_end(ap);
-}
-
-void
-vlog(int pri, const char *fmt, va_list ap)
-{
- char buf[1024];
-
- switch (ldpd_process) {
- case PROC_LDE_ENGINE:
- vsnprintfrr(buf, sizeof(buf), fmt, ap);
- lde_imsg_compose_parent_sync(IMSG_LOG, pri, buf, strlen(buf) + 1);
- break;
- case PROC_LDP_ENGINE:
- vsnprintfrr(buf, sizeof(buf), fmt, ap);
- ldpe_imsg_compose_parent_sync(IMSG_LOG, pri, buf, strlen(buf) + 1);
- break;
- case PROC_MAIN:
- vzlog(pri, fmt, ap);
- break;
- }
-}
-
-void
-log_warn(const char *emsg, ...)
-{
- char *nfmt;
- va_list ap;
-
- /* best effort to even work in out of memory situations */
- if (emsg == NULL)
- logit(LOG_ERR, "%s", strerror(errno));
- else {
- va_start(ap, emsg);
-
- if (asprintf(&nfmt, "%s: %s", emsg, strerror(errno)) == -1) {
- /* we tried it... */
- vlog(LOG_ERR, emsg, ap);
- logit(LOG_ERR, "%s", strerror(errno));
- } else {
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wformat-nonliteral"
- /* format extended above */
- vlog(LOG_ERR, nfmt, ap);
-#pragma GCC diagnostic pop
- free(nfmt);
- }
- va_end(ap);
- }
-}
-
-void
-log_warnx(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_ERR, emsg, ap);
- va_end(ap);
-}
-
-void
-log_info(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_INFO, emsg, ap);
- va_end(ap);
-}
-
-void
-log_notice(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_NOTICE, emsg, ap);
- va_end(ap);
-}
-
-void
-log_debug(const char *emsg, ...)
-{
- va_list ap;
-
- va_start(ap, emsg);
- vlog(LOG_DEBUG, emsg, ap);
- va_end(ap);
-}
-
-void
-fatal(const char *emsg)
-{
- if (emsg == NULL)
- logit(LOG_CRIT, "fatal in %s: %s", log_procname, strerror(errno));
- else
- if (errno)
- logit(LOG_CRIT, "fatal in %s: %s: %s",
- log_procname, emsg, strerror(errno));
- else
- logit(LOG_CRIT, "fatal in %s: %s", log_procname, emsg);
-
- exit(1);
-}
-
-void
-fatalx(const char *emsg)
-{
- errno = 0;
- fatal(emsg);
-}
diff --git a/ldpd/log.h b/ldpd/log.h
index 641ad8a..aa6f700 100644
--- a/ldpd/log.h
+++ b/ldpd/log.h
@@ -8,29 +8,30 @@
#ifndef LOG_H
#define LOG_H
-#include <stdarg.h>
+#include "log.h"
+#include "assert.h"
extern const char *log_procname;
-void logit(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
-void vlog(int, const char *, va_list)
- __attribute__((__format__ (printf, 2, 0)));
-void log_warn(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_warnx(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_info(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_notice(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void log_debug(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
-void fatal(const char *)
- __attribute__ ((noreturn))
- __attribute__((__format__ (printf, 1, 0)));
-void fatalx(const char *)
- __attribute__ ((noreturn))
- __attribute__((__format__ (printf, 1, 0)));
+#define log_warnx zlog_err /* yes this is poorly named */
+#define log_warn zlog_warn
+#define log_info zlog_info
+#define log_notice zlog_notice /* not used anywhere */
+#define log_debug zlog_debug
+
+#define fatal(msg) \
+ do { \
+ assertf(0, "fatal in %s: %pSQq (%m)", log_procname, \
+ (const char *)msg); \
+ __builtin_unreachable(); \
+ } while (0) \
+ /* end */
+#define fatalx(msg) \
+ do { \
+ assertf(0, "fatal in %s: %pSQq", log_procname, \
+ (const char *)msg); \
+ __builtin_unreachable(); \
+ } while (0) \
+ /* end */
#endif /* LOG_H */
diff --git a/ldpd/neighbor.c b/ldpd/neighbor.c
index d40728b..2596c79 100644
--- a/ldpd/neighbor.c
+++ b/ldpd/neighbor.c
@@ -681,6 +681,18 @@ nbr_gtsm_setup(int fd, int af, struct nbr_params *nbrp)
if (nbrp && CHECK_FLAG(nbrp->flags, F_NBRP_GTSM_HOPS))
ttl = 256 - nbrp->gtsm_hops;
+ /*
+ * In linux networking stack, the received mpls packets
+ * will be processed by the host twice, one as mpls packet,
+ * the other as ip packet, so its ttl will be decreased 1.
+ * This behavior is based on the new kernel (5.10 and 6.1),
+ * and older versions may behave differently.
+ *
+ * Here, decrease 1 for IP_MINTTL if GTSM is enabled.
+ * And this workaround makes the GTSM mechanism a bit deviation.
+ */
+ ttl -= 1;
+
switch (af) {
case AF_INET:
if (sock_set_ipv4_minttl(fd, ttl) == -1)
diff --git a/ldpd/subdir.am b/ldpd/subdir.am
index 0b948ad..ad5933f 100644
--- a/ldpd/subdir.am
+++ b/ldpd/subdir.am
@@ -28,7 +28,6 @@ ldpd_libldp_a_SOURCES = \
ldpd/ldp_vty_exec.c \
ldpd/ldp_zebra.c \
ldpd/ldpe.c \
- ldpd/log.c \
ldpd/logmsg.c \
ldpd/neighbor.c \
ldpd/notification.c \
diff --git a/lib/affinitymap.c b/lib/affinitymap.c
index e53d54a..6ff8e83 100644
--- a/lib/affinitymap.c
+++ b/lib/affinitymap.c
@@ -41,8 +41,6 @@
#include "jhash.h"
DEFINE_MTYPE_STATIC(LIB, AFFINITY_MAP, "Affinity map");
-DEFINE_MTYPE(LIB, AFFINITY_MAP_NAME, "Affinity map name");
-DEFINE_MTYPE_STATIC(LIB, AFFINITY_MAP_INDEX, "Affinity map index");
DEFINE_QOBJ_TYPE(affinity_maps);
DEFINE_QOBJ_TYPE(affinity_map);
diff --git a/lib/agentx.c b/lib/agentx.c
index 70ee675..19f2a6b 100644
--- a/lib/agentx.c
+++ b/lib/agentx.c
@@ -22,12 +22,13 @@
#include "hook.h"
#include "libfrr.h"
#include "xref.h"
+#include "lib/libagentx.h"
XREF_SETUP();
DEFINE_HOOK(agentx_enabled, (), ());
-static bool agentx_enabled = false;
+//bool agentx_enabled = false;
static struct event_loop *agentx_tm;
static struct event *timeout_thr = NULL;
@@ -153,15 +154,6 @@ static void agentx_events_update(void)
netsnmp_large_fd_set_cleanup(&lfds);
}
-/* AgentX node. */
-static int config_write_agentx(struct vty *vty);
-static struct cmd_node agentx_node = {
- .name = "smux",
- .node = SMUX_NODE,
- .prompt = "",
- .config_write = config_write_agentx,
-};
-
/* Logging NetSNMP messages */
static int agentx_log_callback(int major, int minor, void *serverarg,
void *clientarg)
@@ -201,17 +193,7 @@ static int agentx_log_callback(int major, int minor, void *serverarg,
return SNMP_ERR_NOERROR;
}
-static int config_write_agentx(struct vty *vty)
-{
- if (agentx_enabled)
- vty_out(vty, "agentx\n");
- return 1;
-}
-
-DEFUN (agentx_enable,
- agentx_enable_cmd,
- "agentx",
- "SNMP AgentX protocol settings\n")
+static int agentx_cli_on(void)
{
if (!agentx_enabled) {
init_snmp(FRR_SMUX_NAME);
@@ -221,19 +203,14 @@ DEFUN (agentx_enable,
hook_call(agentx_enabled);
}
- return CMD_SUCCESS;
+ return 1;
}
-DEFUN (no_agentx,
- no_agentx_cmd,
- "no agentx",
- NO_STR
- "SNMP AgentX protocol settings\n")
+static int agentx_cli_off(void)
{
if (!agentx_enabled)
- return CMD_SUCCESS;
- vty_out(vty, "SNMP AgentX support cannot be disabled once enabled\n");
- return CMD_WARNING_CONFIG_FAILED;
+ return 1;
+ return 0;
}
static int smux_disable(void)
@@ -252,6 +229,9 @@ void smux_init(struct event_loop *tm)
{
agentx_tm = tm;
+ hook_register(agentx_cli_enabled, agentx_cli_on);
+ hook_register(agentx_cli_disabled, agentx_cli_off);
+
netsnmp_enable_subagent();
snmp_disable_log();
snmp_enable_calllog();
@@ -259,10 +239,6 @@ void smux_init(struct event_loop *tm)
agentx_log_callback, NULL);
init_agent(FRR_SMUX_NAME);
- install_node(&agentx_node);
- install_element(CONFIG_NODE, &agentx_enable_cmd);
- install_element(CONFIG_NODE, &no_agentx_cmd);
-
hook_register(frr_early_fini, smux_disable);
}
diff --git a/lib/atomlist.h b/lib/atomlist.h
index 2b6a3a1..3eb498a 100644
--- a/lib/atomlist.h
+++ b/lib/atomlist.h
@@ -7,7 +7,9 @@
#define _FRR_ATOMLIST_H
#include "typesafe.h"
+#ifndef _TYPESAFE_EXPAND_MACROS
#include "frratomic.h"
+#endif /* _TYPESAFE_EXPAND_MACROS */
#ifdef __cplusplus
extern "C" {
diff --git a/lib/base64.c b/lib/base64.c
index ee2e838..00dd35f 100644
--- a/lib/base64.c
+++ b/lib/base64.c
@@ -11,7 +11,6 @@
#include "base64.h"
#include "compiler.h"
-static const int CHARS_PER_LINE = 72;
static const char *ENCODING =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
@@ -19,7 +18,6 @@ void base64_init_encodestate(struct base64_encodestate *state_in)
{
state_in->step = step_A;
state_in->result = 0;
- state_in->stepcount = 0;
}
char base64_encode_value(char value_in)
@@ -76,12 +74,6 @@ int base64_encode_block(const char *plaintext_in, int length_in, char *code_out,
*codechar++ = base64_encode_value(result);
result = (fragment & 0x03f) >> 0;
*codechar++ = base64_encode_value(result);
-
- ++(state_in->stepcount);
- if (state_in->stepcount == CHARS_PER_LINE/4) {
- *codechar++ = '\n';
- state_in->stepcount = 0;
- }
}
}
/* control should not reach here */
@@ -105,7 +97,6 @@ int base64_encode_blockend(char *code_out, struct base64_encodestate *state_in)
case step_A:
break;
}
- *codechar++ = '\n';
return codechar - code_out;
}
diff --git a/lib/base64.h b/lib/base64.h
index 839f92a..9bf4ace 100644
--- a/lib/base64.h
+++ b/lib/base64.h
@@ -14,7 +14,6 @@ enum base64_encodestep {
struct base64_encodestate {
enum base64_encodestep step;
char result;
- int stepcount;
};
void base64_init_encodestate(struct base64_encodestate *state_in);
diff --git a/lib/checksum.c b/lib/checksum.c
index 6c5f06d..b1ad813 100644
--- a/lib/checksum.c
+++ b/lib/checksum.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
/*
* Checksum routine for Internet Protocol family headers (C Version).
*
diff --git a/lib/checksum.h b/lib/checksum.h
index 508c3f3..2856a0d 100644
--- a/lib/checksum.h
+++ b/lib/checksum.h
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#ifndef _FRR_CHECKSUM_H
#define _FRR_CHECKSUM_H
diff --git a/lib/command.c b/lib/command.c
index 8f780d0..51f2529 100644
--- a/lib/command.c
+++ b/lib/command.c
@@ -678,6 +678,21 @@ vector cmd_describe_command(vector vline, struct vty *vty, int *status)
static struct list *varhandlers = NULL;
+static int __add_key_comp(const struct lyd_node *dnode, void *arg)
+{
+ const char *key_value = yang_dnode_get_string(dnode, NULL);
+
+ vector_set((vector)arg, XSTRDUP(MTYPE_COMPLETION, key_value));
+
+ return YANG_ITER_CONTINUE;
+}
+
+static void __get_list_keys(vector comps, const char *xpath)
+{
+ yang_dnode_iterate(__add_key_comp, comps,
+ vty_shared_candidate_config->dnode, "%s", xpath);
+}
+
void cmd_variable_complete(struct cmd_token *token, const char *arg,
vector comps)
{
@@ -694,7 +709,10 @@ void cmd_variable_complete(struct cmd_token *token, const char *arg,
if (cvh->varname && (!token->varname
|| strcmp(cvh->varname, token->varname)))
continue;
- cvh->completions(tmpcomps, token);
+ if (cvh->xpath)
+ __get_list_keys(tmpcomps, cvh->xpath);
+ if (cvh->completions)
+ cvh->completions(tmpcomps, token);
break;
}
@@ -753,7 +771,7 @@ void cmd_variable_handler_register(const struct cmd_variable_handler *cvh)
if (!varhandlers)
return;
- for (; cvh->completions; cvh++)
+ for (; cvh->completions || cvh->xpath; cvh++)
listnode_add(varhandlers, (void *)cvh);
}
diff --git a/lib/command.h b/lib/command.h
index 04c66ad..e4c575e 100644
--- a/lib/command.h
+++ b/lib/command.h
@@ -462,6 +462,8 @@ struct cmd_node {
#define MPLS_LDP_SYNC_HOLDDOWN_STR \
"Time to wait for LDP-SYNC to occur before restoring if cost\n"
#define NO_MPLS_LDP_SYNC_HOLDDOWN_STR "holddown timer disable\n"
+#define BGP_AF_STR "Address Family\n"
+#define BGP_AF_MODIFIER_STR "Address Family modifier\n"
/* Command warnings. */
#define NO_PASSWD_CMD_WARNING \
@@ -636,6 +638,7 @@ extern void cmd_banner_motd_line(const char *line);
struct cmd_variable_handler {
const char *tokenname, *varname;
+ const char *xpath; /* fill comps from set of values at xpath */
void (*completions)(vector out, struct cmd_token *token);
};
diff --git a/lib/compiler.h b/lib/compiler.h
index 0326105..9d39026 100644
--- a/lib/compiler.h
+++ b/lib/compiler.h
@@ -455,6 +455,12 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8,
#define unlikely(_x) !!(_x)
#endif
+#ifdef __MACH__
+#define _DATA_SECTION(name) __attribute__((section("__DATA," name)))
+#else
+#define _DATA_SECTION(name) __attribute__((section(".data." name)))
+#endif
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/elf_py.c b/lib/elf_py.c
index 643495d..2b4fea3 100644
--- a/lib/elf_py.c
+++ b/lib/elf_py.c
@@ -1358,6 +1358,15 @@ bool elf_py_init(PyObject *pymod)
(void)methods_elfpy;
#endif
+#if defined(HAVE_GELF_GETNOTE) && defined(HAVE_ELF_GETDATA_RAWCHUNK)
+ PyObject *elf_notes = Py_True;
+#else
+ PyObject *elf_notes = Py_False;
+#endif
+ Py_INCREF(elf_notes);
+ if (PyModule_AddObject(pymod, "elf_notes", elf_notes))
+ Py_DECREF(elf_notes);
+
ELFFormatError = PyErr_NewException("_clippy.ELFFormatError",
PyExc_ValueError, NULL);
PyModule_AddObject(pymod, "ELFFormatError", ELFFormatError);
diff --git a/lib/explicit_bzero.c b/lib/explicit_bzero.c
index fa64ed8..e838f95 100644
--- a/lib/explicit_bzero.c
+++ b/lib/explicit_bzero.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
/*
* Public domain.
* Written by Matthew Dempsky.
diff --git a/lib/filter.c b/lib/filter.c
index 5a0790f..0722bed 100644
--- a/lib/filter.c
+++ b/lib/filter.c
@@ -458,7 +458,6 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi,
struct filter_cisco *filter;
bool first;
json_object *json = NULL;
- json_object *json_proto = NULL;
master = access_master_get(afi);
if (master == NULL) {
@@ -469,12 +468,7 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi,
if (use_json)
json = json_object_new_object();
-
- /* Print the name of the protocol */
- if (json) {
- json_proto = json_object_new_object();
- json_object_object_add(json, frr_protoname, json_proto);
- } else
+ else
vty_out(vty, "%s:\n", frr_protoname);
for (access = master->str.head; access; access = access->next) {
@@ -496,7 +490,7 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi,
if (json) {
json_acl = json_object_new_object();
- json_object_object_add(json_proto,
+ json_object_object_add(json,
access->name,
json_acl);
@@ -596,7 +590,7 @@ DEFUN (show_mac_access_list_name,
return filter_show(vty, argv[3]->arg, AFI_L2VPN, false);
}
-DEFUN (show_ip_access_list,
+DEFUN_NOSH (show_ip_access_list,
show_ip_access_list_cmd,
"show ip access-list [json]",
SHOW_STR
@@ -608,7 +602,7 @@ DEFUN (show_ip_access_list,
return filter_show(vty, NULL, AFI_IP, uj);
}
-DEFUN (show_ip_access_list_name,
+DEFUN_NOSH (show_ip_access_list_name,
show_ip_access_list_name_cmd,
"show ip access-list ACCESSLIST4_NAME [json]",
SHOW_STR
@@ -622,7 +616,7 @@ DEFUN (show_ip_access_list_name,
return filter_show(vty, argv[idx_acl]->arg, AFI_IP, uj);
}
-DEFUN (show_ipv6_access_list,
+DEFUN_NOSH (show_ipv6_access_list,
show_ipv6_access_list_cmd,
"show ipv6 access-list [json]",
SHOW_STR
@@ -634,7 +628,7 @@ DEFUN (show_ipv6_access_list,
return filter_show(vty, NULL, AFI_IP6, uj);
}
-DEFUN (show_ipv6_access_list_name,
+DEFUN_NOSH (show_ipv6_access_list_name,
show_ipv6_access_list_name_cmd,
"show ipv6 access-list ACCESSLIST6_NAME [json]",
SHOW_STR
diff --git a/lib/frr_pthread.c b/lib/frr_pthread.c
index 1ffa593..3a4bc71 100644
--- a/lib/frr_pthread.c
+++ b/lib/frr_pthread.c
@@ -92,9 +92,14 @@ struct frr_pthread *frr_pthread_new(const struct frr_pthread_attr *attr,
MTYPE_PTHREAD_PRIM, sizeof(pthread_mutex_t));
fpt->running_cond = XCALLOC(MTYPE_PTHREAD_PRIM,
sizeof(pthread_cond_t));
+
pthread_mutex_init(fpt->running_cond_mtx, NULL);
pthread_cond_init(fpt->running_cond, NULL);
+ pthread_mutex_init(&fpt->startup_cond_mtx, NULL);
+ pthread_cond_init(&fpt->startup_cond, NULL);
+ fpt->started = false;
+
frr_with_mutex (&frr_pthread_list_mtx) {
listnode_add(frr_pthread_list, fpt);
}
@@ -108,6 +113,8 @@ static void frr_pthread_destroy_nolock(struct frr_pthread *fpt)
pthread_mutex_destroy(&fpt->mtx);
pthread_mutex_destroy(fpt->running_cond_mtx);
pthread_cond_destroy(fpt->running_cond);
+ pthread_mutex_destroy(&fpt->startup_cond_mtx);
+ pthread_cond_destroy(&fpt->startup_cond);
XFREE(MTYPE_FRR_PTHREAD, fpt->name);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond_mtx);
XFREE(MTYPE_PTHREAD_PRIM, fpt->running_cond);
@@ -140,11 +147,34 @@ int frr_pthread_set_name(struct frr_pthread *fpt)
return ret;
}
+/* New pthread waits before running */
+static void frr_pthread_wait_startup(struct frr_pthread *fpt)
+{
+ frr_with_mutex (&fpt->startup_cond_mtx) {
+ while (!fpt->started)
+ pthread_cond_wait(&fpt->startup_cond,
+ &fpt->startup_cond_mtx);
+ }
+}
+
+/* Parent pthread allows new pthread to start running */
+static void frr_pthread_notify_startup(struct frr_pthread *fpt)
+{
+ frr_with_mutex (&fpt->startup_cond_mtx) {
+ fpt->started = true;
+ pthread_cond_signal(&fpt->startup_cond);
+ }
+}
+
static void *frr_pthread_inner(void *arg)
{
struct frr_pthread *fpt = arg;
+ /* The new pthead waits until the parent allows it to continue. */
+ frr_pthread_wait_startup(fpt);
+
rcu_thread_start(fpt->rcu_thread);
+
return fpt->attr.start(fpt);
}
@@ -169,6 +199,9 @@ int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr)
/* Restore caller's signals */
pthread_sigmask(SIG_SETMASK, &oldsigs, NULL);
+ /* Allow new child pthread to start */
+ frr_pthread_notify_startup(fpt);
+
/*
* Per pthread_create(3), the contents of fpt->thread are undefined if
* pthread_create() did not succeed. Reset this value to zero.
@@ -250,6 +283,8 @@ int frr_pthread_non_controlled_startup(pthread_t thread, const char *name,
fpt->thread = thread;
fpt->rcu_thread = rcu_thread;
+ fpt->started = true;
+
frr_pthread_inner(fpt);
return 0;
diff --git a/lib/frr_pthread.h b/lib/frr_pthread.h
index 1e1b8d7..bb751b7 100644
--- a/lib/frr_pthread.h
+++ b/lib/frr_pthread.h
@@ -47,6 +47,17 @@ struct frr_pthread {
struct frr_pthread_attr attr;
/*
+ * Startup serialization: newly-started pthreads wait at a point
+ * very early in life so that there isn't a race with the
+ * starting pthread. The OS 'start' apis don't make any guarantees
+ * about which pthread runs first - the existing pthread that has
+ * called the 'start' api, or the new pthread that is just starting.
+ */
+ pthread_cond_t startup_cond;
+ pthread_mutex_t startup_cond_mtx;
+ atomic_bool started;
+
+ /*
* Notification mechanism for allowing pthreads to notify their parents
* when they are ready to do work. This mechanism has two associated
* functions:
diff --git a/lib/frr_zmq.c b/lib/frr_zmq.c
index b28dd7f..5273d36 100644
--- a/lib/frr_zmq.c
+++ b/lib/frr_zmq.c
@@ -21,6 +21,8 @@
#include "log.h"
#include "lib_errors.h"
+XREF_SETUP();
+
DEFINE_MTYPE_STATIC(LIB, ZEROMQ_CB, "ZeroMQ callback");
/* libzmq's context */
diff --git a/lib/if.c b/lib/if.c
index a8ceac7..8f15230 100644
--- a/lib/if.c
+++ b/lib/if.c
@@ -6,6 +6,12 @@
#include <zebra.h>
+#include <net/if.h>
+
+#ifdef GNU_LINUX
+#include <linux/if.h>
+#endif /* GNU_LINUX */
+
#include "linklist.h"
#include "vector.h"
#include "lib_errors.h"
@@ -668,21 +674,26 @@ int if_is_running(const struct interface *ifp)
if ptm checking is enabled, then ptm check has passed */
int if_is_operative(const struct interface *ifp)
{
- return ((ifp->flags & IFF_UP)
- && (((ifp->flags & IFF_RUNNING)
- && (ifp->ptm_status || !ifp->ptm_enable))
- || !CHECK_FLAG(ifp->status,
- ZEBRA_INTERFACE_LINKDETECTION)));
+ return ((ifp->flags & IFF_UP) &&
+ (((ifp->flags & IFF_RUNNING)
+#ifdef IFF_LOWER_UP
+ && (ifp->flags & IFF_LOWER_UP)
+#endif /* IFF_LOWER_UP */
+ && (ifp->ptm_status || !ifp->ptm_enable)) ||
+ !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
}
/* Is the interface operative, eg. either UP & RUNNING
or UP & !ZEBRA_INTERFACE_LINK_DETECTION, without PTM check */
int if_is_no_ptm_operative(const struct interface *ifp)
{
- return ((ifp->flags & IFF_UP)
- && ((ifp->flags & IFF_RUNNING)
- || !CHECK_FLAG(ifp->status,
- ZEBRA_INTERFACE_LINKDETECTION)));
+ return ((ifp->flags & IFF_UP) &&
+ (((ifp->flags & IFF_RUNNING)
+#ifdef IFF_LOWER_UP
+ && (ifp->flags & IFF_LOWER_UP)
+#endif /* IFF_LOWER_UP */
+ ) ||
+ !CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_LINKDETECTION)));
}
/* Is this loopback interface ? */
@@ -744,6 +755,9 @@ const char *if_flag_dump(unsigned long flag)
strlcpy(logbuf, "<", BUFSIZ);
IFF_OUT_LOG(IFF_UP, "UP");
+#ifdef IFF_LOWER_UP
+ IFF_OUT_LOG(IFF_LOWER_UP, "LOWER_UP");
+#endif /* IFF_LOWER_UP */
IFF_OUT_LOG(IFF_BROADCAST, "BROADCAST");
IFF_OUT_LOG(IFF_DEBUG, "DEBUG");
IFF_OUT_LOG(IFF_LOOPBACK, "LOOPBACK");
@@ -885,21 +899,6 @@ nbr_connected_log(struct nbr_connected *connected, char *str)
zlog_info("%s", logbuf);
}
-/* If two connected address has same prefix return 1. */
-static int connected_same_prefix(const struct prefix *p1,
- const struct prefix *p2)
-{
- if (p1->family == p2->family) {
- if (p1->family == AF_INET
- && IPV4_ADDR_SAME(&p1->u.prefix4, &p2->u.prefix4))
- return 1;
- if (p1->family == AF_INET6
- && IPV6_ADDR_SAME(&p1->u.prefix6, &p2->u.prefix6))
- return 1;
- }
- return 0;
-}
-
/* count the number of connected addresses that are in the given family */
unsigned int connected_count_by_family(struct interface *ifp, int family)
{
@@ -919,7 +918,7 @@ struct connected *connected_lookup_prefix_exact(struct interface *ifp,
struct connected *ifc;
frr_each (if_connected, ifp->connected, ifc) {
- if (connected_same_prefix(ifc->address, p))
+ if (prefix_same(ifc->address, p))
return ifc;
}
return NULL;
@@ -932,7 +931,7 @@ struct connected *connected_delete_by_prefix(struct interface *ifp,
/* In case of same prefix come, replace it with new one. */
frr_each_safe (if_connected, ifp->connected, ifc) {
- if (connected_same_prefix(ifc->address, p)) {
+ if (prefix_same(ifc->address, p)) {
if_connected_del(ifp->connected, ifc);
return ifc;
}
diff --git a/lib/ipaddr.h b/lib/ipaddr.h
index c86e38c..888955f 100644
--- a/lib/ipaddr.h
+++ b/lib/ipaddr.h
@@ -40,8 +40,9 @@ struct ipaddr {
#define IS_IPADDR_V4(p) ((p)->ipa_type == IPADDR_V4)
#define IS_IPADDR_V6(p) ((p)->ipa_type == IPADDR_V6)
-#define SET_IPADDR_V4(p) (p)->ipa_type = IPADDR_V4
-#define SET_IPADDR_V6(p) (p)->ipa_type = IPADDR_V6
+#define SET_IPADDR_NONE(p) ((p)->ipa_type = IPADDR_NONE)
+#define SET_IPADDR_V4(p) ((p)->ipa_type = IPADDR_V4)
+#define SET_IPADDR_V6(p) ((p)->ipa_type = IPADDR_V6)
#define IPADDRSZ(p) \
(IS_IPADDR_V4((p)) ? sizeof(struct in_addr) : sizeof(struct in6_addr))
@@ -165,9 +166,17 @@ static inline bool ipaddr_is_zero(const struct ipaddr *ip)
return true;
}
+static inline bool ipaddr_is_same(const struct ipaddr *ip1,
+ const struct ipaddr *ip2)
+{
+ return ipaddr_cmp(ip1, ip2) == 0;
+}
+
+/* clang-format off */
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pIA" (struct ipaddr *)
#endif
+/* clang-format on */
#ifdef __cplusplus
}
diff --git a/lib/keychain.c b/lib/keychain.c
index 5ff0d1e..1982220 100644
--- a/lib/keychain.c
+++ b/lib/keychain.c
@@ -6,19 +6,19 @@
#include "config.h"
#include <zebra.h>
-#include "command.h"
-#include "memory.h"
-#include "linklist.h"
#include "keychain.h"
+#include "linklist.h"
+#include "memory.h"
-DEFINE_MTYPE_STATIC(LIB, KEY, "Key");
-DEFINE_MTYPE_STATIC(LIB, KEYCHAIN, "Key chain");
+DEFINE_MTYPE(LIB, KEY, "Key");
+DEFINE_MTYPE(LIB, KEYCHAIN, "Key chain");
+DEFINE_MTYPE(LIB, KEYCHAIN_DESC, "Key chain description");
DEFINE_QOBJ_TYPE(keychain);
DEFINE_QOBJ_TYPE(key);
/* Master list of key chain. */
-static struct list *keychain_list;
+struct list *keychain_list;
static struct keychain *keychain_new(void)
{
@@ -82,7 +82,7 @@ static void key_delete_func(struct key *key)
key_free(key);
}
-static struct keychain *keychain_get(const char *name)
+struct keychain *keychain_get(const char *name)
{
struct keychain *keychain;
@@ -101,7 +101,7 @@ static struct keychain *keychain_get(const char *name)
return keychain;
}
-static void keychain_delete(struct keychain *keychain)
+void keychain_delete(struct keychain *keychain)
{
XFREE(MTYPE_KEYCHAIN, keychain->name);
@@ -110,7 +110,7 @@ static void keychain_delete(struct keychain *keychain)
keychain_free(keychain);
}
-static struct key *key_lookup(const struct keychain *keychain, uint32_t index)
+struct key *key_lookup(const struct keychain *keychain, uint32_t index)
{
struct listnode *node;
struct key *key;
@@ -183,7 +183,7 @@ struct key *key_lookup_for_send(const struct keychain *keychain)
return NULL;
}
-static struct key *key_get(const struct keychain *keychain, uint32_t index)
+struct key *key_get(const struct keychain *keychain, uint32_t index)
{
struct key *key;
@@ -200,7 +200,7 @@ static struct key *key_get(const struct keychain *keychain, uint32_t index)
return key;
}
-static void key_delete(struct keychain *keychain, struct key *key)
+void key_delete(struct keychain *keychain, struct key *key)
{
listnode_delete(keychain->key, key);
@@ -208,122 +208,6 @@ static void key_delete(struct keychain *keychain, struct key *key)
key_free(key);
}
-DEFUN_NOSH (key_chain,
- key_chain_cmd,
- "key chain WORD",
- "Authentication key management\n"
- "Key-chain management\n"
- "Key-chain name\n")
-{
- int idx_word = 2;
- struct keychain *keychain;
-
- keychain = keychain_get(argv[idx_word]->arg);
- VTY_PUSH_CONTEXT(KEYCHAIN_NODE, keychain);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_key_chain,
- no_key_chain_cmd,
- "no key chain WORD",
- NO_STR
- "Authentication key management\n"
- "Key-chain management\n"
- "Key-chain name\n")
-{
- int idx_word = 3;
- struct keychain *keychain;
-
- keychain = keychain_lookup(argv[idx_word]->arg);
-
- if (!keychain) {
- vty_out(vty, "Can't find keychain %s\n", argv[idx_word]->arg);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- keychain_delete(keychain);
-
- return CMD_SUCCESS;
-}
-
-DEFUN_NOSH (key,
- key_cmd,
- "key (0-2147483647)",
- "Configure a key\n"
- "Key identifier number\n")
-{
- int idx_number = 1;
- VTY_DECLVAR_CONTEXT(keychain, keychain);
- struct key *key;
- uint32_t index;
-
- index = strtoul(argv[idx_number]->arg, NULL, 10);
- key = key_get(keychain, index);
- VTY_PUSH_CONTEXT_SUB(KEYCHAIN_KEY_NODE, key);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_key,
- no_key_cmd,
- "no key (0-2147483647)",
- NO_STR
- "Delete a key\n"
- "Key identifier number\n")
-{
- int idx_number = 2;
- VTY_DECLVAR_CONTEXT(keychain, keychain);
- struct key *key;
- uint32_t index;
-
- index = strtoul(argv[idx_number]->arg, NULL, 10);
- key = key_lookup(keychain, index);
- if (!key) {
- vty_out(vty, "Can't find key %d\n", index);
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- key_delete(keychain, key);
-
- vty->node = KEYCHAIN_NODE;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (key_string,
- key_string_cmd,
- "key-string LINE",
- "Set key string\n"
- "The key\n")
-{
- int idx_line = 1;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- if (key->string)
- XFREE(MTYPE_KEY, key->string);
- key->string = XSTRDUP(MTYPE_KEY, argv[idx_line]->arg);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_key_string,
- no_key_string_cmd,
- "no key-string [LINE]",
- NO_STR
- "Unset key string\n"
- "The key\n")
-{
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- if (key->string) {
- XFREE(MTYPE_KEY, key->string);
- key->string = NULL;
- }
-
- return CMD_SUCCESS;
-}
-
const struct keychain_algo_info algo_info[] = {
{KEYCHAIN_ALGO_NULL, "null", 0, 0, "NULL"},
{KEYCHAIN_ALGO_MD5, "md5", KEYCHAIN_MD5_HASH_SIZE,
@@ -394,800 +278,6 @@ const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key)
return algo_info[key].name;
}
-DEFUN(cryptographic_algorithm, cryptographic_algorithm_cmd,
- "cryptographic-algorithm "
- "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>",
- "Cryptographic-algorithm\n"
- "Use MD5 algorithm\n"
- "Use HMAC-SHA-1 algorithm\n"
- "Use HMAC-SHA-256 algorithm\n"
- "Use HMAC-SHA-384 algorithm\n"
- "Use HMAC-SHA-512 algorithm\n")
-{
- int algo_idx = 1;
- uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
-
- VTY_DECLVAR_CONTEXT_SUB(key, key);
- hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg);
-#ifndef CRYPTO_OPENSSL
- if (hash_algo == KEYCHAIN_ALGO_NULL) {
- vty_out(vty,
- "Hash algorithm not supported, compile with --with-crypto=openssl\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-#endif /* CRYPTO_OPENSSL */
- key->hash_algo = hash_algo;
- return CMD_SUCCESS;
-}
-
-DEFUN(no_cryptographic_algorithm, no_cryptographic_algorithm_cmd,
- "no cryptographic-algorithm "
- "[<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>]",
- NO_STR
- "Cryptographic-algorithm\n"
- "Use MD5 algorithm\n"
- "Use HMAC-SHA-1 algorithm\n"
- "Use HMAC-SHA-256 algorithm\n"
- "Use HMAC-SHA-384 algorithm\n"
- "Use HMAC-SHA-512 algorithm\n")
-{
- int algo_idx = 2;
- uint8_t hash_algo = KEYCHAIN_ALGO_NULL;
-
- VTY_DECLVAR_CONTEXT_SUB(key, key);
- if (argc > algo_idx) {
- hash_algo = keychain_get_algo_id_by_name(argv[algo_idx]->arg);
- if (hash_algo == KEYCHAIN_ALGO_NULL) {
- vty_out(vty,
- "Hash algorithm not supported, try compiling with --with-crypto=openssl\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- }
-
- if ((hash_algo != KEYCHAIN_ALGO_NULL) && (hash_algo != key->hash_algo))
- return CMD_SUCCESS;
-
- key->hash_algo = KEYCHAIN_ALGO_NULL;
- return CMD_SUCCESS;
-}
-
-/* Convert HH:MM:SS MON DAY YEAR to time_t value. -1 is returned when
- given string is malformed. */
-static time_t key_str2time(const char *time_str, const char *day_str,
- const char *month_str, const char *year_str)
-{
- int i = 0;
- char *colon;
- struct tm tm;
- time_t time;
- unsigned int sec, min, hour;
- unsigned int day, month, year;
-
- const char *month_name[] = {
- "January", "February", "March", "April", "May",
- "June", "July", "August", "September", "October",
- "November", "December", NULL};
-
-#define _GET_LONG_RANGE(V, STR, MMCOND) \
- { \
- unsigned long tmpl; \
- char *endptr = NULL; \
- tmpl = strtoul((STR), &endptr, 10); \
- if (*endptr != '\0' || tmpl == ULONG_MAX) \
- return -1; \
- if (MMCOND) \
- return -1; \
- (V) = tmpl; \
- }
-#define GET_LONG_RANGE(V, STR, MIN, MAX) \
- _GET_LONG_RANGE(V, STR, tmpl<(MIN) || tmpl>(MAX))
-#define GET_LONG_RANGE0(V, STR, MAX) _GET_LONG_RANGE(V, STR, tmpl > (MAX))
-
- /* Check hour field of time_str. */
- colon = strchr(time_str, ':');
- if (colon == NULL)
- return -1;
- *colon = '\0';
-
- /* Hour must be between 0 and 23. */
- GET_LONG_RANGE0(hour, time_str, 23);
-
- /* Check min field of time_str. */
- time_str = colon + 1;
- colon = strchr(time_str, ':');
- if (*time_str == '\0' || colon == NULL)
- return -1;
- *colon = '\0';
-
- /* Min must be between 0 and 59. */
- GET_LONG_RANGE0(min, time_str, 59);
-
- /* Check sec field of time_str. */
- time_str = colon + 1;
- if (*time_str == '\0')
- return -1;
-
- /* Sec must be between 0 and 59. */
- GET_LONG_RANGE0(sec, time_str, 59);
-
- /* Check day_str. Day must be <1-31>. */
- GET_LONG_RANGE(day, day_str, 1, 31);
-
- /* Check month_str. Month must match month_name. */
- month = 0;
- if (strlen(month_str) >= 3)
- for (i = 0; month_name[i]; i++)
- if (strncmp(month_str, month_name[i], strlen(month_str))
- == 0) {
- month = i;
- break;
- }
- if (!month_name[i])
- return -1;
-
- /* Check year_str. Year must be <1993-2035>. */
- GET_LONG_RANGE(year, year_str, 1993, 2035);
-
- memset(&tm, 0, sizeof(tm));
- tm.tm_sec = sec;
- tm.tm_min = min;
- tm.tm_hour = hour;
- tm.tm_mon = month;
- tm.tm_mday = day;
- tm.tm_year = year - 1900;
-
- time = mktime(&tm);
-
- return time;
-#undef GET_LONG_RANGE
-}
-
-static int key_lifetime_set(struct vty *vty, struct key_range *krange,
- const char *stime_str, const char *sday_str,
- const char *smonth_str, const char *syear_str,
- const char *etime_str, const char *eday_str,
- const char *emonth_str, const char *eyear_str)
-{
- time_t time_start;
- time_t time_end;
-
- time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str);
- if (time_start < 0) {
- vty_out(vty, "Malformed time value\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- time_end = key_str2time(etime_str, eday_str, emonth_str, eyear_str);
-
- if (time_end < 0) {
- vty_out(vty, "Malformed time value\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (time_end <= time_start) {
- vty_out(vty, "Expire time is not later than start time\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- krange->start = time_start;
- krange->end = time_end;
-
- return CMD_SUCCESS;
-}
-
-static int key_lifetime_duration_set(struct vty *vty, struct key_range *krange,
- const char *stime_str,
- const char *sday_str,
- const char *smonth_str,
- const char *syear_str,
- const char *duration_str)
-{
- time_t time_start;
- uint32_t duration;
-
- time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str);
- if (time_start < 0) {
- vty_out(vty, "Malformed time value\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- krange->start = time_start;
-
- duration = strtoul(duration_str, NULL, 10);
- krange->duration = 1;
- krange->end = time_start + duration;
-
- return CMD_SUCCESS;
-}
-
-static int key_lifetime_infinite_set(struct vty *vty, struct key_range *krange,
- const char *stime_str,
- const char *sday_str,
- const char *smonth_str,
- const char *syear_str)
-{
- time_t time_start;
-
- time_start = key_str2time(stime_str, sday_str, smonth_str, syear_str);
- if (time_start < 0) {
- vty_out(vty, "Malformed time value\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
- krange->start = time_start;
-
- krange->end = -1;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (accept_lifetime_day_month_day_month,
- accept_lifetime_day_month_day_month_cmd,
- "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Day of th month to expire\n"
- "Month of the year to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_number_3 = 6;
- int idx_month_2 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (accept_lifetime_day_month_month_day,
- accept_lifetime_day_month_month_day_cmd,
- "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Month of the year to expire\n"
- "Day of th month to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_month_2 = 6;
- int idx_number_3 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (accept_lifetime_month_day_day_month,
- accept_lifetime_month_day_day_month_cmd,
- "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Day of th month to expire\n"
- "Month of the year to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_number_3 = 6;
- int idx_month_2 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (accept_lifetime_month_day_month_day,
- accept_lifetime_month_day_month_day_cmd,
- "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Month of the year to expire\n"
- "Day of th month to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_month_2 = 6;
- int idx_number_3 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (accept_lifetime_infinite_day_month,
- accept_lifetime_infinite_day_month_cmd,
- "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Never expires\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_infinite_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg);
-}
-
-DEFUN (accept_lifetime_infinite_month_day,
- accept_lifetime_infinite_month_day_cmd,
- "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Never expires\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_infinite_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg);
-}
-
-DEFUN (accept_lifetime_duration_day_month,
- accept_lifetime_duration_day_month_cmd,
- "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Duration of the key\n"
- "Duration seconds\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- int idx_number_3 = 6;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_duration_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_number_3]->arg);
-}
-
-DEFUN (accept_lifetime_duration_month_day,
- accept_lifetime_duration_month_day_cmd,
- "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)",
- "Set accept lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Duration of the key\n"
- "Duration seconds\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- int idx_number_3 = 6;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_duration_set(
- vty, &key->accept, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_number_3]->arg);
-}
-
-DEFUN (no_accept_lifetime,
- no_accept_lifetime_cmd,
- "no accept-lifetime",
- NO_STR
- "Unset accept-lifetime\n")
-{
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- if (key->accept.start)
- key->accept.start = 0;
- if (key->accept.end)
- key->accept.end = 0;
- if (key->accept.duration)
- key->accept.duration = 0;
-
- return CMD_SUCCESS;
-}
-
-DEFUN (send_lifetime_day_month_day_month,
- send_lifetime_day_month_day_month_cmd,
- "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Day of th month to expire\n"
- "Month of the year to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_number_3 = 6;
- int idx_month_2 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (send_lifetime_day_month_month_day,
- send_lifetime_day_month_month_day_cmd,
- "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Month of the year to expire\n"
- "Day of th month to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_month_2 = 6;
- int idx_number_3 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (send_lifetime_month_day_day_month,
- send_lifetime_month_day_day_month_cmd,
- "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Day of th month to expire\n"
- "Month of the year to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_number_3 = 6;
- int idx_month_2 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (send_lifetime_month_day_month_day,
- send_lifetime_month_day_month_day_cmd,
- "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Time to expire\n"
- "Month of the year to expire\n"
- "Day of th month to expire\n"
- "Year to expire\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- int idx_hhmmss_2 = 5;
- int idx_month_2 = 6;
- int idx_number_3 = 7;
- int idx_number_4 = 8;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_hhmmss_2]->arg, argv[idx_number_3]->arg,
- argv[idx_month_2]->arg, argv[idx_number_4]->arg);
-}
-
-DEFUN (send_lifetime_infinite_day_month,
- send_lifetime_infinite_day_month_cmd,
- "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Never expires\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_infinite_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg);
-}
-
-DEFUN (send_lifetime_infinite_month_day,
- send_lifetime_infinite_month_day_cmd,
- "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Never expires\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_infinite_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg);
-}
-
-DEFUN (send_lifetime_duration_day_month,
- send_lifetime_duration_day_month_cmd,
- "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Day of th month to start\n"
- "Month of the year to start\n"
- "Year to start\n"
- "Duration of the key\n"
- "Duration seconds\n")
-{
- int idx_hhmmss = 1;
- int idx_number = 2;
- int idx_month = 3;
- int idx_number_2 = 4;
- int idx_number_3 = 6;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_duration_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_number_3]->arg);
-}
-
-DEFUN (send_lifetime_duration_month_day,
- send_lifetime_duration_month_day_cmd,
- "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)",
- "Set send lifetime of the key\n"
- "Time to start\n"
- "Month of the year to start\n"
- "Day of th month to start\n"
- "Year to start\n"
- "Duration of the key\n"
- "Duration seconds\n")
-{
- int idx_hhmmss = 1;
- int idx_month = 2;
- int idx_number = 3;
- int idx_number_2 = 4;
- int idx_number_3 = 6;
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- return key_lifetime_duration_set(
- vty, &key->send, argv[idx_hhmmss]->arg, argv[idx_number]->arg,
- argv[idx_month]->arg, argv[idx_number_2]->arg,
- argv[idx_number_3]->arg);
-}
-
-DEFUN (no_send_lifetime,
- no_send_lifetime_cmd,
- "no send-lifetime",
- NO_STR
- "Unset send-lifetime\n")
-{
- VTY_DECLVAR_CONTEXT_SUB(key, key);
-
- if (key->send.start)
- key->send.start = 0;
- if (key->send.end)
- key->send.end = 0;
- if (key->send.duration)
- key->send.duration = 0;
-
- return CMD_SUCCESS;
-}
-
-static int keychain_config_write(struct vty *vty);
-static struct cmd_node keychain_node = {
- .name = "keychain",
- .node = KEYCHAIN_NODE,
- .parent_node = CONFIG_NODE,
- .prompt = "%s(config-keychain)# ",
- .config_write = keychain_config_write,
-};
-
-static struct cmd_node keychain_key_node = {
- .name = "keychain key",
- .node = KEYCHAIN_KEY_NODE,
- .parent_node = KEYCHAIN_NODE,
- .prompt = "%s(config-keychain-key)# ",
-};
-
-static int keychain_strftime(char *buf, int bufsiz, time_t *time)
-{
- struct tm tm;
- size_t len;
-
- localtime_r(time, &tm);
-
- len = strftime(buf, bufsiz, "%T %b %d %Y", &tm);
-
- return len;
-}
-
-static int keychain_config_write(struct vty *vty)
-{
- struct keychain *keychain;
- struct key *key;
- struct listnode *node;
- struct listnode *knode;
- char buf[BUFSIZ];
-
- for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) {
- vty_out(vty, "key chain %s\n", keychain->name);
-
- for (ALL_LIST_ELEMENTS_RO(keychain->key, knode, key)) {
- vty_out(vty, " key %d\n", key->index);
-
- if (key->string)
- vty_out(vty, " key-string %s\n", key->string);
-
- if (key->hash_algo != KEYCHAIN_ALGO_NULL)
- vty_out(vty, " cryptographic-algorithm %s\n",
- keychain_get_algo_name_by_id(
- key->hash_algo));
-
- if (key->accept.start) {
- keychain_strftime(buf, BUFSIZ,
- &key->accept.start);
- vty_out(vty, " accept-lifetime %s", buf);
-
- if (key->accept.end == -1)
- vty_out(vty, " infinite");
- else if (key->accept.duration)
- vty_out(vty, " duration %ld",
- (long)(key->accept.end
- - key->accept.start));
- else {
- keychain_strftime(buf, BUFSIZ,
- &key->accept.end);
- vty_out(vty, " %s", buf);
- }
- vty_out(vty, "\n");
- }
-
- if (key->send.start) {
- keychain_strftime(buf, BUFSIZ,
- &key->send.start);
- vty_out(vty, " send-lifetime %s", buf);
-
- if (key->send.end == -1)
- vty_out(vty, " infinite");
- else if (key->send.duration)
- vty_out(vty, " duration %ld",
- (long)(key->send.end
- - key->send.start));
- else {
- keychain_strftime(buf, BUFSIZ,
- &key->send.end);
- vty_out(vty, " %s", buf);
- }
- vty_out(vty, "\n");
- }
-
- vty_out(vty, " exit\n");
- }
- vty_out(vty, "exit\n");
- vty_out(vty, "!\n");
- }
-
- return 0;
-}
-
-
-static void keychain_active_config(vector comps, struct cmd_token *token)
-{
- struct keychain *keychain;
- struct listnode *node;
-
- for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain))
- vector_set(comps, XSTRDUP(MTYPE_COMPLETION, keychain->name));
-}
-
-static const struct cmd_variable_handler keychain_var_handlers[] = {
- {.varname = "key_chain", .completions = keychain_active_config},
- {.tokenname = "KEYCHAIN_NAME", .completions = keychain_active_config},
- {.tokenname = "KCHAIN_NAME", .completions = keychain_active_config},
- {.completions = NULL}
-};
-
void keychain_terminate(void)
{
struct keychain *keychain;
@@ -1202,70 +292,25 @@ void keychain_terminate(void)
list_delete(&keychain_list);
}
-void keychain_init(void)
+void keychain_init_new(bool in_backend)
{
keychain_list = list_new();
- /* Register handler for keychain auto config support */
- cmd_variable_handler_register(keychain_var_handlers);
- install_node(&keychain_node);
- install_node(&keychain_key_node);
-
- install_default(KEYCHAIN_NODE);
- install_default(KEYCHAIN_KEY_NODE);
-
- install_element(CONFIG_NODE, &key_chain_cmd);
- install_element(CONFIG_NODE, &no_key_chain_cmd);
- install_element(KEYCHAIN_NODE, &key_cmd);
- install_element(KEYCHAIN_NODE, &no_key_cmd);
-
- install_element(KEYCHAIN_NODE, &key_chain_cmd);
- install_element(KEYCHAIN_NODE, &no_key_chain_cmd);
-
- install_element(KEYCHAIN_KEY_NODE, &key_string_cmd);
- install_element(KEYCHAIN_KEY_NODE, &no_key_string_cmd);
-
- install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd);
- install_element(KEYCHAIN_KEY_NODE, &no_key_chain_cmd);
-
- install_element(KEYCHAIN_KEY_NODE, &key_cmd);
- install_element(KEYCHAIN_KEY_NODE, &no_key_cmd);
-
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_day_month_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_day_month_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_month_day_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_month_day_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_infinite_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_infinite_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_duration_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &accept_lifetime_duration_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE, &no_accept_lifetime_cmd);
+ if (!in_backend)
+ keychain_cli_init();
+}
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_day_month_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_day_month_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_month_day_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_month_day_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_infinite_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_infinite_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_duration_day_month_cmd);
- install_element(KEYCHAIN_KEY_NODE,
- &send_lifetime_duration_month_day_cmd);
- install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd);
- install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd);
- install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd);
+void keychain_init(void)
+{
+ keychain_init_new(false);
}
+
+const struct frr_yang_module_info ietf_key_chain_deviation_info = {
+ .name = "frr-deviations-ietf-key-chain",
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = NULL,
+ },
+ },
+};
diff --git a/lib/keychain.h b/lib/keychain.h
index c96b74e..dc35c2e 100644
--- a/lib/keychain.h
+++ b/lib/keychain.h
@@ -6,6 +6,8 @@
#ifndef _ZEBRA_KEYCHAIN_H
#define _ZEBRA_KEYCHAIN_H
+#include "memory.h"
+#include "northbound.h"
#include "qobj.h"
#ifdef __cplusplus
@@ -44,6 +46,10 @@ struct keychain_algo_info {
const char *desc;
};
+extern const struct frr_yang_module_info ietf_key_chain_info;
+extern const struct frr_yang_module_info ietf_key_chain_cli_info;
+extern const struct frr_yang_module_info ietf_key_chain_deviation_info;
+
extern const struct keychain_algo_info algo_info[];
uint16_t keychain_get_block_size(enum keychain_hash_algo key);
uint16_t keychain_get_hash_len(enum keychain_hash_algo key);
@@ -55,6 +61,8 @@ const char *keychain_get_algo_name_by_id(enum keychain_hash_algo key);
struct keychain {
char *name;
+ char *desc;
+ time_t last_touch;
struct list *key;
@@ -81,13 +89,43 @@ struct key {
};
DECLARE_QOBJ_TYPE(key);
+DECLARE_MTYPE(KEY);
+DECLARE_MTYPE(KEYCHAIN);
+DECLARE_MTYPE(KEYCHAIN_DESC);
+
+/* keychain implementation */
+extern struct list *keychain_list;
+struct keychain *keychain_lookup(const char *name);
+struct keychain *keychain_get(const char *name);
+void keychain_delete(struct keychain *keychain);
+struct key *key_lookup(const struct keychain *keychain, uint32_t index);
+struct key *key_get(const struct keychain *keychain, uint32_t index);
+void key_delete(struct keychain *keychain, struct key *key);
+
+void keychain_cli_init(void);
+extern void key_chains_key_chain_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+extern void key_chains_key_chain_cli_write_end(struct vty *vty, const struct lyd_node *dnode);
+extern void key_chains_key_chain_description_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+void key_chains_key_chain_key_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+extern void key_chains_key_chain_key_cli_write_end(struct vty *vty, const struct lyd_node *dnode);
+extern void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+extern void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+extern void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+extern void key_chains_key_chain_key_crypto_algorithm_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+extern void key_chains_key_chain_key_key_string_keystring_cli_write(struct vty *vty, const struct lyd_node *dnode, bool show_defaults);
+
+/* keychain users */
extern void keychain_init(void);
+extern void keychain_init_new(bool in_backend);
extern void keychain_terminate(void);
extern struct keychain *keychain_lookup(const char *);
extern struct key *key_lookup_for_accept(const struct keychain *, uint32_t);
extern struct key *key_match_for_accept(const struct keychain *, const char *);
extern struct key *key_lookup_for_send(const struct keychain *);
const char *keychain_algo_str(enum keychain_hash_algo hash_algo);
+
+
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/keychain_cli.c b/lib/keychain_cli.c
new file mode 100644
index 0000000..26f56f1
--- /dev/null
+++ b/lib/keychain_cli.c
@@ -0,0 +1,1033 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * February 22 2024, Christian Hopps <chopps@labn.net>
+ *
+ * Copyright (C) 2024 LabN Consulting, L.L.C.
+ *
+ * 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
+ */
+#include <zebra.h>
+#include "command.h"
+#include "keychain.h"
+#include "northbound.h"
+#include "northbound_cli.h"
+#include "vty.h"
+
+#include "lib/keychain_cli_clippy.c"
+
+DEFPY_YANG_NOSH(
+ key_chain,
+ key_chain_cmd,
+ "key chain WORD",
+ "Authentication key management\n"
+ "Key-chain management\n"
+ "Key-chain name\n")
+{
+ char *xpath;
+ int ret;
+
+ xpath = asprintfrr(MTYPE_TMP,
+ "/ietf-key-chain:key-chains/key-chain[name='%s']",
+ chain);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ ret = nb_cli_apply_changes(vty, NULL);
+ if (ret == CMD_SUCCESS)
+ VTY_PUSH_XPATH(KEYCHAIN_NODE, xpath);
+ XFREE(MTYPE_TMP, xpath);
+ return ret;
+}
+
+DEFPY_YANG(
+ no_key_chain,
+ no_key_chain_cmd,
+ "no key chain WORD",
+ NO_STR
+ "Authentication key management\n"
+ "Key-chain management\n"
+ "Key-chain name\n")
+{
+ char *xpath;
+
+ xpath = asprintfrr(MTYPE_TMP,
+ "/ietf-key-chain:key-chains/key-chain[name='%s']",
+ chain);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ XFREE(MTYPE_TMP, xpath);
+ return nb_cli_apply_changes_clear_pending(vty, NULL);
+}
+
+DEFPY_YANG_NOSH(
+ key,
+ key_cmd,
+ "key (0-2147483647)",
+ "Configure a key\n"
+ "Key identifier number\n")
+{
+ char *xpath;
+ int ret;
+
+ xpath = asprintfrr(MTYPE_TMP, "%s/key[key-id='%s']", VTY_CURR_XPATH,
+ key_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+ ret = nb_cli_apply_changes(vty, NULL);
+ if (ret == CMD_SUCCESS)
+ VTY_PUSH_XPATH(KEYCHAIN_KEY_NODE, xpath);
+ XFREE(MTYPE_TMP, xpath);
+ return ret;
+}
+
+DEFPY_YANG(
+ no_key,
+ no_key_cmd,
+ "no key (0-2147483647)",
+ NO_STR
+ "Delete a key\n"
+ "Key identifier number\n")
+{
+ char *xpath;
+
+ xpath = asprintfrr(MTYPE_TMP, "%s/key[key-id='%s']", VTY_CURR_XPATH,
+ key_str);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+ XFREE(MTYPE_TMP, xpath);
+ return nb_cli_apply_changes_clear_pending(vty, NULL);
+}
+
+DEFPY_YANG(
+ key_string,
+ key_string_cmd,
+ "key-string LINE",
+ "Set key string\n"
+ "The key\n")
+{
+ nb_cli_enqueue_change(vty, "./key-string/keystring", NB_OP_CREATE, line);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_key_string,
+ no_key_string_cmd,
+ "no key-string [LINE]",
+ NO_STR
+ "Unset key string\n"
+ "The key\n")
+{
+ nb_cli_enqueue_change(vty, "./key-string/keystring", NB_OP_DESTROY, line);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ cryptographic_algorithm,
+ cryptographic_algorithm_cmd,
+ "cryptographic-algorithm "
+ "<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>$algo",
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n")
+{
+ nb_cli_enqueue_change(vty, "./crypto-algorithm", NB_OP_CREATE, algo);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ no_cryptographic_algorithm,
+ no_cryptographic_algorithm_cmd,
+ "no cryptographic-algorithm "
+ "[<md5|hmac-sha-1|hmac-sha-256|hmac-sha-384|hmac-sha-512>$algo]",
+ NO_STR
+ "Cryptographic-algorithm\n"
+ "Use MD5 algorithm\n"
+ "Use HMAC-SHA-1 algorithm\n"
+ "Use HMAC-SHA-256 algorithm\n"
+ "Use HMAC-SHA-384 algorithm\n"
+ "Use HMAC-SHA-512 algorithm\n")
+{
+ nb_cli_enqueue_change(vty, "./crypto-algorithm", NB_OP_DESTROY, algo);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+const char *month_name[] = {
+ "january", "february", "march", "april", "may", "june", "july",
+ "august", "september", "october", "november", "december", NULL
+};
+
+static int __get_month(const char *month_str)
+{
+ int i, len;
+
+ len = strlen(month_str);
+ if (len < 3)
+ return -1;
+ for (i = 1; month_name[i-1]; i++)
+ if (strncasecmp(month_str, month_name[i-1], len) == 0)
+ return i;
+ return -1;
+}
+
+
+static long __timezone_offset(void)
+{
+ time_t now;
+ struct tm *tm_now;
+
+ time(&now);
+ tm_now = localtime(&now);
+ return tm_now->tm_gmtoff;
+}
+
+static int __lifetime_set(struct vty *vty, char timebuf[32],
+ const char *time_node, const char *leaf_node,
+ const char *time_str, const char *day_str,
+ const char *month_str, const char *year_str)
+{
+ char xpath[128];
+ int month = __get_month(month_str);
+ int hoff, moff;
+ long offset;
+
+ if (month < 1) {
+ vty_out(vty, "Bad month value: %s\n", month_str);
+ return -1;
+ }
+
+ offset = __timezone_offset();
+ hoff = offset / 3600;
+ if (offset < 0)
+ offset = -offset;
+ moff = (offset % 3600) / 60;
+
+ snprintf(timebuf, 32, "%s-%02d-%02dT%s%+03d:%02d", year_str, month,
+ atoi(day_str), time_str, hoff, moff);
+ snprintf(xpath, sizeof(xpath), "./lifetime/%s/%s", time_node, leaf_node);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, timebuf);
+ return 0;
+}
+
+
+static int key_lifetime_set(struct vty *vty, const char *time_node,
+ const char *stime_str, const char *sday_str,
+ const char *smonth_str, const char *syear_str,
+ const char *etime_str, const char *eday_str,
+ const char *emonth_str, const char *eyear_str)
+{
+ char time1[32];
+ char time2[32];
+
+ if (__lifetime_set(vty, time1, time_node, "start-date-time", stime_str,
+ sday_str, smonth_str, syear_str))
+ return CMD_WARNING_CONFIG_FAILED;
+
+ if (__lifetime_set(vty, time2, time_node, "end-date-time", etime_str,
+ eday_str, emonth_str, eyear_str))
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static int key_lifetime_duration_set(struct vty *vty, const char *time_node,
+ const char *stime_str, const char *sday_str,
+ const char *smonth_str,
+ const char *syear_str,
+ const char *duration_str)
+{
+ char xpath[128];
+ char time[32];
+
+ if (__lifetime_set(vty, time, time_node, "start-date-time", stime_str,
+ sday_str, smonth_str, syear_str))
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* End time. */
+ snprintf(xpath, sizeof(xpath), "./lifetime/%s/duration", time_node);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, duration_str);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+static int key_lifetime_infinite_set(struct vty *vty, const char *time_node,
+ const char *stime_str, const char *sday_str,
+ const char *smonth_str,
+ const char *syear_str)
+{
+ char xpath[128];
+ char time[32];
+
+ if (__lifetime_set(vty, time, time_node, "start-date-time", stime_str,
+ sday_str, smonth_str, syear_str))
+ return CMD_WARNING_CONFIG_FAILED;
+
+ /* End time. */
+ snprintf(xpath, sizeof(xpath), "./lifetime/%s/no-end-time", time_node);
+ nb_cli_enqueue_change(vty, xpath, NB_OP_MODIFY, NULL);
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ accept_lifetime_day_month_day_month,
+ accept_lifetime_day_month_day_month_cmd,
+ "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Day of th month to expire\n"
+ "Month of the year to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_number_3 = 6;
+ int idx_month_2 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(accept_lifetime_day_month_month_day,
+ accept_lifetime_day_month_month_day_cmd,
+ "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Month of the year to expire\n"
+ "Day of th month to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_month_2 = 6;
+ int idx_number_3 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(accept_lifetime_month_day_day_month,
+ accept_lifetime_month_day_day_month_cmd,
+ "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Day of th month to expire\n"
+ "Month of the year to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_number_3 = 6;
+ int idx_month_2 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(accept_lifetime_month_day_month_day,
+ accept_lifetime_month_day_month_day_cmd,
+ "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Month of the year to expire\n"
+ "Day of th month to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_month_2 = 6;
+ int idx_number_3 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "accept-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(accept_lifetime_infinite_day_month,
+ accept_lifetime_infinite_day_month_cmd,
+ "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Never expires\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+
+ return key_lifetime_infinite_set(vty, "accept-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg);
+}
+
+DEFPY_YANG(accept_lifetime_infinite_month_day,
+ accept_lifetime_infinite_month_day_cmd,
+ "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Never expires\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+
+ return key_lifetime_infinite_set(vty, "accept-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg);
+}
+
+DEFPY_YANG(accept_lifetime_duration_day_month,
+ accept_lifetime_duration_day_month_cmd,
+ "accept-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Duration of the key\n"
+ "Duration seconds\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+ int idx_number_3 = 6;
+
+ return key_lifetime_duration_set(vty, "accept-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg,
+ argv[idx_number_3]->arg);
+}
+
+DEFPY_YANG(accept_lifetime_duration_month_day,
+ accept_lifetime_duration_month_day_cmd,
+ "accept-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)",
+ "Set accept lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Duration of the key\n"
+ "Duration seconds\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_number_3 = 6;
+
+ return key_lifetime_duration_set(vty, "accept-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg,
+ argv[idx_number_3]->arg);
+}
+
+DEFPY_YANG(no_accept_lifetime,
+ no_accept_lifetime_cmd,
+ "no accept-lifetime",
+ NO_STR
+ "Unset accept-lifetime\n")
+{
+ nb_cli_enqueue_change(vty, "accept-lifetime", NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+DEFPY_YANG(
+ send_lifetime_day_month_day_month, send_lifetime_day_month_day_month_cmd,
+ "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Day of th month to expire\n"
+ "Month of the year to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_number_3 = 6;
+ int idx_month_2 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(send_lifetime_day_month_month_day,
+ send_lifetime_day_month_month_day_cmd,
+ "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Month of the year to expire\n"
+ "Day of th month to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_month_2 = 6;
+ int idx_number_3 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(send_lifetime_month_day_day_month,
+ send_lifetime_month_day_day_month_cmd,
+ "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS (1-31) MONTH (1993-2035)",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Day of th month to expire\n"
+ "Month of the year to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_number_3 = 6;
+ int idx_month_2 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(send_lifetime_month_day_month_day,
+ send_lifetime_month_day_month_day_cmd,
+ "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) HH:MM:SS MONTH (1-31) (1993-2035)",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Time to expire\n"
+ "Month of the year to expire\n"
+ "Day of th month to expire\n"
+ "Year to expire\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_hhmmss_2 = 5;
+ int idx_month_2 = 6;
+ int idx_number_3 = 7;
+ int idx_number_4 = 8;
+
+ return key_lifetime_set(vty, "send-lifetime", argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg, argv[idx_month]->arg,
+ argv[idx_number_2]->arg, argv[idx_hhmmss_2]->arg,
+ argv[idx_number_3]->arg, argv[idx_month_2]->arg,
+ argv[idx_number_4]->arg);
+}
+
+DEFPY_YANG(send_lifetime_infinite_day_month,
+ send_lifetime_infinite_day_month_cmd,
+ "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) infinite",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Never expires\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+
+ return key_lifetime_infinite_set(vty, "send-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg);
+}
+
+DEFPY_YANG(send_lifetime_infinite_month_day,
+ send_lifetime_infinite_month_day_cmd,
+ "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) infinite",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Never expires\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+
+ return key_lifetime_infinite_set(vty, "send-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg);
+}
+
+DEFPY_YANG(send_lifetime_duration_day_month,
+ send_lifetime_duration_day_month_cmd,
+ "send-lifetime HH:MM:SS (1-31) MONTH (1993-2035) duration (1-2147483646)",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Day of th month to start\n"
+ "Month of the year to start\n"
+ "Year to start\n"
+ "Duration of the key\n"
+ "Duration seconds\n")
+{
+ int idx_hhmmss = 1;
+ int idx_number = 2;
+ int idx_month = 3;
+ int idx_number_2 = 4;
+ int idx_number_3 = 6;
+
+ return key_lifetime_duration_set(vty, "send-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg,
+ argv[idx_number_3]->arg);
+}
+
+DEFPY_YANG(send_lifetime_duration_month_day,
+ send_lifetime_duration_month_day_cmd,
+ "send-lifetime HH:MM:SS MONTH (1-31) (1993-2035) duration (1-2147483646)",
+ "Set send lifetime of the key\n"
+ "Time to start\n"
+ "Month of the year to start\n"
+ "Day of th month to start\n"
+ "Year to start\n"
+ "Duration of the key\n"
+ "Duration seconds\n")
+{
+ int idx_hhmmss = 1;
+ int idx_month = 2;
+ int idx_number = 3;
+ int idx_number_2 = 4;
+ int idx_number_3 = 6;
+
+ return key_lifetime_duration_set(vty, "send-lifetime",
+ argv[idx_hhmmss]->arg,
+ argv[idx_number]->arg,
+ argv[idx_month]->arg,
+ argv[idx_number_2]->arg,
+ argv[idx_number_3]->arg);
+}
+
+DEFUN (no_send_lifetime,
+ no_send_lifetime_cmd,
+ "no send-lifetime",
+ NO_STR
+ "Unset send-lifetime\n")
+{
+ nb_cli_enqueue_change(vty, "send-lifetime", NB_OP_DESTROY, NULL);
+ return nb_cli_apply_changes(vty, NULL);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain
+ */
+void key_chains_key_chain_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, "key chain %s\n", yang_dnode_get_string(dnode, "name"));
+}
+
+void key_chains_key_chain_cli_write_end(struct vty *vty,
+ const struct lyd_node *dnode)
+{
+ vty_out(vty, "exit\n");
+ vty_out(vty, "!\n");
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/description
+ */
+void key_chains_key_chain_description_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ /* Implement CLI */
+ /* vty_out(vty, " description %s\n", yang_dnode_get_string(dnode)); */
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key
+ */
+void key_chains_key_chain_key_cli_write(struct vty *vty,
+ const struct lyd_node *dnode,
+ bool show_defaults)
+{
+ vty_out(vty, " key %s\n", yang_dnode_get_string(dnode, "key-id"));
+}
+
+void key_chains_key_chain_key_cli_write_end(struct vty *vty,
+ const struct lyd_node *dnode)
+{
+ vty_out(vty, " exit\n");
+}
+
+static const char *__dnode_to_key_strftime(char *buf, size_t bufsize,
+ const struct lyd_node *lt_start_dnode)
+{
+ const char *timestr;
+ struct lyd_node *end_node;
+ struct tm tm;
+ uint32_t duration;
+ time_t time;
+ int len, sz;
+ char *s;
+
+ s = buf;
+ sz = bufsize;
+
+ timestr = yang_dnode_get_string(lt_start_dnode, NULL);
+ (void)ly_time_str2time(timestr, &time, NULL);
+ localtime_r(&time, &tm);
+ len = strftime(s, sz, "%T %b %e %Y", &tm);
+ s += len;
+ sz -= len;
+
+ if (yang_dnode_exists(lt_start_dnode, "../no-end-time")) {
+ strlcat(s, " infinite", sz);
+ return buf;
+ }
+
+ end_node = yang_dnode_get(lt_start_dnode, "../duration");
+ if (end_node) {
+ duration = yang_dnode_get_uint32(end_node, NULL);
+ snprintf(s, sz, " duration %u", (uint)duration);
+ return buf;
+ }
+
+ timestr = yang_dnode_get_string(lt_start_dnode, "../end-date-time");
+ (void)ly_time_str2time(timestr, &time, NULL);
+ localtime_r(&time, &tm);
+ strftime(s, sz, " %T %b %e %Y", &tm);
+ return buf;
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time
+ */
+void key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ char s[256];
+
+ vty_out(vty, " send-lifetime %s\n",
+ __dnode_to_key_strftime(s, sizeof(s), dnode));
+ vty_out(vty, " accept-lifetime %s\n", s);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time
+ */
+void key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ char s[256];
+
+ vty_out(vty, " send-lifetime %s\n",
+ __dnode_to_key_strftime(s, sizeof(s), dnode));
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time
+ */
+void key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ char s[256];
+
+ vty_out(vty, " accept-lifetime %s\n",
+ __dnode_to_key_strftime(s, sizeof(s), dnode));
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/crypto-algorithm
+ */
+void key_chains_key_chain_key_crypto_algorithm_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ static const char prefix[] = "ietf-key-chain:";
+ static const int prefix_len = sizeof(prefix) - 1;
+ const char *name = yang_dnode_get_string(dnode, NULL);
+
+ if (!strncmp(name, prefix, prefix_len))
+ name += prefix_len;
+ vty_out(vty, " cryptographic-algorithm %s\n", name);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/key-string/keystring
+ */
+void key_chains_key_chain_key_key_string_keystring_cli_write(
+ struct vty *vty, const struct lyd_node *dnode, bool show_defaults)
+{
+ vty_out(vty, " key-string %s\n", yang_dnode_get_string(dnode, NULL));
+}
+
+static const char * const keychain_features[] = {
+ "independent-send-accept-lifetime",
+ NULL,
+};
+
+/* clang-format off */
+const struct frr_yang_module_info ietf_key_chain_cli_info = {
+ .name = "ietf-key-chain",
+ .features = (const char **)keychain_features,
+ .ignore_cfg_cbs = true,
+ .nodes = {
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain",
+ .cbs = {
+ .cli_show = key_chains_key_chain_cli_write,
+ .cli_show_end = key_chains_key_chain_cli_write_end,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/description",
+ .cbs = {
+ .cli_show = key_chains_key_chain_description_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key",
+ .cbs = {
+ .cli_show = key_chains_key_chain_key_cli_write,
+ .cli_show_end = key_chains_key_chain_key_cli_write_end,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time",
+ .cbs = {
+ .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time",
+ .cbs = {
+ .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time",
+ .cbs = {
+ .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm",
+ .cbs = {
+ .cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/key-string/keystring",
+ .cbs = {
+ .cli_show = key_chains_key_chain_key_key_string_keystring_cli_write,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ }
+};
+
+static int keychain_config_write(struct vty *vty)
+{
+ const struct lyd_node *dnode;
+ int written = 0;
+
+ dnode = yang_dnode_get(running_config->dnode,
+ "/ietf-key-chain:key-chains");
+ if (dnode) {
+ nb_cli_show_dnode_cmds(vty, dnode, false);
+ written = 1;
+ }
+ return written;
+}
+
+static struct cmd_node keychain_node = {
+ .name = "keychain",
+ .node = KEYCHAIN_NODE,
+ .parent_node = CONFIG_NODE,
+ .prompt = "%s(config-keychain)# ",
+ .config_write = keychain_config_write,
+};
+
+static struct cmd_node keychain_key_node = {
+ .name = "keychain key",
+ .node = KEYCHAIN_KEY_NODE,
+ .parent_node = KEYCHAIN_NODE,
+ .prompt = "%s(config-keychain-key)# ",
+};
+
+static const struct cmd_variable_handler keychain_var_handlers[] = {
+ {.varname = "key_chain", .xpath = "/ietf-key-chain:key-chains/key-chain/name" },
+ {.tokenname = "KEYCHAIN_NAME", .xpath = "/ietf-key-chain:key-chains/key-chain/name" },
+ {.completions = NULL}
+};
+
+void keychain_cli_init(void)
+{
+ /* Register handler for keychain auto config support */
+ cmd_variable_handler_register(keychain_var_handlers);
+ install_node(&keychain_node);
+ install_node(&keychain_key_node);
+
+ install_default(KEYCHAIN_NODE);
+ install_default(KEYCHAIN_KEY_NODE);
+
+ install_element(CONFIG_NODE, &key_chain_cmd);
+ install_element(CONFIG_NODE, &no_key_chain_cmd);
+ install_element(KEYCHAIN_NODE, &key_cmd);
+ install_element(KEYCHAIN_NODE, &no_key_cmd);
+
+ install_element(KEYCHAIN_NODE, &key_chain_cmd);
+ install_element(KEYCHAIN_NODE, &no_key_chain_cmd);
+
+ install_element(KEYCHAIN_KEY_NODE, &key_string_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &no_key_string_cmd);
+
+ install_element(KEYCHAIN_KEY_NODE, &key_chain_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &no_key_chain_cmd);
+
+ install_element(KEYCHAIN_KEY_NODE, &key_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &no_key_cmd);
+
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_day_month_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_day_month_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_month_day_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_month_day_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_infinite_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_infinite_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_duration_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &accept_lifetime_duration_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &no_accept_lifetime_cmd);
+
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_day_month_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_day_month_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_month_day_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_month_day_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_infinite_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_infinite_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_duration_day_month_cmd);
+ install_element(KEYCHAIN_KEY_NODE,
+ &send_lifetime_duration_month_day_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &no_send_lifetime_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &cryptographic_algorithm_cmd);
+ install_element(KEYCHAIN_KEY_NODE, &no_cryptographic_algorithm_cmd);
+}
diff --git a/lib/keychain_nb.c b/lib/keychain_nb.c
new file mode 100644
index 0000000..57967b3
--- /dev/null
+++ b/lib/keychain_nb.c
@@ -0,0 +1,898 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * February 22 2024, Christian Hopps <chopps@labn.net>
+ *
+ * Copyright (C) 2024 LabN Consulting, L.L.C.
+ *
+ * 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
+ */
+#include <zebra.h>
+#include "lib_errors.h"
+#include "northbound.h"
+#include "keychain.h"
+
+static void keychain_touch(struct keychain *keychain)
+{
+ keychain->last_touch = time(NULL);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain
+ */
+static int key_chains_key_chain_create(struct nb_cb_create_args *args)
+{
+ const char *name;
+ struct keychain *keychain;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "name");
+ keychain = keychain_get(name);
+ keychain_touch(keychain);
+ return NB_OK;
+}
+
+static int key_chains_key_chain_destroy(struct nb_cb_destroy_args *args)
+{
+ const char *name;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "name");
+ keychain_delete(keychain_lookup(name));
+ return NB_OK;
+}
+
+static const void *key_chains_key_chain_get_next(struct nb_cb_get_next_args *args)
+{
+ const struct listnode *prev = args->list_entry;
+
+ return prev ? prev->next : keychain_list->head;
+}
+
+static int key_chains_key_chain_get_keys(struct nb_cb_get_keys_args *args)
+{
+ const struct listnode *node = args->list_entry;
+ const struct keychain *keychain = node->data;
+
+ args->keys->num = 1;
+ strlcpy(args->keys->key[0], keychain->name, sizeof(args->keys->key[0]));
+ return NB_OK;
+}
+
+static const void *key_chains_key_chain_lookup_entry(struct nb_cb_lookup_entry_args *args)
+{
+ const char *name = args->keys->key[0];
+ struct keychain *keychain;
+ struct listnode *node;
+
+ for (ALL_LIST_ELEMENTS_RO(keychain_list, node, keychain)) {
+ if (strcmp(keychain->name, name) == 0)
+ return node;
+ }
+ return NULL;
+}
+
+
+static int __destroy_nop(struct nb_cb_destroy_args *args)
+{
+ /* modified by sibling or cleaned up by container destroy */
+ return NB_OK;
+}
+
+static struct key *__dnode_get_key2(const struct lyd_node *dnode, bool touch)
+{
+ struct keychain *keychain;
+ const char *name;
+ struct key *key;
+ uint32_t index;
+
+ name = yang_dnode_get_string(dnode, "../../../name");
+ keychain = keychain_lookup(name);
+ index = (uint32_t)yang_dnode_get_uint64(dnode, "../../key-id");
+ key = key_lookup(keychain, index);
+ if (touch)
+ keychain_touch(keychain);
+ return key;
+}
+
+static struct key *__dnode_get_key3(const struct lyd_node *dnode, bool touch)
+{
+ struct keychain *keychain;
+ const char *name;
+ struct key *key;
+ uint32_t index;
+
+ name = yang_dnode_get_string(dnode, "../../../../name");
+ keychain = keychain_lookup(name);
+ index = (uint32_t)yang_dnode_get_uint64(dnode, "../../../key-id");
+ key = key_lookup(keychain, index);
+ if (touch)
+ keychain_touch(keychain);
+ return key;
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/description
+ */
+static int key_chains_key_chain_description_modify(struct nb_cb_modify_args *args)
+{
+ struct keychain *keychain;
+ const char *name;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "../name");
+ keychain = keychain_lookup(name);
+ XFREE(MTYPE_KEYCHAIN_DESC, keychain->desc);
+ keychain->desc = XSTRDUP(MTYPE_KEYCHAIN_DESC,
+ yang_dnode_get_string(args->dnode, NULL));
+
+ keychain_touch(keychain);
+ return NB_OK;
+}
+
+static int key_chains_key_chain_description_destroy(struct nb_cb_destroy_args *args)
+{
+ struct keychain *keychain;
+ const char *name;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "../name");
+ keychain = keychain_lookup(name);
+ XFREE(MTYPE_KEYCHAIN_DESC, keychain->desc);
+
+ keychain_touch(keychain);
+ return NB_OK;
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/last-modified-timestamp
+ */
+static struct yang_data *key_chains_key_chain_last_modified_timestamp_get_elem(struct nb_cb_get_elem_args *args)
+{
+ const struct listnode *kcnode = args->list_entry;
+ const struct keychain *keychain = kcnode->data;
+
+ return yang_data_new_date_and_time(args->xpath, keychain->last_touch,
+ false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key
+ */
+static int key_chains_key_chain_key_create(struct nb_cb_create_args *args)
+{
+ struct keychain *keychain;
+ struct key *key;
+ const char *name;
+ uint64_t keyid;
+
+ if (args->event != NB_EV_VALIDATE && args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ keyid = yang_dnode_get_uint64(args->dnode, "key-id");
+ if (args->event == NB_EV_VALIDATE) {
+ if (keyid > UINT32_MAX) {
+ /* Warn most protocols can't use this value */
+ flog_err(EC_LIB_NB_CB_CONFIG_VALIDATE,
+ "Protocols do not accept > 32-bit key-id values");
+ return NB_EV_VALIDATE;
+ }
+ return NB_OK;
+ }
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "../name");
+ keychain = keychain_lookup(name);
+ assert(keyid <= UINT32_MAX);
+ key = key_get(keychain, (uint32_t)keyid);
+ assert(key);
+
+ keychain_touch(keychain);
+ return NB_OK;
+}
+
+static int key_chains_key_chain_key_destroy(struct nb_cb_destroy_args *args)
+{
+ struct keychain *keychain;
+ struct key *key;
+ const char *name;
+ uint64_t keyid;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ keyid = yang_dnode_get_uint64(args->dnode, "key-id");
+ if (keyid > UINT32_MAX)
+ return NB_ERR_NOT_FOUND;
+ name = yang_dnode_get_string(args->dnode, "../name");
+ keychain = keychain_lookup(name);
+ key = key_lookup(keychain, (uint32_t)keyid);
+ key_delete(keychain, key);
+
+ keychain_touch(keychain);
+ return NB_OK;
+}
+
+static const void *key_chains_key_chain_key_get_next(struct nb_cb_get_next_args *args)
+{
+ const struct listnode *kcnode = args->parent_list_entry;
+ const struct keychain *keychain = kcnode->data;
+ const struct listnode *prev = args->list_entry;
+
+ return prev ? prev->next : keychain->key->head;
+}
+
+static int key_chains_key_chain_key_get_keys(struct nb_cb_get_keys_args *args)
+{
+ const struct listnode *node = args->list_entry;
+ const struct key *key = node->data;
+
+ args->keys->num = 1;
+ snprintf(args->keys->key[0], sizeof(args->keys->key[0]), "%" PRIu32,
+ key->index);
+
+ return NB_OK;
+}
+
+static const void *key_chains_key_chain_key_lookup_entry(struct nb_cb_lookup_entry_args *args)
+{
+ const struct listnode *kcnode = args->parent_list_entry;
+ const struct keychain *keychain = kcnode->data;
+ struct listnode *node;
+ struct key *key;
+ uint32_t index;
+
+ index = strtoul(args->keys->key[0], NULL, 0);
+ for (ALL_LIST_ELEMENTS_RO(keychain->key, node, key))
+ if (key->index == index)
+ return node;
+ return NULL;
+}
+
+static int __lifetime_create(struct nb_cb_create_args *args, bool send,
+ bool accept, bool always)
+{
+ struct key *key;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ if (always)
+ key = __dnode_get_key3(args->dnode, true);
+ else
+ key = __dnode_get_key2(args->dnode, true);
+ if (send) {
+ key->send.start = 0;
+ key->send.end = -1;
+ key->send.duration = 0;
+ }
+ if (accept) {
+ key->accept.start = 0;
+ key->accept.end = -1;
+ key->accept.duration = 0;
+ }
+ return NB_OK;
+}
+
+static int __lifetime_start_date_time_modify(struct nb_cb_modify_args *args,
+ bool send, bool accept)
+{
+ struct key *key;
+ time_t time;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ key = __dnode_get_key3(args->dnode, true);
+ time = yang_dnode_get_date_and_time(args->dnode, NULL);
+
+ if (send)
+ key->send.start = time;
+ if (accept)
+ key->accept.start = time;
+
+ return NB_OK;
+}
+
+static int __lifetime_no_end_time_create(struct nb_cb_create_args *args,
+ bool send, bool accept)
+{
+ struct key *key;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ key = __dnode_get_key3(args->dnode, true);
+ if (send)
+ key->send.end = -1;
+ if (accept)
+ key->accept.end = -1;
+ return NB_OK;
+}
+
+static int __lifetime_duration_modify(struct nb_cb_modify_args *args, bool send,
+ bool accept)
+{
+ struct key *key;
+ uint32_t duration;
+ time_t time;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ key = __dnode_get_key3(args->dnode, true);
+ time = yang_dnode_get_date_and_time(args->dnode, "../start-date-time");
+ duration = yang_dnode_get_uint32(args->dnode, NULL);
+
+ if (send)
+ key->send.end = time + duration;
+ if (accept)
+ key->accept.end = time + duration;
+ return NB_OK;
+}
+
+static int __lifetime_end_date_time_modify(struct nb_cb_modify_args *args,
+ bool send, bool accept)
+{
+ struct key *key;
+ time_t time;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ key = __dnode_get_key3(args->dnode, true);
+ time = yang_dnode_get_date_and_time(args->dnode, NULL);
+
+ if (send)
+ key->send.end = time;
+ if (accept)
+ key->accept.end = time;
+ return NB_OK;
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime
+ */
+static int key_chains_key_chain_key_lifetime_send_accept_lifetime_create(
+ struct nb_cb_create_args *args)
+{
+
+ return __lifetime_create(args, true, true, false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always
+ */
+static int key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create(
+ struct nb_cb_create_args *args)
+{
+ return __lifetime_create(args, true, true, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time
+ */
+static int
+key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify(
+ struct nb_cb_modify_args *args)
+{
+ return __lifetime_start_date_time_modify(args, true, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time
+ */
+static int
+key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create(
+ struct nb_cb_create_args *args)
+{
+ return __lifetime_no_end_time_create(args, true, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration
+ */
+static int key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify(
+ struct nb_cb_modify_args *args)
+{
+ return __lifetime_duration_modify(args, true, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time
+ */
+static int
+key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify(
+ struct nb_cb_modify_args *args)
+{
+ return __lifetime_end_date_time_modify(args, true, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime
+ */
+static int key_chains_key_chain_key_lifetime_send_lifetime_create(
+ struct nb_cb_create_args *args)
+{
+
+ return __lifetime_create(args, true, false, false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always
+ */
+static int key_chains_key_chain_key_lifetime_send_lifetime_always_create(
+ struct nb_cb_create_args *args)
+{
+ return __lifetime_create(args, true, false, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time
+ */
+static int key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_modify(struct nb_cb_modify_args *args)
+{
+ return __lifetime_start_date_time_modify(args, true, false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/no-end-time
+ */
+static int key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_create(struct nb_cb_create_args *args)
+{
+ return __lifetime_no_end_time_create(args, true, false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/duration
+ */
+static int key_chains_key_chain_key_lifetime_send_lifetime_duration_modify(struct nb_cb_modify_args *args)
+{
+ return __lifetime_duration_modify(args, true, false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/end-date-time
+ */
+static int key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_modify(struct nb_cb_modify_args *args)
+{
+ return __lifetime_end_date_time_modify(args, true, false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime
+ */
+static int key_chains_key_chain_key_lifetime_accept_lifetime_create(
+ struct nb_cb_create_args *args)
+{
+
+ return __lifetime_create(args, false, true, false);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/always
+ */
+static int key_chains_key_chain_key_lifetime_accept_lifetime_always_create(struct nb_cb_create_args *args)
+{
+ return __lifetime_create(args, false, true, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time
+ */
+static int key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_modify(struct nb_cb_modify_args *args)
+{
+ return __lifetime_start_date_time_modify(args, false, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/no-end-time
+ */
+static int key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_create(struct nb_cb_create_args *args)
+{
+ return __lifetime_no_end_time_create(args, false, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/duration
+ */
+static int key_chains_key_chain_key_lifetime_accept_lifetime_duration_modify(struct nb_cb_modify_args *args)
+{
+ return __lifetime_duration_modify(args, false, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/end-date-time
+ */
+static int key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_modify(struct nb_cb_modify_args *args)
+{
+ return __lifetime_end_date_time_modify(args, false, true);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/crypto-algorithm
+ */
+static int key_chains_key_chain_key_crypto_algorithm_modify(struct nb_cb_modify_args *args)
+{
+ static const char prefix[] = "ietf-key-chain:";
+ static const int prefix_len = sizeof(prefix) - 1;
+ struct keychain *keychain;
+ const char *name;
+ struct key *key;
+ uint32_t index;
+ uint8_t hash_algo;
+
+ if (args->event != NB_EV_VALIDATE && args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, NULL);
+ if (!strncmp(name, prefix, prefix_len))
+ name += prefix_len;
+ hash_algo = keychain_get_algo_id_by_name(name);
+
+ if (args->event == NB_EV_VALIDATE) {
+ if (!hash_algo) {
+ zlog_err("\"%s\" hash algo not supported", name);
+ return NB_ERR_VALIDATION;
+ }
+#ifndef CRYPTO_OPENSSL
+ if (hash_algo == KEYCHAIN_ALGO_NULL) {
+ zlog_err("\"%s\" algo not supported, compile with --with-crypto=openssl",
+ name);
+ return NB_ERR_VALIDATION;
+ }
+#endif /* CRYPTO_OPENSSL */
+ return NB_OK;
+ }
+
+ assert(args->event == NB_EV_APPLY);
+ name = yang_dnode_get_string(args->dnode, "../../name");
+ keychain = keychain_lookup(name);
+ index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../key-id");
+ key = key_lookup(keychain, index);
+ key->hash_algo = hash_algo;
+
+ keychain_touch(keychain);
+ return NB_OK;
+}
+
+static int key_chains_key_chain_key_crypto_algorithm_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ struct keychain *keychain;
+ const char *name;
+ struct key *key;
+ uint32_t index;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "../../../name");
+ keychain = keychain_lookup(name);
+ index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id");
+ key = key_lookup(keychain, index);
+ key->hash_algo = KEYCHAIN_ALGO_NULL;
+ keychain_touch(keychain);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/key-string/keystring
+ */
+static int key_chains_key_chain_key_key_string_keystring_modify(struct nb_cb_modify_args *args)
+{
+ struct keychain *keychain;
+ const char *name;
+ struct key *key;
+ uint32_t index;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "../../../name");
+ keychain = keychain_lookup(name);
+ index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id");
+ key = key_lookup(keychain, index);
+ assert(key);
+
+
+ if (key->string)
+ XFREE(MTYPE_KEY, key->string);
+ key->string = XSTRDUP(MTYPE_KEY,
+ yang_dnode_get_string(args->dnode, NULL));
+
+ keychain_touch(keychain);
+ return NB_OK;
+}
+
+static int key_chains_key_chain_key_key_string_keystring_destroy(struct nb_cb_destroy_args *args)
+{
+ struct keychain *keychain;
+ const char *name;
+ struct key *key;
+ uint32_t index;
+
+ if (args->event != NB_EV_APPLY)
+ return NB_OK;
+
+ name = yang_dnode_get_string(args->dnode, "../../../name");
+ keychain = keychain_lookup(name);
+ index = (uint32_t)yang_dnode_get_uint64(args->dnode, "../../key-id");
+ key = key_lookup(keychain, index);
+ assert(key);
+
+ XFREE(MTYPE_KEY, key->string);
+ keychain_touch(keychain);
+
+ return NB_OK;
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/send-lifetime-active
+ */
+static struct yang_data *key_chains_key_chain_key_send_lifetime_active_get_elem(struct nb_cb_get_elem_args *args)
+{
+ const struct listnode *node = args->list_entry;
+ const struct key *key = node->data;
+ time_t now = time(NULL);
+ bool active = false;
+
+ if (key->send.start == 0)
+ active = true;
+ else if (key->send.start <= now)
+ if (key->send.end >= now || key->send.end == -1)
+ active = true;
+
+ return yang_data_new_bool(args->xpath, active);
+}
+
+/*
+ * XPath: /ietf-key-chain:key-chains/key-chain/key/accept-lifetime-active
+ */
+static struct yang_data *key_chains_key_chain_key_accept_lifetime_active_get_elem(struct nb_cb_get_elem_args *args)
+{
+ const struct listnode *node = args->list_entry;
+ const struct key *key = node->data;
+ time_t now = time(NULL);
+ bool active = false;
+
+ if (key->accept.start == 0)
+ active = true;
+ else if (key->accept.start <= now)
+ if (key->accept.end >= now || key->accept.end == -1)
+ active = true;
+
+ return yang_data_new_bool(args->xpath, active);
+}
+
+static const char * const keychain_features[] = {
+ "independent-send-accept-lifetime",
+ NULL,
+};
+
+/* clang-format off */
+const struct frr_yang_module_info ietf_key_chain_info = {
+ .name = "ietf-key-chain",
+ .features = (const char **)keychain_features,
+ .nodes = {
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain",
+ .cbs = {
+ .create = key_chains_key_chain_create,
+ .destroy = key_chains_key_chain_destroy,
+ .get_next = key_chains_key_chain_get_next,
+ .get_keys = key_chains_key_chain_get_keys,
+ .lookup_entry = key_chains_key_chain_lookup_entry,
+ .cli_show = key_chains_key_chain_cli_write,
+ .cli_show_end = key_chains_key_chain_cli_write_end,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/description",
+ .cbs = {
+ .modify = key_chains_key_chain_description_modify,
+ .destroy = key_chains_key_chain_description_destroy,
+ .cli_show = key_chains_key_chain_description_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/last-modified-timestamp",
+ .cbs = {
+ .get_elem = key_chains_key_chain_last_modified_timestamp_get_elem,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key",
+ .cbs = {
+ .create = key_chains_key_chain_key_create,
+ .destroy = key_chains_key_chain_key_destroy,
+ .get_next = key_chains_key_chain_key_get_next,
+ .get_keys = key_chains_key_chain_key_get_keys,
+ .lookup_entry = key_chains_key_chain_key_lookup_entry,
+ .cli_show = key_chains_key_chain_key_cli_write,
+ .cli_show_end = key_chains_key_chain_key_cli_write_end,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_send_accept_lifetime_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/always",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_send_accept_lifetime_always_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/start-date-time",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_modify,
+ .destroy = __destroy_nop,
+ .cli_show = key_chains_key_chain_key_lifetime_send_accept_lifetime_start_date_time_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/no-end-time",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_send_accept_lifetime_no_end_time_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/duration",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_duration_modify,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-accept-lifetime/end-date-time",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_send_accept_lifetime_end_date_time_modify,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_send_lifetime_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/always",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_send_lifetime_always_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/start-date-time",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_modify,
+ .destroy = __destroy_nop,
+ .cli_show = key_chains_key_chain_key_lifetime_send_lifetime_start_date_time_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/no-end-time",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_send_lifetime_no_end_time_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/duration",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_send_lifetime_duration_modify,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/send-lifetime/end-date-time",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_send_lifetime_end_date_time_modify,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_accept_lifetime_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/always",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_accept_lifetime_always_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/start-date-time",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_modify,
+ .destroy = __destroy_nop,
+ .cli_show = key_chains_key_chain_key_lifetime_accept_lifetime_start_date_time_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/no-end-time",
+ .cbs = {
+ .create = key_chains_key_chain_key_lifetime_accept_lifetime_no_end_time_create,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/duration",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_accept_lifetime_duration_modify,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/lifetime/accept-lifetime/end-date-time",
+ .cbs = {
+ .modify = key_chains_key_chain_key_lifetime_accept_lifetime_end_date_time_modify,
+ .destroy = __destroy_nop,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/crypto-algorithm",
+ .cbs = {
+ .modify = key_chains_key_chain_key_crypto_algorithm_modify,
+ .destroy = key_chains_key_chain_key_crypto_algorithm_destroy,
+ .cli_show = key_chains_key_chain_key_crypto_algorithm_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/key-string/keystring",
+ .cbs = {
+ .modify = key_chains_key_chain_key_key_string_keystring_modify,
+ .destroy = key_chains_key_chain_key_key_string_keystring_destroy,
+ .cli_show = key_chains_key_chain_key_key_string_keystring_cli_write,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/send-lifetime-active",
+ .cbs = {
+ .get_elem = key_chains_key_chain_key_send_lifetime_active_get_elem,
+ }
+ },
+ {
+ .xpath = "/ietf-key-chain:key-chains/key-chain/key/accept-lifetime-active",
+ .cbs = {
+ .get_elem = key_chains_key_chain_key_accept_lifetime_active_get_elem,
+ }
+ },
+ {
+ .xpath = NULL,
+ },
+ },
+};
diff --git a/lib/lib_errors.c b/lib/lib_errors.c
index a96fac9..9d6c043 100644
--- a/lib/lib_errors.c
+++ b/lib/lib_errors.c
@@ -308,24 +308,6 @@ static struct log_ref ferr_lib_err[] = {
.suggestion = "Check if the FRR libyang plugins were installed correctly in the system",
},
{
- .code = EC_LIB_CONFD_INIT,
- .title = "ConfD initialization error",
- .description = "Upon startup FRR failed to properly initialize and startup the ConfD northbound plugin",
- .suggestion = "Check if ConfD is installed correctly in the system. Also, check if the confd daemon is running.",
- },
- {
- .code = EC_LIB_CONFD_DATA_CONVERT,
- .title = "ConfD data conversion error",
- .description = "An error has occurred while converting a ConfD data value (binary) to a string",
- .suggestion = "Open an Issue with all relevant log files and restart FRR"
- },
- {
- .code = EC_LIB_LIBCONFD,
- .title = "libconfd error",
- .description = "The northbound subsystem has detected that the libconfd library returned an error",
- .suggestion = "Open an Issue with all relevant log files and restart FRR"
- },
- {
.code = EC_LIB_SYSREPO_INIT,
.title = "Sysrepo initialization error",
.description = "Upon startup FRR failed to properly initialize and startup the Sysrepo northbound plugin",
diff --git a/lib/lib_errors.h b/lib/lib_errors.h
index 8cdfb16..9e0d539 100644
--- a/lib/lib_errors.h
+++ b/lib/lib_errors.h
@@ -65,9 +65,6 @@ enum lib_log_refs {
EC_LIB_NB_TRANSACTION_RECORD_FAILED,
EC_LIB_LIBYANG,
EC_LIB_LIBYANG_PLUGIN_LOAD,
- EC_LIB_CONFD_INIT,
- EC_LIB_CONFD_DATA_CONVERT,
- EC_LIB_LIBCONFD,
EC_LIB_SYSREPO_INIT,
EC_LIB_SYSREPO_DATA_CONVERT,
EC_LIB_LIBSYSREPO,
diff --git a/lib/libagentx.c b/lib/libagentx.c
new file mode 100644
index 0000000..2382657
--- /dev/null
+++ b/lib/libagentx.c
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* SNMP cli support
+ * Copyright (C) 2024 Donald Sharp <sharpd@nvidia.com> NVIDIA Corporation
+ */
+#include <zebra.h>
+
+#include "lib/hook.h"
+#include "lib/libagentx.h"
+#include "command.h"
+
+DEFINE_HOOK(agentx_cli_enabled, (), ());
+DEFINE_HOOK(agentx_cli_disabled, (), ());
+
+bool agentx_enabled;
+
+/* AgentX node. */
+static int config_write_agentx(struct vty *vty)
+{
+ if (agentx_enabled)
+ vty_out(vty, "agentx\n");
+ return 1;
+}
+
+static struct cmd_node agentx_node = {
+ .name = "smux",
+ .node = SMUX_NODE,
+ .prompt = "",
+ .config_write = config_write_agentx,
+};
+
+DEFUN(agentx_enable, agentx_enable_cmd, "agentx",
+ "SNMP AgentX protocol settings\n")
+{
+ if (!hook_have_hooks(agentx_cli_enabled)) {
+ zlog_info(
+ "agentx specified but the agentx Module is not loaded, is this intentional?");
+
+ return CMD_SUCCESS;
+ }
+
+ hook_call(agentx_cli_enabled);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(no_agentx, no_agentx_cmd, "no agentx",
+ NO_STR "SNMP AgentX protocol settings\n")
+{
+ vty_out(vty, "SNMP AgentX support cannot be disabled once enabled\n");
+ if (!hook_call(agentx_cli_disabled))
+ return CMD_WARNING_CONFIG_FAILED;
+
+ return CMD_SUCCESS;
+}
+
+void libagentx_init(void)
+{
+ agentx_enabled = false;
+
+ install_node(&agentx_node);
+ install_element(CONFIG_NODE, &agentx_enable_cmd);
+ install_element(CONFIG_NODE, &no_agentx_cmd);
+}
diff --git a/lib/libagentx.h b/lib/libagentx.h
new file mode 100644
index 0000000..c3246d9
--- /dev/null
+++ b/lib/libagentx.h
@@ -0,0 +1,14 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/* SNMP cli support
+ * Copyright (C) 2024 Donald Sharp <sharpd@nvidia.com> NVIDIA Corporation
+ */
+#ifndef __LIBAGENTX_H__
+#define __LIBAGENTX_H__
+
+extern void libagentx_init(void);
+extern bool agentx_enabled;
+
+DECLARE_HOOK(agentx_cli_enabled, (), ());
+DECLARE_HOOK(agentx_cli_disabled, (), ());
+
+#endif
diff --git a/lib/libfrr.c b/lib/libfrr.c
index 2861ebe..cc60cfb 100644
--- a/lib/libfrr.c
+++ b/lib/libfrr.c
@@ -59,7 +59,7 @@ char config_default[512];
char frr_zclientpath[512];
static char pidfile_default[1024];
#ifdef HAVE_SQLITE3
-static char dbfile_default[512];
+static char dbfile_default[1024];
#endif
static char vtypath_default[512];
@@ -319,7 +319,12 @@ void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv)
char *p = strrchr(argv[0], '/');
di->progname = p ? p + 1 : argv[0];
- umask(0027);
+ if (!getenv("GCOV_PREFIX"))
+ umask(0027);
+ else {
+ /* If we are profiling use a more generous umask */
+ umask(0002);
+ }
log_args_init(daemon->early_logging);
@@ -1035,7 +1040,17 @@ void frr_config_fork(void)
zlog_tls_buffer_init();
}
-void frr_vty_serv_start(void)
+static void frr_check_detach(void)
+{
+ if (nodetach_term || nodetach_daemon)
+ return;
+
+ if (daemon_ctl_sock != -1)
+ close(daemon_ctl_sock);
+ daemon_ctl_sock = -1;
+}
+
+void frr_vty_serv_start(bool check_detach)
{
/* allow explicit override of vty_path in the future
* (not currently set anywhere) */
@@ -1058,6 +1073,9 @@ void frr_vty_serv_start(void)
}
vty_serv_start(di->vty_addr, di->vty_port, di->vty_path);
+
+ if (check_detach)
+ frr_check_detach();
}
void frr_vty_serv_stop(void)
@@ -1068,16 +1086,6 @@ void frr_vty_serv_stop(void)
unlink(di->vty_path);
}
-static void frr_check_detach(void)
-{
- if (nodetach_term || nodetach_daemon)
- return;
-
- if (daemon_ctl_sock != -1)
- close(daemon_ctl_sock);
- daemon_ctl_sock = -1;
-}
-
static void frr_terminal_close(int isexit)
{
int nullfd;
@@ -1163,7 +1171,7 @@ void frr_run(struct event_loop *master)
char instanceinfo[64] = "";
if (!(di->flags & FRR_MANUAL_VTY_START))
- frr_vty_serv_start();
+ frr_vty_serv_start(false);
if (di->instance)
snprintf(instanceinfo, sizeof(instanceinfo), "instance %u ",
@@ -1201,7 +1209,8 @@ void frr_run(struct event_loop *master)
close(nullfd);
}
- frr_check_detach();
+ if (!(di->flags & FRR_MANUAL_VTY_START))
+ frr_check_detach();
}
/* end fixed stderr startup logging */
@@ -1445,3 +1454,12 @@ void _libfrr_version(void)
write(1, banner, sizeof(banner) - 1);
_exit(0);
}
+
+/* Render simple version tuple to string */
+const char *frr_vers2str(uint32_t version, char *buf, int buflen)
+{
+ snprintf(buf, buflen, "%d.%d.%d", MAJOR_FRRVERSION(version),
+ MINOR_FRRVERSION(version), SUB_FRRVERSION(version));
+
+ return buf;
+}
diff --git a/lib/libfrr.h b/lib/libfrr.h
index ee436d9..d52ee9a 100644
--- a/lib/libfrr.h
+++ b/lib/libfrr.h
@@ -200,7 +200,7 @@ extern void frr_config_fork(void);
extern void frr_run(struct event_loop *master);
extern void frr_detach(void);
-extern void frr_vty_serv_start(void);
+extern void frr_vty_serv_start(bool check_detach);
extern void frr_vty_serv_stop(void);
extern bool frr_zclient_addr(struct sockaddr_storage *sa, socklen_t *sa_len,
@@ -233,6 +233,17 @@ extern bool frr_is_after_fork;
extern bool debug_memstats_at_exit;
+/*
+ * Version numbering: MAJOR (8) | MINOR (16) | SUB (8)
+ */
+#define MAKE_FRRVERSION(maj, min, sub) \
+ ((((maj) & 0xff) << 24) | (((min) & 0xffff) << 8) | ((sub) & 0xff))
+#define MAJOR_FRRVERSION(v) (((v) >> 24) & 0xff)
+#define MINOR_FRRVERSION(v) (((v) >> 8) & 0xffff)
+#define SUB_FRRVERSION(v) ((v) & 0xff)
+
+const char *frr_vers2str(uint32_t version, char *buf, int buflen);
+
#ifdef __cplusplus
}
#endif
diff --git a/lib/libfrr_trace.c b/lib/libfrr_trace.c
index 5932032..14f4a3c 100644
--- a/lib/libfrr_trace.c
+++ b/lib/libfrr_trace.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
diff --git a/lib/libospf.h b/lib/libospf.h
index 45e7fb1..0ac490a 100644
--- a/lib/libospf.h
+++ b/lib/libospf.h
@@ -69,6 +69,7 @@ extern "C" {
#define OSPF_MTU_IGNORE_DEFAULT 0
#define OSPF_FAST_HELLO_DEFAULT 0
#define OSPF_P2MP_DELAY_REFLOOD_DEFAULT false
+#define OSPF_P2MP_NON_BROADCAST_DEFAULT false
#define OSPF_OPAQUE_CAPABLE_DEFAULT true
#define OSPF_PREFIX_SUPPRESSION_DEFAULT false
#define OSPF_AREA_BACKBONE 0x00000000 /* 0.0.0.0 */
diff --git a/lib/link_state.c b/lib/link_state.c
index 25373bd..c758b7f 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -140,6 +140,12 @@ int ls_node_same(struct ls_node *n1, struct ls_node *n2)
if (CHECK_FLAG(n1->flags, LS_NODE_MSD) && (n1->msd != n2->msd))
return 0;
}
+ if (CHECK_FLAG(n1->flags, LS_NODE_SRV6)) {
+ if (n1->srv6_cap_flags != n2->srv6_cap_flags)
+ return 0;
+ if (memcmp(&n1->srv6_msd, &n2->srv6_msd, sizeof(n1->srv6_msd)))
+ return 0;
+ }
/* OK, n1 & n2 are equal */
return 1;
@@ -320,6 +326,23 @@ int ls_attributes_same(struct ls_attributes *l1, struct ls_attributes *l2)
&l2->adj_sid[i].neighbor.addr)))
return 0;
}
+ for (int i = 0; i < ADJ_SRV6_MAX; i++) {
+ if (!CHECK_FLAG(l1->flags, (LS_ATTR_ADJ_SRV6SID << i)))
+ continue;
+ if (memcmp(&l1->adj_srv6_sid[i].sid, &l2->adj_srv6_sid[i].sid,
+ sizeof(struct in6_addr)) ||
+ (l1->adj_srv6_sid[i].flags != l2->adj_srv6_sid[i].flags) ||
+ (l1->adj_srv6_sid[i].weight != l2->adj_srv6_sid[i].weight) ||
+ (l1->adj_srv6_sid[i].endpoint_behavior !=
+ l2->adj_srv6_sid[i].endpoint_behavior))
+ return 0;
+ if (((l1->adv.origin == ISIS_L1) ||
+ (l1->adv.origin == ISIS_L2)) &&
+ (memcmp(&l1->adj_srv6_sid[i].neighbor.sysid,
+ &l2->adj_srv6_sid[i].neighbor.sysid,
+ ISO_SYS_ID_LEN) != 0))
+ return 0;
+ }
if (CHECK_FLAG(l1->flags, LS_ATTR_SRLG)
&& ((l1->srlg_len != l2->srlg_len)
|| memcmp(l1->srlgs, l2->srlgs,
@@ -1298,6 +1321,26 @@ static struct ls_attributes *ls_parse_attributes(struct stream *s)
STREAM_GET(attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid, s,
ISO_SYS_ID_LEN);
}
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) {
+ STREAM_GET(&attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid, s,
+ sizeof(struct in6_addr));
+ STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags);
+ STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight);
+ STREAM_GETW(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6]
+ .endpoint_behavior);
+ STREAM_GET(attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].neighbor.sysid,
+ s, ISO_SYS_ID_LEN);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) {
+ STREAM_GET(&attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid, s,
+ sizeof(struct in6_addr));
+ STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags);
+ STREAM_GETC(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight);
+ STREAM_GETW(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6]
+ .endpoint_behavior);
+ STREAM_GET(attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].neighbor.sysid,
+ s, ISO_SYS_ID_LEN);
+ }
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
STREAM_GETC(s, len);
attr->srlgs = XCALLOC(MTYPE_LS_DB, len*sizeof(uint32_t));
@@ -1532,6 +1575,28 @@ static int ls_format_attributes(struct stream *s, struct ls_attributes *attr)
stream_put(s, attr->adj_sid[ADJ_BCK_IPV6].neighbor.sysid,
ISO_SYS_ID_LEN);
}
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) {
+ stream_put(s, &attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid,
+ sizeof(struct in6_addr));
+ stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags);
+ stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight);
+ stream_putw(s, attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6]
+ .endpoint_behavior);
+ stream_put(s,
+ attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].neighbor.sysid,
+ ISO_SYS_ID_LEN);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) {
+ stream_put(s, &attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid,
+ sizeof(struct in6_addr));
+ stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags);
+ stream_putc(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight);
+ stream_putw(s, attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6]
+ .endpoint_behavior);
+ stream_put(s,
+ attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].neighbor.sysid,
+ ISO_SYS_ID_LEN);
+ }
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
stream_putc(s, attr->srlg_len);
for (len = 0; len < attr->srlg_len; len++)
@@ -2351,6 +2416,24 @@ static void ls_show_edge_vty(struct ls_edge *edge, struct vty *vty,
attr->adj_sid[ADJ_BCK_IPV6].flags,
attr->adj_sid[ADJ_BCK_IPV6].weight);
}
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) {
+ sbuf_push(&sbuf, 4, "IPv6 Adjacency-SRV6-SID: %pI6",
+ &attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid);
+ sbuf_push(&sbuf, 0,
+ "\tFlags: 0x%x\tWeight: 0x%x\tbehavior: 0x%x\n",
+ attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags,
+ attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight,
+ attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].endpoint_behavior);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) {
+ sbuf_push(&sbuf, 4, "IPv6 Bck. Adjacency-SRV6-SID: %pI6",
+ &attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid);
+ sbuf_push(&sbuf, 0,
+ "\tFlags: 0x%x\tWeight: 0x%x\tbehavior: 0x%x\n",
+ attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags,
+ attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight,
+ attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].endpoint_behavior);
+ }
if (CHECK_FLAG(attr->flags, LS_ATTR_SRLG)) {
sbuf_push(&sbuf, 4, "SRLGs: %d", attr->srlg_len);
for (int i = 1; i < attr->srlg_len; i++) {
@@ -2372,7 +2455,7 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
struct ls_attributes *attr;
struct json_object *jte, *jbw, *jobj, *jsr = NULL, *jsrlg, *js_ext_ag,
*js_ext_ag_arr_word,
- *js_ext_ag_arr_bit;
+ *js_ext_ag_arr_bit, *jsrv6 = NULL;
char buf[INET6_BUFSIZ];
char buf_ag[strlen("0xffffffff") + 1];
uint32_t bitmap;
@@ -2557,6 +2640,45 @@ static void ls_show_edge_json(struct ls_edge *edge, struct json_object *json)
attr->adj_sid[ADJ_BCK_IPV6].weight);
json_object_array_add(jsr, jobj);
}
+ if (CHECK_FLAG(attr->flags, LS_ATTR_ADJ_SRV6SID)) {
+ jsrv6 = json_object_new_array();
+ json_object_object_add(json, "segment-routing-ipv6", jsrv6);
+ jobj = json_object_new_object();
+ snprintfrr(buf, INET6_BUFSIZ, "%pI6",
+ &attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].sid);
+ json_object_string_add(jobj, "adj-sid", buf);
+ snprintfrr(buf, 6, "0x%x",
+ attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].flags);
+ json_object_string_add(jobj, "flags", buf);
+ json_object_int_add(jobj, "weight",
+ attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6].weight);
+ snprintfrr(buf, 6, "0x%x",
+ attr->adj_srv6_sid[ADJ_SRV6_PRI_IPV6]
+ .endpoint_behavior);
+ json_object_string_add(jobj, "endpoint-behavior", buf);
+ json_object_array_add(jsr, jobj);
+ }
+ if (CHECK_FLAG(attr->flags, LS_ATTR_BCK_ADJ_SRV6SID)) {
+ if (!jsrv6) {
+ jsrv6 = json_object_new_array();
+ json_object_object_add(json, "segment-routing-ipv6",
+ jsrv6);
+ }
+ jobj = json_object_new_object();
+ snprintfrr(buf, INET6_BUFSIZ, "%pI6",
+ &attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].sid);
+ json_object_string_add(jobj, "adj-sid", buf);
+ snprintfrr(buf, 6, "0x%x",
+ attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].flags);
+ json_object_string_add(jobj, "flags", buf);
+ json_object_int_add(jobj, "weight",
+ attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6].weight);
+ snprintfrr(buf, 6, "0x%x",
+ attr->adj_srv6_sid[ADJ_SRV6_BCK_IPV6]
+ .endpoint_behavior);
+ json_object_string_add(jobj, "endpoint-behavior", buf);
+ json_object_array_add(jsr, jobj);
+ }
}
void ls_show_edge(struct ls_edge *edge, struct vty *vty,
diff --git a/lib/link_state.h b/lib/link_state.h
index d3a0ce3..d819c20 100644
--- a/lib/link_state.h
+++ b/lib/link_state.h
@@ -106,6 +106,7 @@ extern int ls_node_id_same(struct ls_node_id i1, struct ls_node_id i2);
#define LS_NODE_SR 0x0040
#define LS_NODE_SRLB 0x0080
#define LS_NODE_MSD 0x0100
+#define LS_NODE_SRV6 0x0200
/* Link State Node structure */
struct ls_node {
@@ -128,6 +129,14 @@ struct ls_node {
} srlb;
uint8_t algo[LIB_LS_SR_ALGO_COUNT]; /* Segment Routing Algorithms */
uint8_t msd; /* Maximum Stack Depth */
+
+ uint16_t srv6_cap_flags; /* draft-ietf-idr-bgpls-srv6-ext, 3.1., flags field */
+ struct ls_srv6_msd { /* draft-ietf-idr-bgpls-srv6-ext, 3.2. */
+ uint8_t max_seg_left_msd;
+ uint8_t max_end_pop_msd;
+ uint8_t max_h_encaps_msd;
+ uint8_t max_end_d_msd;
+ } srv6_msd;
};
/* Link State flags to indicate which Attribute parameters are valid */
@@ -161,6 +170,8 @@ struct ls_node {
#define LS_ATTR_BCK_ADJ_SID6 0x08000000
#define LS_ATTR_SRLG 0x10000000
#define LS_ATTR_EXT_ADM_GRP 0x20000000
+#define LS_ATTR_ADJ_SRV6SID 0x40000000
+#define LS_ATTR_BCK_ADJ_SRV6SID 0x80000000
/* Link State Attributes */
struct ls_attributes {
@@ -209,6 +220,18 @@ struct ls_attributes {
uint8_t sysid[ISO_SYS_ID_LEN]; /* or Sys-ID for ISIS */
} neighbor;
} adj_sid[4]; /* IPv4/IPv6 & Primary/Backup (LAN)-Adj. SID */
+#define ADJ_SRV6_PRI_IPV6 0
+#define ADJ_SRV6_BCK_IPV6 1
+#define ADJ_SRV6_MAX 2
+ struct ls_srv6_adjacency { /* Adjacency SID for IS-IS */
+ struct in6_addr sid; /* SID as IPv6 address */
+ uint8_t flags; /* Flags */
+ uint8_t weight; /* Administrative weight */
+ uint16_t endpoint_behavior; /* Endpoint Behavior */
+ union {
+ uint8_t sysid[ISO_SYS_ID_LEN]; /* Sys-ID for ISIS */
+ } neighbor;
+ } adj_srv6_sid[2];
uint32_t *srlgs; /* List of Shared Risk Link Group */
uint8_t srlg_len; /* number of SRLG in the list */
};
diff --git a/lib/memory.h b/lib/memory.h
index ba437eb..65b99a5 100644
--- a/lib/memory.h
+++ b/lib/memory.h
@@ -69,14 +69,12 @@ struct memgroup {
#define DECLARE_MGROUP(name) extern struct memgroup _mg_##name
#define _DEFINE_MGROUP(mname, desc, ...) \
- struct memgroup _mg_##mname \
- __attribute__((section(".data.mgroups"))) = { \
- .name = desc, \
- .types = NULL, \
- .next = NULL, \
- .insert = NULL, \
- .ref = NULL, \
- __VA_ARGS__ \
+ struct memgroup _mg_##mname _DATA_SECTION("mgroups") = { \
+ .name = desc, \
+ .types = NULL, \
+ .next = NULL, \
+ .insert = NULL, \
+ .ref = NULL, \
}; \
static void _mginit_##mname(void) __attribute__((_CONSTRUCTOR(1000))); \
static void _mginit_##mname(void) \
@@ -105,13 +103,12 @@ struct memgroup {
/* end */
#define DEFINE_MTYPE_ATTR(group, mname, attr, desc) \
- attr struct memtype MTYPE_##mname[1] \
- __attribute__((section(".data.mtypes"))) = { { \
- .name = desc, \
- .next = NULL, \
- .n_alloc = 0, \
- .size = 0, \
- .ref = NULL, \
+ attr struct memtype MTYPE_##mname[1] _DATA_SECTION("mtypes") = { { \
+ .name = desc, \
+ .next = NULL, \
+ .n_alloc = 0, \
+ .size = 0, \
+ .ref = NULL, \
} }; \
static void _mtinit_##mname(void) __attribute__((_CONSTRUCTOR(1001))); \
static void _mtinit_##mname(void) \
diff --git a/lib/mgmt.proto b/lib/mgmt.proto
index 01a99ab..c953011 100644
--- a/lib/mgmt.proto
+++ b/lib/mgmt.proto
@@ -79,6 +79,7 @@ message BeSubscribeReq {
repeated string config_xpaths = 2;
repeated string oper_xpaths = 3;
repeated string notif_xpaths = 4;
+ repeated string rpc_xpaths = 5;
}
message BeSubscribeReply {
diff --git a/lib/mgmt_be_client.c b/lib/mgmt_be_client.c
index f483d48..6e2fb05 100644
--- a/lib/mgmt_be_client.c
+++ b/lib/mgmt_be_client.c
@@ -915,6 +915,143 @@ static void be_client_handle_get_tree(struct mgmt_be_client *client,
be_client_send_tree_data_batch, args);
}
+static void be_client_send_rpc_reply(struct mgmt_be_client *client,
+ uint64_t txn_id, uint64_t req_id,
+ uint8_t result_type,
+ struct lyd_node *output)
+{
+ struct mgmt_msg_rpc_reply *rpc_reply_msg;
+ uint8_t **darrp;
+ LY_ERR err;
+ int ret = NB_OK;
+
+ rpc_reply_msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc_reply, 0,
+ MTYPE_MSG_NATIVE_RPC_REPLY);
+ rpc_reply_msg->refer_id = txn_id;
+ rpc_reply_msg->req_id = req_id;
+ rpc_reply_msg->code = MGMT_MSG_CODE_RPC_REPLY;
+ rpc_reply_msg->result_type = result_type;
+
+ if (output) {
+ darrp = mgmt_msg_native_get_darrp(rpc_reply_msg);
+ err = yang_print_tree_append(darrp, output, result_type,
+ LYD_PRINT_SHRINK);
+ lyd_free_all(output);
+ if (err) {
+ ret = NB_ERR;
+ goto done;
+ }
+ }
+
+ (void)be_client_send_native_msg(client, rpc_reply_msg,
+ mgmt_msg_native_get_msg_len(
+ rpc_reply_msg),
+ false);
+done:
+ mgmt_msg_native_free_msg(rpc_reply_msg);
+ if (ret != NB_OK)
+ be_client_send_error(client, txn_id, req_id, false, -EINVAL,
+ "Can't format RPC reply");
+}
+
+/*
+ * Process the RPC request.
+ */
+static void be_client_handle_rpc(struct mgmt_be_client *client, uint64_t txn_id,
+ void *msgbuf, size_t msg_len)
+{
+ struct mgmt_msg_rpc *rpc_msg = msgbuf;
+ struct nb_node *nb_node;
+ struct lyd_node *input, *output;
+ const char *xpath;
+ const char *data;
+ char errmsg[BUFSIZ] = { 0 };
+ LY_ERR err;
+ int ret;
+
+ debug_be_client("Received RPC request for client %s txn-id %" PRIu64
+ " req-id %" PRIu64,
+ client->name, txn_id, rpc_msg->req_id);
+
+ xpath = mgmt_msg_native_xpath_data_decode(rpc_msg, msg_len, data);
+ if (!xpath) {
+ be_client_send_error(client, txn_id, rpc_msg->req_id, false,
+ -EINVAL, "Corrupt RPC message");
+ return;
+ }
+
+ nb_node = nb_node_find(xpath);
+ if (!nb_node) {
+ be_client_send_error(client, txn_id, rpc_msg->req_id, false,
+ -EINVAL, "No schema found for RPC: %s",
+ xpath);
+ return;
+ }
+
+ if (!nb_node->cbs.rpc) {
+ be_client_send_error(client, txn_id, rpc_msg->req_id, false,
+ -EINVAL, "No RPC callback for: %s", xpath);
+ return;
+ }
+
+ if (data) {
+ err = yang_parse_rpc(xpath, rpc_msg->request_type, data, false,
+ &input);
+ if (err) {
+ be_client_send_error(client, txn_id, rpc_msg->req_id,
+ false, -EINVAL,
+ "Can't parse RPC data for: %s",
+ xpath);
+ return;
+ }
+ } else {
+ /*
+ * If there's no input data, create an empty input container.
+ * It is especially needed for actions, because their parents
+ * may hold necessary information.
+ */
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0,
+ NULL, &input);
+ if (err) {
+ be_client_send_error(client, txn_id, rpc_msg->req_id,
+ false, -EINVAL,
+ "Can't create input node for RPC: %s",
+ xpath);
+ return;
+ }
+ }
+
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL,
+ &output);
+ if (err) {
+ lyd_free_all(input);
+ be_client_send_error(client, txn_id, rpc_msg->req_id, false,
+ -EINVAL,
+ "Can't create output node for RPC: %s",
+ xpath);
+ return;
+ }
+
+ ret = nb_callback_rpc(nb_node, xpath, input, output, errmsg,
+ sizeof(errmsg));
+ if (ret != NB_OK) {
+ lyd_free_all(input);
+ lyd_free_all(output);
+ be_client_send_error(client, txn_id, rpc_msg->req_id, false,
+ -EINVAL, "%s", errmsg);
+ return;
+ }
+
+ lyd_free_all(input);
+ if (!lyd_child(output)) {
+ lyd_free_all(output);
+ output = NULL;
+ }
+
+ be_client_send_rpc_reply(client, txn_id, rpc_msg->req_id,
+ rpc_msg->request_type, output);
+}
+
/*
* Process the notification.
*/
@@ -975,6 +1112,9 @@ static void be_client_handle_native_msg(struct mgmt_be_client *client,
case MGMT_MSG_CODE_GET_TREE:
be_client_handle_get_tree(client, txn_id, msg, msg_len);
break;
+ case MGMT_MSG_CODE_RPC:
+ be_client_handle_rpc(client, txn_id, msg, msg_len);
+ break;
case MGMT_MSG_CODE_NOTIFY:
be_client_handle_notify(client, msg, msg_len);
break;
@@ -1040,6 +1180,9 @@ int mgmt_be_send_subscr_req(struct mgmt_be_client *client_ctx,
subscr_req.n_notif_xpaths = client_ctx->cbs.nnotif_xpaths;
subscr_req.notif_xpaths = (char **)client_ctx->cbs.notif_xpaths;
+ subscr_req.n_rpc_xpaths = client_ctx->cbs.nrpc_xpaths;
+ subscr_req.rpc_xpaths = (char **)client_ctx->cbs.rpc_xpaths;
+
mgmtd__be_message__init(&be_msg);
be_msg.message_case = MGMTD__BE_MESSAGE__MESSAGE_SUBSCR_REQ;
be_msg.subscr_req = &subscr_req;
diff --git a/lib/mgmt_be_client.h b/lib/mgmt_be_client.h
index cd8b237..7ad0589 100644
--- a/lib/mgmt_be_client.h
+++ b/lib/mgmt_be_client.h
@@ -75,6 +75,8 @@ struct mgmt_be_client_cbs {
const char **notif_xpaths;
uint nnotif_xpaths;
+ const char **rpc_xpaths;
+ uint nrpc_xpaths;
};
/***************************************************************
diff --git a/lib/mgmt_fe_client.c b/lib/mgmt_fe_client.c
index a107582..8cfb025 100644
--- a/lib/mgmt_fe_client.c
+++ b/lib/mgmt_fe_client.c
@@ -329,6 +329,63 @@ int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
return ret;
}
+int mgmt_fe_send_edit_req(struct mgmt_fe_client *client, uint64_t session_id,
+ uint64_t req_id, uint8_t datastore,
+ LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath, const char *data)
+{
+ struct mgmt_msg_edit *msg;
+ int ret;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_edit, 0,
+ MTYPE_MSG_NATIVE_EDIT);
+ msg->refer_id = session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_EDIT;
+ msg->request_type = request_type;
+ msg->flags = flags;
+ msg->datastore = datastore;
+ msg->operation = operation;
+
+ mgmt_msg_native_xpath_encode(msg, xpath);
+ if (data)
+ mgmt_msg_native_append(msg, data, strlen(data) + 1);
+
+ debug_fe_client("Sending EDIT_REQ session-id %" PRIu64
+ " req-id %" PRIu64 " xpath: %s",
+ session_id, req_id, xpath);
+
+ ret = mgmt_msg_native_send_msg(&client->client.conn, msg, false);
+ mgmt_msg_native_free_msg(msg);
+ return ret;
+}
+
+int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client, uint64_t session_id,
+ uint64_t req_id, LYD_FORMAT request_type,
+ const char *xpath, const char *data)
+{
+ struct mgmt_msg_rpc *msg;
+ int ret;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc, 0,
+ MTYPE_MSG_NATIVE_RPC);
+ msg->refer_id = session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_RPC;
+ msg->request_type = request_type;
+
+ mgmt_msg_native_xpath_encode(msg, xpath);
+ if (data)
+ mgmt_msg_native_append(msg, data, strlen(data) + 1);
+
+ debug_fe_client("Sending RPC_REQ session-id %" PRIu64 " req-id %" PRIu64
+ " xpath: %s",
+ session_id, req_id, xpath);
+
+ ret = mgmt_msg_native_send_msg(&client->client.conn, msg, false);
+ mgmt_msg_native_free_msg(msg);
+ return ret;
+}
static int mgmt_fe_client_handle_msg(struct mgmt_fe_client *client,
Mgmtd__FeMessage *fe_msg)
@@ -503,7 +560,10 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
struct mgmt_fe_client_session *session = NULL;
struct mgmt_msg_notify_data *notify_msg;
struct mgmt_msg_tree_data *tree_msg;
+ struct mgmt_msg_edit_reply *edit_msg;
+ struct mgmt_msg_rpc_reply *rpc_msg;
struct mgmt_msg_error *err_msg;
+ const char *xpath = NULL;
const char *data = NULL;
size_t dlen;
@@ -554,6 +614,45 @@ static void fe_client_handle_native_msg(struct mgmt_fe_client *client,
msg_len - sizeof(*tree_msg),
tree_msg->partial_error);
break;
+ case MGMT_MSG_CODE_EDIT_REPLY:
+ if (!session->client->cbs.edit_notify)
+ return;
+
+ edit_msg = (typeof(edit_msg))msg;
+ if (msg_len < sizeof(*edit_msg)) {
+ log_err_fe_client("Corrupt edit-reply msg recv");
+ return;
+ }
+
+ xpath = mgmt_msg_native_xpath_decode(edit_msg, msg_len);
+ if (!xpath) {
+ log_err_fe_client("Corrupt edit-reply msg recv");
+ return;
+ }
+
+ session->client->cbs.edit_notify(client, client->user_data,
+ session->client_id,
+ msg->refer_id,
+ session->user_ctx, msg->req_id,
+ xpath);
+ break;
+ case MGMT_MSG_CODE_RPC_REPLY:
+ if (!session->client->cbs.rpc_notify)
+ return;
+
+ rpc_msg = (typeof(rpc_msg))msg;
+ if (msg_len < sizeof(*rpc_msg)) {
+ log_err_fe_client("Corrupt rpc-reply msg recv");
+ return;
+ }
+ dlen = msg_len - sizeof(*rpc_msg);
+
+ session->client->cbs.rpc_notify(client, client->user_data,
+ session->client_id,
+ msg->refer_id,
+ session->user_ctx, msg->req_id,
+ dlen ? rpc_msg->data : NULL);
+ break;
case MGMT_MSG_CODE_NOTIFY:
if (!session->client->cbs.async_notification)
return;
diff --git a/lib/mgmt_fe_client.h b/lib/mgmt_fe_client.h
index eee4594..20c8704 100644
--- a/lib/mgmt_fe_client.h
+++ b/lib/mgmt_fe_client.h
@@ -114,6 +114,18 @@ struct mgmt_fe_client_cbs {
LYD_FORMAT result_type, void *result, size_t len,
int partial_error);
+ /* Called when edit result is returned */
+ int (*edit_notify)(struct mgmt_fe_client *client, uintptr_t user_data,
+ uint64_t client_id, uint64_t session_id,
+ uintptr_t session_ctx, uint64_t req_id,
+ const char *xpath);
+
+ /* Called when RPC result is returned */
+ int (*rpc_notify)(struct mgmt_fe_client *client, uintptr_t user_data,
+ uint64_t client_id, uint64_t session_id,
+ uintptr_t session_ctx, uint64_t req_id,
+ const char *result);
+
/* Called with asynchronous notifications from backends */
int (*async_notification)(struct mgmt_fe_client *client,
uintptr_t user_data, uint64_t client_id,
@@ -410,6 +422,74 @@ extern int mgmt_fe_send_get_data_req(struct mgmt_fe_client *client,
const char *xpath);
/*
+ * Send EDIT to MGMTD daemon.
+ *
+ * client
+ * Client object.
+ *
+ * session_id
+ * Client session ID.
+ *
+ * req_id
+ * Client request ID.
+ *
+ * datastore
+ * Datastore for editing.
+ *
+ * request_type
+ * The LYD_FORMAT of the request.
+ *
+ * flags
+ * Flags to control the behavior of the request.
+ *
+ * operation
+ * NB_OP_* operation to perform.
+ *
+ * xpath
+ * the xpath to edit.
+ *
+ * data
+ * the data tree.
+ *
+ * Returns:
+ * 0 on success, otherwise msg_conn_send_msg() return values.
+ */
+extern int mgmt_fe_send_edit_req(struct mgmt_fe_client *client,
+ uint64_t session_id, uint64_t req_id,
+ uint8_t datastore, LYD_FORMAT request_type,
+ uint8_t flags, uint8_t operation,
+ const char *xpath, const char *data);
+
+/*
+ * Send RPC request to MGMTD daemon.
+ *
+ * client
+ * Client object.
+ *
+ * session_id
+ * Client session ID.
+ *
+ * req_id
+ * Client request ID.
+ *
+ * result_type
+ * The LYD_FORMAT of the result.
+ *
+ * xpath
+ * the xpath of the RPC.
+ *
+ * data
+ * the data tree.
+ *
+ * Returns:
+ * 0 on success, otherwise msg_conn_send_msg() return values.
+ */
+extern int mgmt_fe_send_rpc_req(struct mgmt_fe_client *client,
+ uint64_t session_id, uint64_t req_id,
+ LYD_FORMAT request_type, const char *xpath,
+ const char *data);
+
+/*
* Destroy library and cleanup everything.
*/
extern void mgmt_fe_client_destroy(struct mgmt_fe_client *client);
diff --git a/lib/mgmt_msg_native.c b/lib/mgmt_msg_native.c
index d27c5d3..39ce9ab 100644
--- a/lib/mgmt_msg_native.c
+++ b/lib/mgmt_msg_native.c
@@ -9,12 +9,15 @@
#include "mgmt_msg_native.h"
DEFINE_MGROUP(MSG_NATIVE, "Native message allocations");
-DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_MSG, "native mgmt msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_ERROR, "native error msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_GET_TREE, "native get tree msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_TREE_DATA, "native tree data msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_GET_DATA, "native get data msg");
DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_NOTIFY, "native get data msg");
+DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT, "native edit msg");
+DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_EDIT_REPLY, "native edit reply msg");
+DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC, "native RPC msg");
+DEFINE_MTYPE(MSG_NATIVE, MSG_NATIVE_RPC_REPLY, "native RPC reply msg");
int vmgmt_msg_native_send_error(struct msg_conn *conn, uint64_t sess_or_txn_id,
uint64_t req_id, bool short_circuit_ok,
diff --git a/lib/mgmt_msg_native.h b/lib/mgmt_msg_native.h
index 53bb81b..21f702c 100644
--- a/lib/mgmt_msg_native.h
+++ b/lib/mgmt_msg_native.h
@@ -4,6 +4,15 @@
*
* Copyright (c) 2023, LabN Consulting, L.L.C.
*
+ * Public APIs:
+ *
+ * The message type codes and corresponding message data definitions for
+ * front-end client messages represent a public API, as such any changes should
+ * only be made according to backward compatible principles (basically never,
+ * just use a new message type). Back-end clients being always compiled with FRR
+ * can be updated (although one should take care in modifying BE messages as it
+ * could impact private back-end client implementations which will then need to
+ * be updated by their owners).
*/
#ifndef _FRR_MGMT_MSG_NATIVE_H_
@@ -21,6 +30,7 @@ extern "C" {
#include "memory.h"
#include "mgmt_msg.h"
#include "mgmt_defines.h"
+#include "northbound.h"
#include <stdalign.h>
@@ -149,15 +159,23 @@ DECLARE_MTYPE(MSG_NATIVE_GET_TREE);
DECLARE_MTYPE(MSG_NATIVE_TREE_DATA);
DECLARE_MTYPE(MSG_NATIVE_GET_DATA);
DECLARE_MTYPE(MSG_NATIVE_NOTIFY);
+DECLARE_MTYPE(MSG_NATIVE_EDIT);
+DECLARE_MTYPE(MSG_NATIVE_EDIT_REPLY);
+DECLARE_MTYPE(MSG_NATIVE_RPC);
+DECLARE_MTYPE(MSG_NATIVE_RPC_REPLY);
/*
* Native message codes
*/
-#define MGMT_MSG_CODE_ERROR 0
-#define MGMT_MSG_CODE_GET_TREE 1
-#define MGMT_MSG_CODE_TREE_DATA 2
-#define MGMT_MSG_CODE_GET_DATA 3
-#define MGMT_MSG_CODE_NOTIFY 4
+#define MGMT_MSG_CODE_ERROR 0 /* Public API */
+#define MGMT_MSG_CODE_GET_TREE 1 /* BE only, non-public API */
+#define MGMT_MSG_CODE_TREE_DATA 2 /* Public API */
+#define MGMT_MSG_CODE_GET_DATA 3 /* Public API */
+#define MGMT_MSG_CODE_NOTIFY 4 /* Public API */
+#define MGMT_MSG_CODE_EDIT 5 /* Public API */
+#define MGMT_MSG_CODE_EDIT_REPLY 6 /* Public API */
+#define MGMT_MSG_CODE_RPC 7 /* Public API */
+#define MGMT_MSG_CODE_RPC_REPLY 8 /* Public API */
/*
* Datastores
@@ -318,6 +336,96 @@ _Static_assert(sizeof(struct mgmt_msg_notify_data) ==
offsetof(struct mgmt_msg_notify_data, data),
"Size mismatch");
+#define EDIT_FLAG_IMPLICIT_LOCK 0x01
+#define EDIT_FLAG_IMPLICIT_COMMIT 0x02
+
+#define EDIT_OP_CREATE 0
+#define EDIT_OP_DELETE 4
+#define EDIT_OP_MERGE 2
+#define EDIT_OP_REPLACE 5
+#define EDIT_OP_REMOVE 3
+
+_Static_assert(EDIT_OP_CREATE == NB_OP_CREATE_EXCL, "Operation mismatch");
+_Static_assert(EDIT_OP_DELETE == NB_OP_DELETE, "Operation mismatch");
+_Static_assert(EDIT_OP_MERGE == NB_OP_MODIFY, "Operation mismatch");
+_Static_assert(EDIT_OP_REPLACE == NB_OP_REPLACE, "Operation mismatch");
+_Static_assert(EDIT_OP_REMOVE == NB_OP_DESTROY, "Operation mismatch");
+
+/**
+ * struct mgmt_msg_edit - frontend edit request.
+ *
+ * @request_type: ``LYD_FORMAT`` for the @data.
+ * @flags: combination of ``EDIT_FLAG_*`` flags.
+ * @datastore: the datastore to edit.
+ * @operation: one of ``EDIT_OP_*`` operations.
+ * @data: the xpath followed by the tree data for the operation.
+ * for CREATE, xpath points to the parent node.
+ */
+struct mgmt_msg_edit {
+ struct mgmt_msg_header;
+ uint8_t request_type;
+ uint8_t flags;
+ uint8_t datastore;
+ uint8_t operation;
+ uint8_t resv2[4];
+
+ alignas(8) char data[];
+};
+_Static_assert(sizeof(struct mgmt_msg_edit) ==
+ offsetof(struct mgmt_msg_edit, data),
+ "Size mismatch");
+
+/**
+ * struct mgmt_msg_edit_reply - frontend edit reply.
+ *
+ * @data: the xpath of the data node that was created.
+ */
+struct mgmt_msg_edit_reply {
+ struct mgmt_msg_header;
+ uint8_t resv2[8];
+
+ alignas(8) char data[];
+};
+_Static_assert(sizeof(struct mgmt_msg_edit_reply) ==
+ offsetof(struct mgmt_msg_edit_reply, data),
+ "Size mismatch");
+
+/**
+ * struct mgmt_msg_rpc - RPC/action request.
+ *
+ * @request_type: ``LYD_FORMAT`` for the @data.
+ * @data: the xpath followed by the tree data for the operation.
+ */
+struct mgmt_msg_rpc {
+ struct mgmt_msg_header;
+ uint8_t request_type;
+ uint8_t resv2[7];
+
+ alignas(8) char data[];
+};
+
+_Static_assert(sizeof(struct mgmt_msg_rpc) ==
+ offsetof(struct mgmt_msg_rpc, data),
+ "Size mismatch");
+
+/**
+ * struct mgmt_msg_rpc_reply - RPC/action reply.
+ *
+ * @result_type: ``LYD_FORMAT`` for the @data.
+ * @data: the tree data for the reply.
+ */
+struct mgmt_msg_rpc_reply {
+ struct mgmt_msg_header;
+ uint8_t result_type;
+ uint8_t resv2[7];
+
+ alignas(8) char data[];
+};
+
+_Static_assert(sizeof(struct mgmt_msg_rpc_reply) ==
+ offsetof(struct mgmt_msg_rpc_reply, data),
+ "Size mismatch");
+
/*
* Validate that the message ends in a NUL terminating byte
*/
@@ -504,13 +612,16 @@ extern int vmgmt_msg_native_send_error(struct msg_conn *conn,
* The xpath string or NULL if there was an error decoding (i.e., the
* message is corrupt).
*/
-#define mgmt_msg_native_xpath_data_decode(msg, msglen, data) \
+#define mgmt_msg_native_xpath_data_decode(msg, msglen, __data) \
({ \
size_t __len = (msglen) - sizeof(*msg); \
const char *__s = NULL; \
if (msg->vsplit && msg->vsplit <= __len && \
msg->data[msg->vsplit - 1] == 0) { \
- (data) = msg->data + msg->vsplit; \
+ if (msg->vsplit < __len) \
+ (__data) = msg->data + msg->vsplit; \
+ else \
+ (__data) = NULL; \
__s = msg->data; \
} \
__s; \
diff --git a/lib/netns_other.c b/lib/netns_other.c
index 3021840..545a962 100644
--- a/lib/netns_other.c
+++ b/lib/netns_other.c
@@ -13,10 +13,6 @@
#include "log.h"
#include "memory.h"
-DEFINE_MTYPE_STATIC(LIB, NS, "NetNS Context");
-DEFINE_MTYPE_STATIC(LIB, NS_NAME, "NetNS Name");
-
-
static inline int ns_compare(const struct ns *ns, const struct ns *ns2);
RB_GENERATE(ns_head, ns, entry, ns_compare)
@@ -39,7 +35,6 @@ void ns_init_management(ns_id_t ns_id)
{
}
-
/*
* NS utilities
*/
diff --git a/lib/nexthop.c b/lib/nexthop.c
index 243b52d..26c3382 100644
--- a/lib/nexthop.c
+++ b/lib/nexthop.c
@@ -1154,3 +1154,346 @@ bool nexthop_is_blackhole(const struct nexthop *nh)
{
return nh->type == NEXTHOP_TYPE_BLACKHOLE;
}
+
+/*
+ * Render a nexthop into a json object; the caller allocates and owns
+ * the json object memory.
+ */
+void nexthop_json_helper(json_object *json_nexthop,
+ const struct nexthop *nexthop, bool display_vrfid,
+ uint8_t rn_family)
+{
+ json_object *json_labels = NULL;
+ json_object *json_backups = NULL;
+ json_object *json_seg6local = NULL;
+ json_object *json_seg6 = NULL;
+ json_object *json_segs = NULL;
+ int i;
+
+ json_object_int_add(json_nexthop, "flags", nexthop->flags);
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ json_object_boolean_true_add(json_nexthop, "duplicate");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
+ json_object_boolean_true_add(json_nexthop, "fib");
+
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ json_object_string_addf(json_nexthop, "ip", "%pI4",
+ &nexthop->gate.ipv4);
+ json_object_string_add(json_nexthop, "afi", "ipv4");
+
+ if (nexthop->ifindex) {
+ json_object_int_add(json_nexthop, "interfaceIndex",
+ nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ }
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ json_object_string_addf(json_nexthop, "ip", "%pI6",
+ &nexthop->gate.ipv6);
+ json_object_string_add(json_nexthop, "afi", "ipv6");
+
+ if (nexthop->ifindex) {
+ json_object_int_add(json_nexthop, "interfaceIndex",
+ nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ }
+ break;
+
+ case NEXTHOP_TYPE_IFINDEX:
+ json_object_boolean_true_add(json_nexthop, "directlyConnected");
+ json_object_int_add(json_nexthop, "interfaceIndex",
+ nexthop->ifindex);
+ json_object_string_add(json_nexthop, "interfaceName",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ json_object_boolean_true_add(json_nexthop, "unreachable");
+ switch (nexthop->bh_type) {
+ case BLACKHOLE_REJECT:
+ json_object_boolean_true_add(json_nexthop, "reject");
+ break;
+ case BLACKHOLE_ADMINPROHIB:
+ json_object_boolean_true_add(json_nexthop,
+ "adminProhibited");
+ break;
+ case BLACKHOLE_NULL:
+ json_object_boolean_true_add(json_nexthop, "blackhole");
+ break;
+ case BLACKHOLE_UNSPEC:
+ break;
+ }
+ break;
+ }
+
+ /* This nexthop is a resolver for the parent nexthop.
+ * Set resolver flag for better clarity and delimiter
+ * in flat list of nexthops in json.
+ */
+ if (nexthop->rparent)
+ json_object_boolean_true_add(json_nexthop, "resolver");
+
+ if (display_vrfid)
+ json_object_string_add(json_nexthop, "vrf",
+ vrf_id_to_name(nexthop->vrf_id));
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
+ json_object_boolean_true_add(json_nexthop, "duplicate");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ json_object_boolean_true_add(json_nexthop, "active");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
+ json_object_boolean_true_add(json_nexthop, "onLink");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
+ json_object_boolean_true_add(json_nexthop, "linkDown");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ json_object_boolean_true_add(json_nexthop, "recursive");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
+ json_backups = json_object_new_array();
+ for (i = 0; i < nexthop->backup_num; i++) {
+ json_object_array_add(json_backups,
+ json_object_new_int(
+ nexthop->backup_idx[i]));
+ }
+
+ json_object_object_add(json_nexthop, "backupIndex",
+ json_backups);
+ }
+
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ if (nexthop->rmap_src.ipv4.s_addr)
+ json_object_string_addf(json_nexthop, "rmapSource",
+ "%pI4", &nexthop->rmap_src.ipv4);
+ else if (nexthop->src.ipv4.s_addr)
+ json_object_string_addf(json_nexthop, "source", "%pI4",
+ &nexthop->src.ipv4);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ /* Allow for 5549 ipv4 prefix with ipv6 nexthop */
+ if (rn_family == AF_INET && nexthop->rmap_src.ipv4.s_addr)
+ json_object_string_addf(json_nexthop, "rmapSource",
+ "%pI4", &nexthop->rmap_src.ipv4);
+ else if (!IPV6_ADDR_SAME(&nexthop->rmap_src.ipv6, &in6addr_any))
+ json_object_string_addf(json_nexthop, "rmapSource",
+ "%pI6", &nexthop->rmap_src.ipv6);
+ else if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+ json_object_string_addf(json_nexthop, "source", "%pI6",
+ &nexthop->src.ipv6);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ case NEXTHOP_TYPE_BLACKHOLE:
+ break;
+ }
+
+ if (nexthop->nh_label && nexthop->nh_label->num_labels) {
+ json_labels = json_object_new_array();
+
+ for (int label_index = 0;
+ label_index < nexthop->nh_label->num_labels; label_index++)
+ json_object_array_add(
+ json_labels,
+ json_object_new_int((
+ (nexthop->nh_label_type == ZEBRA_LSP_EVPN)
+ ? label2vni(
+ &nexthop->nh_label->label
+ [label_index])
+ : nexthop->nh_label
+ ->label[label_index])));
+
+ json_object_object_add(json_nexthop, "labels", json_labels);
+ }
+
+ if (nexthop->weight)
+ json_object_int_add(json_nexthop, "weight", nexthop->weight);
+
+ if (nexthop->srte_color)
+ json_object_int_add(json_nexthop, "srteColor",
+ nexthop->srte_color);
+
+ if (nexthop->nh_srv6) {
+ json_seg6local = json_object_new_object();
+ json_object_string_add(json_seg6local, "action",
+ seg6local_action2str(
+ nexthop->nh_srv6
+ ->seg6local_action));
+ json_object_object_add(json_nexthop, "seg6local",
+ json_seg6local);
+ if (nexthop->nh_srv6->seg6_segs &&
+ nexthop->nh_srv6->seg6_segs->num_segs == 1) {
+ json_seg6 = json_object_new_object();
+ json_object_string_addf(json_seg6, "segs", "%pI6",
+ &nexthop->nh_srv6->seg6_segs
+ ->seg[0]);
+ json_object_object_add(json_nexthop, "seg6", json_seg6);
+ } else {
+ if (nexthop->nh_srv6->seg6_segs) {
+ json_segs = json_object_new_array();
+ for (int seg_idx = 0;
+ seg_idx <
+ nexthop->nh_srv6->seg6_segs->num_segs;
+ seg_idx++)
+ json_object_array_add(
+ json_segs,
+ json_object_new_stringf(
+ "%pI6",
+ &nexthop->nh_srv6
+ ->seg6_segs
+ ->seg[seg_idx]));
+ json_object_object_add(json_nexthop, "seg6",
+ json_segs);
+ }
+ }
+ }
+}
+
+/*
+ * Helper for nexthop output
+ */
+void nexthop_vty_helper(struct vty *vty, const struct nexthop *nexthop,
+ bool display_vrfid, uint8_t rn_family)
+{
+ char buf[MPLS_LABEL_STRLEN];
+ char seg_buf[SRV6_SEG_STRLEN];
+ struct seg6_segs segs;
+ uint8_t i;
+
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ vty_out(vty, " via %pI4", &nexthop->gate.ipv4);
+ if (nexthop->ifindex)
+ vty_out(vty, ", %s",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ vty_out(vty, " via %s",
+ inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
+ sizeof(buf)));
+ if (nexthop->ifindex)
+ vty_out(vty, ", %s",
+ ifindex2ifname(nexthop->ifindex,
+ nexthop->vrf_id));
+ break;
+
+ case NEXTHOP_TYPE_IFINDEX:
+ vty_out(vty, " is directly connected, %s",
+ ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
+ break;
+ case NEXTHOP_TYPE_BLACKHOLE:
+ vty_out(vty, " unreachable");
+ switch (nexthop->bh_type) {
+ case BLACKHOLE_REJECT:
+ vty_out(vty, " (ICMP unreachable)");
+ break;
+ case BLACKHOLE_ADMINPROHIB:
+ vty_out(vty, " (ICMP admin-prohibited)");
+ break;
+ case BLACKHOLE_NULL:
+ vty_out(vty, " (blackhole)");
+ break;
+ case BLACKHOLE_UNSPEC:
+ break;
+ }
+ break;
+ }
+
+ if (display_vrfid)
+ vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id));
+
+ if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
+ vty_out(vty, " inactive");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
+ vty_out(vty, " onlink");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
+ vty_out(vty, " linkdown");
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
+ vty_out(vty, " (recursive)");
+
+ switch (nexthop->type) {
+ case NEXTHOP_TYPE_IPV4:
+ case NEXTHOP_TYPE_IPV4_IFINDEX:
+ if (nexthop->rmap_src.ipv4.s_addr)
+ vty_out(vty, ", rmapsrc %pI4", &nexthop->rmap_src.ipv4);
+ else if (nexthop->src.ipv4.s_addr)
+ vty_out(vty, ", src %pI4", &nexthop->src.ipv4);
+ break;
+ case NEXTHOP_TYPE_IPV6:
+ case NEXTHOP_TYPE_IPV6_IFINDEX:
+ /* Allow for 5549 ipv4 prefix with ipv6 nexthop */
+ if (rn_family == AF_INET && nexthop->rmap_src.ipv4.s_addr)
+ vty_out(vty, ", rmapsrc %pI4", &nexthop->rmap_src.ipv4);
+ else if (!IPV6_ADDR_SAME(&nexthop->rmap_src.ipv6, &in6addr_any))
+ vty_out(vty, ", rmapsrc %pI6", &nexthop->rmap_src.ipv6);
+ else if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+ vty_out(vty, ", src %pI6", &nexthop->src.ipv6);
+ break;
+ case NEXTHOP_TYPE_IFINDEX:
+ case NEXTHOP_TYPE_BLACKHOLE:
+ break;
+ }
+
+ /* SR-TE information */
+ if (nexthop->srte_color)
+ vty_out(vty, ", SR-TE color %u", nexthop->srte_color);
+
+ /* Label information */
+ if (nexthop->nh_label && nexthop->nh_label->num_labels) {
+ vty_out(vty, ", label %s",
+ mpls_label2str(nexthop->nh_label->num_labels,
+ nexthop->nh_label->label, buf,
+ sizeof(buf), nexthop->nh_label_type, 1));
+ }
+
+ if (nexthop->nh_srv6) {
+ seg6local_context2str(buf, sizeof(buf),
+ &nexthop->nh_srv6->seg6local_ctx,
+ nexthop->nh_srv6->seg6local_action);
+ if (nexthop->nh_srv6->seg6local_action !=
+ ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
+ vty_out(vty, ", seg6local %s %s",
+ seg6local_action2str(
+ nexthop->nh_srv6->seg6local_action),
+ buf);
+ if (nexthop->nh_srv6->seg6_segs &&
+ IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs->seg[0],
+ &in6addr_any)) {
+ segs.num_segs = nexthop->nh_srv6->seg6_segs->num_segs;
+ for (i = 0; i < segs.num_segs; i++)
+ memcpy(&segs.segs[i],
+ &nexthop->nh_srv6->seg6_segs->seg[i],
+ sizeof(struct in6_addr));
+ snprintf_seg6_segs(seg_buf, SRV6_SEG_STRLEN, &segs);
+ vty_out(vty, ", seg6 %s", seg_buf);
+ }
+ }
+
+ if (nexthop->weight)
+ vty_out(vty, ", weight %u", nexthop->weight);
+
+ if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
+ vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
+
+ for (i = 1; i < nexthop->backup_num; i++)
+ vty_out(vty, ",%d", nexthop->backup_idx[i]);
+ }
+}
diff --git a/lib/nexthop.h b/lib/nexthop.h
index 958d06a..27073b9 100644
--- a/lib/nexthop.h
+++ b/lib/nexthop.h
@@ -252,6 +252,12 @@ extern bool nexthop_is_blackhole(const struct nexthop *nh);
int nexthop_str2backups(const char *str, int *num_backups,
uint8_t *backups);
+void nexthop_json_helper(json_object *json_nexthop,
+ const struct nexthop *nexthop, bool display_vrfid,
+ uint8_t rn_family);
+void nexthop_vty_helper(struct vty *vty, const struct nexthop *nexthop,
+ bool display_vrfid, uint8_t rn_family);
+
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pNH" (struct nexthop *)
#endif
diff --git a/lib/northbound.c b/lib/northbound.c
index 487f225..0bc79d0 100644
--- a/lib/northbound.c
+++ b/lib/northbound.c
@@ -813,6 +813,231 @@ int nb_candidate_edit(struct nb_config *candidate, const struct nb_node *nb_node
return NB_OK;
}
+static int nb_candidate_edit_tree_add(struct nb_config *candidate,
+ enum nb_operation operation,
+ LYD_FORMAT format, const char *xpath,
+ const char *data, char *xpath_created,
+ char *errmsg, size_t errmsg_len)
+{
+ struct lyd_node *tree = NULL;
+ struct lyd_node *parent = NULL;
+ struct lyd_node *dnode = NULL;
+ struct lyd_node *existing = NULL;
+ struct lyd_node *ex_parent = NULL;
+ char *parent_xpath = NULL;
+ struct ly_in *in;
+ LY_ERR err;
+ bool root;
+ int ret;
+
+ ly_in_new_memory(data, &in);
+
+ root = xpath[0] == 0 || (xpath[0] == '/' && xpath[1] == 0);
+
+ /* get parent xpath if xpath is not root */
+ if (!root) {
+ /* NB_OP_CREATE_EXCT already expects parent xpath */
+ parent_xpath = XSTRDUP(MTYPE_TMP, xpath);
+
+ /* for other operations - pop one level */
+ if (operation != NB_OP_CREATE_EXCL) {
+ ret = yang_xpath_pop_node(parent_xpath);
+ if (ret) {
+ snprintf(errmsg, errmsg_len, "Invalid xpath");
+ goto done;
+ }
+
+ /* root is not actually a parent */
+ if (parent_xpath[0] == 0)
+ XFREE(MTYPE_TMP, parent_xpath);
+ }
+ }
+
+ /*
+ * Create parent if it's not root. We're creating a new tree here to be
+ * merged later with candidate.
+ */
+ if (parent_xpath) {
+ err = lyd_new_path2(NULL, ly_native_ctx, parent_xpath, NULL, 0,
+ 0, 0, &tree, &parent);
+ if (err) {
+ yang_print_errors(ly_native_ctx, errmsg, errmsg_len);
+ ret = NB_ERR;
+ goto done;
+ }
+ assert(parent);
+ }
+
+ /* parse data */
+ err = yang_lyd_parse_data(ly_native_ctx, parent, in, format,
+ LYD_PARSE_ONLY | LYD_PARSE_STRICT |
+ LYD_PARSE_NO_STATE,
+ 0, &dnode);
+ if (err) {
+ yang_print_errors(ly_native_ctx, errmsg, errmsg_len);
+ ret = NB_ERR;
+ goto done;
+ }
+
+ /* set the tree if we created a top-level node */
+ if (!parent)
+ tree = dnode;
+
+ /* save xpath of the created node */
+ lyd_path(dnode, LYD_PATH_STD, xpath_created, XPATH_MAXLEN);
+
+ /* verify that list keys are the same in the xpath and the data tree */
+ if (!root && (operation == NB_OP_REPLACE || operation == NB_OP_MODIFY)) {
+ if (lyd_find_path(tree, xpath, 0, NULL)) {
+ snprintf(errmsg, errmsg_len,
+ "List keys in xpath and data tree are different");
+ ret = NB_ERR;
+ goto done;
+ }
+ }
+
+ /* check if the node already exists in candidate */
+ if (operation == NB_OP_CREATE_EXCL || operation == NB_OP_REPLACE) {
+ existing = yang_dnode_get(candidate->dnode, xpath_created);
+
+ /* if the existing node is implicit default, ignore */
+ if (existing && (existing->flags & LYD_DEFAULT))
+ existing = NULL;
+
+ if (existing) {
+ if (operation == NB_OP_CREATE_EXCL) {
+ snprintf(errmsg, errmsg_len,
+ "Data already exists");
+ ret = NB_ERR;
+ goto done;
+ }
+
+ if (root) {
+ candidate->dnode = NULL;
+ } else {
+ /* if it's the first top-level node, update candidate */
+ if (candidate->dnode == existing)
+ candidate->dnode =
+ candidate->dnode->next;
+
+ ex_parent = lyd_parent(existing);
+ lyd_unlink_tree(existing);
+ }
+ }
+ }
+
+ err = lyd_merge_siblings(&candidate->dnode, tree,
+ LYD_MERGE_DESTRUCT | LYD_MERGE_WITH_FLAGS);
+ if (err) {
+ /* if replace failed, restore the original node */
+ if (existing) {
+ if (root) {
+ /* Restoring the whole config. */
+ candidate->dnode = existing;
+ } else if (ex_parent) {
+ /*
+ * Restoring a nested node. Insert it as a
+ * child.
+ */
+ lyd_insert_child(ex_parent, existing);
+ } else {
+ /*
+ * Restoring a top-level node. Insert it as a
+ * sibling to candidate->dnode to make sure
+ * the linkage is correct.
+ */
+ lyd_insert_sibling(candidate->dnode, existing,
+ &candidate->dnode);
+ }
+ }
+ yang_print_errors(ly_native_ctx, errmsg, errmsg_len);
+ ret = NB_ERR;
+ goto done;
+ } else {
+ /*
+ * Free existing node after replace.
+ * We're using `lyd_free_siblings` here to free the whole
+ * tree if we replaced the root node. It won't affect other
+ * siblings if it wasn't root, because the existing node
+ * was unlinked from the tree.
+ */
+ if (existing)
+ lyd_free_siblings(existing);
+
+ tree = NULL; /* LYD_MERGE_DESTRUCT deleted the tree */
+ }
+
+ ret = NB_OK;
+done:
+ if (tree)
+ lyd_free_all(tree);
+ XFREE(MTYPE_TMP, parent_xpath);
+ ly_in_free(in, 0);
+
+ return ret;
+}
+
+static int nb_candidate_edit_tree_del(struct nb_config *candidate,
+ enum nb_operation operation,
+ const char *xpath, char *errmsg,
+ size_t errmsg_len)
+{
+ struct lyd_node *dnode;
+
+ /* deleting root - remove the whole config */
+ if (xpath[0] == 0 || (xpath[0] == '/' && xpath[1] == 0)) {
+ lyd_free_all(candidate->dnode);
+ candidate->dnode = NULL;
+ return NB_OK;
+ }
+
+ dnode = yang_dnode_get(candidate->dnode, xpath);
+ if (!dnode || (dnode->flags & LYD_DEFAULT)) {
+ if (operation == NB_OP_DELETE) {
+ snprintf(errmsg, errmsg_len, "Data missing");
+ return NB_ERR;
+ } else
+ return NB_OK;
+ }
+
+ /* if it's the first top-level node, update candidate */
+ if (candidate->dnode == dnode)
+ candidate->dnode = candidate->dnode->next;
+
+ lyd_free_tree(dnode);
+
+ return NB_OK;
+}
+
+int nb_candidate_edit_tree(struct nb_config *candidate,
+ enum nb_operation operation, LYD_FORMAT format,
+ const char *xpath, const char *data,
+ char *xpath_created, char *errmsg, size_t errmsg_len)
+{
+ int ret = NB_ERR;
+
+ switch (operation) {
+ case NB_OP_CREATE_EXCL:
+ case NB_OP_CREATE:
+ case NB_OP_MODIFY:
+ case NB_OP_REPLACE:
+ ret = nb_candidate_edit_tree_add(candidate, operation, format,
+ xpath, data, xpath_created,
+ errmsg, errmsg_len);
+ break;
+ case NB_OP_DESTROY:
+ case NB_OP_DELETE:
+ ret = nb_candidate_edit_tree_del(candidate, operation, xpath,
+ errmsg, errmsg_len);
+ break;
+ case NB_OP_MOVE:
+ /* not supported yet */
+ break;
+ }
+
+ return ret;
+}
+
const char *nb_operation_name(enum nb_operation operation)
{
switch (operation) {
@@ -1603,14 +1828,11 @@ const void *nb_callback_lookup_next(const struct nb_node *nb_node,
}
int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
- const struct list *input, struct list *output, char *errmsg,
- size_t errmsg_len)
+ const struct lyd_node *input, struct lyd_node *output,
+ char *errmsg, size_t errmsg_len)
{
struct nb_cb_rpc_args args = {};
- if (CHECK_FLAG(nb_node->flags, F_NB_NODE_IGNORE_CFG_CBS))
- return 0;
-
DEBUGD(&nb_dbg_cbs_rpc, "northbound RPC: %s", xpath);
args.xpath = xpath;
@@ -2403,8 +2625,6 @@ const char *nb_client_name(enum nb_client client)
switch (client) {
case NB_CLIENT_CLI:
return "CLI";
- case NB_CLIENT_CONFD:
- return "ConfD";
case NB_CLIENT_SYSREPO:
return "Sysrepo";
case NB_CLIENT_GRPC:
diff --git a/lib/northbound.h b/lib/northbound.h
index 5be111c..34d17a5 100644
--- a/lib/northbound.h
+++ b/lib/northbound.h
@@ -274,11 +274,11 @@ struct nb_cb_rpc_args {
/* XPath of the YANG RPC or action. */
const char *xpath;
- /* Read-only list of input parameters. */
- const struct list *input;
+ /* Read-only "input" tree of the RPC/action. */
+ const struct lyd_node *input;
- /* List of output parameters to be populated by the callback. */
- struct list *output;
+ /* The "output" tree of the RPC/action to be populated by the callback. */
+ struct lyd_node *output;
/* Buffer to store human-readable error message in case of error. */
char *errmsg;
@@ -621,11 +621,6 @@ struct nb_node {
/* Flags. */
uint8_t flags;
-
-#ifdef HAVE_CONFD
- /* ConfD hash value corresponding to this YANG path. */
- int confd_hash;
-#endif
};
/* The YANG container or list contains only config data. */
#define F_NB_NODE_CONFIG_ONLY 0x01
@@ -700,7 +695,6 @@ enum nb_error {
enum nb_client {
NB_CLIENT_NONE = 0,
NB_CLIENT_CLI,
- NB_CLIENT_CONFD,
NB_CLIENT_SYSREPO,
NB_CLIENT_GRPC,
NB_CLIENT_PCEP,
@@ -839,7 +833,7 @@ extern const void *nb_callback_lookup_next(const struct nb_node *nb_node,
const void *parent_list_entry,
const struct yang_list_keys *keys);
extern int nb_callback_rpc(const struct nb_node *nb_node, const char *xpath,
- const struct list *input, struct list *output,
+ const struct lyd_node *input, struct lyd_node *output,
char *errmsg, size_t errmsg_len);
extern void nb_callback_notify(const struct nb_node *nb_node, const char *xpath,
struct lyd_node *dnode);
@@ -1005,6 +999,44 @@ extern int nb_candidate_edit(struct nb_config *candidate,
const struct yang_data *data);
/*
+ * Edit a candidate configuration. Value is given as JSON/XML.
+ *
+ * candidate
+ * Candidate configuration to edit.
+ *
+ * operation
+ * Operation to apply.
+ *
+ * format
+ * LYD_FORMAT of the value.
+ *
+ * xpath
+ * XPath of the configuration node being edited.
+ * For create, it must be the parent.
+ *
+ * data
+ * New data tree for the node.
+ *
+ * xpath_created
+ * XPath of the created node if operation is "create".
+ *
+ * errmsg
+ * Buffer to store human-readable error message in case of error.
+ *
+ * errmsg_len
+ * Size of errmsg.
+ *
+ * Returns:
+ * - NB_OK on success.
+ * - NB_ERR for other errors.
+ */
+extern int nb_candidate_edit_tree(struct nb_config *candidate,
+ enum nb_operation operation,
+ LYD_FORMAT format, const char *xpath,
+ const char *data, char *xpath_created,
+ char *errmsg, size_t errmsg_len);
+
+/*
* Create diff for configuration.
*
* dnode
diff --git a/lib/northbound_cli.c b/lib/northbound_cli.c
index 8809ec2..4f962cd 100644
--- a/lib/northbound_cli.c
+++ b/lib/northbound_cli.c
@@ -275,10 +275,31 @@ int nb_cli_apply_changes_clear_pending(struct vty *vty,
return nb_cli_apply_changes_internal(vty, xpath_base_abs, true);
}
-int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input,
- struct list *output)
+int nb_cli_rpc_enqueue(struct vty *vty, const char *xpath, const char *value)
+{
+ struct nb_cfg_change *param;
+
+ if (vty->num_rpc_params == VTY_MAXCFGCHANGES) {
+ /* Not expected to happen. */
+ vty_out(vty,
+ "%% Exceeded the maximum number of params (%u) for a single command\n\n",
+ VTY_MAXCFGCHANGES);
+ return CMD_WARNING;
+ }
+
+ param = &vty->rpc_params[vty->num_rpc_params++];
+ strlcpy(param->xpath, xpath, sizeof(param->xpath));
+ param->value = value;
+
+ return CMD_SUCCESS;
+}
+
+int nb_cli_rpc(struct vty *vty, const char *xpath, struct lyd_node **output_p)
{
struct nb_node *nb_node;
+ struct lyd_node *input = NULL;
+ struct lyd_node *output = NULL;
+ LY_ERR err;
int ret;
char errmsg[BUFSIZ] = {0};
@@ -289,12 +310,62 @@ int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input,
return CMD_WARNING;
}
+ /* create input tree */
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL,
+ &input);
+ assert(err == LY_SUCCESS);
+
+ for (size_t i = 0; i < vty->num_rpc_params; i++) {
+ err = lyd_new_path(input, ly_native_ctx,
+ vty->rpc_params[i].xpath,
+ vty->rpc_params[i].value, 0, NULL);
+ assert(err == LY_SUCCESS);
+ }
+
+ if (vty_mgmt_fe_enabled()) {
+ char *data = NULL;
+
+ err = lyd_print_mem(&data, input, LYD_JSON, LYD_PRINT_SHRINK);
+ assert(err == LY_SUCCESS);
+
+ ret = vty_mgmt_send_rpc_req(vty, LYD_JSON, xpath, data);
+
+ free(data);
+ lyd_free_all(input);
+
+ if (ret < 0)
+ return CMD_WARNING;
+ return CMD_SUCCESS;
+ }
+
+ /* validate input tree to create implicit defaults */
+ err = lyd_validate_op(input, NULL, LYD_TYPE_RPC_YANG, NULL);
+ assert(err == LY_SUCCESS);
+
+ /* create output tree root for population in the callback */
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0, 0, 0, NULL,
+ &output);
+ assert(err == LY_SUCCESS);
+
ret = nb_callback_rpc(nb_node, xpath, input, output, errmsg,
sizeof(errmsg));
+
+ /* validate output tree to create implicit defaults */
+ err = lyd_validate_op(output, NULL, LYD_TYPE_REPLY_YANG, NULL);
+ assert(err == LY_SUCCESS);
+
+ lyd_free_all(input);
+ vty->num_rpc_params = 0;
+
switch (ret) {
case NB_OK:
+ if (output_p)
+ *output_p = output;
+ else
+ lyd_free_all(output);
return CMD_SUCCESS;
default:
+ lyd_free_all(output);
if (strlen(errmsg))
vty_show_nb_errors(vty, ret, errmsg);
return CMD_WARNING;
diff --git a/lib/northbound_cli.h b/lib/northbound_cli.h
index 1a45794..4c8dc50 100644
--- a/lib/northbound_cli.h
+++ b/lib/northbound_cli.h
@@ -80,7 +80,23 @@ extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt,
...) PRINTFRR(2, 3);
/*
- * Execute a YANG RPC or Action.
+ * Add an input child node for an RPC or an action.
+ *
+ * vty
+ * The vty context.
+ *
+ * xpath
+ * XPath of the child being added, relative to the input container.
+ *
+ * value
+ * Value of the child being added. Can be NULL for containers and leafs of
+ * type 'empty'.
+ */
+extern int nb_cli_rpc_enqueue(struct vty *vty, const char *xpath,
+ const char *value);
+
+/*
+ * Execute a YANG RPC or Action using the enqueued input parameters.
*
* vty
* The vty terminal to dump any error.
@@ -88,20 +104,16 @@ extern int nb_cli_apply_changes(struct vty *vty, const char *xpath_base_fmt,
* xpath
* XPath of the YANG RPC or Action node.
*
- * input
- * List of 'yang_data' structures containing the RPC input parameters. It
- * can be set to NULL when there are no input parameters.
- *
- * output
- * List of 'yang_data' structures used to retrieve the RPC output parameters.
- * It can be set to NULL when it's known that the given YANG RPC or Action
- * doesn't have any output parameters.
+ * output_p
+ * A pointer to the libyang data node that will hold the output data tree.
+ * It can be set to NULL if the caller is not interested in processing the
+ * output. The caller is responsible for freeing the output data tree.
*
* Returns:
* CMD_SUCCESS on success, CMD_WARNING otherwise.
*/
-extern int nb_cli_rpc(struct vty *vty, const char *xpath, struct list *input,
- struct list *output);
+extern int nb_cli_rpc(struct vty *vty, const char *xpath,
+ struct lyd_node **output_p);
/*
* Show CLI commands associated to the given YANG data node.
diff --git a/lib/northbound_confd.c b/lib/northbound_confd.c
deleted file mode 100644
index 8503d18..0000000
--- a/lib/northbound_confd.c
+++ /dev/null
@@ -1,1494 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-/*
- * Copyright (C) 2018 NetDEF, Inc.
- * Renato Westphal
- */
-
-#include <zebra.h>
-
-#include "log.h"
-#include "lib_errors.h"
-#include "command.h"
-#include "debug.h"
-#include "libfrr.h"
-#include "lib/version.h"
-#include "northbound.h"
-
-#include <confd_lib.h>
-#include <confd_cdb.h>
-#include <confd_dp.h>
-#include <confd_maapi.h>
-
-DEFINE_MTYPE_STATIC(LIB, CONFD, "ConfD module");
-
-static struct debug nb_dbg_client_confd = {0, "Northbound client: ConfD"};
-
-static struct event_loop *master;
-static struct sockaddr confd_addr;
-static int cdb_sub_sock, dp_ctl_sock, dp_worker_sock;
-static struct event *t_cdb_sub, *t_dp_ctl, *t_dp_worker;
-static struct confd_daemon_ctx *dctx;
-static struct confd_notification_ctx *live_ctx;
-static bool confd_connected;
-static struct list *confd_spoints;
-static struct nb_transaction *transaction;
-
-static void frr_confd_finish_cdb(void);
-static void frr_confd_finish_dp(void);
-static int frr_confd_finish(void);
-
-#define flog_err_confd(funcname) \
- flog_err(EC_LIB_LIBCONFD, "%s: %s() failed: %s (%d): %s", __func__, \
- (funcname), confd_strerror(confd_errno), confd_errno, \
- confd_lasterr())
-
-
-/* ------------ Utils ------------ */
-
-/* Get XPath string from ConfD hashed keypath. */
-static void frr_confd_get_xpath(const confd_hkeypath_t *kp, char *xpath,
- size_t len)
-{
- char *p;
-
- confd_xpath_pp_kpath(xpath, len, 0, kp);
-
- /*
- * Replace double quotes by single quotes (the format accepted by the
- * northbound API).
- */
- p = xpath;
- while ((p = strchr(p, '"')) != NULL)
- *p++ = '\'';
-}
-
-/* Convert ConfD binary value to a string. */
-static int frr_confd_val2str(const char *xpath, const confd_value_t *value,
- char *string, size_t string_size)
-{
- struct confd_cs_node *csp;
-
- csp = confd_cs_node_cd(NULL, xpath);
- if (!csp) {
- flog_err_confd("confd_cs_node_cd");
- return -1;
- }
- if (confd_val2str(csp->info.type, value, string, string_size)
- == CONFD_ERR) {
- flog_err_confd("confd_val2str");
- return -1;
- }
-
- return 0;
-}
-
-/* Obtain list entry from ConfD hashed keypath. */
-static int frr_confd_hkeypath_get_list_entry(const confd_hkeypath_t *kp,
- struct nb_node *nb_node,
- const void **list_entry)
-{
- struct nb_node *nb_node_list;
- int parent_lists = 0;
- int curr_list = 0;
-
- *list_entry = NULL;
-
- /*
- * Count the number of YANG lists in the path, disconsidering the
- * last element.
- */
- nb_node_list = nb_node;
- while (nb_node_list->parent_list) {
- nb_node_list = nb_node_list->parent_list;
- parent_lists++;
- }
- if (nb_node->snode->nodetype != LYS_LIST && parent_lists == 0)
- return 0;
-
- /* Start from the beginning and move down the tree. */
- for (int i = kp->len; i >= 0; i--) {
- struct yang_list_keys keys;
-
- /* Not a YANG list. */
- if (kp->v[i][0].type != C_BUF)
- continue;
-
- /* Obtain list keys. */
- memset(&keys, 0, sizeof(keys));
- for (int j = 0; kp->v[i][j].type != C_NOEXISTS; j++) {
- strlcpy(keys.key[keys.num],
- (char *)kp->v[i][j].val.buf.ptr,
- sizeof(keys.key[keys.num]));
- keys.num++;
- }
-
- /* Obtain northbound node associated to the YANG list. */
- nb_node_list = nb_node;
- for (int j = curr_list; j < parent_lists; j++)
- nb_node_list = nb_node_list->parent_list;
-
- /* Obtain list entry. */
- if (!CHECK_FLAG(nb_node_list->flags, F_NB_NODE_KEYLESS_LIST)) {
- *list_entry = nb_callback_lookup_entry(
- nb_node, *list_entry, &keys);
- if (*list_entry == NULL)
- return -1;
- } else {
- unsigned long ptr_ulong;
-
- /* Retrieve list entry from pseudo-key (string). */
- if (sscanf(keys.key[0], "%lu", &ptr_ulong) != 1)
- return -1;
- *list_entry = (const void *)ptr_ulong;
- }
-
- curr_list++;
- }
-
- return 0;
-}
-
-/* Fill the current date and time into a confd_datetime structure. */
-static void getdatetime(struct confd_datetime *datetime)
-{
- struct tm tm;
- struct timeval tv;
-
- gettimeofday(&tv, NULL);
- gmtime_r(&tv.tv_sec, &tm);
-
- memset(datetime, 0, sizeof(*datetime));
- datetime->year = 1900 + tm.tm_year;
- datetime->month = tm.tm_mon + 1;
- datetime->day = tm.tm_mday;
- datetime->sec = tm.tm_sec;
- datetime->micro = tv.tv_usec;
- datetime->timezone = 0;
- datetime->timezone_minutes = 0;
- datetime->hour = tm.tm_hour;
- datetime->min = tm.tm_min;
-}
-
-/* ------------ CDB code ------------ */
-
-struct cdb_iter_args {
- struct nb_config *candidate;
- bool error;
-};
-
-static enum cdb_iter_ret
-frr_confd_cdb_diff_iter(confd_hkeypath_t *kp, enum cdb_iter_op cdb_op,
- confd_value_t *oldv, confd_value_t *newv, void *args)
-{
- char xpath[XPATH_MAXLEN];
- struct nb_node *nb_node;
- enum nb_operation nb_op;
- struct cdb_iter_args *iter_args = args;
- char value_str[YANG_VALUE_MAXLEN];
- struct yang_data *data;
- char *sb1, *sb2;
- int ret;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- /*
- * HACK: obtain value of leaf-list elements from the XPath due to
- * a bug in the ConfD API.
- */
- value_str[0] = '\0';
- sb1 = strrchr(xpath, '[');
- sb2 = strrchr(xpath, ']');
- if (sb1 && sb2 && !strchr(sb1, '=')) {
- *sb2 = '\0';
- strlcpy(value_str, sb1 + 1, sizeof(value_str));
- *sb1 = '\0';
- }
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- /* Map operation values. */
- switch (cdb_op) {
- case MOP_CREATED:
- nb_op = NB_OP_CREATE;
- break;
- case MOP_DELETED:
- nb_op = NB_OP_DESTROY;
- break;
- case MOP_VALUE_SET:
- if (nb_is_operation_allowed(nb_node, NB_OP_MODIFY))
- nb_op = NB_OP_MODIFY;
- else
- /* Ignore list keys modifications. */
- return ITER_RECURSE;
- break;
- case MOP_MOVED_AFTER:
- nb_op = NB_OP_MOVE;
- break;
- case MOP_MODIFIED:
- /* We're not interested on this. */
- return ITER_RECURSE;
- default:
- flog_err(EC_LIB_DEVELOPMENT,
- "%s: unexpected operation %u [xpath %s]", __func__,
- cdb_op, xpath);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- /* Convert ConfD value to a string. */
- if (nb_node->snode->nodetype != LYS_LEAFLIST && newv
- && frr_confd_val2str(nb_node->xpath, newv, value_str,
- sizeof(value_str))
- != 0) {
- flog_err(EC_LIB_CONFD_DATA_CONVERT,
- "%s: failed to convert ConfD value to a string",
- __func__);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- /* Edit the candidate configuration. */
- data = yang_data_new(xpath, value_str);
- ret = nb_candidate_edit(iter_args->candidate, nb_node, nb_op, xpath,
- NULL, data);
- yang_data_free(data);
- if (ret != NB_OK) {
- flog_warn(
- EC_LIB_NB_CANDIDATE_EDIT_ERROR,
- "%s: failed to edit candidate configuration: operation [%s] xpath [%s]",
- __func__, nb_operation_name(nb_op), xpath);
- iter_args->error = true;
- return ITER_STOP;
- }
-
- return ITER_RECURSE;
-}
-
-static void frr_confd_cdb_read_cb_prepare(int fd, int *subp, int reslen)
-{
- struct nb_context context = {};
- struct nb_config *candidate;
- struct cdb_iter_args iter_args;
- char errmsg[BUFSIZ] = {0};
- int ret;
-
- candidate = nb_config_dup(running_config);
-
- /* Iterate over all configuration changes. */
- iter_args.candidate = candidate;
- iter_args.error = false;
- for (int i = 0; i < reslen; i++) {
- if (cdb_diff_iterate(fd, subp[i], frr_confd_cdb_diff_iter,
- ITER_WANT_PREV, &iter_args)
- != CONFD_OK) {
- flog_err_confd("cdb_diff_iterate");
- }
- }
- free(subp);
-
- if (iter_args.error) {
- nb_config_free(candidate);
-
- if (cdb_sub_abort_trans(
- cdb_sub_sock, CONFD_ERRCODE_APPLICATION_INTERNAL, 0,
- 0, "Couldn't apply configuration changes")
- != CONFD_OK) {
- flog_err_confd("cdb_sub_abort_trans");
- return;
- }
- return;
- }
-
- /*
- * Validate the configuration changes and allocate all resources
- * required to apply them.
- */
- transaction = NULL;
- context.client = NB_CLIENT_CONFD;
- ret = nb_candidate_commit_prepare(context, candidate, NULL,
- &transaction, false, false, errmsg,
- sizeof(errmsg));
- if (ret != NB_OK && ret != NB_ERR_NO_CHANGES) {
- enum confd_errcode errcode;
-
- switch (ret) {
- case NB_ERR_LOCKED:
- errcode = CONFD_ERRCODE_IN_USE;
- break;
- case NB_ERR_RESOURCE:
- errcode = CONFD_ERRCODE_RESOURCE_DENIED;
- break;
- default:
- errcode = CONFD_ERRCODE_APPLICATION;
- break;
- }
-
- /* Reject the configuration changes. */
- if (cdb_sub_abort_trans(cdb_sub_sock, errcode, 0, 0, "%s",
- errmsg)
- != CONFD_OK) {
- flog_err_confd("cdb_sub_abort_trans");
- return;
- }
- } else {
- /* Acknowledge the notification. */
- if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY)
- != CONFD_OK) {
- flog_err_confd("cdb_sync_subscription_socket");
- return;
- }
-
- /* No configuration changes. */
- if (!transaction)
- nb_config_free(candidate);
- }
-}
-
-static void frr_confd_cdb_read_cb_commit(int fd, int *subp, int reslen)
-{
- /*
- * No need to process the configuration changes again as we're already
- * keeping track of them in the "transaction" variable.
- */
- free(subp);
-
- /* Apply the transaction. */
- if (transaction) {
- struct nb_config *candidate = transaction->config;
- char errmsg[BUFSIZ] = {0};
-
- nb_candidate_commit_apply(transaction, true, NULL, errmsg,
- sizeof(errmsg));
- nb_config_free(candidate);
- }
-
- /* Acknowledge the notification. */
- if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY) != CONFD_OK) {
- flog_err_confd("cdb_sync_subscription_socket");
- return;
- }
-}
-
-static int frr_confd_cdb_read_cb_abort(int fd, int *subp, int reslen)
-{
- /*
- * No need to process the configuration changes again as we're already
- * keeping track of them in the "transaction" variable.
- */
- free(subp);
-
- /* Abort the transaction. */
- if (transaction) {
- struct nb_config *candidate = transaction->config;
- char errmsg[BUFSIZ] = {0};
-
- nb_candidate_commit_abort(transaction, errmsg, sizeof(errmsg));
- nb_config_free(candidate);
- }
-
- /* Acknowledge the notification. */
- if (cdb_sync_subscription_socket(fd, CDB_DONE_PRIORITY) != CONFD_OK) {
- flog_err_confd("cdb_sync_subscription_socket");
- return -1;
- }
-
- return 0;
-}
-
-static void frr_confd_cdb_read_cb(struct event *thread)
-{
- int fd = EVENT_FD(thread);
- enum cdb_sub_notification cdb_ev;
- int flags;
- int *subp = NULL;
- int reslen = 0;
-
- event_add_read(master, frr_confd_cdb_read_cb, NULL, fd, &t_cdb_sub);
-
- if (cdb_read_subscription_socket2(fd, &cdb_ev, &flags, &subp, &reslen)
- != CONFD_OK) {
- flog_err_confd("cdb_read_subscription_socket2");
- return;
- }
-
- switch (cdb_ev) {
- case CDB_SUB_PREPARE:
- frr_confd_cdb_read_cb_prepare(fd, subp, reslen);
- break;
- case CDB_SUB_COMMIT:
- frr_confd_cdb_read_cb_commit(fd, subp, reslen);
- break;
- case CDB_SUB_ABORT:
- frr_confd_cdb_read_cb_abort(fd, subp, reslen);
- break;
- default:
- flog_err_confd("unknown CDB event");
- break;
- }
-}
-
-/* Trigger CDB subscriptions to read the startup configuration. */
-static void *thread_cdb_trigger_subscriptions(void *data)
-{
- int sock;
- int *sub_points = NULL, len = 0;
- struct listnode *node;
- int *spoint;
- int i = 0;
-
- /* Create CDB data socket. */
- sock = socket(PF_INET, SOCK_STREAM, 0);
- if (sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- return NULL;
- }
-
- if (cdb_connect(sock, CDB_DATA_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("cdb_connect");
- return NULL;
- }
-
- /*
- * Fill array containing the subscription point of all loaded YANG
- * modules.
- */
- len = listcount(confd_spoints);
- sub_points = XCALLOC(MTYPE_CONFD, len * sizeof(int));
- for (ALL_LIST_ELEMENTS_RO(confd_spoints, node, spoint))
- sub_points[i++] = *spoint;
-
- if (cdb_trigger_subscriptions(sock, sub_points, len) != CONFD_OK) {
- flog_err_confd("cdb_trigger_subscriptions");
- return NULL;
- }
-
- /* Cleanup and exit thread. */
- XFREE(MTYPE_CONFD, sub_points);
- cdb_close(sock);
-
- return NULL;
-}
-
-static int frr_confd_subscribe(const struct lysc_node *snode, void *arg)
-{
- struct yang_module *module = arg;
- struct nb_node *nb_node;
- int *spoint;
- int ret;
-
- switch (snode->nodetype) {
- case LYS_CONTAINER:
- case LYS_LEAF:
- case LYS_LEAFLIST:
- case LYS_LIST:
- break;
- default:
- return YANG_ITER_CONTINUE;
- }
-
- if (CHECK_FLAG(snode->flags, LYS_CONFIG_R))
- return YANG_ITER_CONTINUE;
-
- nb_node = snode->priv;
- if (!nb_node)
- return YANG_ITER_CONTINUE;
-
- DEBUGD(&nb_dbg_client_confd, "%s: subscribing to '%s'", __func__,
- nb_node->xpath);
-
- spoint = XMALLOC(MTYPE_CONFD, sizeof(*spoint));
- ret = cdb_subscribe2(cdb_sub_sock, CDB_SUB_RUNNING_TWOPHASE,
- CDB_SUB_WANT_ABORT_ON_ABORT, 3, spoint,
- module->confd_hash, nb_node->xpath);
- if (ret != CONFD_OK) {
- flog_err_confd("cdb_subscribe2");
- XFREE(MTYPE_CONFD, spoint);
- return YANG_ITER_CONTINUE;
- }
-
- listnode_add(confd_spoints, spoint);
- return YANG_ITER_CONTINUE;
-}
-
-static int frr_confd_init_cdb(void)
-{
- struct yang_module *module;
- pthread_t cdb_trigger_thread;
-
- /* Create CDB subscription socket. */
- cdb_sub_sock = socket(PF_INET, SOCK_STREAM, 0);
- if (cdb_sub_sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- return -1;
- }
-
- if (cdb_connect(cdb_sub_sock, CDB_SUBSCRIPTION_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("cdb_connect");
- goto error;
- }
-
- /* Subscribe to all loaded YANG data modules. */
- confd_spoints = list_new();
- RB_FOREACH (module, yang_modules, &yang_modules) {
- module->confd_hash = confd_str2hash(module->info->ns);
- if (module->confd_hash == 0) {
- flog_err(
- EC_LIB_LIBCONFD,
- "%s: failed to find hash value for namespace %s",
- __func__, module->info->ns);
- goto error;
- }
-
- /*
- * The CDB API doesn't provide a mechanism to subscribe to an
- * entire YANG module. So we have to find the top level
- * nodes ourselves and subscribe to their paths.
- */
- yang_snodes_iterate(module->info, frr_confd_subscribe, 0,
- module);
- }
-
- if (cdb_subscribe_done(cdb_sub_sock) != CONFD_OK) {
- flog_err_confd("cdb_subscribe_done");
- goto error;
- }
-
- /* Create short lived pthread to trigger the CDB subscriptions. */
- if (pthread_create(&cdb_trigger_thread, NULL,
- thread_cdb_trigger_subscriptions, NULL)) {
- flog_err(EC_LIB_SYSTEM_CALL, "%s: error creating pthread: %s",
- __func__, safe_strerror(errno));
- goto error;
- }
- pthread_detach(cdb_trigger_thread);
-
- event_add_read(master, frr_confd_cdb_read_cb, NULL, cdb_sub_sock,
- &t_cdb_sub);
-
- return 0;
-
-error:
- frr_confd_finish_cdb();
-
- return -1;
-}
-
-static void frr_confd_finish_cdb(void)
-{
- if (cdb_sub_sock > 0) {
- EVENT_OFF(t_cdb_sub);
- cdb_close(cdb_sub_sock);
- }
-}
-
-/* ------------ DP code ------------ */
-
-static int frr_confd_transaction_init(struct confd_trans_ctx *tctx)
-{
- confd_trans_set_fd(tctx, dp_worker_sock);
-
- return CONFD_OK;
-}
-
-#define CONFD_MAX_CHILD_NODES 32
-
-static int frr_confd_data_get_elem(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp)
-{
- struct nb_node *nb_node;
- char xpath[XPATH_MAXLEN];
- struct yang_data *data;
- confd_value_t v;
- const void *list_entry = NULL;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_not_found(tctx);
- return CONFD_OK;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &list_entry) != 0) {
- confd_data_reply_not_found(tctx);
- return CONFD_OK;
- }
-
- data = nb_callback_get_elem(nb_node, xpath, list_entry);
- if (data) {
- if (data->value) {
- CONFD_SET_STR(&v, data->value);
- confd_data_reply_value(tctx, &v);
- } else
- confd_data_reply_found(tctx);
- yang_data_free(data);
- } else
- confd_data_reply_not_found(tctx);
-
- return CONFD_OK;
-}
-
-static int frr_confd_data_get_next(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp, long next)
-{
- struct nb_node *nb_node;
- char xpath[XPATH_MAXLEN];
- struct yang_data *data;
- const void *parent_list_entry, *nb_next;
- confd_value_t v[LIST_MAXKEYS];
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &parent_list_entry)
- != 0) {
- /* List entry doesn't exist anymore. */
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- nb_next = nb_callback_get_next(nb_node, parent_list_entry,
- (next == -1) ? NULL : (void *)next);
- if (!nb_next) {
- /* End of the list or leaf-list. */
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- switch (nb_node->snode->nodetype) {
- case LYS_LIST:
- if (!CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) {
- struct yang_list_keys keys;
-
- memset(&keys, 0, sizeof(keys));
- if (nb_callback_get_keys(nb_node, nb_next, &keys)
- != NB_OK) {
- flog_warn(EC_LIB_NB_CB_STATE,
- "%s: failed to get list keys",
- __func__);
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- return CONFD_OK;
- }
-
- /* Feed keys to ConfD. */
- for (size_t i = 0; i < keys.num; i++)
- CONFD_SET_STR(&v[i], keys.key[i]);
- confd_data_reply_next_key(tctx, v, keys.num,
- (long)nb_next);
- } else {
- char pointer_str[32];
-
- /*
- * ConfD 6.6 user guide, chapter 6.11 (Operational data
- * lists without keys):
- * "To support this without having completely separate
- * APIs, we use a "pseudo" key in the ConfD APIs for
- * this type of list. This key is not part of the data
- * model, and completely hidden in the northbound agent
- * interfaces, but is used with e.g. the get_next() and
- * get_elem() callbacks as if it were a normal key. This
- * "pseudo" key is always a single signed 64-bit
- * integer, i.e. the confd_value_t type is C_INT64. The
- * values can be chosen arbitrarily by the application,
- * as long as a key value returned by get_next() can be
- * used to get the data for the corresponding list entry
- * with get_elem() or get_object() as usual. It could
- * e.g. be an index into an array that holds the data,
- * or even a memory address in integer form".
- *
- * Since we're using the CONFD_DAEMON_FLAG_STRINGSONLY
- * option, we must convert our pseudo-key (a void
- * pointer) to a string before sending it to confd.
- */
- snprintf(pointer_str, sizeof(pointer_str), "%lu",
- (unsigned long)nb_next);
- CONFD_SET_STR(&v[0], pointer_str);
- confd_data_reply_next_key(tctx, v, 1, (long)nb_next);
- }
- break;
- case LYS_LEAFLIST:
- data = nb_callback_get_elem(nb_node, xpath, nb_next);
- if (data) {
- if (data->value) {
- CONFD_SET_STR(&v[0], data->value);
- confd_data_reply_next_key(tctx, v, 1,
- (long)nb_next);
- }
- yang_data_free(data);
- } else
- confd_data_reply_next_key(tctx, NULL, -1, -1);
- break;
- default:
- break;
- }
-
- return CONFD_OK;
-}
-
-/*
- * Optional callback - implemented for performance reasons.
- */
-static int frr_confd_data_get_object(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp)
-{
- struct nb_node *nb_node;
- const struct lysc_node *child;
- char xpath[XPATH_MAXLEN];
- char xpath_child[XPATH_MAXLEN * 2];
- struct list *elements;
- struct yang_data *data;
- const void *list_entry;
- confd_value_t values[CONFD_MAX_CHILD_NODES];
- size_t nvalues = 0;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_not_found(tctx);
- return CONFD_ERR;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &list_entry) != 0) {
- confd_data_reply_not_found(tctx);
- return CONFD_OK;
- }
-
- elements = yang_data_list_new();
-
- /* Loop through list child nodes. */
- LY_LIST_FOR (lysc_node_child(nb_node->snode), child) {
- struct nb_node *nb_node_child = child->priv;
- confd_value_t *v;
-
- if (nvalues > CONFD_MAX_CHILD_NODES)
- break;
-
- v = &values[nvalues++];
-
- /* Non-presence containers, lists and leaf-lists. */
- if (!nb_node_child->cbs.get_elem) {
- CONFD_SET_NOEXISTS(v);
- continue;
- }
-
- snprintf(xpath_child, sizeof(xpath_child), "%s/%s", xpath,
- child->name);
- data = nb_callback_get_elem(nb_node_child, xpath_child,
- list_entry);
- if (data) {
- if (data->value)
- CONFD_SET_STR(v, data->value);
- else {
- /* Presence containers and empty leafs. */
- CONFD_SET_XMLTAG(
- v, nb_node_child->confd_hash,
- confd_str2hash(nb_node_child->snode
- ->module->ns));
- }
- listnode_add(elements, data);
- } else
- CONFD_SET_NOEXISTS(v);
- }
-
- confd_data_reply_value_array(tctx, values, nvalues);
-
- /* Release memory. */
- list_delete(&elements);
-
- return CONFD_OK;
-}
-
-/*
- * Optional callback - implemented for performance reasons.
- */
-static int frr_confd_data_get_next_object(struct confd_trans_ctx *tctx,
- confd_hkeypath_t *kp, long next)
-{
- char xpath[XPATH_MAXLEN];
- struct nb_node *nb_node;
- struct list *elements;
- const void *parent_list_entry;
- const void *nb_next;
-#define CONFD_OBJECTS_PER_TIME 100
- struct confd_next_object objects[CONFD_OBJECTS_PER_TIME + 1];
- char pseudo_keys[CONFD_OBJECTS_PER_TIME][32];
- int nobjects = 0;
-
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- confd_data_reply_next_object_array(tctx, NULL, 0, 0);
- return CONFD_OK;
- }
-
- if (frr_confd_hkeypath_get_list_entry(kp, nb_node, &parent_list_entry)
- != 0) {
- confd_data_reply_next_object_array(tctx, NULL, 0, 0);
- return CONFD_OK;
- }
-
- elements = yang_data_list_new();
- nb_next = (next == -1) ? NULL : (void *)next;
-
- memset(objects, 0, sizeof(objects));
- for (int j = 0; j < CONFD_OBJECTS_PER_TIME; j++) {
- struct confd_next_object *object;
- const struct lysc_node *child;
- struct yang_data *data;
- size_t nvalues = 0;
-
- object = &objects[j];
-
- nb_next = nb_callback_get_next(nb_node, parent_list_entry,
- nb_next);
- if (!nb_next)
- /* End of the list. */
- break;
-
- object->next = (long)nb_next;
-
- /* Leaf-lists require special handling. */
- if (nb_node->snode->nodetype == LYS_LEAFLIST) {
- object->v = XMALLOC(MTYPE_CONFD, sizeof(confd_value_t));
- data = nb_callback_get_elem(nb_node, xpath, nb_next);
- assert(data && data->value);
- CONFD_SET_STR(object->v, data->value);
- nvalues++;
- listnode_add(elements, data);
- goto next;
- }
-
- object->v =
- XMALLOC(MTYPE_CONFD,
- CONFD_MAX_CHILD_NODES * sizeof(confd_value_t));
-
- /*
- * ConfD 6.6 user guide, chapter 6.11 (Operational data lists
- * without keys):
- * "In the response to the get_next_object() callback, the data
- * provider is expected to provide the key values along with the
- * other leafs in an array that is populated according to the
- * data model. This must be done also for this type of list,
- * even though the key isn't actually in the data model. The
- * "pseudo" key must always be the first element in the array".
- */
- if (CHECK_FLAG(nb_node->flags, F_NB_NODE_KEYLESS_LIST)) {
- confd_value_t *v;
-
- snprintf(pseudo_keys[j], sizeof(pseudo_keys[j]), "%lu",
- (unsigned long)nb_next);
-
- v = &object->v[nvalues++];
- CONFD_SET_STR(v, pseudo_keys[j]);
- }
-
- /* Loop through list child nodes. */
- LY_LIST_FOR (lysc_node_child(nb_node->snode), child) {
- struct nb_node *nb_node_child = child->priv;
- char xpath_child[XPATH_MAXLEN * 2];
- confd_value_t *v;
-
- if (nvalues > CONFD_MAX_CHILD_NODES)
- break;
-
- v = &object->v[nvalues++];
-
- /* Non-presence containers, lists and leaf-lists. */
- if (!nb_node_child->cbs.get_elem) {
- CONFD_SET_NOEXISTS(v);
- continue;
- }
-
- snprintf(xpath_child, sizeof(xpath_child), "%s/%s",
- xpath, child->name);
- data = nb_callback_get_elem(nb_node_child, xpath_child,
- nb_next);
- if (data) {
- if (data->value)
- CONFD_SET_STR(v, data->value);
- else {
- /*
- * Presence containers and empty leafs.
- */
- CONFD_SET_XMLTAG(
- v, nb_node_child->confd_hash,
- confd_str2hash(
- nb_node_child->snode
- ->module->ns));
- }
- listnode_add(elements, data);
- } else
- CONFD_SET_NOEXISTS(v);
- }
- next:
- object->n = nvalues;
- nobjects++;
- }
-
- if (nobjects == 0) {
- confd_data_reply_next_object_array(tctx, NULL, 0, 0);
- list_delete(&elements);
- return CONFD_OK;
- }
-
- /* Detect end of the list. */
- if (!nb_next) {
- nobjects++;
- objects[nobjects].v = NULL;
- }
-
- /* Reply to ConfD. */
- confd_data_reply_next_object_arrays(tctx, objects, nobjects, 0);
- if (!nb_next)
- nobjects--;
-
- /* Release memory. */
- list_delete(&elements);
- for (int j = 0; j < nobjects; j++) {
- struct confd_next_object *object;
-
- object = &objects[j];
- XFREE(MTYPE_CONFD, object->v);
- }
-
- return CONFD_OK;
-}
-
-static int frr_confd_notification_send(const char *xpath,
- struct list *arguments)
-{
- struct nb_node *nb_node;
- struct yang_module *module;
- struct confd_datetime now;
- confd_tag_value_t *values;
- int nvalues;
- int i = 0;
- struct yang_data *data;
- struct listnode *node;
- int ret;
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- return -1;
- }
- module = yang_module_find(nb_node->snode->module->name);
- assert(module);
-
- nvalues = 2;
- if (arguments)
- nvalues += listcount(arguments);
-
- values = XMALLOC(MTYPE_CONFD, nvalues * sizeof(*values));
-
- CONFD_SET_TAG_XMLBEGIN(&values[i++], nb_node->confd_hash,
- module->confd_hash);
- for (ALL_LIST_ELEMENTS_RO(arguments, node, data)) {
- struct nb_node *nb_node_arg;
-
- nb_node_arg = nb_node_find(data->xpath);
- if (!nb_node_arg) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__,
- data->xpath);
- XFREE(MTYPE_CONFD, values);
- return NB_ERR;
- }
-
- CONFD_SET_TAG_STR(&values[i++], nb_node_arg->confd_hash,
- data->value);
- }
- CONFD_SET_TAG_XMLEND(&values[i++], nb_node->confd_hash,
- module->confd_hash);
-
- getdatetime(&now);
- ret = confd_notification_send(live_ctx, &now, values, nvalues);
-
- /* Release memory. */
- XFREE(MTYPE_CONFD, values);
-
- /* Map ConfD return code to northbound return code. */
- switch (ret) {
- case CONFD_OK:
- return NB_OK;
- default:
- return NB_ERR;
- }
-}
-
-static int frr_confd_action_init(struct confd_user_info *uinfo)
-{
- confd_action_set_fd(uinfo, dp_worker_sock);
-
- return CONFD_OK;
-}
-
-static int frr_confd_action_execute(struct confd_user_info *uinfo,
- struct xml_tag *name, confd_hkeypath_t *kp,
- confd_tag_value_t *params, int nparams)
-{
- char xpath[XPATH_MAXLEN];
- struct nb_node *nb_node;
- struct list *input;
- struct list *output;
- struct yang_data *data;
- confd_tag_value_t *reply;
- int ret = CONFD_OK;
- char errmsg[BUFSIZ] = {0};
-
- /* Getting the XPath is tricky. */
- if (kp) {
- /* This is a YANG RPC. */
- frr_confd_get_xpath(kp, xpath, sizeof(xpath));
- strlcat(xpath, "/", sizeof(xpath));
- strlcat(xpath, confd_hash2str(name->tag), sizeof(xpath));
- } else {
- /* This is a YANG action. */
- snprintf(xpath, sizeof(xpath), "/%s:%s",
- confd_ns2prefix(name->ns), confd_hash2str(name->tag));
- }
-
- nb_node = nb_node_find(xpath);
- if (!nb_node) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__, xpath);
- return CONFD_ERR;
- }
-
- input = yang_data_list_new();
- output = yang_data_list_new();
-
- /* Process input nodes. */
- for (int i = 0; i < nparams; i++) {
- char xpath_input[XPATH_MAXLEN * 2];
- char value_str[YANG_VALUE_MAXLEN];
-
- snprintf(xpath_input, sizeof(xpath_input), "%s/%s", xpath,
- confd_hash2str(params[i].tag.tag));
-
- if (frr_confd_val2str(xpath_input, &params[i].v, value_str,
- sizeof(value_str))
- != 0) {
- flog_err(
- EC_LIB_CONFD_DATA_CONVERT,
- "%s: failed to convert ConfD value to a string",
- __func__);
- ret = CONFD_ERR;
- goto exit;
- }
-
- data = yang_data_new(xpath_input, value_str);
- listnode_add(input, data);
- }
-
- /* Execute callback registered for this XPath. */
- if (nb_callback_rpc(nb_node, xpath, input, output, errmsg,
- sizeof(errmsg))
- != NB_OK) {
- flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s",
- __func__, xpath);
- ret = CONFD_ERR;
- goto exit;
- }
-
- /* Process output nodes. */
- if (listcount(output) > 0) {
- struct listnode *node;
- int i = 0;
-
- reply = XMALLOC(MTYPE_CONFD,
- listcount(output) * sizeof(*reply));
-
- for (ALL_LIST_ELEMENTS_RO(output, node, data)) {
- struct nb_node *nb_node_output;
- int hash;
-
- nb_node_output = nb_node_find(data->xpath);
- if (!nb_node_output) {
- flog_warn(EC_LIB_YANG_UNKNOWN_DATA_PATH,
- "%s: unknown data path: %s", __func__,
- data->xpath);
- goto exit;
- }
-
- hash = confd_str2hash(nb_node_output->snode->name);
- CONFD_SET_TAG_STR(&reply[i++], hash, data->value);
- }
- confd_action_reply_values(uinfo, reply, listcount(output));
- XFREE(MTYPE_CONFD, reply);
- }
-
-exit:
- /* Release memory. */
- list_delete(&input);
- list_delete(&output);
-
- return ret;
-}
-
-
-static int frr_confd_dp_read(struct confd_daemon_ctx *dctx, int fd)
-{
- int ret;
-
- ret = confd_fd_ready(dctx, fd);
- if (ret == CONFD_EOF) {
- flog_err_confd("confd_fd_ready");
- frr_confd_finish();
- return -1;
- } else if (ret == CONFD_ERR && confd_errno != CONFD_ERR_EXTERNAL) {
- flog_err_confd("confd_fd_ready");
- frr_confd_finish();
- return -1;
- }
-
- return 0;
-}
-
-static void frr_confd_dp_ctl_read(struct event *thread)
-{
- struct confd_daemon_ctx *dctx = EVENT_ARG(thread);
- int fd = EVENT_FD(thread);
-
- event_add_read(master, frr_confd_dp_ctl_read, dctx, fd, &t_dp_ctl);
-
- frr_confd_dp_read(dctx, fd);
-}
-
-static void frr_confd_dp_worker_read(struct event *thread)
-{
- struct confd_daemon_ctx *dctx = EVENT_ARG(thread);
- int fd = EVENT_FD(thread);
-
- event_add_read(master, frr_confd_dp_worker_read, dctx, fd,
- &t_dp_worker);
-
- frr_confd_dp_read(dctx, fd);
-}
-
-static int frr_confd_subscribe_state(const struct lysc_node *snode, void *arg)
-{
- struct nb_node *nb_node = snode->priv;
- struct confd_data_cbs *data_cbs = arg;
-
- if (!nb_node || !CHECK_FLAG(snode->flags, LYS_CONFIG_R))
- return YANG_ITER_CONTINUE;
- /* We only need to subscribe to the root of the state subtrees. */
- if (snode->parent && CHECK_FLAG(snode->parent->flags, LYS_CONFIG_R))
- return YANG_ITER_CONTINUE;
-
- DEBUGD(&nb_dbg_client_confd,
- "%s: providing data to '%s' (callpoint %s)", __func__,
- nb_node->xpath, snode->name);
-
- strlcpy(data_cbs->callpoint, snode->name, sizeof(data_cbs->callpoint));
- if (confd_register_data_cb(dctx, data_cbs) != CONFD_OK)
- flog_err_confd("confd_register_data_cb");
-
- return YANG_ITER_CONTINUE;
-}
-
-static int frr_confd_init_dp(const char *program_name)
-{
- struct confd_trans_cbs trans_cbs;
- struct confd_data_cbs data_cbs;
- struct confd_notification_stream_cbs ncbs;
- struct confd_action_cbs acbs;
-
- /* Initialize daemon context. */
- dctx = confd_init_daemon(program_name);
- if (!dctx) {
- flog_err_confd("confd_init_daemon");
- goto error;
- }
-
- /*
- * Inform we want to receive YANG values as raw strings, and that we
- * want to provide only strings in the reply functions, regardless of
- * the YANG type.
- */
- confd_set_daemon_flags(dctx, CONFD_DAEMON_FLAG_STRINGSONLY);
-
- /* Establish a control socket. */
- dp_ctl_sock = socket(PF_INET, SOCK_STREAM, 0);
- if (dp_ctl_sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- goto error;
- }
-
- if (confd_connect(dctx, dp_ctl_sock, CONTROL_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("confd_connect");
- goto error;
- }
-
- /*
- * Establish a worker socket (only one since this plugin runs on a
- * single thread).
- */
- dp_worker_sock = socket(PF_INET, SOCK_STREAM, 0);
- if (dp_worker_sock < 0) {
- flog_err(EC_LIB_SOCKET, "%s: failed to create socket: %s",
- __func__, safe_strerror(errno));
- goto error;
- }
- if (confd_connect(dctx, dp_worker_sock, WORKER_SOCKET, &confd_addr,
- sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("confd_connect");
- goto error;
- }
-
- /* Register transaction callback functions. */
- memset(&trans_cbs, 0, sizeof(trans_cbs));
- trans_cbs.init = frr_confd_transaction_init;
- confd_register_trans_cb(dctx, &trans_cbs);
-
- /* Register our read/write callbacks. */
- memset(&data_cbs, 0, sizeof(data_cbs));
- data_cbs.get_elem = frr_confd_data_get_elem;
- data_cbs.exists_optional = frr_confd_data_get_elem;
- data_cbs.get_next = frr_confd_data_get_next;
- data_cbs.get_object = frr_confd_data_get_object;
- data_cbs.get_next_object = frr_confd_data_get_next_object;
-
- /*
- * Iterate over all loaded YANG modules and subscribe to the paths
- * referent to state data.
- */
- yang_snodes_iterate(NULL, frr_confd_subscribe_state, 0, &data_cbs);
-
- /* Register notification stream. */
- memset(&ncbs, 0, sizeof(ncbs));
- ncbs.fd = dp_worker_sock;
- /*
- * RFC 5277 - Section 3.2.3:
- * A NETCONF server implementation supporting the notification
- * capability MUST support the "NETCONF" notification event
- * stream. This stream contains all NETCONF XML event notifications
- * supported by the NETCONF server.
- */
- strlcpy(ncbs.streamname, "NETCONF", sizeof(ncbs.streamname));
- if (confd_register_notification_stream(dctx, &ncbs, &live_ctx)
- != CONFD_OK) {
- flog_err_confd("confd_register_notification_stream");
- goto error;
- }
-
- /* Register the action handler callback. */
- memset(&acbs, 0, sizeof(acbs));
- strlcpy(acbs.actionpoint, "actionpoint", sizeof(acbs.actionpoint));
- acbs.init = frr_confd_action_init;
- acbs.action = frr_confd_action_execute;
- if (confd_register_action_cbs(dctx, &acbs) != CONFD_OK) {
- flog_err_confd("confd_register_action_cbs");
- goto error;
- }
-
- /* Notify we registered all callbacks we wanted. */
- if (confd_register_done(dctx) != CONFD_OK) {
- flog_err_confd("confd_register_done");
- goto error;
- }
-
- event_add_read(master, frr_confd_dp_ctl_read, dctx, dp_ctl_sock,
- &t_dp_ctl);
- event_add_read(master, frr_confd_dp_worker_read, dctx, dp_worker_sock,
- &t_dp_worker);
-
- return 0;
-
-error:
- frr_confd_finish_dp();
-
- return -1;
-}
-
-static void frr_confd_finish_dp(void)
-{
- if (dp_worker_sock > 0) {
- EVENT_OFF(t_dp_worker);
- close(dp_worker_sock);
- }
- if (dp_ctl_sock > 0) {
- EVENT_OFF(t_dp_ctl);
- close(dp_ctl_sock);
- }
- if (dctx != NULL)
- confd_release_daemon(dctx);
-}
-
-/* ------------ CLI ------------ */
-
-DEFUN (debug_nb_confd,
- debug_nb_confd_cmd,
- "[no] debug northbound client confd",
- NO_STR
- DEBUG_STR
- "Northbound debugging\n"
- "Client\n"
- "ConfD\n")
-{
- uint32_t mode = DEBUG_NODE2MODE(vty->node);
- bool no = strmatch(argv[0]->text, "no");
-
- DEBUG_MODE_SET(&nb_dbg_client_confd, mode, !no);
-
- return CMD_SUCCESS;
-}
-
-static int frr_confd_debug_config_write(struct vty *vty)
-{
- if (DEBUG_MODE_CHECK(&nb_dbg_client_confd, DEBUG_MODE_CONF))
- vty_out(vty, "debug northbound client confd\n");
-
- return 0;
-}
-
-static int frr_confd_debug_set_all(uint32_t flags, bool set)
-{
- DEBUG_FLAGS_SET(&nb_dbg_client_confd, flags, set);
-
- /* If all modes have been turned off, don't preserve options. */
- if (!DEBUG_MODE_CHECK(&nb_dbg_client_confd, DEBUG_MODE_ALL))
- DEBUG_CLEAR(&nb_dbg_client_confd);
-
- return 0;
-}
-
-static void frr_confd_cli_init(void)
-{
- hook_register(nb_client_debug_config_write,
- frr_confd_debug_config_write);
- hook_register(nb_client_debug_set_all, frr_confd_debug_set_all);
-
- install_element(ENABLE_NODE, &debug_nb_confd_cmd);
- install_element(CONFIG_NODE, &debug_nb_confd_cmd);
-}
-
-/* ------------ Main ------------ */
-
-static int frr_confd_calculate_snode_hash(const struct lysc_node *snode,
- void *arg)
-{
- struct nb_node *nb_node = snode->priv;
-
- if (nb_node)
- nb_node->confd_hash = confd_str2hash(snode->name);
-
- return YANG_ITER_CONTINUE;
-}
-
-static int frr_confd_init(const char *program_name)
-{
- struct sockaddr_in *confd_addr4 = (struct sockaddr_in *)&confd_addr;
- int debuglevel = CONFD_SILENT;
- int ret = -1;
-
- /* Initialize ConfD library. */
- confd_init(program_name, stderr, debuglevel);
-
- confd_addr4->sin_family = AF_INET;
- confd_addr4->sin_addr.s_addr = inet_addr("127.0.0.1");
- confd_addr4->sin_port = htons(CONFD_PORT);
- if (confd_load_schemas(&confd_addr, sizeof(struct sockaddr_in))
- != CONFD_OK) {
- flog_err_confd("confd_load_schemas");
- return -1;
- }
-
- ret = frr_confd_init_cdb();
- if (ret != 0)
- goto error;
-
- ret = frr_confd_init_dp(program_name);
- if (ret != 0) {
- frr_confd_finish_cdb();
- goto error;
- }
-
- yang_snodes_iterate(NULL, frr_confd_calculate_snode_hash, 0, NULL);
-
- hook_register(nb_notification_send, frr_confd_notification_send);
-
- confd_connected = true;
- return 0;
-
-error:
- confd_free_schemas();
-
- return ret;
-}
-
-static int frr_confd_finish(void)
-{
- if (!confd_connected)
- return 0;
-
- frr_confd_finish_cdb();
- frr_confd_finish_dp();
-
- confd_free_schemas();
-
- confd_connected = false;
-
- return 0;
-}
-
-static int frr_confd_module_late_init(struct event_loop *tm)
-{
- master = tm;
-
- if (frr_confd_init(frr_get_progname()) < 0) {
- flog_err(EC_LIB_CONFD_INIT,
- "failed to initialize the ConfD module");
- return -1;
- }
-
- hook_register(frr_fini, frr_confd_finish);
- frr_confd_cli_init();
-
- return 0;
-}
-
-static int frr_confd_module_init(void)
-{
- hook_register(frr_late_init, frr_confd_module_late_init);
-
- return 0;
-}
-
-FRR_MODULE_SETUP(.name = "frr_confd", .version = FRR_VERSION,
- .description = "FRR ConfD integration module",
- .init = frr_confd_module_init,
-);
diff --git a/lib/northbound_grpc.cpp b/lib/northbound_grpc.cpp
index 7957752..612ec39 100644
--- a/lib/northbound_grpc.cpp
+++ b/lib/northbound_grpc.cpp
@@ -1011,12 +1011,11 @@ grpc::Status HandleUnaryExecute(
grpc_debug("%s: entered", __func__);
struct nb_node *nb_node;
- struct list *input_list;
- struct list *output_list;
- struct listnode *node;
- struct yang_data *data;
+ struct lyd_node *input_tree, *output_tree, *child;
const char *xpath;
char errmsg[BUFSIZ] = {0};
+ char path[XPATH_MAXLEN];
+ LY_ERR err;
// Request: string path = 1;
xpath = tag->request.path().c_str();
@@ -1032,40 +1031,66 @@ grpc::Status HandleUnaryExecute(
return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
"Unknown data path");
- input_list = yang_data_list_new();
- output_list = yang_data_list_new();
+ // Create input data tree.
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0,
+ (LYD_ANYDATA_VALUETYPE)0, 0, NULL, &input_tree);
+ if (err != LY_SUCCESS) {
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid data path");
+ }
// Read input parameters.
auto input = tag->request.input();
for (const frr::PathValue &pv : input) {
// Request: repeated PathValue input = 2;
- data = yang_data_new(pv.path().c_str(), pv.value().c_str());
- listnode_add(input_list, data);
+ err = lyd_new_path(input_tree, ly_native_ctx, pv.path().c_str(),
+ pv.value().c_str(), 0, NULL);
+ if (err != LY_SUCCESS) {
+ lyd_free_tree(input_tree);
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid input data");
+ }
+ }
+
+ // Validate input data.
+ err = lyd_validate_op(input_tree, NULL, LYD_TYPE_RPC_YANG, NULL);
+ if (err != LY_SUCCESS) {
+ lyd_free_tree(input_tree);
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid input data");
+ }
+
+ // Create output data tree.
+ err = lyd_new_path2(NULL, ly_native_ctx, xpath, NULL, 0,
+ (LYD_ANYDATA_VALUETYPE)0, 0, NULL, &output_tree);
+ if (err != LY_SUCCESS) {
+ lyd_free_tree(input_tree);
+ return grpc::Status(grpc::StatusCode::INVALID_ARGUMENT,
+ "Invalid data path");
}
// Execute callback registered for this XPath.
- if (nb_callback_rpc(nb_node, xpath, input_list, output_list, errmsg,
- sizeof(errmsg))
- != NB_OK) {
+ if (nb_callback_rpc(nb_node, xpath, input_tree, output_tree, errmsg,
+ sizeof(errmsg)) != NB_OK) {
flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s",
__func__, xpath);
- list_delete(&input_list);
- list_delete(&output_list);
+ lyd_free_tree(input_tree);
+ lyd_free_tree(output_tree);
return grpc::Status(grpc::StatusCode::INTERNAL, "RPC failed");
}
// Process output parameters.
- for (ALL_LIST_ELEMENTS_RO(output_list, node, data)) {
+ LY_LIST_FOR (lyd_child(output_tree), child) {
// Response: repeated PathValue output = 1;
frr::PathValue *pv = tag->response.add_output();
- pv->set_path(data->xpath);
- pv->set_value(data->value);
+ pv->set_path(lyd_path(child, LYD_PATH_STD, path, sizeof(path)));
+ pv->set_value(yang_dnode_get_string(child, NULL));
}
// Release memory.
- list_delete(&input_list);
- list_delete(&output_list);
+ lyd_free_tree(input_tree);
+ lyd_free_tree(output_tree);
return grpc::Status::OK;
}
diff --git a/lib/northbound_oper.c b/lib/northbound_oper.c
index 2394b5e..5f38c97 100644
--- a/lib/northbound_oper.c
+++ b/lib/northbound_oper.c
@@ -342,38 +342,6 @@ static void nb_op_resume_data_tree(struct nb_op_yield_state *ys)
/* ======================= */
/**
- * __xpath_pop_node() - remove the last node from xpath string
- * @xpath: an xpath string
- *
- * Return: NB_OK or NB_ERR_NOT_FOUND if nothing left to pop.
- */
-static int __xpath_pop_node(char *xpath)
-{
- int len = strlen(xpath);
- bool abs = xpath[0] == '/';
- char *slash;
-
- /* "//" or "/" => NULL */
- if (abs && (len == 1 || (len == 2 && xpath[1] == '/')))
- return NB_ERR_NOT_FOUND;
-
- slash = (char *)frrstr_back_to_char(xpath, '/');
- /* "/foo/bar/" or "/foo/bar//" => "/foo " */
- if (slash && slash == &xpath[len - 1]) {
- xpath[--len] = 0;
- slash = (char *)frrstr_back_to_char(xpath, '/');
- if (slash && slash == &xpath[len - 1]) {
- xpath[--len] = 0;
- slash = (char *)frrstr_back_to_char(xpath, '/');
- }
- }
- if (!slash)
- return NB_ERR_NOT_FOUND;
- *slash = 0;
- return NB_OK;
-}
-
-/**
* nb_op_xpath_to_trunk() - generate a lyd_node tree (trunk) using an xpath.
* @xpath_in: xpath query string to build trunk from.
* @dnode: resulting tree (trunk)
@@ -398,7 +366,7 @@ static enum nb_error nb_op_xpath_to_trunk(const char *xpath_in,
if (err == LY_SUCCESS)
break;
- ret = __xpath_pop_node(xpath);
+ ret = yang_xpath_pop_node(xpath);
if (ret != NB_OK)
break;
}
@@ -1588,8 +1556,9 @@ static enum nb_error nb_op_yield(struct nb_op_yield_state *ys)
unsigned long min_us = MAX(1, NB_OP_WALK_INTERVAL_US / 50000);
struct timeval tv = { .tv_sec = 0, .tv_usec = min_us };
- DEBUGD(&nb_dbg_events, "NB oper-state: yielding %s for %lus (should_batch %d)",
- ys->xpath, tv.tv_usec, ys->should_batch);
+ DEBUGD(&nb_dbg_events,
+ "NB oper-state: yielding %s for %lldus (should_batch %d)",
+ ys->xpath, (long long)tv.tv_usec, ys->should_batch);
if (ys->should_batch) {
/*
diff --git a/lib/northbound_sysrepo.c b/lib/northbound_sysrepo.c
index 4942d66..0ec7610 100644
--- a/lib/northbound_sysrepo.c
+++ b/lib/northbound_sysrepo.c
@@ -19,8 +19,6 @@
#include <sysrepo/values.h>
#include <sysrepo/xpath.h>
-DEFINE_MTYPE_STATIC(LIB, SYSREPO, "Sysrepo module");
-
static struct debug nb_dbg_client_sysrepo = {0, "Northbound client: Sysrepo"};
static struct event_loop *master;
@@ -379,16 +377,11 @@ static int frr_sr_state_cb(sr_session_ctx_t *session, uint32_t sub_id,
return SR_ERR_OK;
}
static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id,
- const char *xpath, const sr_val_t *sr_input,
- const size_t input_cnt, sr_event_t sr_ev,
- uint32_t request_id, sr_val_t **sr_output,
- size_t *sr_output_cnt, void *private_ctx)
+ const char *xpath, const struct lyd_node *input,
+ sr_event_t sr_ev, uint32_t request_id,
+ struct lyd_node *output, void *private_ctx)
{
struct nb_node *nb_node;
- struct list *input;
- struct list *output;
- struct yang_data *data;
- size_t cb_output_cnt;
int ret = SR_ERR_OK;
char errmsg[BUFSIZ] = {0};
@@ -399,19 +392,6 @@ static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id,
return SR_ERR_INTERNAL;
}
- input = yang_data_list_new();
- output = yang_data_list_new();
-
- /* Process input. */
- for (size_t i = 0; i < input_cnt; i++) {
- char value_str[YANG_VALUE_MAXLEN];
-
- sr_val_to_buff(&sr_input[i], value_str, sizeof(value_str));
-
- data = yang_data_new(xpath, value_str);
- listnode_add(input, data);
- }
-
/* Execute callback registered for this XPath. */
if (nb_callback_rpc(nb_node, xpath, input, output, errmsg,
sizeof(errmsg))
@@ -419,44 +399,8 @@ static int frr_sr_config_rpc_cb(sr_session_ctx_t *session, uint32_t sub_id,
flog_warn(EC_LIB_NB_CB_RPC, "%s: rpc callback failed: %s",
__func__, xpath);
ret = SR_ERR_OPERATION_FAILED;
- goto exit;
- }
-
- /* Process output. */
- if (listcount(output) > 0) {
- sr_val_t *values = NULL;
- struct listnode *node;
- int i = 0;
-
- cb_output_cnt = listcount(output);
- ret = sr_new_values(cb_output_cnt, &values);
- if (ret != SR_ERR_OK) {
- flog_err(EC_LIB_LIBSYSREPO, "%s: sr_new_values(): %s",
- __func__, sr_strerror(ret));
- goto exit;
- }
-
- for (ALL_LIST_ELEMENTS_RO(output, node, data)) {
- if (yang_data_frr2sr(data, &values[i++]) != 0) {
- flog_err(
- EC_LIB_SYSREPO_DATA_CONVERT,
- "%s: failed to convert data to Sysrepo format",
- __func__);
- ret = SR_ERR_INTERNAL;
- sr_free_values(values, cb_output_cnt);
- goto exit;
- }
- }
-
- *sr_output = values;
- *sr_output_cnt = cb_output_cnt;
}
-exit:
- /* Release memory. */
- list_delete(&input);
- list_delete(&output);
-
return ret;
}
@@ -581,8 +525,9 @@ static int frr_sr_subscribe_rpc(const struct lysc_node *snode, void *arg)
DEBUGD(&nb_dbg_client_sysrepo, "sysrepo: providing RPC to '%s'",
nb_node->xpath);
- ret = sr_rpc_subscribe(session, nb_node->xpath, frr_sr_config_rpc_cb,
- NULL, 0, 0, &module->sr_subscription);
+ ret = sr_rpc_subscribe_tree(session, nb_node->xpath,
+ frr_sr_config_rpc_cb, NULL, 0, 0,
+ &module->sr_subscription);
if (ret != SR_ERR_OK)
flog_err(EC_LIB_LIBSYSREPO, "sr_rpc_subscribe(): %s",
sr_strerror(ret));
diff --git a/lib/plist.c b/lib/plist.c
index 618d92b..2cfaa7d 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1073,17 +1073,13 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
struct prefix_master *master;
int64_t seqnum = 0;
json_object *json = NULL;
- json_object *json_proto = NULL;
master = prefix_master_get(afi, 0);
if (master == NULL)
return CMD_WARNING;
- if (uj) {
+ if (uj)
json = json_object_new_object();
- json_proto = json_object_new_object();
- json_object_object_add(json, frr_protoname, json_proto);
- }
if (seq)
seqnum = (int64_t)atol(seq);
@@ -1096,8 +1092,8 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
"%% Can't find specified prefix-list\n");
return CMD_WARNING;
}
- vty_show_prefix_entry(vty, json_proto, afi, plist, master,
- dtype, seqnum);
+ vty_show_prefix_entry(vty, json, afi, plist, master, dtype,
+ seqnum);
} else {
if (dtype == detail_display || dtype == summary_display) {
if (master->recent && !uj)
@@ -1107,8 +1103,8 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
}
frr_each (plist, &master->str, plist)
- vty_show_prefix_entry(vty, json_proto, afi, plist,
- master, dtype, seqnum);
+ vty_show_prefix_entry(vty, json, afi, plist, master,
+ dtype, seqnum);
}
return vty_json(vty, json);
@@ -1227,7 +1223,7 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
#include "lib/plist_clippy.c"
-DEFPY (show_ip_prefix_list,
+DEFPY_NOSH (show_ip_prefix_list,
show_ip_prefix_list_cmd,
"show ip prefix-list [PREFIXLIST4_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
SHOW_STR
@@ -1239,6 +1235,7 @@ DEFPY (show_ip_prefix_list,
JSON_STR)
{
enum display_type dtype = normal_display;
+
if (dseq)
dtype = sequential_display;
@@ -1258,6 +1255,7 @@ DEFPY (show_ip_prefix_list_prefix,
"First matched prefix\n")
{
enum display_type dtype = normal_display;
+
if (dl)
dtype = longer_display;
else if (dfm)
@@ -1267,7 +1265,7 @@ DEFPY (show_ip_prefix_list_prefix,
dtype);
}
-DEFPY (show_ip_prefix_list_summary,
+DEFPY_NOSH (show_ip_prefix_list_summary,
show_ip_prefix_list_summary_cmd,
"show ip prefix-list summary [PREFIXLIST4_NAME$name] [json$uj]",
SHOW_STR
@@ -1281,7 +1279,7 @@ DEFPY (show_ip_prefix_list_summary,
summary_display, !!uj);
}
-DEFPY (show_ip_prefix_list_detail,
+DEFPY_NOSH (show_ip_prefix_list_detail,
show_ip_prefix_list_detail_cmd,
"show ip prefix-list detail [PREFIXLIST4_NAME$name] [json$uj]",
SHOW_STR
@@ -1307,7 +1305,7 @@ DEFPY (clear_ip_prefix_list,
return vty_clear_prefix_list(vty, AFI_IP, name, prefix_str);
}
-DEFPY (show_ipv6_prefix_list,
+DEFPY_NOSH(show_ipv6_prefix_list,
show_ipv6_prefix_list_cmd,
"show ipv6 prefix-list [PREFIXLIST6_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
SHOW_STR
@@ -1319,6 +1317,7 @@ DEFPY (show_ipv6_prefix_list,
JSON_STR)
{
enum display_type dtype = normal_display;
+
if (dseq)
dtype = sequential_display;
@@ -1338,6 +1337,7 @@ DEFPY (show_ipv6_prefix_list_prefix,
"First matched prefix\n")
{
enum display_type dtype = normal_display;
+
if (dl)
dtype = longer_display;
else if (dfm)
@@ -1347,7 +1347,7 @@ DEFPY (show_ipv6_prefix_list_prefix,
prefix_str, dtype);
}
-DEFPY (show_ipv6_prefix_list_summary,
+DEFPY_NOSH (show_ipv6_prefix_list_summary,
show_ipv6_prefix_list_summary_cmd,
"show ipv6 prefix-list summary [PREFIXLIST6_NAME$name] [json$uj]",
SHOW_STR
@@ -1361,7 +1361,7 @@ DEFPY (show_ipv6_prefix_list_summary,
summary_display, !!uj);
}
-DEFPY (show_ipv6_prefix_list_detail,
+DEFPY_NOSH (show_ipv6_prefix_list_detail,
show_ipv6_prefix_list_detail_cmd,
"show ipv6 prefix-list detail [PREFIXLIST6_NAME$name] [json$uj]",
SHOW_STR
diff --git a/lib/prefix.c b/lib/prefix.c
index f342c4c..2485c3e 100644
--- a/lib/prefix.c
+++ b/lib/prefix.c
@@ -1124,6 +1124,15 @@ const char *prefix2str(union prefixconstptr pu, char *str, int size)
return str;
}
+void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
+ char *buf, int buf_size)
+{
+ if (ipaddr_is_zero(addr))
+ strlcpy(buf, "*", buf_size);
+ else
+ (void)snprintfrr(buf, buf_size, "%pIA", addr);
+}
+
static ssize_t prefixhost2str(struct fbuf *fbuf, union prefixconstptr pu)
{
const struct prefix *p = pu.p;
@@ -1166,7 +1175,7 @@ const char *prefix_sg2str(const struct prefix_sg *sg, char *sg_str)
char src_str[INET_ADDRSTRLEN];
char grp_str[INET_ADDRSTRLEN];
- prefix_mcast_inet4_dump("<src?>", sg->src, src_str, sizeof(src_str));
+ prefix_mcast_ip_dump("<src?>", &sg->src, src_str, sizeof(src_str));
prefix_mcast_inet4_dump("<grp?>", sg->grp, grp_str, sizeof(grp_str));
snprintf(sg_str, PREFIX_SG_STR_LEN, "(%s,%s)", src_str, grp_str);
@@ -1637,10 +1646,10 @@ static ssize_t printfrr_psg(struct fbuf *buf, struct printfrr_eargs *ea,
if (!sg)
return bputs(buf, "(null)");
- if (sg->src.s_addr == INADDR_ANY)
+ if (ipaddr_is_zero(&sg->src))
ret += bputs(buf, "(*,");
else
- ret += bprintfrr(buf, "(%pI4,", &sg->src);
+ ret += bprintfrr(buf, "(%pIA,", &sg->src);
if (sg->grp.s_addr == INADDR_ANY)
ret += bputs(buf, "*)");
diff --git a/lib/prefix.h b/lib/prefix.h
index 14f2695..2d679d0 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -52,10 +52,10 @@ typedef enum {
/* Maximum number of VTEPs per-ES -
* XXX - temporary limit for allocating strings etc.
*/
-#define ES_VTEP_MAX_CNT 10
-#define ES_VTEP_LIST_STR_SZ (ES_VTEP_MAX_CNT * 16)
+#define ES_VTEP_MAX_CNT 10
+#define ES_VTEP_LIST_STR_SZ (ES_VTEP_MAX_CNT * IPADDR_STRING_SIZE)
-#define ETHER_ADDR_STRLEN (3*ETH_ALEN)
+#define ETHER_ADDR_STRLEN (3 * ETH_ALEN)
/*
* there isn't a portable ethernet address type. We define our
* own to simplify internal handling
@@ -282,7 +282,7 @@ struct prefix_fs {
struct prefix_sg {
uint8_t family;
uint16_t prefixlen;
- struct in_addr src __attribute__((aligned(8)));
+ struct ipaddr src __attribute__((aligned(8)));
struct in_addr grp;
};
@@ -415,6 +415,8 @@ extern int str2prefix(const char *string, struct prefix *prefix);
#define PREFIX2STR_BUFFER PREFIX_STRLEN
+extern void prefix_mcast_ip_dump(const char *onfail, const struct ipaddr *addr,
+ char *buf, int buf_size);
extern void prefix_mcast_inet4_dump(const char *onfail, struct in_addr addr,
char *buf, int buf_size);
extern const char *prefix_sg2str(const struct prefix_sg *sg, char *str);
diff --git a/lib/printf/README b/lib/printf/README
index 46d51ce..3c3ef74 100644
--- a/lib/printf/README
+++ b/lib/printf/README
@@ -1,6 +1,7 @@
This is the printf implementation from FreeBSD. The history of this code is:
- imported on 2019-05-12, from SVN revision 347514
- resynced on 2023-09-03, to pick up `%b` implementation
+- resynced on 2024-03-10, to pick up `%w[f](8|16|32|64)d` implementation
Please don't reindent or otherwise mangle the files to make importing fixes
easy (not that there are significant changes likely to happen...)
diff --git a/lib/printf/printflocal.h b/lib/printf/printflocal.h
index 4b03091..93318c8 100644
--- a/lib/printf/printflocal.h
+++ b/lib/printf/printflocal.h
@@ -52,6 +52,7 @@
#define PTRDIFFT 0x800 /* ptrdiff_t */
#define INTMAXT 0x1000 /* intmax_t */
#define CHARINT 0x2000 /* print char using int format */
+#define FASTINT 0x4000 /* int_fastN_t */
/*
* Macros for converting digits to letters and vice versa
diff --git a/lib/printf/vfprintf.c b/lib/printf/vfprintf.c
index 2083642..3f6700c 100644
--- a/lib/printf/vfprintf.c
+++ b/lib/printf/vfprintf.c
@@ -416,6 +416,49 @@ reswitch: switch (ch) {
case 't':
flags |= PTRDIFFT;
goto rflag;
+ case 'w':
+ /*
+ * Fixed-width integer types. On all platforms we
+ * support, int8_t is equivalent to char, int16_t
+ * is equivalent to short, int32_t is equivalent
+ * to int, int64_t is equivalent to long long int.
+ * Furthermore, int_fast8_t, int_fast16_t and
+ * int_fast32_t are equivalent to int, and
+ * int_fast64_t is equivalent to long long int.
+ */
+ flags &= ~(CHARINT|SHORTINT|LONGINT|LLONGINT|INTMAXT);
+ if (fmt[0] == 'f') {
+ flags |= FASTINT;
+ fmt++;
+ } else {
+ flags &= ~FASTINT;
+ }
+ if (fmt[0] == '8') {
+ if (!(flags & FASTINT))
+ flags |= CHARINT;
+ else
+ (void) 0; /* no flag set = 32 */
+ fmt += 1;
+ } else if (fmt[0] == '1' && fmt[1] == '6') {
+ if (!(flags & FASTINT))
+ flags |= SHORTINT;
+ else
+ (void) 0; /* no flag set = 32 */
+ fmt += 2;
+ } else if (fmt[0] == '3' && fmt[1] == '2') {
+ /* no flag set = 32 */
+ fmt += 2;
+ } else if (fmt[0] == '6' && fmt[1] == '4') {
+ flags |= LLONGINT;
+ fmt += 2;
+ } else {
+ if (flags & FASTINT) {
+ flags &= ~FASTINT;
+ fmt--;
+ }
+ goto invalid;
+ }
+ goto rflag;
case 'z':
flags |= SIZET;
goto rflag;
@@ -684,6 +727,7 @@ number: if ((dprec = prec) >= 0)
default: /* "%?" prints ?, unless ? is NUL */
if (ch == '\0')
goto done;
+invalid:
/* pretend it was %c with argument ch */
buf[0] = ch;
cp = buf;
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index 88b341c..8e2e497 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -490,29 +490,33 @@ DEFPY_YANG(
DEFPY_YANG(
match_tag, match_tag_cmd,
- "match tag (1-4294967295)$tag",
+ "match tag <untagged$untagged|(1-4294967295)$tagged>",
MATCH_STR
"Match tag of route\n"
+ "Untagged route\n"
"Tag value\n")
{
const char *xpath =
"./match-condition[condition='frr-route-map:match-tag']";
char xpath_value[XPATH_MAXLEN];
+ char value[64];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value),
"%s/rmap-match-condition/tag", xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, tag_str);
+ snprintf(value, sizeof(value), "%lu", tagged ? tagged : 0);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_match_tag, no_match_tag_cmd,
- "no match tag [(1-4294967295)]",
+ "no match tag [<untagged|(1-4294967295)>]",
NO_STR
MATCH_STR
"Match tag of route\n"
+ "Untagged route\n"
"Tag value\n")
{
const char *xpath =
@@ -581,9 +585,15 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(dnode,
"./rmap-match-condition/metric"));
} else if (IS_MATCH_TAG(condition)) {
- vty_out(vty, " match tag %s\n",
- yang_dnode_get_string(dnode,
- "./rmap-match-condition/tag"));
+ uint32_t tag =
+ strtoul(yang_dnode_get_string(dnode,
+ "./rmap-match-condition/tag"),
+ NULL, 10);
+
+ if (!tag)
+ vty_out(vty, " match tag untagged\n");
+ else
+ vty_out(vty, " match tag %u\n", tag);
} else if (IS_MATCH_IPv4_PREFIX_LEN(condition)) {
vty_out(vty, " match ip address prefix-len %s\n",
yang_dnode_get_string(
@@ -973,28 +983,32 @@ DEFPY_YANG(no_set_max_metric, no_set_max_metric_cmd,
DEFPY_YANG(
set_tag, set_tag_cmd,
- "set tag (1-4294967295)$tag",
+ "set tag <untagged$untagged|(1-4294967295)$tagged>",
SET_STR
"Tag value for routing protocol\n"
+ "Untagged route\n"
"Tag value\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-tag']";
char xpath_value[XPATH_MAXLEN];
+ char value[64];
nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
snprintf(xpath_value, sizeof(xpath_value), "%s/rmap-set-action/tag",
xpath);
- nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, tag_str);
+ snprintf(value, sizeof(value), "%lu", tagged ? tagged : 0);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, value);
return nb_cli_apply_changes(vty, NULL);
}
DEFPY_YANG(
no_set_tag, no_set_tag_cmd,
- "no set tag [(1-4294967295)]",
+ "no set tag [<untagged|(1-4294967295)>]",
NO_STR
SET_STR
"Tag value for routing protocol\n"
+ "Untagged route\n"
"Tag value\n")
{
const char *xpath = "./set-action[action='frr-route-map:set-tag']";
@@ -1101,8 +1115,15 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(dnode,
"./rmap-set-action/max-metric"));
} else if (IS_SET_TAG(action)) {
- vty_out(vty, " set tag %s\n",
- yang_dnode_get_string(dnode, "rmap-set-action/tag"));
+ uint32_t tag =
+ strtoul(yang_dnode_get_string(dnode,
+ "rmap-set-action/tag"),
+ NULL, 10);
+
+ if (!tag)
+ vty_out(vty, " set tag untagged\n");
+ else
+ vty_out(vty, " set tag %u\n", tag);
} else if (IS_SET_SR_TE_COLOR(action)) {
vty_out(vty, " set sr-te color %s\n",
yang_dnode_get_string(dnode,
@@ -1252,14 +1273,14 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
} else if (IS_SET_EXTCOMMUNITY_LB(action)) {
enum ecommunity_lb_type lb_type;
char str[VTY_BUFSIZ];
- uint16_t bandwidth;
+ uint32_t bandwidth;
lb_type = yang_dnode_get_enum(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/lb-type");
switch (lb_type) {
case EXPLICIT_BANDWIDTH:
- bandwidth = yang_dnode_get_uint16(
+ bandwidth = yang_dnode_get_uint32(
dnode,
"./rmap-set-action/frr-bgp-route-map:extcommunity-lb/bandwidth");
snprintf(str, sizeof(str), "%d", bandwidth);
diff --git a/lib/routing_nb.h b/lib/routing_nb.h
index e805e1c..26b4cf0 100644
--- a/lib/routing_nb.h
+++ b/lib/routing_nb.h
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#ifndef _FRR_ROUTING_NB_H_
#define _FRR_ROUTING_NB_H_
diff --git a/lib/sigevent.c b/lib/sigevent.c
index 06f80db..3e69f28 100644
--- a/lib/sigevent.c
+++ b/lib/sigevent.c
@@ -240,7 +240,17 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
/* dump memory stats on core */
log_memstats(stderr, "core_handler");
- zlog_tls_buffer_fini();
+ /*
+ * This is a buffer flush because FRR is going down
+ * hard. This is especially important if the crash
+ * was caused by a memory operation and if we call
+ * zlog_tls_buffer_fini() then it has memory
+ * operations as well. This will cause the
+ * core dump to not happen. BAD MOJO
+ * So this is intentional, let's try to flush
+ * what we can and let the crash happen.
+ */
+ zlog_tls_buffer_flush();
/* give the kernel a chance to generate a coredump */
sigaddset(&sigset, signo);
diff --git a/lib/smux.h b/lib/smux.h
index cec4d2a..8ec847a 100644
--- a/lib/smux.h
+++ b/lib/smux.h
@@ -99,6 +99,7 @@ struct index_oid {
*/
extern bool smux_enabled(void);
+extern void libagentx_init(void);
extern void smux_init(struct event_loop *tm);
extern void smux_agentx_enable(void);
extern void smux_register_mib(const char *, struct variable *, size_t, int,
diff --git a/lib/srv6.c b/lib/srv6.c
index dceb6ab..a82103e 100644
--- a/lib/srv6.c
+++ b/lib/srv6.c
@@ -94,9 +94,11 @@ const char *seg6local_context2str(char *str, size_t size,
snprintf(str, size, "table %u", ctx->table);
return str;
- case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
+ snprintfrr(str, size, "nh6 %pI6", &ctx->nh6);
+ return str;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
case ZEBRA_SEG6_LOCAL_ACTION_END_S:
case ZEBRA_SEG6_LOCAL_ACTION_END_AS:
diff --git a/lib/stream.c b/lib/stream.c
index c6de3ae..bb90f3b 100644
--- a/lib/stream.c
+++ b/lib/stream.c
@@ -921,7 +921,7 @@ int stream_put_in_addr(struct stream *s, const struct in_addr *addr)
return sizeof(uint32_t);
}
-bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip)
+bool stream_put_ipaddr(struct stream *s, const struct ipaddr *ip)
{
stream_putw(s, ip->ipa_type);
@@ -1241,9 +1241,7 @@ void stream_fifo_init(struct stream_fifo *fifo)
/* Add new stream to fifo. */
void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
{
-#if defined DEV_BUILD
size_t max, curmax;
-#endif
if (fifo->tail)
fifo->tail->next = s;
@@ -1252,15 +1250,11 @@ void stream_fifo_push(struct stream_fifo *fifo, struct stream *s)
fifo->tail = s;
fifo->tail->next = NULL;
-#if !defined DEV_BUILD
- atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
-#else
max = atomic_fetch_add_explicit(&fifo->count, 1, memory_order_release);
curmax = atomic_load_explicit(&fifo->max_count, memory_order_relaxed);
if (max > curmax)
atomic_store_explicit(&fifo->max_count, max,
memory_order_relaxed);
-#endif
}
void stream_fifo_push_safe(struct stream_fifo *fifo, struct stream *s)
diff --git a/lib/stream.h b/lib/stream.h
index 85eebb4..e48cedc 100644
--- a/lib/stream.h
+++ b/lib/stream.h
@@ -105,9 +105,7 @@ struct stream_fifo {
/* number of streams in this fifo */
atomic_size_t count;
-#if defined DEV_BUILD
atomic_size_t max_count;
-#endif
struct stream *head;
struct stream *tail;
@@ -177,7 +175,7 @@ extern int stream_putq(struct stream *, uint64_t);
extern int stream_putq_at(struct stream *, size_t, uint64_t);
extern int stream_put_ipv4(struct stream *, uint32_t);
extern int stream_put_in_addr(struct stream *s, const struct in_addr *addr);
-extern bool stream_put_ipaddr(struct stream *s, struct ipaddr *ip);
+extern bool stream_put_ipaddr(struct stream *s, const struct ipaddr *ip);
extern int stream_put_in_addr_at(struct stream *s, size_t putp,
const struct in_addr *addr);
extern int stream_put_in6_addr_at(struct stream *s, size_t putp,
diff --git a/lib/subdir.am b/lib/subdir.am
index 6893049..3264f31 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -53,9 +53,12 @@ lib_libfrr_la_SOURCES = \
lib/jhash.c \
lib/json.c \
lib/keychain.c \
+ lib/keychain_cli.c \
+ lib/keychain_nb.c \
lib/ldp_sync.c \
lib/lib_errors.c \
lib/lib_vty.c \
+ lib/libagentx.c \
lib/libfrr.c \
lib/libfrr_trace.c \
lib/linklist.c \
@@ -129,6 +132,7 @@ lib_libfrr_la_SOURCES = \
lib/zlog_5424.c \
lib/zlog_5424_cli.c \
lib/zlog_live.c \
+ lib/zlog_recirculate.c \
lib/zlog_targets.c \
lib/printf/printf-pos.c \
lib/printf/vfprintf.c \
@@ -148,7 +152,10 @@ nodist_lib_libfrr_la_SOURCES = \
yang/frr-vrf.yang.c \
yang/frr-routing.yang.c \
yang/frr-nexthop.yang.c \
+ yang/ietf/frr-deviations-ietf-key-chain.yang.c \
yang/ietf/ietf-routing-types.yang.c \
+ yang/ietf/ietf-netconf-acm.yang.c \
+ yang/ietf/ietf-key-chain.yang.c \
yang/ietf/ietf-interfaces.yang.c \
yang/ietf/ietf-bgp-types.yang.c \
yang/frr-module-translator.yang.c \
@@ -181,6 +188,7 @@ clippy_scan += \
lib/if.c \
lib/filter_cli.c \
lib/if_rmap.c \
+ lib/keychain_cli.c \
lib/log_vty.c \
lib/mgmt_be_client.c \
lib/mgmt_fe_client.c \
@@ -245,6 +253,7 @@ pkginclude_HEADERS += \
lib/ldp_sync.h \
lib/lib_errors.h \
lib/lib_vty.h \
+ lib/libagentx.h \
lib/libfrr.h \
lib/libfrr_trace.h \
lib/libospf.h \
@@ -324,6 +333,7 @@ pkginclude_HEADERS += \
lib/zlog.h \
lib/zlog_5424.h \
lib/zlog_live.h \
+ lib/zlog_recirculate.h \
lib/zlog_targets.h \
lib/pbr.h \
lib/tc.h \
@@ -403,18 +413,6 @@ lib_libfrrzmq_la_SOURCES = \
#end
#
-# Tail-f's ConfD support
-#
-if CONFD
-module_LTLIBRARIES += lib/confd.la
-endif
-
-lib_confd_la_CFLAGS = $(AM_CFLAGS) $(CONFD_CFLAGS)
-lib_confd_la_LDFLAGS = $(MODULE_LDFLAGS)
-lib_confd_la_LIBADD = lib/libfrr.la $(CONFD_LIBS)
-lib_confd_la_SOURCES = lib/northbound_confd.c
-
-#
# Sysrepo support
#
if SYSREPO
diff --git a/lib/typerb.h b/lib/typerb.h
index b020a66..93370e1 100644
--- a/lib/typerb.h
+++ b/lib/typerb.h
@@ -9,8 +9,10 @@
#ifndef _FRR_TYPERB_H
#define _FRR_TYPERB_H
+#ifndef _TYPESAFE_EXPAND_MACROS
#include <string.h>
#include "typesafe.h"
+#endif /* _TYPESAFE_EXPAND_MACROS */
#ifdef __cplusplus
extern "C" {
diff --git a/lib/typesafe.h b/lib/typesafe.h
index 93258c5..fc02804 100644
--- a/lib/typesafe.h
+++ b/lib/typesafe.h
@@ -6,10 +6,12 @@
#ifndef _FRR_TYPESAFE_H
#define _FRR_TYPESAFE_H
+#ifndef _TYPESAFE_EXPAND_MACROS
#include <stddef.h>
#include <stdint.h>
#include <stdbool.h>
#include "compiler.h"
+#endif /* _TYPESAFE_EXPAND_MACROS */
#ifdef __cplusplus
extern "C" {
diff --git a/lib/vty.c b/lib/vty.c
index 1c9cff4..d0bbf0e 100644
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -39,6 +39,7 @@
#include "libfrr.h"
#include "frrstr.h"
#include "lib_errors.h"
+#include <libyang/version.h>
#include "northbound_cli.h"
#include "printfrr.h"
#include "json.h"
@@ -389,6 +390,21 @@ int vty_json_no_pretty(struct vty *vty, struct json_object *json)
return vty_json_helper(vty, json, JSON_C_TO_STRING_NOSLASHESCAPE);
}
+
+void vty_json_key(struct vty *vty, const char *key, bool *first_key)
+{
+ vty_out(vty, "%s\"%s\":", *first_key ? "{" : ",", key);
+ *first_key = false;
+}
+
+void vty_json_close(struct vty *vty, bool first_key)
+{
+ if (first_key)
+ /* JSON was not opened */
+ vty_out(vty, "{");
+ vty_out(vty, "}\n");
+}
+
void vty_json_empty(struct vty *vty, struct json_object *json)
{
json_object *jsonobj = json;
@@ -3486,7 +3502,7 @@ static void vty_mgmt_server_connected(struct mgmt_fe_client *client,
/* Start or stop listening for vty connections */
if (connected)
- frr_vty_serv_start();
+ frr_vty_serv_start(true);
else
frr_vty_serv_stop();
}
@@ -3570,12 +3586,14 @@ static void vty_mgmt_set_config_result_notified(
zlog_err("SET_CONFIG request for client 0x%" PRIx64
" failed, Error: '%s'",
client_id, errmsg_if_any ? errmsg_if_any : "Unknown");
- vty_out(vty, "ERROR: SET_CONFIG request failed, Error: %s\n",
- errmsg_if_any ? errmsg_if_any : "Unknown");
+ vty_out(vty, "%% Configuration failed.\n\n");
+ if (errmsg_if_any)
+ vty_out(vty, "%s\n", errmsg_if_any);
} else {
debug_fe_client("SET_CONFIG request for client 0x%" PRIx64
- " req-id %" PRIu64 " was successfull",
- client_id, req_id);
+ " req-id %" PRIu64 " was successfull%s%s",
+ client_id, req_id, errmsg_if_any ? ": " : "",
+ errmsg_if_any ?: "");
}
if (implicit_commit) {
@@ -3602,12 +3620,14 @@ static void vty_mgmt_commit_config_result_notified(
zlog_err("COMMIT_CONFIG request for client 0x%" PRIx64
" failed, Error: '%s'",
client_id, errmsg_if_any ? errmsg_if_any : "Unknown");
- vty_out(vty, "ERROR: COMMIT_CONFIG request failed, Error: %s\n",
- errmsg_if_any ? errmsg_if_any : "Unknown");
+ vty_out(vty, "%% Configuration failed.\n\n");
+ if (errmsg_if_any)
+ vty_out(vty, "%s\n", errmsg_if_any);
} else {
debug_fe_client("COMMIT_CONFIG request for client 0x%" PRIx64
- " req-id %" PRIu64 " was successfull",
- client_id, req_id);
+ " req-id %" PRIu64 " was successfull%s%s",
+ client_id, req_id, errmsg_if_any ? ": " : "",
+ errmsg_if_any ?: "");
if (errmsg_if_any)
vty_out(vty, "MGMTD: %s\n", errmsg_if_any);
}
@@ -3638,8 +3658,9 @@ static int vty_mgmt_get_data_result_notified(
}
debug_fe_client("GET_DATA request succeeded, client 0x%" PRIx64
- " req-id %" PRIu64,
- client_id, req_id);
+ " req-id %" PRIu64 "%s%s",
+ client_id, req_id, errmsg_if_any ? ": " : "",
+ errmsg_if_any ?: "");
if (req_id != mgmt_last_req_id) {
mgmt_last_req_id = req_id;
@@ -3668,15 +3689,24 @@ static ssize_t vty_mgmt_libyang_print(void *user_data, const void *buf,
}
static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format,
- struct ly_err_item *ei)
+ const struct ly_err_item *ei)
{
+#if (LY_VERSION_MAJOR < 3)
+#define data_path path
+#else
+#define data_path data_path
+#endif
bool have_apptag = ei->apptag && ei->apptag[0] != 0;
- bool have_path = ei->path && ei->path[0] != 0;
+ bool have_path = ei->data_path && ei->data_path[0] != 0;
bool have_msg = ei->msg && ei->msg[0] != 0;
const char *severity = NULL;
const char *evalid = NULL;
const char *ecode = NULL;
+#if (LY_VERSION_MAJOR < 3)
LY_ERR err = ei->no;
+#else
+ LY_ERR err = ei->err;
+#endif
if (ei->level == LY_LLERR)
severity = "error";
@@ -3701,7 +3731,8 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format,
vty_out(vty, "<error-validation>%s</error-validation>\n",
evalid);
if (have_path)
- vty_out(vty, "<error-path>%s</error-path>\n", ei->path);
+ vty_out(vty, "<error-path>%s</error-path>\n",
+ ei->data_path);
if (have_apptag)
vty_out(vty, "<error-app-tag>%s</error-app-tag>\n",
ei->apptag);
@@ -3720,7 +3751,7 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format,
if (evalid)
vty_out(vty, ", \"error-validation\": \"%s\"", evalid);
if (have_path)
- vty_out(vty, ", \"error-path\": \"%s\"", ei->path);
+ vty_out(vty, ", \"error-path\": \"%s\"", ei->data_path);
if (have_apptag)
vty_out(vty, ", \"error-app-tag\": \"%s\"", ei->apptag);
if (have_msg)
@@ -3737,18 +3768,19 @@ static void vty_out_yang_error(struct vty *vty, LYD_FORMAT format,
if (evalid)
vty_out(vty, " invalid: %s", evalid);
if (have_path)
- vty_out(vty, " path: %s", ei->path);
+ vty_out(vty, " path: %s", ei->data_path);
if (have_apptag)
vty_out(vty, " app-tag: %s", ei->apptag);
if (have_msg)
vty_out(vty, " msg: %s", ei->msg);
break;
}
+#undef data_path
}
static uint vty_out_yang_errors(struct vty *vty, LYD_FORMAT format)
{
- struct ly_err_item *ei = ly_err_first(ly_native_ctx);
+ const struct ly_err_item *ei = ly_err_first(ly_native_ctx);
uint count;
if (!ei)
@@ -3824,6 +3856,43 @@ static int vty_mgmt_get_tree_result_notified(
return 0;
}
+static int vty_mgmt_edit_result_notified(struct mgmt_fe_client *client,
+ uintptr_t user_data,
+ uint64_t client_id, uint64_t session_id,
+ uintptr_t session_ctx, uint64_t req_id,
+ const char *xpath)
+{
+ struct vty *vty = (struct vty *)session_ctx;
+
+ debug_fe_client("EDIT request for client 0x%" PRIx64 " req-id %" PRIu64
+ " was successful, xpath: %s",
+ client_id, req_id, xpath);
+
+ vty_mgmt_resume_response(vty, CMD_SUCCESS);
+
+ return 0;
+}
+
+static int vty_mgmt_rpc_result_notified(struct mgmt_fe_client *client,
+ uintptr_t user_data, uint64_t client_id,
+ uint64_t session_id,
+ uintptr_t session_ctx, uint64_t req_id,
+ const char *result)
+{
+ struct vty *vty = (struct vty *)session_ctx;
+
+ debug_fe_client("RPC request for client 0x%" PRIx64 " req-id %" PRIu64
+ " was successful",
+ client_id, req_id);
+
+ if (result)
+ vty_out(vty, "%s\n", result);
+
+ vty_mgmt_resume_response(vty, CMD_SUCCESS);
+
+ return 0;
+}
+
static int vty_mgmt_error_notified(struct mgmt_fe_client *client,
uintptr_t user_data, uint64_t client_id,
uint64_t session_id, uintptr_t session_ctx,
@@ -3865,6 +3934,8 @@ static struct mgmt_fe_client_cbs mgmt_cbs = {
.commit_config_notify = vty_mgmt_commit_config_result_notified,
.get_data_notify = vty_mgmt_get_data_result_notified,
.get_tree_notify = vty_mgmt_get_tree_result_notified,
+ .edit_notify = vty_mgmt_edit_result_notified,
+ .rpc_notify = vty_mgmt_rpc_result_notified,
.error_notify = vty_mgmt_error_notified,
};
@@ -4120,6 +4191,47 @@ int vty_mgmt_send_get_data_req(struct vty *vty, uint8_t datastore,
return 0;
}
+int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
+ LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath,
+ const char *data)
+{
+ vty->mgmt_req_id++;
+
+ if (mgmt_fe_send_edit_req(mgmt_fe_client, vty->mgmt_session_id,
+ vty->mgmt_req_id, datastore, request_type,
+ flags, operation, xpath, data)) {
+ zlog_err("Failed to send EDIT to MGMTD session-id: %" PRIu64
+ " req-id %" PRIu64 ".",
+ vty->mgmt_session_id, vty->mgmt_req_id);
+ vty_out(vty, "Failed to send EDIT to MGMTD!\n");
+ return -1;
+ }
+
+ vty->mgmt_req_pending_cmd = "MESSAGE_EDIT_REQ";
+
+ return 0;
+}
+
+int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type,
+ const char *xpath, const char *data)
+{
+ vty->mgmt_req_id++;
+
+ if (mgmt_fe_send_rpc_req(mgmt_fe_client, vty->mgmt_session_id,
+ vty->mgmt_req_id, request_type, xpath, data)) {
+ zlog_err("Failed to send RPC to MGMTD session-id: %" PRIu64
+ " req-id %" PRIu64 ".",
+ vty->mgmt_session_id, vty->mgmt_req_id);
+ vty_out(vty, "Failed to send RPC to MGMTD!\n");
+ return -1;
+ }
+
+ vty->mgmt_req_pending_cmd = "MESSAGE_RPC_REQ";
+
+ return 0;
+}
+
/* Install vty's own commands like `who' command. */
void vty_init(struct event_loop *master_thread, bool do_command_logging)
{
diff --git a/lib/vty.h b/lib/vty.h
index a59ac7a..c336a81 100644
--- a/lib/vty.h
+++ b/lib/vty.h
@@ -122,6 +122,10 @@ struct vty {
size_t num_cfg_changes;
struct nb_cfg_change cfg_changes[VTY_MAXCFGCHANGES];
+ /* Input parameters */
+ size_t num_rpc_params;
+ struct nb_cfg_change rpc_params[VTY_MAXCFGCHANGES];
+
/* XPath of the current node */
int xpath_index;
char xpath[VTY_MAXDEPTH][XPATH_MAXLEN];
@@ -374,6 +378,8 @@ extern bool vty_set_include(struct vty *vty, const char *regexp);
*/
extern int vty_json(struct vty *vty, struct json_object *json);
extern int vty_json_no_pretty(struct vty *vty, struct json_object *json);
+void vty_json_key(struct vty *vty, const char *key, bool *first_key);
+void vty_json_close(struct vty *vty, bool first_key);
extern void vty_json_empty(struct vty *vty, struct json_object *json);
/* post fd to be passed to the vtysh client
* fd is owned by the VTY code after this and will be closed when done
@@ -419,6 +425,12 @@ extern int vty_mgmt_send_get_req(struct vty *vty, bool is_config,
extern int vty_mgmt_send_get_data_req(struct vty *vty, uint8_t datastore,
LYD_FORMAT result_type, uint8_t flags,
uint8_t defaults, const char *xpath);
+extern int vty_mgmt_send_edit_req(struct vty *vty, uint8_t datastore,
+ LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath,
+ const char *data);
+extern int vty_mgmt_send_rpc_req(struct vty *vty, LYD_FORMAT request_type,
+ const char *xpath, const char *data);
extern int vty_mgmt_send_lockds_req(struct vty *vty, Mgmtd__DatastoreId ds_id,
bool lock, bool scok);
extern void vty_mgmt_resume_response(struct vty *vty, int ret);
diff --git a/lib/yang.c b/lib/yang.c
index 03044fc..44459df 100644
--- a/lib/yang.c
+++ b/lib/yang.c
@@ -11,13 +11,26 @@
#include "lib_errors.h"
#include "yang.h"
#include "yang_translator.h"
+#include <libyang/version.h>
#include "northbound.h"
+#include "frrstr.h"
#include "lib/config_paths.h"
DEFINE_MTYPE_STATIC(LIB, YANG_MODULE, "YANG module");
DEFINE_MTYPE_STATIC(LIB, YANG_DATA, "YANG data structure");
+/* Safe to remove after libyang 2.2.8 */
+#if (LY_VERSION_MAJOR < 3)
+#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \
+ set) \
+ lyd_find_xpath3(ctx_node, tree, xpath, vars, set)
+#else
+#define yang_lyd_find_xpath3(ctx_node, tree, xpath, format, prefix_data, vars, \
+ set) \
+ lyd_find_xpath3(ctx_node, tree, xpath, LY_VALUE_JSON, NULL, vars, set)
+#endif
+
/* libyang container. */
struct ly_ctx *ly_native_ctx;
@@ -199,6 +212,16 @@ next:
if (ret == YANG_ITER_STOP)
return ret;
}
+ LY_LIST_FOR ((const struct lysc_node *)lysc_node_notifs(snode), child) {
+ ret = yang_snodes_iterate_subtree(child, module, cb, flags, arg);
+ if (ret == YANG_ITER_STOP)
+ return ret;
+ }
+ LY_LIST_FOR ((const struct lysc_node *)lysc_node_actions(snode), child) {
+ ret = yang_snodes_iterate_subtree(child, module, cb, flags, arg);
+ if (ret == YANG_ITER_STOP)
+ return ret;
+ }
return ret;
}
@@ -642,6 +665,16 @@ void yang_dnode_free(struct lyd_node *dnode)
lyd_free_all(dnode);
}
+void yang_dnode_rpc_output_add(struct lyd_node *output, const char *xpath,
+ const char *value)
+{
+ LY_ERR err;
+
+ err = lyd_new_path(output, ly_native_ctx, xpath, value,
+ LYD_NEW_PATH_OUTPUT | LYD_NEW_PATH_UPDATE, NULL);
+ assert(err == LY_SUCCESS);
+}
+
struct yang_data *yang_data_new(const char *xpath, const char *value)
{
struct yang_data *data;
@@ -691,7 +724,12 @@ struct yang_data *yang_data_list_find(const struct list *list,
}
/* Make libyang log its errors using FRR logging infrastructure. */
-static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path)
+static void ly_zlog_cb(LY_LOG_LEVEL level, const char *msg, const char *data_path
+#if !(LY_VERSION_MAJOR < 3)
+ ,
+ const char *schema_path, uint64_t line
+#endif
+)
{
int priority = LOG_ERR;
@@ -708,8 +746,14 @@ static void ly_log_cb(LY_LOG_LEVEL level, const char *msg, const char *path)
break;
}
- if (path)
- zlog(priority, "libyang: %s (%s)", msg, path);
+ if (data_path)
+ zlog(priority, "libyang: %s (%s)", msg, data_path);
+#if !(LY_VERSION_MAJOR < 3)
+ else if (schema_path)
+ zlog(priority, "libyang %s (%s)\n", msg, schema_path);
+ else if (line)
+ zlog(priority, "libyang %s (line %" PRIu64 ")\n", msg, line);
+#endif
else
zlog(priority, "libyang: %s", msg);
}
@@ -736,7 +780,8 @@ LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format,
return err;
}
- err = lyd_find_xpath3(NULL, tree, xpath, NULL, &set);
+ err = yang_lyd_find_xpath3(NULL, tree, xpath, LY_VALUE_JSON, NULL, NULL,
+ &set);
if (err) {
zlog_err("Failed to parse notification: %s", ly_last_errmsg());
lyd_free_all(tree);
@@ -753,6 +798,63 @@ LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format,
return LY_SUCCESS;
}
+LY_ERR yang_parse_rpc(const char *xpath, LYD_FORMAT format, const char *data,
+ bool reply, struct lyd_node **rpc)
+{
+ const struct lysc_node *snode;
+ struct lyd_node *parent = NULL;
+ struct ly_in *in = NULL;
+ LY_ERR err;
+
+ snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
+ if (!snode) {
+ zlog_err("Failed to find RPC/action schema node: %s", xpath);
+ return LY_ENOTFOUND;
+ }
+
+ /* If it's an action, create its parent */
+ if (snode->nodetype == LYS_ACTION) {
+ char *parent_xpath = XSTRDUP(MTYPE_TMP, xpath);
+
+ if (yang_xpath_pop_node(parent_xpath) != NB_OK) {
+ XFREE(MTYPE_TMP, parent_xpath);
+ zlog_err("Invalid action xpath: %s", xpath);
+ return LY_EINVAL;
+ }
+
+ err = lyd_new_path2(NULL, ly_native_ctx, parent_xpath, NULL, 0,
+ 0, 0, NULL, &parent);
+ XFREE(MTYPE_TMP, parent_xpath);
+ if (err) {
+ zlog_err("Failed to create parent node for action: %s",
+ ly_last_errmsg());
+ return err;
+ }
+ } else if (snode->nodetype != LYS_RPC) {
+ zlog_err("Schema node is not an RPC/action: %s", xpath);
+ return LY_EINVAL;
+ }
+
+ err = ly_in_new_memory(data, &in);
+ if (err) {
+ lyd_free_all(parent);
+ zlog_err("Failed to initialize ly_in: %s", ly_last_errmsg());
+ return err;
+ }
+
+ err = lyd_parse_op(ly_native_ctx, parent, in, format,
+ reply ? LYD_TYPE_REPLY_YANG : LYD_TYPE_RPC_YANG,
+ NULL, rpc);
+ ly_in_free(in, 0);
+ if (err) {
+ lyd_free_all(parent);
+ zlog_err("Failed to parse RPC/action: %s", ly_last_errmsg());
+ return err;
+ }
+
+ return LY_SUCCESS;
+}
+
static ssize_t yang_print_darr(void *arg, const void *buf, size_t count)
{
uint8_t *dst = darr_append_n(*(uint8_t **)arg, count);
@@ -795,7 +897,7 @@ char *yang_convert_lyd_format(const char *data, size_t data_len,
assert(out_format != LYD_LYB);
- if (in_format != LYD_LYB && !MGMT_MSG_VALIDATE_NUL_TERM(data, data_len)) {
+ if (in_format != LYD_LYB && (!data_len || data[data_len - 1] != 0)) {
zlog_err("Corrupt input data, no NUL terminating byte");
return NULL;
}
@@ -829,23 +931,29 @@ char *yang_convert_lyd_format(const char *data, size_t data_len,
const char *yang_print_errors(struct ly_ctx *ly_ctx, char *buf, size_t buf_len)
{
- struct ly_err_item *ei;
+ const struct ly_err_item *ei;
ei = ly_err_first(ly_ctx);
if (!ei)
return "";
strlcpy(buf, "YANG error(s):\n", buf_len);
+#if (LY_VERSION_MAJOR < 3)
+#define data_path path
+#else
+#define data_path data_path
+#endif
for (; ei; ei = ei->next) {
- if (ei->path) {
+ if (ei->data_path) {
strlcat(buf, " Path: ", buf_len);
- strlcat(buf, ei->path, buf_len);
+ strlcat(buf, ei->data_path, buf_len);
strlcat(buf, "\n", buf_len);
}
strlcat(buf, " Error: ", buf_len);
strlcat(buf, ei->msg, buf_len);
strlcat(buf, "\n", buf_len);
}
+#undef data_path
ly_err_clean(ly_ctx, NULL);
@@ -897,7 +1005,12 @@ struct ly_ctx *yang_ctx_new_setup(bool embedded_modules, bool explicit_compile)
void yang_init(bool embedded_modules, bool defer_compile)
{
/* Initialize libyang global parameters that affect all containers. */
- ly_set_log_clb(ly_log_cb, 1);
+ ly_set_log_clb(ly_zlog_cb
+#if (LY_VERSION_MAJOR < 3)
+ ,
+ 1
+#endif
+ );
ly_log_options(LY_LOLOG | LY_LOSTORE);
/* Initialize libyang container for native models. */
@@ -1112,6 +1225,32 @@ int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys)
return NB_OK;
}
+int yang_xpath_pop_node(char *xpath)
+{
+ int len = strlen(xpath);
+ bool abs = xpath[0] == '/';
+ char *slash;
+
+ /* "//" or "/" => NULL */
+ if (abs && (len == 1 || (len == 2 && xpath[1] == '/')))
+ return NB_ERR_NOT_FOUND;
+
+ slash = (char *)frrstr_back_to_char(xpath, '/');
+ /* "/foo/bar/" or "/foo/bar//" => "/foo " */
+ if (slash && slash == &xpath[len - 1]) {
+ xpath[--len] = 0;
+ slash = (char *)frrstr_back_to_char(xpath, '/');
+ if (slash && slash == &xpath[len - 1]) {
+ xpath[--len] = 0;
+ slash = (char *)frrstr_back_to_char(xpath, '/');
+ }
+ }
+ if (!slash)
+ return NB_ERR_NOT_FOUND;
+ *slash = 0;
+ return NB_OK;
+}
+
/*
* ------------------------
* Libyang Future Functions
@@ -1209,7 +1348,8 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath)
*root = lyd_first_sibling(*root);
- err = lyd_find_xpath3(NULL, *root, xpath, NULL, &set);
+ err = yang_lyd_find_xpath3(NULL, *root, xpath, LY_VALUE_JSON, NULL,
+ NULL, &set);
if (err) {
flog_err_sys(EC_LIB_LIBYANG,
"cannot obtain specific result for xpath \"%s\": %s",
@@ -1265,6 +1405,42 @@ LY_ERR yang_lyd_trim_xpath(struct lyd_node **root, const char *xpath)
#endif
}
+/* Can be replaced by `lyd_parse_data` with libyang >= 2.1.156 */
+LY_ERR yang_lyd_parse_data(const struct ly_ctx *ctx, struct lyd_node *parent,
+ struct ly_in *in, LYD_FORMAT format,
+ uint32_t parse_options, uint32_t validate_options,
+ struct lyd_node **tree)
+{
+ struct lyd_node *child;
+ LY_ERR err;
+
+ err = lyd_parse_data(ctx, parent, in, format, parse_options,
+ validate_options, tree);
+ if (err)
+ return err;
+
+ if (!parent || !(parse_options & LYD_PARSE_ONLY))
+ return LY_SUCCESS;
+
+ /*
+ * Versions prior to 2.1.156 don't return `tree` if `parent` is not NULL
+ * and validation is disabled (`LYD_PARSE_ONLY`). To work around this,
+ * go through the children and find the one with `LYD_NEW` flag set.
+ */
+ *tree = NULL;
+
+ LY_LIST_FOR (lyd_child_no_keys(parent), child) {
+ if (child->flags & LYD_NEW) {
+ *tree = child;
+ break;
+ }
+ }
+
+ assert(tree);
+
+ return LY_SUCCESS;
+}
+
/*
* Safe to remove after libyang v2.1.128 is required
*/
diff --git a/lib/yang.h b/lib/yang.h
index 65f6a73..57131f4 100644
--- a/lib/yang.h
+++ b/lib/yang.h
@@ -45,9 +45,6 @@ struct yang_module {
RB_ENTRY(yang_module) entry;
const char *name;
const struct lys_module *info;
-#ifdef HAVE_CONFD
- int confd_hash;
-#endif
#ifdef HAVE_SYSREPO
sr_subscription_ctx_t *sr_subscription;
struct event *sr_thread;
@@ -539,6 +536,21 @@ extern struct lyd_node *yang_dnode_dup(const struct lyd_node *dnode);
extern void yang_dnode_free(struct lyd_node *dnode);
/*
+ * Add a libyang data node to an RPC/action output container.
+ *
+ * output
+ * RPC/action output container.
+ *
+ * xpath
+ * XPath of the data node to add, relative to the output container.
+ *
+ * value
+ * String representing the value of the data node.
+ */
+extern void yang_dnode_rpc_output_add(struct lyd_node *output,
+ const char *xpath, const char *value);
+
+/*
* Create a new yang_data structure.
*
* xpath
@@ -623,6 +635,25 @@ extern LY_ERR yang_parse_notification(const char *xpath, LYD_FORMAT format,
const char *data, struct lyd_node **notif);
/*
+ * Parse a YANG RPC.
+ *
+ * Args:
+ * xpath: xpath of an RPC/action.
+ * format: LYD_FORMAT of input data.
+ * data: input data.
+ * reply: true if the data represents a reply to an RPC/action.
+ * rpc: pointer to the libyang data tree to store the parsed RPC/action.
+ * If data represents an action, the pointer to the action node is
+ * still returned, but it's part of the full data tree with all its
+ * parents.
+ *
+ * Returns:
+ * LY_ERR from underlying calls.
+ */
+LY_ERR yang_parse_rpc(const char *xpath, LYD_FORMAT format, const char *data,
+ bool reply, struct lyd_node **rpc);
+
+/*
* "Print" the yang tree in `root` into dynamic sized array.
*
* Args:
@@ -771,6 +802,14 @@ extern int yang_get_key_preds(char *s, const struct lysc_node *snode,
extern int yang_get_node_keys(struct lyd_node *node, struct yang_list_keys *keys);
/**
+ * yang_xpath_pop_node() - remove the last node from xpath string
+ * @xpath: an xpath string
+ *
+ * Return: NB_OK or NB_ERR_NOT_FOUND if nothing left to pop.
+ */
+extern int yang_xpath_pop_node(char *xpath);
+
+/**
* yang_resolve_snodes() - Resolve an XPath to matching schema nodes.
* @ly_ctx: libyang context to operate on.
* @xpath: the path or XPath to resolve.
@@ -800,6 +839,11 @@ extern LY_ERR yang_lyd_new_list(struct lyd_node_inner *parent,
const struct yang_list_keys *keys,
struct lyd_node **nodes);
extern LY_ERR yang_lyd_trim_xpath(struct lyd_node **rootp, const char *xpath);
+extern LY_ERR yang_lyd_parse_data(const struct ly_ctx *ctx,
+ struct lyd_node *parent, struct ly_in *in,
+ LYD_FORMAT format, uint32_t parse_options,
+ uint32_t validate_options,
+ struct lyd_node **tree);
#ifdef __cplusplus
}
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index a013395..4e49a12 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -1026,30 +1026,50 @@ void yang_dnode_get_mac(struct ethaddr *mac, const struct lyd_node *dnode,
(void)prefix_str2mac(canon, mac);
}
-struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time)
+struct yang_data *yang_data_new_date_and_time(const char *xpath, time_t time, bool is_monotime)
{
- struct tm tm;
- char timebuf[MONOTIME_STRLEN];
- struct timeval _time, time_real;
- char *ts_dot;
- uint16_t buflen;
+ struct yang_data *yd;
+ char *times = NULL;
- _time.tv_sec = time;
- _time.tv_usec = 0;
- monotime_to_realtime(&_time, &time_real);
+ if (is_monotime) {
+ struct timeval _time = { time, 0 };
+ struct timeval time_real;
- gmtime_r(&time_real.tv_sec, &tm);
+ monotime_to_realtime(&_time, &time_real);
+ time = time_real.tv_sec;
+ }
+
+ (void)ly_time_time2str(time, NULL, &times);
+ yd = yang_data_new(xpath, times);
+ free(times);
+
+ return yd;
+}
+
+struct timespec yang_dnode_get_date_and_timespec(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+{
+ const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
+ struct timespec ts;
+ LY_ERR err;
+
+ err = ly_time_str2ts(canon, &ts);
+ assert(!err);
+
+ return ts;
+}
- /* rfc-3339 format */
- strftime(timebuf, sizeof(timebuf), "%Y-%m-%dT%H:%M:%S", &tm);
- buflen = strlen(timebuf);
- ts_dot = timebuf + buflen;
+time_t yang_dnode_get_date_and_time(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+{
+ const char *canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
+ time_t time;
+ LY_ERR err;
- /* microseconds and appends Z */
- snprintfrr(ts_dot, sizeof(timebuf) - buflen, ".%06luZ",
- (unsigned long)time_real.tv_usec);
+ err = ly_time_str2time(canon, &time, NULL);
+ assert(!err);
- return yang_data_new(xpath, timebuf);
+ return time;
}
float yang_dnode_get_bandwidth_ieee_float32(const struct lyd_node *dnode,
diff --git a/lib/yang_wrappers.h b/lib/yang_wrappers.h
index 59b5b13..d3d8419 100644
--- a/lib/yang_wrappers.h
+++ b/lib/yang_wrappers.h
@@ -7,6 +7,7 @@
#ifndef _FRR_NORTHBOUND_WRAPPERS_H_
#define _FRR_NORTHBOUND_WRAPPERS_H_
+#include <libyang/libyang.h>
#include "prefix.h"
#ifdef __cplusplus
@@ -200,7 +201,14 @@ extern void yang_dnode_get_mac(struct ethaddr *mac, const struct lyd_node *dnode
/*data-and-time */
extern struct yang_data *yang_data_new_date_and_time(const char *xpath,
- time_t time);
+ time_t time,
+ bool is_monotime);
+struct timespec yang_dnode_get_date_and_timespec(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
+time_t yang_dnode_get_date_and_time(const struct lyd_node *dnode,
+ const char *xpath_fmt, ...)
+ PRINTFRR(2, 3);
/* rt-types:bandwidth-ieee-float32 */
extern float yang_dnode_get_bandwidth_ieee_float32(const struct lyd_node *dnode,
diff --git a/lib/zclient.c b/lib/zclient.c
index 51ebb56..1aab7b4 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -282,6 +282,7 @@ static void zclient_flush_data(struct event *thread)
zclient->sock, &zclient->t_write);
break;
case BUFFER_EMPTY:
+ /* Currently only Sharpd and Bgpd has callbacks defined */
if (zclient->zebra_buffer_write_ready)
(*zclient->zebra_buffer_write_ready)();
break;
@@ -1039,7 +1040,7 @@ int zapi_nexthop_encode(struct stream *s, const struct zapi_nexthop *api_nh,
}
if (api_nh->weight)
- stream_putl(s, api_nh->weight);
+ stream_putq(s, api_nh->weight);
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(nh_flags, ZAPI_NEXTHOP_FLAG_EVPN))
@@ -1124,6 +1125,7 @@ int zapi_srv6_locator_encode(struct stream *s, const struct srv6_locator *l)
stream_put(s, l->name, strlen(l->name));
stream_putw(s, l->prefix.prefixlen);
stream_put(s, &l->prefix.prefix, sizeof(l->prefix.prefix));
+ stream_putc(s, l->flags);
return 0;
}
@@ -1139,6 +1141,7 @@ int zapi_srv6_locator_decode(struct stream *s, struct srv6_locator *l)
STREAM_GETW(s, l->prefix.prefixlen);
STREAM_GET(&l->prefix.prefix, s, sizeof(l->prefix.prefix));
l->prefix.family = AF_INET6;
+ STREAM_GETC(s, l->flags);
return 0;
stream_failure:
@@ -1411,7 +1414,7 @@ int zapi_nexthop_decode(struct stream *s, struct zapi_nexthop *api_nh,
}
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_WEIGHT))
- STREAM_GETL(s, api_nh->weight);
+ STREAM_GETQ(s, api_nh->weight);
/* Router MAC for EVPN routes. */
if (CHECK_FLAG(api_nh->flags, ZAPI_NEXTHOP_FLAG_EVPN))
@@ -2171,6 +2174,7 @@ int zapi_nexthop_from_nexthop(struct zapi_nexthop *znh,
znh->weight = nh->weight;
znh->ifindex = nh->ifindex;
znh->gate = nh->gate;
+ znh->srte_color = nh->srte_color;
if (CHECK_FLAG(nh->flags, NEXTHOP_FLAG_ONLINK))
SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_ONLINK);
@@ -4669,21 +4673,25 @@ char *zclient_dump_route_flags(uint32_t flags, char *buf, size_t len)
return buf;
}
- snprintfrr(
- buf, len, "%s%s%s%s%s%s%s%s%s%s",
- CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion "
- : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance "
- : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "",
- CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED) ? "Offload Failed "
- : "");
+ snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s",
+ CHECK_FLAG(flags, ZEBRA_FLAG_ALLOW_RECURSION) ? "Recursion "
+ : "",
+
+ CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) ? "Self " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_IBGP) ? "iBGP " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_SELECTED) ? "Selected " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_FIB_OVERRIDE) ? "Override " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_EVPN_ROUTE) ? "Evpn " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_RR_USE_DISTANCE) ? "RR Distance "
+ : "",
+
+ CHECK_FLAG(flags, ZEBRA_FLAG_TRAPPED) ? "Trapped " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOADED) ? "Offloaded " : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_OFFLOAD_FAILED)
+ ? "Offload Failed "
+ : "",
+ CHECK_FLAG(flags, ZEBRA_FLAG_OUTOFSYNC) ? "OutOfSync " : "");
+
return buf;
}
diff --git a/lib/zclient.h b/lib/zclient.h
index 1bf9106..3759f94 100644
--- a/lib/zclient.h
+++ b/lib/zclient.h
@@ -441,7 +441,7 @@ struct zapi_nexthop {
struct ethaddr rmac;
- uint32_t weight;
+ uint64_t weight;
/* Backup nexthops, for IP-FRR, TI-LFA, etc */
uint8_t backup_num;
diff --git a/lib/zlog.c b/lib/zlog.c
index 8734fd5..ffca572 100644
--- a/lib/zlog.c
+++ b/lib/zlog.c
@@ -50,6 +50,7 @@
#include "printfrr.h"
#include "frrcu.h"
#include "zlog.h"
+#include "zlog_live.h"
#include "libfrr_trace.h"
#include "frrevent.h"
@@ -109,6 +110,9 @@ struct zlog_msg {
size_t textlen;
size_t hdrlen;
+ /* for relayed log messages ONLY (cf. zlog_recirculate_live_msg) */
+ intmax_t pid, tid;
+
/* This is always ISO8601 with sub-second precision 9 here, it's
* converted for callers as needed. ts_dot points to the "."
* separating sub-seconds. ts_zonetail is "Z" or "+00:00" for the
@@ -357,6 +361,16 @@ void zlog_msg_pid(struct zlog_msg *msg, intmax_t *pid, intmax_t *tid)
{
#ifndef __OpenBSD__
static thread_local intmax_t cached_pid = -1;
+#endif
+
+ /* recirculated messages */
+ if (msg->pid) {
+ *pid = msg->pid;
+ *tid = msg->tid;
+ return;
+ }
+
+#ifndef __OpenBSD__
if (cached_pid != -1)
*pid = cached_pid;
else
@@ -507,6 +521,89 @@ static void vzlog_tls(struct zlog_tls *zlog_tls, const struct xref_logmsg *xref,
XFREE(MTYPE_LOG_MESSAGE, msg->text);
}
+/* reinject log message received by zlog_recirculate_recv(). As of writing,
+ * only used in the ldpd parent process to proxy messages from lde/ldpe
+ * subprocesses.
+ */
+void zlog_recirculate_live_msg(uint8_t *data, size_t len)
+{
+ struct zlog_target *zt;
+ struct zlog_msg stackmsg = {}, *msg = &stackmsg;
+ struct zlog_live_hdr *hdr;
+ struct xrefdata *xrefdata, ref = {};
+
+ if (len < sizeof(*hdr))
+ return;
+
+ hdr = (struct zlog_live_hdr *)data;
+ if (hdr->hdrlen < sizeof(*hdr))
+ return;
+ data += hdr->hdrlen;
+ len -= sizeof(*hdr);
+
+ msg->ts.tv_sec = hdr->ts_sec;
+ msg->ts.tv_nsec = hdr->ts_nsec;
+ msg->pid = hdr->pid;
+ msg->tid = hdr->tid;
+ msg->prio = hdr->prio;
+
+ if (hdr->textlen > len)
+ return;
+ msg->textlen = hdr->textlen;
+ msg->hdrlen = hdr->texthdrlen;
+ msg->text = (char *)data;
+
+ /* caller needs to make sure we have a trailing \n\0, it's not
+ * transmitted on zlog_live
+ */
+ if (msg->text[msg->textlen] != '\n' ||
+ msg->text[msg->textlen + 1] != '\0')
+ return;
+
+ static_assert(sizeof(msg->argpos[0]) == sizeof(hdr->argpos[0]),
+ "in-memory struct doesn't match on-wire variant");
+ msg->n_argpos = MIN(hdr->n_argpos, array_size(msg->argpos));
+ memcpy(msg->argpos, hdr->argpos, msg->n_argpos * sizeof(msg->argpos[0]));
+
+ /* This will only work if we're in the same daemon: we received a log
+ * message uid and are now doing a lookup in *our* known uids to find
+ * it. This works for ldpd because it's the same binary containing the
+ * same log messages, and ldpd is the only use case right now.
+ *
+ * When the uid is not found, the log message uid is lost but the
+ * message itself is still processed correctly. If this is needed,
+ * this can be made to work in two ways:
+ * (a) synthesize a temporary xref_logmsg from the received data.
+ * This is a bit annoying due to lifetimes with per-thread buffers.
+ * (b) extract and aggregate all log messages. This already happens
+ * with frr.xref but that would need to be fed back in.
+ */
+ strlcpy(ref.uid, hdr->uid, sizeof(ref.uid));
+ xrefdata = xrefdata_uid_find(&xrefdata_uid, &ref);
+
+ if (xrefdata && xrefdata->xref->type == XREFT_LOGMSG) {
+ struct xref_logmsg *xref_logmsg;
+
+ xref_logmsg = (struct xref_logmsg *)xrefdata->xref;
+ msg->xref = xref_logmsg;
+ msg->fmt = xref_logmsg->fmtstring;
+ } else {
+ /* fake out format string... */
+ msg->fmt = msg->text + hdr->texthdrlen;
+ }
+
+ rcu_read_lock();
+ frr_each_safe (zlog_targets, &zlog_targets, zt) {
+ if (msg->prio > zt->prio_min)
+ continue;
+ if (!zt->logfn)
+ continue;
+
+ zt->logfn(zt, &msg, 1);
+ }
+ rcu_read_unlock();
+}
+
static void zlog_backtrace_msg(const struct xref_logmsg *xref, int prio)
{
struct event *tc = pthread_getspecific(thread_current);
diff --git a/lib/zlog.h b/lib/zlog.h
index 27401d5..9d93979 100644
--- a/lib/zlog.h
+++ b/lib/zlog.h
@@ -125,6 +125,9 @@ static inline void zlog_ref(const struct xref_logmsg *xref,
extern void zlog_sigsafe(const char *text, size_t len);
+/* recirculate a log message from zlog_live */
+extern void zlog_recirculate_live_msg(uint8_t *data, size_t len);
+
/* extra priority value to disable a target without deleting it */
#define ZLOG_DISABLED (LOG_EMERG-1)
diff --git a/lib/zlog_recirculate.c b/lib/zlog_recirculate.c
new file mode 100644
index 0000000..abc73ee
--- /dev/null
+++ b/lib/zlog_recirculate.c
@@ -0,0 +1,56 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2024 David Lamparter, for NetDEF, Inc.
+ */
+
+#include "zebra.h"
+
+#include "log.h"
+#include "frrevent.h"
+
+#include "zlog_recirculate.h"
+
+/* This is only the event loop part; it's split off from
+ * zlog_recirculate_live_msg since there's an integration boundary; this
+ * half deals with events, the other half with zlog interna.
+ *
+ * As of writing, this runs in ldpd in the *parent* process and receives log
+ * messages from the lde/ldpe subprocesses. It is not used anywhere else
+ * (yet?)
+ */
+static void zlog_recirculate_recv(struct event *ev)
+{
+ uint8_t rxbuf[4096];
+ ssize_t n_rd;
+ int fd = EVENT_FD(ev);
+
+ /* see below for -2, "\n\0" are added */
+ n_rd = read(fd, rxbuf, sizeof(rxbuf) - 2);
+ if (n_rd == 0) {
+ /* EOF */
+ close(fd);
+ /* event_add_read not called yet, nothing to cancel */
+ return;
+ }
+ if (n_rd < 0 && (errno != EAGAIN) && (errno != EWOULDBLOCK)) {
+ /* error */
+ zlog_warn("error on log relay socket %d: %m", fd);
+ close(fd);
+ /* event_add_read not called yet, nothing to cancel */
+ return;
+ }
+
+ event_add_read(ev->master, zlog_recirculate_recv, NULL, fd, NULL);
+ if (n_rd < 0)
+ return;
+
+ /* log infrastructure has an implicit \n\0 at the end */
+ rxbuf[n_rd] = '\n';
+ rxbuf[n_rd + 1] = '\0';
+ zlog_recirculate_live_msg(rxbuf, n_rd);
+}
+
+void zlog_recirculate_subscribe(struct event_loop *el, int fd)
+{
+ event_add_read(el, zlog_recirculate_recv, NULL, fd, NULL);
+}
diff --git a/lib/zlog_recirculate.h b/lib/zlog_recirculate.h
new file mode 100644
index 0000000..a2ddb4e
--- /dev/null
+++ b/lib/zlog_recirculate.h
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2024 David Lamparter, for NetDEF, Inc.
+ */
+
+#ifndef _FRR_ZLOG_RECIRCULATE_H
+#define _FRR_ZLOG_RECIRCULATE_H
+
+/* fd should be one end of a socketpair() */
+extern void zlog_recirculate_subscribe(struct event_loop *tm, int fd);
+
+#endif
diff --git a/mgmtd/mgmt_be_adapter.c b/mgmtd/mgmt_be_adapter.c
index b311bf4..c7f4fb9 100644
--- a/mgmtd/mgmt_be_adapter.c
+++ b/mgmtd/mgmt_be_adapter.c
@@ -90,10 +90,16 @@ static const char *const ripd_config_xpaths[] = {
"/frr-ripd:ripd",
"/frr-route-map:lib",
"/frr-vrf:lib",
+ "/ietf-key-chain:key-chains",
NULL,
};
static const char *const ripd_oper_xpaths[] = {
"/frr-ripd:ripd",
+ "/ietf-key-chain:key-chains",
+ NULL,
+};
+static const char *const ripd_rpc_xpaths[] = {
+ "/frr-ripd",
NULL,
};
#endif
@@ -111,6 +117,10 @@ static const char *const ripngd_oper_xpaths[] = {
"/frr-ripngd:ripngd",
NULL,
};
+static const char *const ripngd_rpc_xpaths[] = {
+ "/frr-ripngd",
+ NULL,
+};
#endif
#if HAVE_STATICD
@@ -145,6 +155,18 @@ static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
[MGMTD_BE_CLIENT_ID_ZEBRA] = zebra_oper_xpaths,
};
+static const char *const *be_client_notif_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
+};
+
+static const char *const *be_client_rpc_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
+#ifdef HAVE_RIPD
+ [MGMTD_BE_CLIENT_ID_RIPD] = ripd_rpc_xpaths,
+#endif
+#ifdef HAVE_RIPNGD
+ [MGMTD_BE_CLIENT_ID_RIPNGD] = ripngd_rpc_xpaths,
+#endif
+};
+
/*
* We would like to have a better ADT than one with O(n) comparisons
*
@@ -157,6 +179,7 @@ static const char *const *be_client_oper_xpaths[MGMTD_BE_CLIENT_ID_MAX] = {
static struct mgmt_be_xpath_map *be_cfg_xpath_map;
static struct mgmt_be_xpath_map *be_oper_xpath_map;
static struct mgmt_be_xpath_map *be_notif_xpath_map;
+static struct mgmt_be_xpath_map *be_rpc_xpath_map;
static struct event_loop *mgmt_loop;
static struct msg_server mgmt_be_server = {.fd = -1};
@@ -171,8 +194,8 @@ static struct mgmt_be_client_adapter
static void
mgmt_be_adapter_sched_init_event(struct mgmt_be_client_adapter *adapter);
-static bool be_is_client_interested(const char *xpath,
- enum mgmt_be_client_id id, bool config);
+static bool be_is_client_interested(const char *xpath, enum mgmt_be_client_id id,
+ enum mgmt_be_xpath_subscr_type type);
const char *mgmt_be_client_id2name(enum mgmt_be_client_id id)
{
@@ -221,16 +244,25 @@ mgmt_be_find_adapter_by_name(const char *name)
}
static void mgmt_register_client_xpath(enum mgmt_be_client_id id,
- const char *xpath, bool config, bool oper)
+ const char *xpath,
+ enum mgmt_be_xpath_subscr_type type)
{
struct mgmt_be_xpath_map **maps, *map;
- if (config)
+ switch (type) {
+ case MGMT_BE_XPATH_SUBSCR_TYPE_CFG:
maps = &be_cfg_xpath_map;
- else if (oper)
+ break;
+ case MGMT_BE_XPATH_SUBSCR_TYPE_OPER:
maps = &be_oper_xpath_map;
- else
+ break;
+ case MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF:
maps = &be_notif_xpath_map;
+ break;
+ case MGMT_BE_XPATH_SUBSCR_TYPE_RPC:
+ maps = &be_rpc_xpath_map;
+ break;
+ }
darr_foreach_p (*maps, map) {
if (!strcmp(xpath, map->xpath_prefix)) {
@@ -258,18 +290,36 @@ static void mgmt_be_xpath_map_init(void)
/* Initialize the common config init map */
for (init = be_client_config_xpaths[id]; init && *init; init++) {
__dbg(" - CFG XPATH: '%s'", *init);
- mgmt_register_client_xpath(id, *init, true, false);
+ mgmt_register_client_xpath(id, *init,
+ MGMT_BE_XPATH_SUBSCR_TYPE_CFG);
}
/* Initialize the common oper init map */
for (init = be_client_oper_xpaths[id]; init && *init; init++) {
__dbg(" - OPER XPATH: '%s'", *init);
- mgmt_register_client_xpath(id, *init, false, true);
+ mgmt_register_client_xpath(id, *init,
+ MGMT_BE_XPATH_SUBSCR_TYPE_OPER);
+ }
+
+ /* Initialize the common NOTIF init map */
+ for (init = be_client_notif_xpaths[id]; init && *init; init++) {
+ __dbg(" - NOTIF XPATH: '%s'", *init);
+ mgmt_register_client_xpath(id, *init,
+ MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF);
+ }
+
+ /* Initialize the common RPC init map */
+ for (init = be_client_rpc_xpaths[id]; init && *init; init++) {
+ __dbg(" - RPC XPATH: '%s'", *init);
+ mgmt_register_client_xpath(id, *init,
+ MGMT_BE_XPATH_SUBSCR_TYPE_RPC);
}
}
__dbg("Total Cfg XPath Maps: %u", darr_len(be_cfg_xpath_map));
__dbg("Total Oper XPath Maps: %u", darr_len(be_oper_xpath_map));
+ __dbg("Total Noitf XPath Maps: %u", darr_len(be_notif_xpath_map));
+ __dbg("Total RPC XPath Maps: %u", darr_len(be_rpc_xpath_map));
}
static void mgmt_be_xpath_map_cleanup(void)
@@ -287,6 +337,10 @@ static void mgmt_be_xpath_map_cleanup(void)
darr_foreach_p (be_notif_xpath_map, map)
XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
darr_free(be_notif_xpath_map);
+
+ darr_foreach_p (be_rpc_xpath_map, map)
+ XFREE(MTYPE_MGMTD_XPATH, map->xpath_prefix);
+ darr_free(be_rpc_xpath_map);
}
@@ -403,11 +457,12 @@ mgmt_be_adapter_handle_msg(struct mgmt_be_client_adapter *adapter,
*/
switch ((int)be_msg->message_case) {
case MGMTD__BE_MESSAGE__MESSAGE_SUBSCR_REQ:
- __dbg("Got SUBSCR_REQ from '%s' to register xpaths config: %zu oper: %zu notif: %zu",
+ __dbg("Got SUBSCR_REQ from '%s' to register xpaths config: %zu oper: %zu notif: %zu rpc: %zu",
be_msg->subscr_req->client_name,
be_msg->subscr_req->n_config_xpaths,
be_msg->subscr_req->n_oper_xpaths,
- be_msg->subscr_req->n_notif_xpaths);
+ be_msg->subscr_req->n_notif_xpaths,
+ be_msg->subscr_req->n_rpc_xpaths);
if (strlen(be_msg->subscr_req->client_name)) {
strlcpy(adapter->name, be_msg->subscr_req->client_name,
@@ -430,22 +485,29 @@ mgmt_be_adapter_handle_msg(struct mgmt_be_client_adapter *adapter,
num = be_msg->subscr_req->n_config_xpaths;
for (i = 0; i < num; i++) {
xpath = be_msg->subscr_req->config_xpaths[i];
- mgmt_register_client_xpath(adapter->id, xpath, true,
- false);
+ mgmt_register_client_xpath(adapter->id, xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_CFG);
}
num = be_msg->subscr_req->n_oper_xpaths;
for (i = 0; i < num; i++) {
xpath = be_msg->subscr_req->oper_xpaths[i];
- mgmt_register_client_xpath(adapter->id, xpath, false,
- true);
+ mgmt_register_client_xpath(adapter->id, xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_OPER);
}
num = be_msg->subscr_req->n_notif_xpaths;
for (i = 0; i < num; i++) {
xpath = be_msg->subscr_req->notif_xpaths[i];
- mgmt_register_client_xpath(adapter->id, xpath, false,
- false);
+ mgmt_register_client_xpath(adapter->id, xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF);
+ }
+
+ num = be_msg->subscr_req->n_rpc_xpaths;
+ for (i = 0; i < num; i++) {
+ xpath = be_msg->subscr_req->rpc_xpaths[i];
+ mgmt_register_client_xpath(adapter->id, xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_RPC);
}
mgmt_be_send_subscr_reply(adapter, true);
@@ -636,6 +698,7 @@ static void be_adapter_handle_native_msg(struct mgmt_be_client_adapter *adapter,
{
struct mgmt_msg_notify_data *notify_msg;
struct mgmt_msg_tree_data *tree_msg;
+ struct mgmt_msg_rpc_reply *rpc_msg;
struct mgmt_msg_error *error_msg;
/* get the transaction */
@@ -660,6 +723,15 @@ static void be_adapter_handle_native_msg(struct mgmt_be_client_adapter *adapter,
/* Forward the reply to the txn module */
mgmt_txn_notify_tree_data_reply(adapter, tree_msg, msg_len);
break;
+ case MGMT_MSG_CODE_RPC_REPLY:
+ /* RPC reply from a backend client */
+ rpc_msg = (typeof(rpc_msg))msg;
+ __dbg("Got RPC_REPLY from '%s' txn-id %" PRIx64, adapter->name,
+ msg->refer_id);
+
+ /* Forward the reply to the txn module */
+ mgmt_txn_notify_rpc_reply(adapter, rpc_msg, msg_len);
+ break;
case MGMT_MSG_CODE_NOTIFY:
notify_msg = (typeof(notify_msg))msg;
__dbg("Got NOTIFY from '%s'", adapter->name);
@@ -880,7 +952,8 @@ void mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
goto walk_cont;
xpath = lyd_path(dnode, LYD_PATH_STD, NULL, 0);
- if (be_is_client_interested(xpath, adapter->id, true))
+ if (be_is_client_interested(xpath, adapter->id,
+ MGMT_BE_XPATH_SUBSCR_TYPE_CFG))
nb_config_diff_add_change(*changes, NB_CB_CREATE, &seq, dnode);
else
LYD_TREE_DFS_continue = 1; /* skip any subtree */
@@ -891,13 +964,27 @@ void mgmt_be_get_adapter_config(struct mgmt_be_client_adapter *adapter,
}
}
-uint64_t mgmt_be_interested_clients(const char *xpath, bool config)
+uint64_t mgmt_be_interested_clients(const char *xpath,
+ enum mgmt_be_xpath_subscr_type type)
{
- struct mgmt_be_xpath_map *maps, *map;
+ struct mgmt_be_xpath_map *maps = NULL, *map;
enum mgmt_be_client_id id;
uint64_t clients;
- maps = config ? be_cfg_xpath_map : be_oper_xpath_map;
+ switch (type) {
+ case MGMT_BE_XPATH_SUBSCR_TYPE_CFG:
+ maps = be_cfg_xpath_map;
+ break;
+ case MGMT_BE_XPATH_SUBSCR_TYPE_OPER:
+ maps = be_oper_xpath_map;
+ break;
+ case MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF:
+ maps = be_notif_xpath_map;
+ break;
+ case MGMT_BE_XPATH_SUBSCR_TYPE_RPC:
+ maps = be_rpc_xpath_map;
+ break;
+ }
clients = 0;
@@ -926,8 +1013,8 @@ uint64_t mgmt_be_interested_clients(const char *xpath, bool config)
* Returns:
* Interested or not.
*/
-static bool be_is_client_interested(const char *xpath,
- enum mgmt_be_client_id id, bool config)
+static bool be_is_client_interested(const char *xpath, enum mgmt_be_client_id id,
+ enum mgmt_be_xpath_subscr_type type)
{
uint64_t clients;
@@ -936,7 +1023,7 @@ static bool be_is_client_interested(const char *xpath,
__dbg("Checking client: %s for xpath: '%s'", mgmt_be_client_id2name(id),
xpath);
- clients = mgmt_be_interested_clients(xpath, config);
+ clients = mgmt_be_interested_clients(xpath, type);
if (IS_IDBIT_SET(clients, id)) {
__dbg("client: %s: interested", mgmt_be_client_id2name(id));
return true;
@@ -996,23 +1083,41 @@ void mgmt_be_xpath_register_write(struct vty *vty)
darr_len(be_oper_xpath_map));
darr_foreach_p (be_oper_xpath_map, map)
be_show_xpath_register(vty, map);
+
+ vty_out(vty, "\nMGMTD Backend NOTIFY XPath Registry: Count: %u\n",
+ darr_len(be_notif_xpath_map));
+ darr_foreach_p (be_notif_xpath_map, map)
+ be_show_xpath_register(vty, map);
+
+ vty_out(vty, "\nMGMTD Backend RPC XPath Registry: Count: %u\n",
+ darr_len(be_rpc_xpath_map));
+ darr_foreach_p (be_rpc_xpath_map, map)
+ be_show_xpath_register(vty, map);
}
void mgmt_be_show_xpath_registries(struct vty *vty, const char *xpath)
{
enum mgmt_be_client_id id;
struct mgmt_be_client_adapter *adapter;
- uint64_t cclients, oclients, combined;
-
- cclients = mgmt_be_interested_clients(xpath, true);
- oclients = mgmt_be_interested_clients(xpath, false);
- combined = cclients | oclients;
+ uint64_t cclients, nclients, oclients, rclients, combined;
+
+ cclients = mgmt_be_interested_clients(xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_CFG);
+ oclients = mgmt_be_interested_clients(xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_OPER);
+ nclients = mgmt_be_interested_clients(xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF);
+ rclients = mgmt_be_interested_clients(xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_RPC);
+ combined = cclients | nclients | oclients | rclients;
vty_out(vty, "XPath: '%s'\n", xpath);
FOREACH_BE_CLIENT_BITS (id, combined) {
- vty_out(vty, " -- Client: '%s'\tconfig:%d oper:%d\n",
+ vty_out(vty,
+ " -- Client: '%s'\tconfig:%d notify:%d oper:%d rpc:%d\n",
mgmt_be_client_id2name(id), IS_IDBIT_SET(cclients, id),
- IS_IDBIT_SET(oclients, id));
+ IS_IDBIT_SET(nclients, id), IS_IDBIT_SET(oclients, id),
+ IS_IDBIT_SET(rclients, id));
adapter = mgmt_be_get_adapter_by_id(id);
if (adapter)
vty_out(vty, " -- Adapter: %p\n", adapter);
diff --git a/mgmtd/mgmt_be_adapter.h b/mgmtd/mgmt_be_adapter.h
index 491410a..c9f2ab1 100644
--- a/mgmtd/mgmt_be_adapter.h
+++ b/mgmtd/mgmt_be_adapter.h
@@ -235,15 +235,23 @@ extern void mgmt_be_xpath_register_write(struct vty *vty);
*/
extern int mgmt_be_send_native(enum mgmt_be_client_id id, void *msg);
+enum mgmt_be_xpath_subscr_type {
+ MGMT_BE_XPATH_SUBSCR_TYPE_CFG,
+ MGMT_BE_XPATH_SUBSCR_TYPE_OPER,
+ MGMT_BE_XPATH_SUBSCR_TYPE_NOTIF,
+ MGMT_BE_XPATH_SUBSCR_TYPE_RPC,
+};
+
/**
* Lookup the clients which are subscribed to a given `xpath`
* and the way they are subscribed.
*
* Args:
* xpath - the xpath to check for subscription information.
- * config - true for config interest false for oper interest.
+ * type - type of subscription to check for.
*/
-extern uint64_t mgmt_be_interested_clients(const char *xpath, bool config);
+extern uint64_t mgmt_be_interested_clients(const char *xpath,
+ enum mgmt_be_xpath_subscr_type type);
/**
* mgmt_fe_adapter_send_notify() - notify FE clients of a notification.
diff --git a/mgmtd/mgmt_be_nb.c b/mgmtd/mgmt_be_nb.c
new file mode 100644
index 0000000..613272d
--- /dev/null
+++ b/mgmtd/mgmt_be_nb.c
@@ -0,0 +1,6 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include "config.h"
+#include "xref.h"
+
+XREF_SETUP();
diff --git a/mgmtd/mgmt_fe_adapter.c b/mgmtd/mgmt_fe_adapter.c
index ec8e773..fc1bde0 100644
--- a/mgmtd/mgmt_fe_adapter.c
+++ b/mgmtd/mgmt_fe_adapter.c
@@ -898,11 +898,13 @@ static int mgmt_fe_session_handle_commit_config_req_msg(
/*
* Create COMMITConfig request under the transaction
*/
- if (mgmt_txn_send_commit_config_req(
- session->cfg_txn_id, commcfg_req->req_id,
- commcfg_req->src_ds_id, src_ds_ctx, commcfg_req->dst_ds_id,
- dst_ds_ctx, commcfg_req->validate_only, commcfg_req->abort,
- false) != 0) {
+ if (mgmt_txn_send_commit_config_req(session->cfg_txn_id,
+ commcfg_req->req_id,
+ commcfg_req->src_ds_id, src_ds_ctx,
+ commcfg_req->dst_ds_id, dst_ds_ctx,
+ commcfg_req->validate_only,
+ commcfg_req->abort, false,
+ NULL) != 0) {
fe_adapter_send_commit_cfg_reply(
session, commcfg_req->src_ds_id, commcfg_req->dst_ds_id,
commcfg_req->req_id, MGMTD_INTERNAL_ERROR,
@@ -1099,6 +1101,74 @@ done:
return ret;
}
+static int fe_adapter_send_rpc_reply(struct mgmt_fe_session_ctx *session,
+ uint64_t req_id, uint8_t result_type,
+ const struct lyd_node *result)
+{
+ struct mgmt_msg_rpc_reply *msg;
+ uint8_t **darrp = NULL;
+ int ret;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc_reply, 0,
+ MTYPE_MSG_NATIVE_RPC_REPLY);
+ msg->refer_id = session->session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_RPC_REPLY;
+ msg->result_type = result_type;
+
+ if (result) {
+ darrp = mgmt_msg_native_get_darrp(msg);
+ ret = yang_print_tree_append(darrp, result, result_type, 0);
+ if (ret != LY_SUCCESS) {
+ __log_err("Error building rpc-reply result for client %s session-id %" PRIu64
+ " req-id %" PRIu64 " result type %u",
+ session->adapter->name, session->session_id,
+ req_id, result_type);
+ goto done;
+ }
+ }
+
+ __dbg("Sending rpc-reply from adapter %s to session-id %" PRIu64
+ " req-id %" PRIu64 " len %u",
+ session->adapter->name, session->session_id, req_id,
+ mgmt_msg_native_get_msg_len(msg));
+
+ ret = fe_adapter_send_native_msg(session->adapter, msg,
+ mgmt_msg_native_get_msg_len(msg),
+ false);
+done:
+ mgmt_msg_native_free_msg(msg);
+
+ return ret;
+}
+
+static int fe_adapter_send_edit_reply(struct mgmt_fe_session_ctx *session,
+ uint64_t req_id, const char *xpath)
+{
+ struct mgmt_msg_edit_reply *msg;
+ int ret;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_edit_reply, 0,
+ MTYPE_MSG_NATIVE_EDIT_REPLY);
+ msg->refer_id = session->session_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_EDIT_REPLY;
+
+ mgmt_msg_native_xpath_encode(msg, xpath);
+
+ __dbg("Sending edit-reply from adapter %s to session-id %" PRIu64
+ " req-id %" PRIu64 " len %u",
+ session->adapter->name, session->session_id, req_id,
+ mgmt_msg_native_get_msg_len(msg));
+
+ ret = fe_adapter_send_native_msg(session->adapter, msg,
+ mgmt_msg_native_get_msg_len(msg),
+ false);
+ mgmt_msg_native_free_msg(msg);
+
+ return ret;
+}
+
/**
* fe_adapter_handle_get_data() - Handle a get-tree message from a FE client.
* @session: the client session.
@@ -1186,7 +1256,8 @@ static void fe_adapter_handle_get_data(struct mgmt_fe_session_ctx *session,
}
darr_free(snodes);
- clients = mgmt_be_interested_clients(msg->xpath, false);
+ clients = mgmt_be_interested_clients(msg->xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_OPER);
if (!clients && !CHECK_FLAG(msg->flags, GET_DATA_FLAG_CONFIG)) {
__dbg("No backends provide xpath: %s for txn-id: %" PRIu64
" session-id: %" PRIu64,
@@ -1224,6 +1295,196 @@ done:
darr_free(xpath_resolved);
}
+static void fe_adapter_handle_edit(struct mgmt_fe_session_ctx *session,
+ void *__msg, size_t msg_len)
+{
+ struct mgmt_msg_edit *msg = __msg;
+ Mgmtd__DatastoreId ds_id, rds_id;
+ struct mgmt_ds_ctx *ds_ctx, *rds_ctx;
+ const char *xpath, *data;
+ bool lock, commit;
+ int ret;
+
+ if (msg->datastore != MGMT_MSG_DATASTORE_CANDIDATE) {
+ fe_adapter_send_error(session, msg->req_id, false, -EINVAL,
+ "Unsupported datastore");
+ return;
+ }
+
+ xpath = mgmt_msg_native_xpath_data_decode(msg, msg_len, data);
+ if (!xpath) {
+ fe_adapter_send_error(session, msg->req_id, false, -EINVAL,
+ "Invalid message");
+ return;
+ }
+
+ ds_id = MGMTD_DS_CANDIDATE;
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, ds_id);
+ assert(ds_ctx);
+
+ rds_id = MGMTD_DS_RUNNING;
+ rds_ctx = mgmt_ds_get_ctx_by_id(mm, rds_id);
+ assert(rds_ctx);
+
+ lock = CHECK_FLAG(msg->flags, EDIT_FLAG_IMPLICIT_LOCK);
+ commit = CHECK_FLAG(msg->flags, EDIT_FLAG_IMPLICIT_COMMIT);
+
+ if (lock) {
+ if (mgmt_fe_session_write_lock_ds(ds_id, ds_ctx, session)) {
+ fe_adapter_send_error(session, msg->req_id, false,
+ -EBUSY,
+ "Candidate DS is locked by another session");
+ return;
+ }
+
+ if (commit) {
+ if (mgmt_fe_session_write_lock_ds(rds_id, rds_ctx,
+ session)) {
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx,
+ session);
+ fe_adapter_send_error(
+ session, msg->req_id, false, -EBUSY,
+ "Running DS is locked by another session");
+ return;
+ }
+ }
+ } else {
+ if (!session->ds_locked[ds_id]) {
+ fe_adapter_send_error(session, msg->req_id, false,
+ -EBUSY,
+ "Candidate DS is not locked");
+ return;
+ }
+
+ if (commit) {
+ if (!session->ds_locked[rds_id]) {
+ fe_adapter_send_error(session, msg->req_id,
+ false, -EBUSY,
+ "Running DS is not locked");
+ return;
+ }
+ }
+ }
+
+ session->cfg_txn_id = mgmt_create_txn(session->session_id,
+ MGMTD_TXN_TYPE_CONFIG);
+ if (session->cfg_txn_id == MGMTD_SESSION_ID_NONE) {
+ if (lock) {
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx, session);
+ if (commit)
+ mgmt_fe_session_unlock_ds(rds_id, rds_ctx,
+ session);
+ }
+ fe_adapter_send_error(session, msg->req_id, false, -EBUSY,
+ "Failed to create a configuration transaction");
+ return;
+ }
+
+ __dbg("Created new config txn-id: %" PRIu64 " for session-id: %" PRIu64,
+ session->cfg_txn_id, session->session_id);
+
+ ret = mgmt_txn_send_edit(session->cfg_txn_id, msg->req_id, ds_id,
+ ds_ctx, rds_id, rds_ctx, lock, commit,
+ msg->request_type, msg->flags, msg->operation,
+ xpath, data);
+ if (ret) {
+ /* destroy the just created txn */
+ mgmt_destroy_txn(&session->cfg_txn_id);
+ if (lock) {
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx, session);
+ if (commit)
+ mgmt_fe_session_unlock_ds(rds_id, rds_ctx,
+ session);
+ }
+ fe_adapter_send_error(session, msg->req_id, false, -EBUSY,
+ "Failed to create a configuration transaction");
+ }
+}
+
+/**
+ * fe_adapter_handle_rpc() - Handle an RPC message from an FE client.
+ * @session: the client session.
+ * @msg_raw: the message data.
+ * @msg_len: the length of the message data.
+ */
+static void fe_adapter_handle_rpc(struct mgmt_fe_session_ctx *session,
+ void *__msg, size_t msg_len)
+{
+ struct mgmt_msg_rpc *msg = __msg;
+ const struct lysc_node *snode;
+ const char *xpath, *data;
+ uint64_t req_id = msg->req_id;
+ uint64_t clients;
+ int ret;
+
+ __dbg("Received RPC request from client %s for session-id %" PRIu64
+ " req-id %" PRIu64,
+ session->adapter->name, session->session_id, msg->req_id);
+
+ xpath = mgmt_msg_native_xpath_data_decode(msg, msg_len, data);
+ if (!xpath) {
+ fe_adapter_send_error(session, req_id, false, -EINVAL,
+ "Invalid message");
+ return;
+ }
+
+ if (session->txn_id != MGMTD_TXN_ID_NONE) {
+ fe_adapter_send_error(session, req_id, false, -EINPROGRESS,
+ "Transaction in progress txn-id: %" PRIu64
+ " for session-id: %" PRIu64,
+ session->txn_id, session->session_id);
+ return;
+ }
+
+ snode = lys_find_path(ly_native_ctx, NULL, xpath, 0);
+ if (!snode) {
+ fe_adapter_send_error(session, req_id, false, -ENOENT,
+ "No such path: %s", xpath);
+ return;
+ }
+
+ if (snode->nodetype != LYS_RPC && snode->nodetype != LYS_ACTION) {
+ fe_adapter_send_error(session, req_id, false, -EINVAL,
+ "Not an RPC or action path: %s", xpath);
+ return;
+ }
+
+ clients = mgmt_be_interested_clients(xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_RPC);
+ if (!clients) {
+ __dbg("No backends implement xpath: %s for txn-id: %" PRIu64
+ " session-id: %" PRIu64,
+ xpath, session->txn_id, session->session_id);
+
+ fe_adapter_send_error(session, req_id, false, -ENOENT,
+ "No backends implement xpath: %s", xpath);
+ return;
+ }
+
+ /* Start a RPC Transaction */
+ session->txn_id = mgmt_create_txn(session->session_id,
+ MGMTD_TXN_TYPE_RPC);
+ if (session->txn_id == MGMTD_SESSION_ID_NONE) {
+ fe_adapter_send_error(session, req_id, false, -EINPROGRESS,
+ "Failed to create an RPC transaction");
+ return;
+ }
+
+ __dbg("Created new rpc txn-id: %" PRIu64 " for session-id: %" PRIu64,
+ session->txn_id, session->session_id);
+
+ /* Create an RPC request under the transaction */
+ ret = mgmt_txn_send_rpc(session->txn_id, req_id, clients,
+ msg->request_type, xpath, data,
+ mgmt_msg_native_data_len_decode(msg, msg_len));
+ if (ret) {
+ /* destroy the just created txn */
+ mgmt_destroy_txn(&session->txn_id);
+ fe_adapter_send_error(session, req_id, false, -EINPROGRESS,
+ "Failed to create an RPC transaction");
+ }
+}
+
/**
* Handle a native encoded message from the FE client.
*/
@@ -1245,6 +1506,12 @@ static void fe_adapter_handle_native_msg(struct mgmt_fe_client_adapter *adapter,
case MGMT_MSG_CODE_GET_DATA:
fe_adapter_handle_get_data(session, msg, msg_len);
break;
+ case MGMT_MSG_CODE_EDIT:
+ fe_adapter_handle_edit(session, msg, msg_len);
+ break;
+ case MGMT_MSG_CODE_RPC:
+ fe_adapter_handle_rpc(session, msg, msg_len);
+ break;
default:
__log_err("unknown native message session-id %" PRIu64
" req-id %" PRIu64 " code %u to FE adapter %s",
@@ -1484,6 +1751,70 @@ int mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
return ret;
}
+int mgmt_fe_adapter_send_rpc_reply(uint64_t session_id, uint64_t txn_id,
+ uint64_t req_id, LYD_FORMAT result_type,
+ const struct lyd_node *result)
+{
+ struct mgmt_fe_session_ctx *session;
+ int ret;
+
+ session = mgmt_session_id2ctx(session_id);
+ if (!session || session->txn_id != txn_id)
+ return -1;
+
+ ret = fe_adapter_send_rpc_reply(session, req_id, result_type, result);
+
+ mgmt_destroy_txn(&session->txn_id);
+
+ return ret;
+}
+
+int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,
+ uint64_t req_id, bool unlock, bool commit,
+ const char *xpath, int16_t error,
+ const char *errstr)
+{
+ struct mgmt_fe_session_ctx *session;
+ Mgmtd__DatastoreId ds_id, rds_id;
+ struct mgmt_ds_ctx *ds_ctx, *rds_ctx;
+ int ret;
+
+ session = mgmt_session_id2ctx(session_id);
+ if (!session || session->cfg_txn_id != txn_id)
+ return -1;
+
+ if (session->cfg_txn_id != MGMTD_TXN_ID_NONE && commit)
+ mgmt_fe_session_register_event(session,
+ MGMTD_FE_SESSION_CFG_TXN_CLNUP);
+
+ if (unlock) {
+ ds_id = MGMTD_DS_CANDIDATE;
+ ds_ctx = mgmt_ds_get_ctx_by_id(mm, ds_id);
+ assert(ds_ctx);
+
+ mgmt_fe_session_unlock_ds(ds_id, ds_ctx, session);
+
+ if (commit) {
+ rds_id = MGMTD_DS_RUNNING;
+ rds_ctx = mgmt_ds_get_ctx_by_id(mm, rds_id);
+ assert(rds_ctx);
+
+ mgmt_fe_session_unlock_ds(rds_id, rds_ctx, session);
+ }
+ }
+
+ if (error)
+ ret = fe_adapter_send_error(session, req_id, false, error, "%s",
+ errstr);
+ else
+ ret = fe_adapter_send_edit_reply(session, req_id, xpath);
+
+ if (session->cfg_txn_id != MGMTD_TXN_ID_NONE && !commit)
+ mgmt_destroy_txn(&session->cfg_txn_id);
+
+ return ret;
+}
+
/**
* Send an error back to the FE client and cleanup any in-progress txn.
*/
@@ -1586,15 +1917,6 @@ mgmt_fe_adapter_cmt_stats_write(struct vty *vty,
mgmt_realtime_to_string(
&adapter->cmt_stats.txn_create_start,
buf, sizeof(buf)));
- vty_out(vty,
-#ifdef MGMTD_LOCAL_VALIDATIONS_ENABLED
- " Send-Config Start: \t\t%s\n",
-#else
- " Send-Config-Validate Start: \t%s\n",
-#endif
- mgmt_realtime_to_string(
- &adapter->cmt_stats.send_cfg_start, buf,
- sizeof(buf)));
vty_out(vty, " Apply-Config Start: \t\t%s\n",
mgmt_realtime_to_string(
&adapter->cmt_stats.apply_cfg_start,
diff --git a/mgmtd/mgmt_fe_adapter.h b/mgmtd/mgmt_fe_adapter.h
index 2150f86..61d6cfa 100644
--- a/mgmtd/mgmt_fe_adapter.h
+++ b/mgmtd/mgmt_fe_adapter.h
@@ -24,7 +24,6 @@ struct mgmt_commit_stats {
#endif
struct timeval prep_cfg_start;
struct timeval txn_create_start;
- struct timeval send_cfg_start;
struct timeval apply_cfg_start;
struct timeval apply_cfg_end;
struct timeval txn_del_start;
@@ -164,6 +163,46 @@ mgmt_fe_adapter_send_tree_data(uint64_t session_id, uint64_t txn_id,
int partial_error, bool short_circuit_ok);
/**
+ * Send RPC reply back to client.
+ *
+ * This also cleans up and frees the transaction.
+ *
+ * Args:
+ * session_id: the session.
+ * txn_id: the txn_id this data pertains to
+ * req_id: the req id for the rpc message
+ * result_type: the format of the result data.
+ * result: the results.
+ *
+ * Return:
+ * the return value from the underlying send function.
+ */
+extern int mgmt_fe_adapter_send_rpc_reply(uint64_t session_id, uint64_t txn_id,
+ uint64_t req_id,
+ LYD_FORMAT result_type,
+ const struct lyd_node *result);
+
+/**
+ * Send edit reply back to client. If error is not 0, a native error is sent.
+ *
+ * This also cleans up and frees the transaction.
+ *
+ * Args:
+ * session_id: the session.
+ * txn_id: the txn_id this data pertains to
+ * req_id: the req id for the edit message
+ * unlock: implicit-lock flag was set in the request
+ * commit: implicit-commit flag was set in the request
+ * xpath: the xpath of the data node that was created
+ * error: the error code, zero for successful request
+ * errstr: the error string, if error is non-zero
+ */
+extern int mgmt_fe_adapter_send_edit_reply(uint64_t session_id, uint64_t txn_id,
+ uint64_t req_id, bool unlock,
+ bool commit, const char *xpath,
+ int16_t error, const char *errstr);
+
+/**
* Send an error back to the FE client using native messaging.
*
* This also cleans up and frees the transaction.
diff --git a/mgmtd/mgmt_main.c b/mgmtd/mgmt_main.c
index cce16f5..e181d0d 100644
--- a/mgmtd/mgmt_main.c
+++ b/mgmtd/mgmt_main.c
@@ -10,6 +10,7 @@
#include "lib/version.h"
#include "routemap.h"
#include "filter.h"
+#include "keychain.h"
#include "libfrr.h"
#include "frr_pthread.h"
#include "mgmtd/mgmt.h"
@@ -185,6 +186,8 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
&frr_zebra_cli_info,
&zebra_route_map_info,
+ &ietf_key_chain_cli_info,
+ &ietf_key_chain_deviation_info,
#ifdef HAVE_RIPD
&frr_ripd_cli_info,
@@ -199,20 +202,20 @@ static const struct frr_yang_module_info *const mgmt_yang_modules[] = {
/* clang-format off */
FRR_DAEMON_INFO(mgmtd, MGMTD,
- .vty_port = MGMTD_VTY_PORT,
- .proghelp = "FRR Management Daemon.",
+ .vty_port = MGMTD_VTY_PORT,
+ .proghelp = "FRR Management Daemon.",
- .signals = mgmt_signals,
- .n_signals = array_size(mgmt_signals),
+ .signals = mgmt_signals,
+ .n_signals = array_size(mgmt_signals),
- .privs = &mgmt_privs,
+ .privs = &mgmt_privs,
- .yang_modules = mgmt_yang_modules,
- .n_yang_modules = array_size(mgmt_yang_modules),
+ .yang_modules = mgmt_yang_modules,
+ .n_yang_modules = array_size(mgmt_yang_modules),
- /* avoid libfrr trying to read our config file for us */
- .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG,
-);
+ /* avoid libfrr trying to read our config file for us */
+ .flags = FRR_MANUAL_VTY_START | FRR_NO_SPLIT_CONFIG,
+ );
/* clang-format on */
#define DEPRECATED_OPTIONS ""
diff --git a/mgmtd/mgmt_memory.c b/mgmtd/mgmt_memory.c
index 0fce61a..72ccca0 100644
--- a/mgmtd/mgmt_memory.c
+++ b/mgmtd/mgmt_memory.c
@@ -20,6 +20,7 @@
DEFINE_MGROUP(MGMTD, "mgmt");
DEFINE_MTYPE(MGMTD, MGMTD, "instance");
DEFINE_MTYPE(MGMTD, MGMTD_XPATH, "xpath regex");
+DEFINE_MTYPE(MGMTD, MGMTD_ERR, "error");
DEFINE_MTYPE(MGMTD, MGMTD_BE_ADPATER, "backend adapter");
DEFINE_MTYPE(MGMTD, MGMTD_FE_ADPATER, "frontend adapter");
DEFINE_MTYPE(MGMTD, MGMTD_FE_SESSION, "frontend session");
@@ -30,5 +31,6 @@ DEFINE_MTYPE(MGMTD, MGMTD_TXN_COMMCFG_REQ, "txn commit-config requests");
DEFINE_MTYPE(MGMTD, MGMTD_TXN_GETDATA_REQ, "txn get-data requests");
DEFINE_MTYPE(MGMTD, MGMTD_TXN_GETDATA_REPLY, "txn get-data replies");
DEFINE_MTYPE(MGMTD, MGMTD_TXN_GETTREE_REQ, "txn get-tree requests");
+DEFINE_MTYPE(MGMTD, MGMTD_TXN_RPC_REQ, "txn rpc requests");
DEFINE_MTYPE(MGMTD, MGMTD_TXN_CFG_BATCH, "txn config batches");
DEFINE_MTYPE(MGMTD, MGMTD_CMT_INFO, "commit info");
diff --git a/mgmtd/mgmt_memory.h b/mgmtd/mgmt_memory.h
index d5b6aa6..e28586e 100644
--- a/mgmtd/mgmt_memory.h
+++ b/mgmtd/mgmt_memory.h
@@ -14,6 +14,7 @@
DECLARE_MGROUP(MGMTD);
DECLARE_MTYPE(MGMTD);
DECLARE_MTYPE(MGMTD_XPATH);
+DECLARE_MTYPE(MGMTD_ERR);
DECLARE_MTYPE(MGMTD_BE_ADPATER);
DECLARE_MTYPE(MGMTD_FE_ADPATER);
DECLARE_MTYPE(MGMTD_FE_SESSION);
@@ -24,6 +25,7 @@ DECLARE_MTYPE(MGMTD_TXN_COMMCFG_REQ);
DECLARE_MTYPE(MGMTD_TXN_GETDATA_REQ);
DECLARE_MTYPE(MGMTD_TXN_GETDATA_REPLY);
DECLARE_MTYPE(MGMTD_TXN_GETTREE_REQ);
+DECLARE_MTYPE(MGMTD_TXN_RPC_REQ);
DECLARE_MTYPE(MGMTD_TXN_CFG_BATCH);
DECLARE_MTYPE(MGMTD_BE_ADAPTER_MSG_BUF);
DECLARE_MTYPE(MGMTD_CMT_INFO);
diff --git a/mgmtd/mgmt_testc.c b/mgmtd/mgmt_testc.c
index 7e3ded8..8bb07ed 100644
--- a/mgmtd/mgmt_testc.c
+++ b/mgmtd/mgmt_testc.c
@@ -18,6 +18,7 @@
/* ---------------- */
static void async_notification(struct nb_cb_notify_args *args);
+static int rpc_callback(struct nb_cb_rpc_args *args);
static void sigusr1(void);
static void sigint(void);
@@ -87,6 +88,10 @@ static const struct frr_yang_module_info frr_ripd_info = {
.cbs.notify = async_notification,
},
{
+ .xpath = "/frr-ripd:clear-rip-route",
+ .cbs.rpc = rpc_callback,
+ },
+ {
.xpath = NULL,
}
}
@@ -113,6 +118,7 @@ FRR_DAEMON_INFO(mgmtd_testc, MGMTD_TESTC,
/* clang-format on */
const char **__notif_xpaths;
+const char **__rpc_xpaths;
struct mgmt_be_client_cbs __client_cbs = {};
struct event *event_timeout;
@@ -133,8 +139,11 @@ static void sigusr1(void)
static void quit(int exit_code)
{
EVENT_OFF(event_timeout);
- frr_fini();
darr_free(__client_cbs.notif_xpaths);
+ darr_free(__client_cbs.rpc_xpaths);
+
+ frr_fini();
+
exit(exit_code);
}
@@ -150,6 +159,12 @@ static void timeout(struct event *event)
quit(1);
}
+static void success(struct event *event)
+{
+ zlog_notice("Success, exiting");
+ quit(0);
+}
+
static void async_notification(struct nb_cb_notify_args *args)
{
zlog_notice("Received YANG notification");
@@ -161,6 +176,23 @@ static void async_notification(struct nb_cb_notify_args *args)
quit(0);
}
+static int rpc_callback(struct nb_cb_rpc_args *args)
+{
+ const char *vrf = NULL;
+
+ zlog_notice("Received YANG RPC");
+
+ if (yang_dnode_exists(args->input, "vrf"))
+ vrf = yang_dnode_get_string(args->input, "vrf");
+
+ printf("{\"frr-ripd:clear-rip-route\": {\"vrf\": \"%s\"}}\n", vrf);
+
+ event_cancel(&event_timeout);
+ event_add_timer(master, success, NULL, 1, NULL);
+
+ return 0;
+}
+
int main(int argc, char **argv)
{
int f_listen = 0;
@@ -215,6 +247,10 @@ int main(int argc, char **argv)
__client_cbs.nnotif_xpaths = darr_len(__notif_xpaths);
}
+ darr_push(__rpc_xpaths, "/frr-ripd:clear-rip-route");
+ __client_cbs.rpc_xpaths = __rpc_xpaths;
+ __client_cbs.nrpc_xpaths = darr_len(__rpc_xpaths);
+
mgmt_be_client = mgmt_be_client_create("mgmtd-testc", &__client_cbs, 0,
master);
diff --git a/mgmtd/mgmt_txn.c b/mgmtd/mgmt_txn.c
index c1cb33f..0f0cccb 100644
--- a/mgmtd/mgmt_txn.c
+++ b/mgmtd/mgmt_txn.c
@@ -29,8 +29,8 @@ enum mgmt_txn_event {
MGMTD_TXN_PROC_COMMITCFG,
MGMTD_TXN_PROC_GETCFG,
MGMTD_TXN_PROC_GETTREE,
+ MGMTD_TXN_PROC_RPC,
MGMTD_TXN_COMMITCFG_TIMEOUT,
- MGMTD_TXN_GETTREE_TIMEOUT,
};
PREDECL_LIST(mgmt_txn_reqs);
@@ -49,7 +49,6 @@ struct mgmt_set_cfg_req {
enum mgmt_commit_phase {
MGMTD_COMMIT_PHASE_PREPARE_CFG = 0,
MGMTD_COMMIT_PHASE_TXN_CREATE,
- MGMTD_COMMIT_PHASE_SEND_CFG,
MGMTD_COMMIT_PHASE_APPLY_CFG,
MGMTD_COMMIT_PHASE_TXN_DELETE,
MGMTD_COMMIT_PHASE_MAX
@@ -62,8 +61,6 @@ static inline const char *mgmt_commit_phase2str(enum mgmt_commit_phase cmt_phase
return "PREP-CFG";
case MGMTD_COMMIT_PHASE_TXN_CREATE:
return "CREATE-TXN";
- case MGMTD_COMMIT_PHASE_SEND_CFG:
- return "SEND-CFG";
case MGMTD_COMMIT_PHASE_APPLY_CFG:
return "APPLY-CFG";
case MGMTD_COMMIT_PHASE_TXN_DELETE:
@@ -95,6 +92,11 @@ DECLARE_LIST(mgmt_txn_batches, struct mgmt_txn_be_cfg_batch, list_linkage);
#define FOREACH_TXN_CFG_BATCH_IN_LIST(list, batch) \
frr_each_safe (mgmt_txn_batches, list, batch)
+struct mgmt_edit_req {
+ char xpath_created[XPATH_MAXLEN];
+ bool unlock;
+};
+
struct mgmt_commit_cfg_req {
Mgmtd__DatastoreId src_ds_id;
struct mgmt_ds_ctx *src_ds_ctx;
@@ -113,6 +115,12 @@ struct mgmt_commit_cfg_req {
enum mgmt_commit_phase be_phase[MGMTD_BE_CLIENT_ID_MAX];
/*
+ * Additional information when the commit is triggered by native edit
+ * request.
+ */
+ struct mgmt_edit_req *edit;
+
+ /*
* Set of config changes to commit. This is used only
* when changes are NOT to be determined by comparing
* candidate and running DSs. This is typically used
@@ -181,6 +189,15 @@ struct txn_req_get_tree {
struct lyd_node *client_results; /* result tree from clients */
};
+struct txn_req_rpc {
+ char *xpath; /* xpath of rpc/action to invoke */
+ uint64_t sent_clients; /* Bitmask of clients sent req to */
+ uint64_t recv_clients; /* Bitmask of clients recv reply from */
+ uint8_t result_type; /* LYD_FORMAT for results */
+ char *errstr; /* error string */
+ struct lyd_node *client_results; /* result tree from clients */
+};
+
struct mgmt_txn_req {
struct mgmt_txn_ctx *txn;
enum mgmt_txn_event req_event;
@@ -189,6 +206,7 @@ struct mgmt_txn_req {
struct mgmt_set_cfg_req *set_cfg;
struct mgmt_get_data_req *get_data;
struct txn_req_get_tree *get_tree;
+ struct txn_req_rpc *rpc;
struct mgmt_commit_cfg_req commit_cfg;
} req;
@@ -214,6 +232,7 @@ struct mgmt_txn_ctx {
struct event *proc_get_tree;
struct event *comm_cfg_timeout;
struct event *get_tree_timeout;
+ struct event *rpc_timeout;
struct event *clnup;
/* List of backend adapters involved in this transaction */
@@ -246,6 +265,10 @@ struct mgmt_txn_ctx {
*/
struct mgmt_txn_reqs_head get_tree_reqs;
/*
+ * List of pending rpc requests.
+ */
+ struct mgmt_txn_reqs_head rpc_reqs;
+ /*
* There will always be one commit-config allowed for a given
* transaction/session. No need to maintain lists for it.
*/
@@ -409,8 +432,16 @@ static struct mgmt_txn_req *mgmt_txn_req_alloc(struct mgmt_txn_ctx *txn,
" session-id: %" PRIu64,
txn_req->req_id, txn->txn_id, txn->session_id);
break;
+ case MGMTD_TXN_PROC_RPC:
+ txn_req->req.rpc = XCALLOC(MTYPE_MGMTD_TXN_RPC_REQ,
+ sizeof(struct txn_req_rpc));
+ assert(txn_req->req.rpc);
+ mgmt_txn_reqs_add_tail(&txn->rpc_reqs, txn_req);
+ __dbg("Added a new RPC req-id: %" PRIu64 " txn-id: %" PRIu64
+ " session-id: %" PRIu64,
+ txn_req->req_id, txn->txn_id, txn->session_id);
+ break;
case MGMTD_TXN_COMMITCFG_TIMEOUT:
- case MGMTD_TXN_GETTREE_TIMEOUT:
break;
}
@@ -449,6 +480,8 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req)
cleanup = (ccreq->phase >= MGMTD_COMMIT_PHASE_TXN_CREATE &&
ccreq->phase < MGMTD_COMMIT_PHASE_TXN_DELETE);
+ XFREE(MTYPE_MGMTD_TXN_REQ, ccreq->edit);
+
FOREACH_MGMTD_BE_CLIENT_ID (id) {
/*
* Send TXN_DELETE to cleanup state for this
@@ -498,8 +531,16 @@ static void mgmt_txn_req_free(struct mgmt_txn_req **txn_req)
XFREE(MTYPE_MGMTD_XPATH, (*txn_req)->req.get_tree->xpath);
XFREE(MTYPE_MGMTD_TXN_GETTREE_REQ, (*txn_req)->req.get_tree);
break;
+ case MGMTD_TXN_PROC_RPC:
+ __dbg("Deleting RPC req-id: %" PRIu64 " txn-id: %" PRIu64,
+ (*txn_req)->req_id, (*txn_req)->txn->txn_id);
+ req_list = &(*txn_req)->txn->rpc_reqs;
+ lyd_free_all((*txn_req)->req.rpc->client_results);
+ XFREE(MTYPE_MGMTD_ERR, (*txn_req)->req.rpc->errstr);
+ XFREE(MTYPE_MGMTD_XPATH, (*txn_req)->req.rpc->xpath);
+ XFREE(MTYPE_MGMTD_TXN_RPC_REQ, (*txn_req)->req.rpc);
+ break;
case MGMTD_TXN_COMMITCFG_TIMEOUT:
- case MGMTD_TXN_GETTREE_TIMEOUT:
break;
}
@@ -610,7 +651,8 @@ static void mgmt_txn_process_set_cfg(struct event *thread)
->dst_ds_id,
txn_req->req.set_cfg
->dst_ds_ctx,
- false, false, true);
+ false, false, true,
+ NULL);
if (mm->perf_stats_en)
gettimeofday(&cmt_stats->last_start, NULL);
@@ -661,7 +703,8 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
* b/c right now that is special cased.. that special casing should be
* removed; however...
*/
- if (!txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
+ if (!txn->commit_cfg_req->req.commit_cfg.edit &&
+ !txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
!txn->commit_cfg_req->req.commit_cfg.rollback &&
mgmt_fe_send_commit_cfg_reply(txn->session_id, txn->txn_id,
txn->commit_cfg_req->req.commit_cfg
@@ -677,7 +720,8 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
txn->txn_id, txn->session_id);
}
- if (txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
+ if (!txn->commit_cfg_req->req.commit_cfg.edit &&
+ txn->commit_cfg_req->req.commit_cfg.implicit && txn->session_id &&
!txn->commit_cfg_req->req.commit_cfg.rollback &&
mgmt_fe_send_set_cfg_reply(txn->session_id, txn->txn_id,
txn->commit_cfg_req->req.commit_cfg
@@ -691,6 +735,21 @@ static int mgmt_txn_send_commit_cfg_reply(struct mgmt_txn_ctx *txn,
txn->txn_id, txn->session_id);
}
+ if (txn->commit_cfg_req->req.commit_cfg.edit &&
+ mgmt_fe_adapter_send_edit_reply(txn->session_id, txn->txn_id,
+ txn->commit_cfg_req->req_id,
+ txn->commit_cfg_req->req.commit_cfg
+ .edit->unlock,
+ true,
+ txn->commit_cfg_req->req.commit_cfg
+ .edit->xpath_created,
+ success ? 0 : -1,
+ error_if_any) != 0) {
+ __log_err("Failed to send EDIT-REPLY txn-id: %" PRIu64
+ " session-id: %" PRIu64,
+ txn->txn_id, txn->session_id);
+ }
+
if (success) {
/* Stop the commit-timeout timer */
/* XXX why only on success? */
@@ -855,7 +914,9 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
__dbg("XPATH: %s, Value: '%s'", xpath, value ? value : "NIL");
- clients = mgmt_be_interested_clients(xpath, true);
+ clients =
+ mgmt_be_interested_clients(xpath,
+ MGMT_BE_XPATH_SUBSCR_TYPE_CFG);
chg_clients = 0;
@@ -919,8 +980,8 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
}
if (!chg_clients)
- __log_err("No connected daemon is interested in XPATH %s",
- xpath);
+ __dbg("Daemons interested in XPATH are not currently connected: %s",
+ xpath);
cmtcfg_req->clients |= chg_clients;
@@ -931,7 +992,7 @@ static int mgmt_txn_create_config_batches(struct mgmt_txn_req *txn_req,
if (!num_chgs) {
(void)mgmt_txn_send_commit_cfg_reply(txn_req->txn,
MGMTD_NO_CFG_CHANGES,
- "No changes found to commit!");
+ "No connected daemons interested in changes");
return -1;
}
@@ -1183,13 +1244,10 @@ static int mgmt_txn_send_be_cfg_data(struct mgmt_txn_ctx *txn,
cmtcfg_req->cmt_stats->last_num_cfgdata_reqs++;
}
- cmtcfg_req->be_phase[adapter->id] = MGMTD_COMMIT_PHASE_SEND_CFG;
-
/*
- * This could be the last Backend Client to send CFGDATA_CREATE_REQ to.
- * Try moving the commit to next phase.
+ * We don't advance the phase here, instead that is driven by the
+ * cfg_reply.
*/
- mgmt_try_move_commit_to_next_phase(txn, cmtcfg_req);
return 0;
}
@@ -1284,6 +1342,33 @@ static int txn_get_tree_data_done(struct mgmt_txn_ctx *txn,
return ret;
}
+static int txn_rpc_done(struct mgmt_txn_ctx *txn, struct mgmt_txn_req *txn_req)
+{
+ struct txn_req_rpc *rpc = txn_req->req.rpc;
+ uint64_t req_id = txn_req->req_id;
+
+ /* cancel timer and send reply onward */
+ EVENT_OFF(txn->rpc_timeout);
+
+ if (rpc->errstr)
+ mgmt_fe_adapter_txn_error(txn->txn_id, req_id, false, -1,
+ rpc->errstr);
+ else if (mgmt_fe_adapter_send_rpc_reply(txn->session_id, txn->txn_id,
+ req_id, rpc->result_type,
+ rpc->client_results)) {
+ __log_err("Error sending the results of RPC for txn-id %" PRIu64
+ " req_id %" PRIu64 " to requested type %u",
+ txn->txn_id, req_id, rpc->result_type);
+
+ (void)mgmt_fe_adapter_txn_error(txn->txn_id, req_id, false, -1,
+ "Error converting results of RPC");
+ }
+
+ /* we're done with the request */
+ mgmt_txn_req_free(&txn_req);
+
+ return 0;
+}
static void txn_get_tree_timeout(struct event *thread)
{
@@ -1311,6 +1396,31 @@ static void txn_get_tree_timeout(struct event *thread)
txn_get_tree_data_done(txn, txn_req);
}
+static void txn_rpc_timeout(struct event *thread)
+{
+ struct mgmt_txn_ctx *txn;
+ struct mgmt_txn_req *txn_req;
+
+ txn_req = (struct mgmt_txn_req *)EVENT_ARG(thread);
+ txn = txn_req->txn;
+
+ assert(txn);
+ assert(txn->type == MGMTD_TXN_TYPE_RPC);
+
+ __log_err("Backend timeout txn-id: %" PRIu64 " ending rpc", txn->txn_id);
+
+ /*
+ * Send a get-tree data reply.
+ *
+ * NOTE: The transaction cleanup will be triggered from Front-end
+ * adapter.
+ */
+
+ txn_req->req.rpc->errstr =
+ XSTRDUP(MTYPE_MGMTD_ERR, "Operation on the backend timed-out");
+ txn_rpc_done(txn, txn_req);
+}
+
/*
* Send CFG_APPLY_REQs to all the backend client.
*
@@ -1390,24 +1500,6 @@ static void mgmt_txn_process_commit_cfg(struct event *thread)
*/
mgmt_txn_send_be_txn_create(txn);
break;
- case MGMTD_COMMIT_PHASE_SEND_CFG:
- if (mm->perf_stats_en)
- gettimeofday(&cmtcfg_req->cmt_stats->send_cfg_start,
- NULL);
- /*
- * All CFGDATA_CREATE_REQ should have been sent to
- * Backend by now.
- */
-#ifndef MGMTD_LOCAL_VALIDATIONS_ENABLED
- __dbg("txn-id: %" PRIu64 " session-id: %" PRIu64
- " trigger sending CFG_VALIDATE_REQ to all backend clients",
- txn->txn_id, txn->session_id);
-#else /* ifndef MGMTD_LOCAL_VALIDATIONS_ENABLED */
- __dbg("txn-id: %" PRIu64 " session-id: %" PRIu64
- " trigger sending CFG_APPLY_REQ to all backend clients",
- txn->txn_id, txn->session_id);
-#endif /* ifndef MGMTD_LOCAL_VALIDATIONS_ENABLED */
- break;
case MGMTD_COMMIT_PHASE_APPLY_CFG:
if (mm->perf_stats_en)
gettimeofday(&cmtcfg_req->cmt_stats->apply_cfg_start,
@@ -1512,7 +1604,7 @@ static void mgmt_txn_send_getcfg_reply_data(struct mgmt_txn_req *txn_req,
case MGMTD_TXN_PROC_SETCFG:
case MGMTD_TXN_PROC_COMMITCFG:
case MGMTD_TXN_PROC_GETTREE:
- case MGMTD_TXN_GETTREE_TIMEOUT:
+ case MGMTD_TXN_PROC_RPC:
case MGMTD_TXN_COMMITCFG_TIMEOUT:
__log_err("Invalid Txn-Req-Event %u", txn_req->req_event);
break;
@@ -1718,6 +1810,7 @@ static struct mgmt_txn_ctx *mgmt_txn_create_new(uint64_t session_id,
mgmt_txn_reqs_init(&txn->set_cfg_reqs);
mgmt_txn_reqs_init(&txn->get_cfg_reqs);
mgmt_txn_reqs_init(&txn->get_tree_reqs);
+ mgmt_txn_reqs_init(&txn->rpc_reqs);
txn->commit_cfg_req = NULL;
txn->refcount = 0;
if (!mgmt_txn_mm->next_txn_id)
@@ -1886,12 +1979,8 @@ static void mgmt_txn_register_event(struct mgmt_txn_ctx *txn,
MGMTD_TXN_CFG_COMMIT_MAX_DELAY_SEC,
&txn->comm_cfg_timeout);
break;
- case MGMTD_TXN_GETTREE_TIMEOUT:
- event_add_timer(mgmt_txn_tm, txn_get_tree_timeout, txn,
- MGMTD_TXN_GET_TREE_MAX_DELAY_SEC,
- &txn->get_tree_timeout);
- break;
case MGMTD_TXN_PROC_GETTREE:
+ case MGMTD_TXN_PROC_RPC:
assert(!"code bug do not register this event");
break;
}
@@ -2044,7 +2133,7 @@ int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
Mgmtd__DatastoreId dst_ds_id,
struct mgmt_ds_ctx *dst_ds_ctx,
bool validate_only, bool abort,
- bool implicit)
+ bool implicit, struct mgmt_edit_req *edit)
{
struct mgmt_txn_ctx *txn;
struct mgmt_txn_req *txn_req;
@@ -2068,6 +2157,7 @@ int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
txn_req->req.commit_cfg.validate_only = validate_only;
txn_req->req.commit_cfg.abort = abort;
txn_req->req.commit_cfg.implicit = implicit;
+ txn_req->req.commit_cfg.edit = edit;
txn_req->req.commit_cfg.cmt_stats =
mgmt_fe_get_session_commit_stats(txn->session_id);
@@ -2451,6 +2541,110 @@ state:
return 0;
}
+int mgmt_txn_send_edit(uint64_t txn_id, uint64_t req_id,
+ Mgmtd__DatastoreId ds_id, struct mgmt_ds_ctx *ds_ctx,
+ Mgmtd__DatastoreId commit_ds_id,
+ struct mgmt_ds_ctx *commit_ds_ctx, bool unlock,
+ bool commit, LYD_FORMAT request_type, uint8_t flags,
+ uint8_t operation, const char *xpath, const char *data)
+{
+ struct mgmt_txn_ctx *txn;
+ struct mgmt_edit_req *edit;
+ struct nb_config *nb_config;
+ char errstr[BUFSIZ];
+ int ret;
+
+ txn = mgmt_txn_id2ctx(txn_id);
+ if (!txn)
+ return -1;
+
+ edit = XCALLOC(MTYPE_MGMTD_TXN_REQ, sizeof(struct mgmt_edit_req));
+
+ nb_config = mgmt_ds_get_nb_config(ds_ctx);
+ assert(nb_config);
+
+ ret = nb_candidate_edit_tree(nb_config, operation, request_type, xpath,
+ data, edit->xpath_created, errstr,
+ sizeof(errstr));
+ if (ret)
+ goto reply;
+
+ if (commit) {
+ edit->unlock = unlock;
+
+ mgmt_txn_send_commit_config_req(txn_id, req_id, ds_id, ds_ctx,
+ commit_ds_id, commit_ds_ctx,
+ false, false, true, edit);
+ return 0;
+ }
+reply:
+ mgmt_fe_adapter_send_edit_reply(txn->session_id, txn->txn_id, req_id,
+ unlock, commit, edit->xpath_created,
+ ret ? -1 : 0, errstr);
+
+ XFREE(MTYPE_MGMTD_TXN_REQ, edit);
+
+ return 0;
+}
+
+int mgmt_txn_send_rpc(uint64_t txn_id, uint64_t req_id, uint64_t clients,
+ LYD_FORMAT result_type, const char *xpath,
+ const char *data, size_t data_len)
+{
+ struct mgmt_txn_ctx *txn;
+ struct mgmt_txn_req *txn_req;
+ struct mgmt_msg_rpc *msg;
+ struct txn_req_rpc *rpc;
+ uint64_t id;
+ int ret;
+
+ txn = mgmt_txn_id2ctx(txn_id);
+ if (!txn)
+ return -1;
+
+ txn_req = mgmt_txn_req_alloc(txn, req_id, MGMTD_TXN_PROC_RPC);
+ rpc = txn_req->req.rpc;
+ rpc->xpath = XSTRDUP(MTYPE_MGMTD_XPATH, xpath);
+ rpc->result_type = result_type;
+
+ msg = mgmt_msg_native_alloc_msg(struct mgmt_msg_rpc, 0,
+ MTYPE_MSG_NATIVE_RPC);
+ msg->refer_id = txn_id;
+ msg->req_id = req_id;
+ msg->code = MGMT_MSG_CODE_RPC;
+ msg->request_type = result_type;
+
+ mgmt_msg_native_xpath_encode(msg, xpath);
+ if (data)
+ mgmt_msg_native_append(msg, data, data_len);
+
+ assert(clients);
+ FOREACH_BE_CLIENT_BITS (id, clients) {
+ ret = mgmt_be_send_native(id, msg);
+ if (ret) {
+ __log_err("Could not send rpc message to backend client %s",
+ mgmt_be_client_id2name(id));
+ continue;
+ }
+
+ __dbg("Sent rpc req to backend client %s",
+ mgmt_be_client_id2name(id));
+
+ /* record that we sent the request to the client */
+ rpc->sent_clients |= (1u << id);
+ }
+
+ mgmt_msg_native_free_msg(msg);
+
+ if (!rpc->sent_clients)
+ return txn_rpc_done(txn, txn_req);
+
+ event_add_timer(mgmt_txn_tm, txn_rpc_timeout, txn_req,
+ MGMTD_TXN_RPC_MAX_DELAY_SEC, &txn->rpc_timeout);
+
+ return 0;
+}
+
/*
* Error reply from the backend client.
*/
@@ -2461,6 +2655,7 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter,
enum mgmt_be_client_id id = adapter->id;
struct mgmt_txn_ctx *txn = mgmt_txn_id2ctx(txn_id);
struct txn_req_get_tree *get_tree;
+ struct txn_req_rpc *rpc;
struct mgmt_txn_req *txn_req;
if (!txn) {
@@ -2473,6 +2668,10 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter,
FOREACH_TXN_REQ_IN_LIST (&txn->get_tree_reqs, txn_req)
if (txn_req->req_id == req_id)
break;
+ if (!txn_req)
+ FOREACH_TXN_REQ_IN_LIST (&txn->rpc_reqs, txn_req)
+ if (txn_req->req_id == req_id)
+ break;
if (!txn_req) {
__log_err("Error reply from %s for txn-id %" PRIu64
" cannot find req_id %" PRIu64,
@@ -2493,13 +2692,23 @@ int mgmt_txn_notify_error(struct mgmt_be_client_adapter *adapter,
if (get_tree->recv_clients != get_tree->sent_clients)
return 0;
return txn_get_tree_data_done(txn, txn_req);
+ case MGMTD_TXN_PROC_RPC:
+ rpc = txn_req->req.rpc;
+ rpc->recv_clients |= (1u << id);
+ if (errstr) {
+ XFREE(MTYPE_MGMTD_ERR, rpc->errstr);
+ rpc->errstr = XSTRDUP(MTYPE_MGMTD_ERR, errstr);
+ }
+ /* check if done yet */
+ if (rpc->recv_clients != rpc->sent_clients)
+ return 0;
+ return txn_rpc_done(txn, txn_req);
/* non-native message events */
case MGMTD_TXN_PROC_SETCFG:
case MGMTD_TXN_PROC_COMMITCFG:
case MGMTD_TXN_PROC_GETCFG:
case MGMTD_TXN_COMMITCFG_TIMEOUT:
- case MGMTD_TXN_GETTREE_TIMEOUT:
default:
assert(!"non-native req event in native erorr path");
return -1;
@@ -2581,6 +2790,77 @@ int mgmt_txn_notify_tree_data_reply(struct mgmt_be_client_adapter *adapter,
return txn_get_tree_data_done(txn, txn_req);
}
+int mgmt_txn_notify_rpc_reply(struct mgmt_be_client_adapter *adapter,
+ struct mgmt_msg_rpc_reply *reply_msg,
+ size_t msg_len)
+{
+ uint64_t txn_id = reply_msg->refer_id;
+ uint64_t req_id = reply_msg->req_id;
+ enum mgmt_be_client_id id = adapter->id;
+ struct mgmt_txn_ctx *txn = mgmt_txn_id2ctx(txn_id);
+ struct mgmt_txn_req *txn_req;
+ struct txn_req_rpc *rpc;
+ struct lyd_node *tree;
+ size_t data_len = msg_len - sizeof(*reply_msg);
+ LY_ERR err = LY_SUCCESS;
+
+ if (!txn) {
+ __log_err("RPC reply from %s for a missing txn-id %" PRIu64,
+ adapter->name, txn_id);
+ return -1;
+ }
+
+ /* Find the request. */
+ FOREACH_TXN_REQ_IN_LIST (&txn->rpc_reqs, txn_req)
+ if (txn_req->req_id == req_id)
+ break;
+ if (!txn_req) {
+ __log_err("RPC reply from %s for txn-id %" PRIu64
+ " missing req_id %" PRIu64,
+ adapter->name, txn_id, req_id);
+ return -1;
+ }
+
+ rpc = txn_req->req.rpc;
+
+ tree = NULL;
+ if (data_len)
+ err = yang_parse_rpc(rpc->xpath, reply_msg->result_type,
+ reply_msg->data, true, &tree);
+ if (err) {
+ __log_err("RPC reply from %s for txn-id %" PRIu64
+ " req_id %" PRIu64 " error parsing result of type %u: %s",
+ adapter->name, txn_id, req_id, reply_msg->result_type,
+ ly_strerrcode(err));
+ }
+ if (!err && tree) {
+ if (!rpc->client_results)
+ rpc->client_results = tree;
+ else
+ err = lyd_merge_siblings(&rpc->client_results, tree,
+ LYD_MERGE_DESTRUCT);
+ if (err) {
+ __log_err("RPC reply from %s for txn-id %" PRIu64
+ " req_id %" PRIu64 " error merging result: %s",
+ adapter->name, txn_id, req_id,
+ ly_strerrcode(err));
+ }
+ }
+ if (err) {
+ XFREE(MTYPE_MGMTD_ERR, rpc->errstr);
+ rpc->errstr = XSTRDUP(MTYPE_MGMTD_ERR,
+ "Cannot parse result from the backend");
+ }
+
+ rpc->recv_clients |= (1u << id);
+
+ /* check if done yet */
+ if (rpc->recv_clients != rpc->sent_clients)
+ return 0;
+
+ return txn_rpc_done(txn, txn_req);
+}
+
void mgmt_txn_status_write(struct vty *vty)
{
struct mgmt_txn_ctx *txn;
diff --git a/mgmtd/mgmt_txn.h b/mgmtd/mgmt_txn.h
index b719832..b6ca288 100644
--- a/mgmtd/mgmt_txn.h
+++ b/mgmtd/mgmt_txn.h
@@ -21,6 +21,7 @@
#define MGMTD_TXN_CFG_COMMIT_MAX_DELAY_SEC 600
#define MGMTD_TXN_GET_TREE_MAX_DELAY_SEC 600
+#define MGMTD_TXN_RPC_MAX_DELAY_SEC 60
#define MGMTD_TXN_CLEANUP_DELAY_USEC 10
@@ -43,11 +44,13 @@
PREDECL_LIST(mgmt_txns);
struct mgmt_master;
+struct mgmt_edit_req;
enum mgmt_txn_type {
MGMTD_TXN_TYPE_NONE = 0,
MGMTD_TXN_TYPE_CONFIG,
- MGMTD_TXN_TYPE_SHOW
+ MGMTD_TXN_TYPE_SHOW,
+ MGMTD_TXN_TYPE_RPC,
};
static inline const char *mgmt_txn_type2str(enum mgmt_txn_type type)
@@ -59,6 +62,8 @@ static inline const char *mgmt_txn_type2str(enum mgmt_txn_type type)
return "CONFIG";
case MGMTD_TXN_TYPE_SHOW:
return "SHOW";
+ case MGMTD_TXN_TYPE_RPC:
+ return "RPC";
}
return "Unknown";
@@ -171,16 +176,17 @@ extern int mgmt_txn_send_set_config_req(uint64_t txn_id, uint64_t req_id,
* implicit
* TRUE if the commit is implicit, FALSE otherwise.
*
+ * edit
+ * Additional info when triggered from native edit request.
+ *
* Returns:
* 0 on success, -1 on failures.
*/
-extern int mgmt_txn_send_commit_config_req(uint64_t txn_id, uint64_t req_id,
- Mgmtd__DatastoreId src_ds_id,
- struct mgmt_ds_ctx *dst_ds_ctx,
- Mgmtd__DatastoreId dst_ds_id,
- struct mgmt_ds_ctx *src_ds_ctx,
- bool validate_only, bool abort,
- bool implicit);
+extern int mgmt_txn_send_commit_config_req(
+ uint64_t txn_id, uint64_t req_id, Mgmtd__DatastoreId src_ds_id,
+ struct mgmt_ds_ctx *dst_ds_ctx, Mgmtd__DatastoreId dst_ds_id,
+ struct mgmt_ds_ctx *src_ds_ctx, bool validate_only, bool abort,
+ bool implicit, struct mgmt_edit_req *edit);
/*
* Send get-{cfg,data} request to be processed later in transaction.
@@ -219,6 +225,50 @@ extern int mgmt_txn_send_get_tree_oper(uint64_t txn_id, uint64_t req_id,
uint32_t wd_options, bool simple_xpath,
const char *xpath);
+/**
+ * Send edit request.
+ *
+ * Args:
+ * txn_id: Transaction identifier.
+ * req_id: FE client request identifier.
+ * ds_id: Datastore ID.
+ * ds_ctx: Datastore context.
+ * commit_ds_id: Commit datastore ID.
+ * commit_ds_ctx: Commit datastore context.
+ * unlock: Unlock datastores after the edit.
+ * commit: Commit the candidate datastore after the edit.
+ * request_type: LYD_FORMAT request type.
+ * flags: option flags for the request.
+ * operation: The operation to perform.
+ * xpath: The xpath of data node to edit.
+ * data: The data tree.
+ */
+extern int
+mgmt_txn_send_edit(uint64_t txn_id, uint64_t req_id, Mgmtd__DatastoreId ds_id,
+ struct mgmt_ds_ctx *ds_ctx, Mgmtd__DatastoreId commit_ds_id,
+ struct mgmt_ds_ctx *commit_ds_ctx, bool unlock, bool commit,
+ LYD_FORMAT request_type, uint8_t flags, uint8_t operation,
+ const char *xpath, const char *data);
+
+/**
+ * Send RPC request.
+ *
+ * Args:
+ * txn_id: Transaction identifier.
+ * req_id: FE client request identifier.
+ * clients: Bitmask of clients to send RPC to.
+ * result_type: LYD_FORMAT result format.
+ * xpath: The xpath of the RPC.
+ * data: The input parameters data tree.
+ * data_len: The length of the input parameters data.
+ *
+ * Return:
+ * 0 on success.
+ */
+extern int mgmt_txn_send_rpc(uint64_t txn_id, uint64_t req_id, uint64_t clients,
+ LYD_FORMAT result_type, const char *xpath,
+ const char *data, size_t data_len);
+
/*
* Notifiy backend adapter on connection.
*/
@@ -285,6 +335,18 @@ extern int mgmt_txn_notify_tree_data_reply(struct mgmt_be_client_adapter *adapte
struct mgmt_msg_tree_data *data_msg,
size_t msg_len);
+/**
+ * Process a reply from a backend client to our RPC request
+ *
+ * Args:
+ * adapter: The adapter that received the result.
+ * reply_msg: The message from the backend.
+ * msg_len: Total length of the message.
+ */
+extern int mgmt_txn_notify_rpc_reply(struct mgmt_be_client_adapter *adapter,
+ struct mgmt_msg_rpc_reply *reply_msg,
+ size_t msg_len);
+
/*
* Dump transaction status to vty.
*/
diff --git a/mgmtd/mgmt_vty.c b/mgmtd/mgmt_vty.c
index bbc1077..8ccb463 100644
--- a/mgmtd/mgmt_vty.c
+++ b/mgmtd/mgmt_vty.c
@@ -12,6 +12,7 @@
#include "command.h"
#include "filter.h"
#include "json.h"
+#include "keychain.h"
#include "network.h"
#include "northbound_cli.h"
#include "routemap.h"
@@ -237,6 +238,79 @@ DEFPY(mgmt_replace_config_data, mgmt_replace_config_data_cmd,
return CMD_SUCCESS;
}
+DEFPY(mgmt_edit, mgmt_edit_cmd,
+ "mgmt edit {create|delete|merge|replace|remove}$op XPATH [json|xml]$fmt [lock$lock] [commit$commit] [DATA]",
+ MGMTD_STR
+ "Edit configuration data\n"
+ "Create data\n"
+ "Delete data\n"
+ "Merge data\n"
+ "Replace data\n"
+ "Remove data\n"
+ "XPath expression specifying the YANG data path\n"
+ "JSON input format (default)\n"
+ "XML input format\n"
+ "Lock the datastores automatically\n"
+ "Commit the changes automatically\n"
+ "Data tree\n")
+{
+ LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON;
+ uint8_t operation;
+ uint8_t flags = 0;
+
+ switch (op[2]) {
+ case 'e':
+ operation = NB_OP_CREATE_EXCL;
+ break;
+ case 'l':
+ operation = NB_OP_DELETE;
+ break;
+ case 'r':
+ operation = NB_OP_MODIFY;
+ break;
+ case 'p':
+ operation = NB_OP_REPLACE;
+ break;
+ case 'm':
+ operation = NB_OP_DESTROY;
+ break;
+ default:
+ vty_out(vty, "Invalid operation!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (!data && (operation == NB_OP_CREATE_EXCL ||
+ operation == NB_OP_MODIFY || operation == NB_OP_REPLACE)) {
+ vty_out(vty, "Data tree is missing!\n");
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+
+ if (lock)
+ flags |= EDIT_FLAG_IMPLICIT_LOCK;
+
+ if (commit)
+ flags |= EDIT_FLAG_IMPLICIT_COMMIT;
+
+ vty_mgmt_send_edit_req(vty, MGMT_MSG_DATASTORE_CANDIDATE, format, flags,
+ operation, xpath, data);
+ return CMD_SUCCESS;
+}
+
+DEFPY(mgmt_rpc, mgmt_rpc_cmd,
+ "mgmt rpc XPATH [json|xml]$fmt [DATA]",
+ MGMTD_STR
+ "Invoke RPC\n"
+ "XPath expression specifying the YANG data path\n"
+ "JSON input format (default)\n"
+ "XML input format\n"
+ "Input data tree\n")
+{
+ LYD_FORMAT format = (fmt && fmt[0] == 'x') ? LYD_XML : LYD_JSON;
+
+ vty_mgmt_send_rpc_req(vty, format, xpath, data);
+ return CMD_SUCCESS;
+}
+
DEFPY(show_mgmt_get_config, show_mgmt_get_config_cmd,
"show mgmt get-config [candidate|operational|running]$dsname WORD$path",
SHOW_STR MGMTD_STR
@@ -600,6 +674,7 @@ void mgmt_vty_init(void)
filter_cli_init();
route_map_cli_init();
affinity_map_init();
+ keychain_cli_init();
/*
* Initialize command handling from VTYSH connection.
@@ -641,6 +716,8 @@ void mgmt_vty_init(void)
install_element(CONFIG_NODE, &mgmt_delete_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_remove_config_data_cmd);
install_element(CONFIG_NODE, &mgmt_replace_config_data_cmd);
+ install_element(CONFIG_NODE, &mgmt_edit_cmd);
+ install_element(CONFIG_NODE, &mgmt_rpc_cmd);
install_element(CONFIG_NODE, &mgmt_load_config_cmd);
install_element(CONFIG_NODE, &mgmt_save_config_cmd);
install_element(CONFIG_NODE, &mgmt_rollback_cmd);
diff --git a/mgmtd/subdir.am b/mgmtd/subdir.am
index 1624c6e..14544c4 100644
--- a/mgmtd/subdir.am
+++ b/mgmtd/subdir.am
@@ -16,6 +16,7 @@ clippy_scan += \
lib_LTLIBRARIES += mgmtd/libmgmt_be_nb.la
mgmtd_libmgmt_be_nb_la_SOURCES = \
+ mgmtd/mgmt_be_nb.c \
zebra/zebra_cli.c \
# end
nodist_mgmtd_libmgmt_be_nb_la_SOURCES = \
@@ -61,7 +62,6 @@ mgmtd_mgmtd_SOURCES = \
nodist_mgmtd_mgmtd_SOURCES = \
yang/frr-zebra.yang.c \
yang/frr-zebra-route-map.yang.c \
- yang/ietf/ietf-netconf-acm.yang.c \
yang/ietf/ietf-netconf.yang.c \
yang/ietf/ietf-netconf-with-defaults.yang.c \
# nothing
diff --git a/mlag/mlag_pb.c b/mlag/mlag_pb.c
new file mode 100644
index 0000000..01c4f0b
--- /dev/null
+++ b/mlag/mlag_pb.c
@@ -0,0 +1,9 @@
+// SPDX-License-Identifier: ISC
+/*
+ * libmlag_pb library stub
+ */
+
+#include "config.h"
+#include "xref.h"
+
+XREF_SETUP();
diff --git a/mlag/subdir.am b/mlag/subdir.am
index 376eea8..aa30d33 100644
--- a/mlag/subdir.am
+++ b/mlag/subdir.am
@@ -5,6 +5,7 @@ endif
mlag_libmlag_pb_la_LDFLAGS = $(LIB_LDFLAGS) -version-info 0:0:0
mlag_libmlag_pb_la_CPPFLAGS = $(AM_CPPFLAGS) $(PROTOBUF_C_CFLAGS)
mlag_libmlag_pb_la_SOURCES = \
+ mlag/mlag_pb.c \
# end
nodist_mlag_libmlag_pb_la_SOURCES = \
diff --git a/nhrpd/debug.h b/nhrpd/debug.h
index f2c7022..d5c00ad 100644
--- a/nhrpd/debug.h
+++ b/nhrpd/debug.h
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include "log.h"
#define NHRP_DEBUG_COMMON (1 << 0)
diff --git a/nhrpd/nhrp_nhs.c b/nhrpd/nhrp_nhs.c
index acd3b7d..f779f93 100644
--- a/nhrpd/nhrp_nhs.c
+++ b/nhrpd/nhrp_nhs.c
@@ -169,9 +169,15 @@ static void nhrp_reg_send_req(struct event *t)
struct nhrp_cie_header *cie;
if (!nhrp_peer_check(r->peer, 2)) {
- debugf(NHRP_DEBUG_COMMON, "NHS: Waiting link for %pSU",
- &r->peer->vc->remote.nbma);
- event_add_timer(master, nhrp_reg_send_req, r, 120,
+ int renewtime = if_ad->holdtime / 4;
+ /* RFC 2332 5.2.0.1 says "a retry is sent after an appropriate
+ * interval." Using holdtime/4, to be shorter than
+ * recommended renew time (holdtime/3), see RFC2332 Sec 5.2.3
+ */
+ debugf(NHRP_DEBUG_COMMON,
+ "NHS: Waiting link for %pSU, retrying in %d seconds",
+ &r->peer->vc->remote.nbma, renewtime);
+ event_add_timer(master, nhrp_reg_send_req, r, renewtime,
&r->t_register);
return;
}
diff --git a/nhrpd/os.h b/nhrpd/os.h
index 2b9e07f..3f3b0de 100644
--- a/nhrpd/os.h
+++ b/nhrpd/os.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
int os_socket(void);
int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
diff --git a/nhrpd/reqid.c b/nhrpd/reqid.c
index 738e935..c2f5d24 100644
--- a/nhrpd/reqid.c
+++ b/nhrpd/reqid.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include "zebra.h"
#include "hash.h"
#include "nhrpd.h"
diff --git a/nhrpd/vici.h b/nhrpd/vici.h
index f2ad3a9..8a8011f 100644
--- a/nhrpd/vici.h
+++ b/nhrpd/vici.h
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
enum vici_type_t {
VICI_START = 0,
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index ef780af..0c5be29 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -553,9 +553,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
lsa_header = (struct ospf6_lsa_header *)buffer;
if (route->type == OSPF6_DEST_TYPE_ROUTER) {
- router_lsa = (struct ospf6_inter_router_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ router_lsa = (struct ospf6_inter_router_lsa *)
+ ospf6_lsa_header_end(lsa_header);
p = (caddr_t)router_lsa + sizeof(struct ospf6_inter_router_lsa);
/* Fill Inter-Area-Router-LSA */
@@ -566,9 +565,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
router_lsa->router_id = ADV_ROUTER_IN_PREFIX(&route->prefix);
type = htons(OSPF6_LSTYPE_INTER_ROUTER);
} else {
- prefix_lsa = (struct ospf6_inter_prefix_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ prefix_lsa = (struct ospf6_inter_prefix_lsa *)
+ ospf6_lsa_header_end(lsa_header);
p = (caddr_t)prefix_lsa + sizeof(struct ospf6_inter_prefix_lsa);
/* Fill Inter-Area-Prefix-LSA */
@@ -1018,9 +1016,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
oa->name);
}
- prefix_lsa =
- (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
- lsa->header);
+ prefix_lsa = (struct ospf6_inter_prefix_lsa *)
+ ospf6_lsa_header_end(lsa->header);
prefix.family = AF_INET6;
prefix.prefixlen = prefix_lsa->prefix.prefix_length;
ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
@@ -1039,11 +1036,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
oa->name);
}
- router_lsa =
- (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
- lsa->header);
- ospf6_linkstate_prefix(router_lsa->router_id, htonl(0),
- &prefix);
+ router_lsa = (struct ospf6_inter_router_lsa *)
+ ospf6_lsa_header_end(lsa->header);
+ ospf6_linkstate_prefix(router_lsa->router_id, htonl(0), &prefix);
if (is_debug)
inet_ntop(AF_INET, &router_lsa->router_id, buf,
sizeof(buf));
@@ -1275,8 +1270,6 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
continue;
}
- list_delete_all_node(old_route->nh_list);
- ospf6_route_copy_nexthops(old_route, route);
old_entry_updated = true;
for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode,
@@ -1330,6 +1323,15 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
}
}
+ /* We added a path or updated a path's nexthops above,
+ * recompute (old) route nexthops by merging all path nexthops
+ */
+ list_delete_all_node(old_route->nh_list);
+ for (ALL_LIST_ELEMENTS_RO(old_route->paths, anode, o_path)) {
+ ospf6_merge_nexthops(old_route->nh_list,
+ o_path->nh_list);
+ }
+
if (is_debug)
zlog_debug(
"%s: Update route: %s %p old cost %u new cost %u nh %u",
@@ -1427,9 +1429,8 @@ static char *ospf6_inter_area_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
char tbuf[16];
if (lsa != NULL) {
- prefix_lsa =
- (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
- lsa->header);
+ prefix_lsa = (struct ospf6_inter_prefix_lsa *)
+ ospf6_lsa_header_end(lsa->header);
ospf6_prefix_in6_addr(&in6, prefix_lsa, &prefix_lsa->prefix);
if (buf) {
@@ -1451,7 +1452,7 @@ static int ospf6_inter_area_prefix_lsa_show(struct vty *vty,
struct ospf6_inter_prefix_lsa *prefix_lsa;
char buf[INET6_ADDRSTRLEN];
- prefix_lsa = (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
+ prefix_lsa = (struct ospf6_inter_prefix_lsa *)ospf6_lsa_header_end(
lsa->header);
if (use_json) {
@@ -1488,9 +1489,8 @@ static char *ospf6_inter_area_router_lsa_get_prefix_str(struct ospf6_lsa *lsa,
struct ospf6_inter_router_lsa *router_lsa;
if (lsa != NULL) {
- router_lsa =
- (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
- lsa->header);
+ router_lsa = (struct ospf6_inter_router_lsa *)
+ ospf6_lsa_header_end(lsa->header);
if (buf)
@@ -1508,7 +1508,7 @@ static int ospf6_inter_area_router_lsa_show(struct vty *vty,
struct ospf6_inter_router_lsa *router_lsa;
char buf[64];
- router_lsa = (struct ospf6_inter_router_lsa *)OSPF6_LSA_HEADER_END(
+ router_lsa = (struct ospf6_inter_router_lsa *)ospf6_lsa_header_end(
lsa->header);
ospf6_options_printbuf(router_lsa->options, buf, sizeof(buf));
diff --git a/ospf6d/ospf6_abr.h b/ospf6d/ospf6_abr.h
index 7bb1619..52686ed 100644
--- a/ospf6d/ospf6_abr.h
+++ b/ospf6d/ospf6_abr.h
@@ -33,11 +33,12 @@ struct ospf6_inter_router_lsa {
uint32_t router_id;
};
-#define OSPF6_ABR_SUMMARY_METRIC(E) (ntohl ((E)->metric & htonl (0x00ffffff)))
+#define OSPF6_ABR_SUMMARY_METRIC(E) \
+ (ntohl((E)->metric & htonl(OSPF6_EXT_PATH_METRIC_MAX)))
#define OSPF6_ABR_SUMMARY_METRIC_SET(E, C) \
{ \
(E)->metric &= htonl(0x00000000); \
- (E)->metric |= htonl(0x00ffffff) & htonl(C); \
+ (E)->metric |= htonl(OSPF6_EXT_PATH_METRIC_MAX) & htonl(C); \
}
#define OSPF6_ABR_RANGE_CLEAR_COST(range) (range->path.cost = OSPF_AREA_RANGE_COST_UNSPEC)
diff --git a/ospf6d/ospf6_asbr.c b/ospf6d/ospf6_asbr.c
index d1c2b8b..2065527 100644
--- a/ospf6d/ospf6_asbr.c
+++ b/ospf6d/ospf6_asbr.c
@@ -14,6 +14,7 @@
#include "table.h"
#include "plist.h"
#include "frrevent.h"
+#include "frrstr.h"
#include "linklist.h"
#include "lib/northbound_cli.h"
@@ -101,9 +102,8 @@ struct ospf6_lsa *ospf6_as_external_lsa_originate(struct ospf6_route *route,
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- as_external_lsa = (struct ospf6_as_external_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ as_external_lsa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ lsa_header);
p = (caddr_t)((caddr_t)as_external_lsa
+ sizeof(struct ospf6_as_external_lsa));
@@ -216,7 +216,7 @@ static route_tag_t ospf6_as_external_lsa_get_tag(struct ospf6_lsa *lsa)
if (!lsa)
return 0;
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (!CHECK_FLAG(external->bits_metric, OSPF6_ASBR_BIT_T))
@@ -520,7 +520,7 @@ void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa)
type = ntohs(lsa->header->type);
oa = lsa->lsdb->data;
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL))
@@ -725,7 +725,7 @@ void ospf6_asbr_lsa_remove(struct ospf6_lsa *lsa,
int type;
bool debug = false;
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (IS_OSPF6_DEBUG_EXAMIN(AS_EXTERNAL) || (IS_OSPF6_DEBUG_NSSA))
@@ -1426,10 +1426,9 @@ static void ospf6_external_lsa_fwd_addr_set(struct ospf6 *ospf6,
}
void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
- struct prefix *prefix,
- unsigned int nexthop_num,
- const struct in6_addr *nexthop,
- route_tag_t tag, struct ospf6 *ospf6)
+ struct prefix *prefix, unsigned int nexthop_num,
+ const struct in6_addr *nexthop, route_tag_t tag,
+ struct ospf6 *ospf6, uint32_t metric)
{
route_map_result_t ret;
struct ospf6_route troute;
@@ -1472,6 +1471,7 @@ void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
if (ROUTEMAP(red)) {
troute.route_option = &tinfo;
troute.ospf6 = ospf6;
+ troute.path.redistribute_cost = metric;
tinfo.ifindex = ifindex;
tinfo.tag = tag;
@@ -1924,7 +1924,7 @@ static void ospf6_redistribute_default_set(struct ospf6 *ospf6, int originate)
case DEFAULT_ORIGINATE_ALWAYS:
ospf6_asbr_redistribute_add(DEFAULT_ROUTE, 0,
(struct prefix *)&p, 0, &nexthop, 0,
- ospf6);
+ ospf6, 0);
break;
}
}
@@ -2153,25 +2153,81 @@ static const struct route_map_rule_cmd
ospf6_routemap_rule_set_metric_type_free,
};
+struct ospf6_metric {
+ enum { metric_increment, metric_decrement, metric_absolute } type;
+ bool used;
+ uint32_t metric;
+};
+
static enum route_map_cmd_result_t
ospf6_routemap_rule_set_metric(void *rule, const struct prefix *prefix,
void *object)
{
- char *metric = rule;
- struct ospf6_route *route = object;
+ struct ospf6_metric *metric;
+ struct ospf6_route *route;
+
+ /* Fetch routemap's rule information. */
+ metric = rule;
+ route = object;
+
+ /* Set metric out value. */
+ if (!metric->used)
+ return RMAP_OKAY;
+
+ if (route->path.redistribute_cost > OSPF6_EXT_PATH_METRIC_MAX)
+ route->path.redistribute_cost = OSPF6_EXT_PATH_METRIC_MAX;
+
+ if (metric->type == metric_increment) {
+ route->path.cost = route->path.redistribute_cost +
+ metric->metric;
+
+ /* Check overflow */
+ if (route->path.cost > OSPF6_EXT_PATH_METRIC_MAX ||
+ route->path.cost < metric->metric)
+ route->path.cost = OSPF6_EXT_PATH_METRIC_MAX;
+ } else if (metric->type == metric_decrement) {
+ route->path.cost = route->path.redistribute_cost -
+ metric->metric;
+
+ /* Check overflow */
+ if (route->path.cost == 0 ||
+ route->path.cost > route->path.redistribute_cost)
+ route->path.cost = 1;
+ } else if (metric->type == metric_absolute)
+ route->path.cost = metric->metric;
- route->path.cost = atoi(metric);
return RMAP_OKAY;
}
static void *ospf6_routemap_rule_set_metric_compile(const char *arg)
{
- uint32_t metric;
- char *endp;
- metric = strtoul(arg, &endp, 0);
- if (metric > OSPF_LS_INFINITY || *endp != '\0')
- return NULL;
- return XSTRDUP(MTYPE_ROUTE_MAP_COMPILED, arg);
+ struct ospf6_metric *metric;
+
+ metric = XCALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(*metric));
+ metric->used = false;
+
+ if (all_digit(arg))
+ metric->type = metric_absolute;
+
+ if ((arg[0] == '+') && all_digit(arg + 1)) {
+ metric->type = metric_increment;
+ arg++;
+ }
+
+ if ((arg[0] == '-') && all_digit(arg + 1)) {
+ metric->type = metric_decrement;
+ arg++;
+ }
+
+ metric->metric = strtoul(arg, NULL, 10);
+
+ if (metric->metric > OSPF6_EXT_PATH_METRIC_MAX)
+ metric->metric = OSPF6_EXT_PATH_METRIC_MAX;
+
+ if (metric->metric)
+ metric->used = true;
+
+ return metric;
}
static void ospf6_routemap_rule_set_metric_free(void *rule)
@@ -2368,7 +2424,7 @@ static char *ospf6_as_external_lsa_get_prefix_str(struct ospf6_lsa *lsa,
char tbuf[16];
if (lsa) {
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (pos == 0) {
@@ -2403,7 +2459,7 @@ static int ospf6_as_external_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
char buf[64];
assert(lsa->header);
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
/* bits */
@@ -2971,8 +3027,8 @@ ospf6_originate_summary_lsa(struct ospf6 *ospf6,
return;
}
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END
- (aggr_lsa->header);
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ aggr_lsa->header);
metric = (unsigned long)OSPF6_ASBR_METRIC(external);
tag = ospf6_as_external_lsa_get_tag(aggr_lsa);
mtype = CHECK_FLAG(external->bits_metric,
@@ -3120,8 +3176,7 @@ ospf6_handle_external_aggr_modify(struct ospf6 *ospf6,
return OSPF6_FAILURE;
}
- asel = (struct ospf6_as_external_lsa *)
- OSPF6_LSA_HEADER_END(lsa->header);
+ asel = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(lsa->header);
metric = (unsigned long)OSPF6_ASBR_METRIC(asel);
tag = ospf6_as_external_lsa_get_tag(lsa);
mtype = CHECK_FLAG(asel->bits_metric,
@@ -3310,9 +3365,8 @@ static void ospf6_handle_aggregated_exnl_rt(struct ospf6 *ospf6,
lsa = ospf6_lsdb_lookup(htons(OSPF6_LSTYPE_AS_EXTERNAL),
htonl(info->id), ospf6->router_id, ospf6->lsdb);
if (lsa) {
- ext_lsa = (struct ospf6_as_external_lsa
- *)((char *)(lsa->header)
- + sizeof(struct ospf6_lsa_header));
+ ext_lsa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ lsa->header);
if (rt->prefix.prefixlen != ext_lsa->prefix.prefix_length)
return;
diff --git a/ospf6d/ospf6_asbr.h b/ospf6d/ospf6_asbr.h
index d63e467..21e6d89 100644
--- a/ospf6d/ospf6_asbr.h
+++ b/ospf6d/ospf6_asbr.h
@@ -94,11 +94,13 @@ struct ospf6_as_external_lsa {
#define OSPF6_ASBR_BIT_F ntohl (0x02000000)
#define OSPF6_ASBR_BIT_E ntohl (0x04000000)
-#define OSPF6_ASBR_METRIC(E) (ntohl ((E)->bits_metric & htonl (0x00ffffff)))
+#define OSPF6_ASBR_METRIC(E) \
+ (ntohl((E)->bits_metric & htonl(OSPF6_EXT_PATH_METRIC_MAX)))
#define OSPF6_ASBR_METRIC_SET(E, C) \
{ \
- (E)->bits_metric &= htonl(0xff000000); \
- (E)->bits_metric |= htonl(0x00ffffff) & htonl(C); \
+ (E)->bits_metric &= htonl(~OSPF6_EXT_PATH_METRIC_MAX); \
+ (E)->bits_metric |= htonl(OSPF6_EXT_PATH_METRIC_MAX) & \
+ htonl(C); \
}
extern void ospf6_asbr_lsa_add(struct ospf6_lsa *lsa);
@@ -115,7 +117,8 @@ extern void ospf6_asbr_redistribute_add(int type, ifindex_t ifindex,
struct prefix *prefix,
unsigned int nexthop_num,
const struct in6_addr *nexthop,
- route_tag_t tag, struct ospf6 *ospf6);
+ route_tag_t tag, struct ospf6 *ospf6,
+ uint32_t metric);
extern void ospf6_asbr_redistribute_remove(int type, ifindex_t ifindex,
struct prefix *prefix,
struct ospf6 *ospf6);
diff --git a/ospf6d/ospf6_auth_trailer.c b/ospf6d/ospf6_auth_trailer.c
index 8d9eff4..860d273 100644
--- a/ospf6d/ospf6_auth_trailer.c
+++ b/ospf6d/ospf6_auth_trailer.c
@@ -517,6 +517,15 @@ int ospf6_auth_check_digest(struct ospf6_header *oh, struct ospf6_interface *oi,
}
} else if (CHECK_FLAG(oi->at_data.flags,
OSPF6_AUTH_TRAILER_MANUAL_KEY)) {
+ if (oi->at_data.key_id != ntohs(ospf6_auth->id)) {
+ if (IS_OSPF6_DEBUG_AUTH_RX)
+ zlog_err("RECV[%s]: Auth SA ID mismatch for %s, received %u vs configured %u",
+ oi->interface->name,
+ ospf6_message_type(oh->type),
+ ntohs(ospf6_auth->id),
+ oi->at_data.key_id);
+ return OSPF6_AUTH_VALIDATE_FAILURE;
+ }
auth_str = oi->at_data.auth_key;
hash_algo = oi->at_data.hash_algo;
}
diff --git a/ospf6d/ospf6_flood.c b/ospf6d/ospf6_flood.c
index 98d3bbc..b87aa2f 100644
--- a/ospf6d/ospf6_flood.c
+++ b/ospf6d/ospf6_flood.c
@@ -295,9 +295,7 @@ void ospf6_install_lsa(struct ospf6_lsa *lsa)
lsa->installed = now;
/* Topo change handling */
- if (CHECK_LSA_TOPO_CHG_ELIGIBLE(ntohs(lsa->header->type))
- && !CHECK_FLAG(lsa->flag, OSPF6_LSA_DUPLICATE)) {
-
+ if (CHECK_LSA_TOPO_CHG_ELIGIBLE(ntohs(lsa->header->type))) {
/* check if it is new lsa ? or existing lsa got modified ?*/
if (!old || OSPF6_LSA_IS_CHANGED(old, lsa))
ospf6_helper_handle_topo_chg(ospf6, lsa);
diff --git a/ospf6d/ospf6_gr.c b/ospf6d/ospf6_gr.c
index 34cb970..ab119a4 100644
--- a/ospf6d/ospf6_gr.c
+++ b/ospf6d/ospf6_gr.c
@@ -54,9 +54,7 @@ static int ospf6_gr_lsa_originate(struct ospf6_interface *oi,
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- grace_lsa =
- (struct ospf6_grace_lsa *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ grace_lsa = (struct ospf6_grace_lsa *)ospf6_lsa_header_end(lsa_header);
/* Put grace period. */
grace_lsa->tlv_period.header.type = htons(GRACE_PERIOD_TYPE);
diff --git a/ospf6d/ospf6_gr_helper.c b/ospf6d/ospf6_gr_helper.c
index 42ea048..f0e5d3a 100644
--- a/ospf6d/ospf6_gr_helper.c
+++ b/ospf6d/ospf6_gr_helper.c
@@ -939,15 +939,6 @@ static void show_ospf6_gr_helper_details(struct vty *vty, struct ospf6 *ospf6,
? "Enabled"
: "Disabled");
-#if CONFDATE > 20240401
- CPP_NOTICE("Remove deprecated json key: restartSupoort")
-#endif
- json_object_string_add(
- json, "restartSupoort",
- (ospf6->ospf6_helper_cfg.only_planned_restart)
- ? "Planned Restart only"
- : "Planned and Unplanned Restarts");
-
json_object_string_add(
json, "restartSupport",
(ospf6->ospf6_helper_cfg.only_planned_restart)
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index cb03675..b06796a 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -242,9 +242,7 @@ void ospf6_router_lsa_originate(struct event *thread)
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- router_lsa =
- (struct ospf6_router_lsa *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ router_lsa = (struct ospf6_router_lsa *)ospf6_lsa_header_end(lsa_header);
ospf6_router_lsa_options_set(oa, router_lsa);
@@ -305,10 +303,8 @@ void ospf6_router_lsa_originate(struct event *thread)
/* Reset Buffer to fill next Router LSA */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- router_lsa =
- (struct ospf6_router_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ router_lsa = (struct ospf6_router_lsa *)
+ ospf6_lsa_header_end(lsa_header);
ospf6_router_lsa_options_set(oa, router_lsa);
@@ -568,16 +564,14 @@ void ospf6_network_lsa_originate(struct event *thread)
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
network_lsa =
- (struct ospf6_network_lsa *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ (struct ospf6_network_lsa *)ospf6_lsa_header_end(lsa_header);
/* Collect the interface's Link-LSAs to describe
network's optional capabilities */
type = htons(OSPF6_LSTYPE_LINK);
for (ALL_LSDB_TYPED(oi->lsdb, type, lsa)) {
- link_lsa = (struct ospf6_link_lsa
- *)((caddr_t)lsa->header
- + sizeof(struct ospf6_lsa_header));
+ link_lsa = (struct ospf6_link_lsa *)ospf6_lsa_header_end(
+ lsa->header);
network_lsa->options[0] |= link_lsa->options[0];
network_lsa->options[1] |= link_lsa->options[1];
network_lsa->options[2] |= link_lsa->options[2];
@@ -711,7 +705,8 @@ static int ospf6_link_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
}
start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
- end = (char *)lsa->header + ntohs(lsa->header->length);
+ end = ospf6_lsa_end(lsa->header);
+
for (current = start; current < end;
current += OSPF6_PREFIX_SIZE(prefix)) {
prefix = (struct ospf6_prefix *)current;
@@ -800,8 +795,7 @@ void ospf6_link_lsa_originate(struct event *thread)
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- link_lsa = (struct ospf6_link_lsa *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ link_lsa = (struct ospf6_link_lsa *)ospf6_lsa_header_end(lsa_header);
/* Fill Link-LSA */
link_lsa->priority = oi->priority;
@@ -871,7 +865,7 @@ static char *ospf6_intra_prefix_lsa_get_prefix_str(struct ospf6_lsa *lsa,
start = (char *)intra_prefix_lsa
+ sizeof(struct ospf6_intra_prefix_lsa);
- end = (char *)lsa->header + ntohs(lsa->header->length);
+ end = ospf6_lsa_end(lsa->header);
current = start;
while (current + sizeof(struct ospf6_prefix) <= end) {
@@ -942,7 +936,8 @@ static int ospf6_intra_prefix_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
start = (char *)intra_prefix_lsa
+ sizeof(struct ospf6_intra_prefix_lsa);
- end = (char *)lsa->header + ntohs(lsa->header->length);
+ end = ospf6_lsa_end(lsa->header);
+
for (current = start; current < end;
current += OSPF6_PREFIX_SIZE(prefix)) {
prefix = (struct ospf6_prefix *)current;
@@ -1042,9 +1037,8 @@ void ospf6_intra_prefix_lsa_originate_stub(struct event *thread)
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)ospf6_lsa_header_end(
+ lsa_header);
/* Fill Intra-Area-Prefix-LSA */
intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
@@ -1159,10 +1153,8 @@ void ospf6_intra_prefix_lsa_originate_stub(struct event *thread)
/* Prepare next buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- intra_prefix_lsa =
- (struct ospf6_intra_prefix_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)
+ ospf6_lsa_header_end(lsa_header);
/* Fill Intra-Area-Prefix-LSA */
intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_ROUTER);
@@ -1269,9 +1261,8 @@ void ospf6_intra_prefix_lsa_originate_transit(struct event *thread)
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- intra_prefix_lsa = (struct ospf6_intra_prefix_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)ospf6_lsa_header_end(
+ lsa_header);
/* Fill Intra-Area-Prefix-LSA */
intra_prefix_lsa->ref_type = htons(OSPF6_LSTYPE_NETWORK);
@@ -1326,7 +1317,8 @@ void ospf6_intra_prefix_lsa_originate_transit(struct event *thread)
prefix_num = (unsigned short)ntohl(link_lsa->prefix_num);
start = (char *)link_lsa + sizeof(struct ospf6_link_lsa);
- end = (char *)lsa->header + ntohs(lsa->header->length);
+ end = ospf6_lsa_end(lsa->header);
+
for (current = start; current < end && prefix_num;
current += OSPF6_PREFIX_SIZE(op)) {
op = (struct ospf6_prefix *)current;
@@ -1668,7 +1660,8 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
}
intra_prefix_lsa =
(struct ospf6_intra_prefix_lsa *)
- OSPF6_LSA_HEADER_END(lsa->header);
+ ospf6_lsa_header_end(
+ lsa->header);
if (intra_prefix_lsa->ref_adv_router
== oa->ospf6->router_id) {
@@ -1749,9 +1742,8 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
oa = OSPF6_AREA(lsa->lsdb->data);
- intra_prefix_lsa =
- (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
- lsa->header);
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)ospf6_lsa_header_end(
+ lsa->header);
if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER) ||
intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
@@ -1781,7 +1773,7 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
prefix_num = ntohs(intra_prefix_lsa->prefix_num);
start = (caddr_t)intra_prefix_lsa
+ sizeof(struct ospf6_intra_prefix_lsa);
- end = OSPF6_LSA_END(lsa->header);
+ end = ospf6_lsa_end(lsa->header);
for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
op = (struct ospf6_prefix *)current;
if (prefix_num == 0)
@@ -1979,14 +1971,13 @@ void ospf6_intra_prefix_lsa_remove(struct ospf6_lsa *lsa)
oa = OSPF6_AREA(lsa->lsdb->data);
- intra_prefix_lsa =
- (struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
- lsa->header);
+ intra_prefix_lsa = (struct ospf6_intra_prefix_lsa *)ospf6_lsa_header_end(
+ lsa->header);
prefix_num = ntohs(intra_prefix_lsa->prefix_num);
start = (caddr_t)intra_prefix_lsa
+ sizeof(struct ospf6_intra_prefix_lsa);
- end = OSPF6_LSA_END(lsa->header);
+ end = ospf6_lsa_end(lsa->header);
for (current = start; current < end; current += OSPF6_PREFIX_SIZE(op)) {
op = (struct ospf6_prefix *)current;
if (prefix_num == 0)
diff --git a/ospf6d/ospf6_lsa.c b/ospf6d/ospf6_lsa.c
index bc39579..0177518 100644
--- a/ospf6d/ospf6_lsa.c
+++ b/ospf6d/ospf6_lsa.c
@@ -63,10 +63,10 @@ struct ospf6 *ospf6_get_by_lsdb(struct ospf6_lsa *lsa)
static int ospf6_unknown_lsa_show(struct vty *vty, struct ospf6_lsa *lsa,
json_object *json_obj, bool use_json)
{
- uint8_t *start, *end, *current;
+ char *start, *end, *current;
- start = (uint8_t *)lsa->header + sizeof(struct ospf6_lsa_header);
- end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
+ start = ospf6_lsa_header_end(lsa->header);
+ end = ospf6_lsa_end(lsa->header);
if (use_json) {
json_object_string_add(json_obj, "lsaType", "unknown");
@@ -201,10 +201,10 @@ int ospf6_lsa_is_differ(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
return 1;
/* compare body */
- if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
+ if (ospf6_lsa_size(lsa1->header) != ospf6_lsa_size(lsa2->header))
return 1;
- len = ntohs(lsa1->header->length) - sizeof(struct ospf6_lsa_header);
+ len = ospf6_lsa_size(lsa1->header) - sizeof(struct ospf6_lsa_header);
return memcmp(lsa1->header + 1, lsa2->header + 1, len);
}
@@ -214,7 +214,7 @@ int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
if (OSPF6_LSA_IS_MAXAGE(lsa1) ^ OSPF6_LSA_IS_MAXAGE(lsa2))
return 1;
- if (ntohs(lsa1->header->length) != ntohs(lsa2->header->length))
+ if (ospf6_lsa_size(lsa1->header) != ospf6_lsa_size(lsa2->header))
return 1;
/* Going beyond LSA headers to compare the payload only makes sense,
* when both LSAs aren't header-only. */
@@ -228,14 +228,14 @@ int ospf6_lsa_is_changed(struct ospf6_lsa *lsa1, struct ospf6_lsa *lsa2)
if (CHECK_FLAG(lsa1->flag, OSPF6_LSA_HEADERONLY))
return 0;
- length = OSPF6_LSA_SIZE(lsa1->header) - sizeof(struct ospf6_lsa_header);
+ length = ospf6_lsa_size(lsa1->header) - sizeof(struct ospf6_lsa_header);
/* Once upper layer verifies LSAs received, length underrun should
* become a warning. */
if (length <= 0)
return 0;
- return memcmp(OSPF6_LSA_HEADER_END(lsa1->header),
- OSPF6_LSA_HEADER_END(lsa2->header), length);
+ return memcmp(ospf6_lsa_header_end(lsa1->header),
+ ospf6_lsa_header_end(lsa2->header), length);
}
/* ospf6 age functions */
@@ -548,7 +548,7 @@ void ospf6_lsa_show_dump(struct vty *vty, struct ospf6_lsa *lsa,
json_object *json = NULL;
start = (uint8_t *)lsa->header;
- end = (uint8_t *)lsa->header + ntohs(lsa->header->length);
+ end = (uint8_t *)ospf6_lsa_end(lsa->header);
if (use_json) {
json = json_object_new_object();
@@ -613,7 +613,7 @@ void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa,
json_object_int_add(json_obj, "checksum",
ntohs(lsa->header->checksum));
json_object_int_add(json_obj, "length",
- ntohs(lsa->header->length));
+ ospf6_lsa_size(lsa->header));
json_object_int_add(json_obj, "flag", lsa->flag);
json_object_int_add(json_obj, "lock", lsa->lock);
json_object_int_add(json_obj, "reTxCount", lsa->retrans_count);
@@ -630,7 +630,7 @@ void ospf6_lsa_show_internal(struct vty *vty, struct ospf6_lsa *lsa,
(unsigned long)ntohl(lsa->header->seqnum));
vty_out(vty, "CheckSum: %#06hx Length: %hu\n",
ntohs(lsa->header->checksum),
- ntohs(lsa->header->length));
+ ospf6_lsa_size(lsa->header));
vty_out(vty, "Flag: %x \n", lsa->flag);
vty_out(vty, "Lock: %d \n", lsa->lock);
vty_out(vty, "ReTx Count: %d\n", lsa->retrans_count);
@@ -720,7 +720,7 @@ struct ospf6_lsa *ospf6_lsa_create(struct ospf6_lsa_header *header)
uint16_t lsa_size = 0;
/* size of the entire LSA */
- lsa_size = ntohs(header->length); /* XXX vulnerable */
+ lsa_size = ospf6_lsa_size(header); /* XXX vulnerable */
lsa = ospf6_lsa_alloc(lsa_size);
@@ -947,7 +947,7 @@ unsigned short ospf6_lsa_checksum(struct ospf6_lsa_header *lsa_header)
buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
/* Skip the AGE field */
- uint16_t len = ntohs(lsa_header->length) - type_offset;
+ uint16_t len = ospf6_lsa_size(lsa_header) - type_offset;
/* Checksum offset starts from "type" field, not the beginning of the
lsa_header struct. The offset is 14, rather than 16. */
@@ -963,7 +963,7 @@ int ospf6_lsa_checksum_valid(struct ospf6_lsa_header *lsa_header)
buffer - (uint8_t *)&lsa_header->age; /* should be 2 */
/* Skip the AGE field */
- uint16_t len = ntohs(lsa_header->length) - type_offset;
+ uint16_t len = ospf6_lsa_size(lsa_header) - type_offset;
return (fletcher_checksum(buffer, len, FLETCHER_CHECKSUM_VALIDATE)
== 0);
diff --git a/ospf6d/ospf6_lsa.h b/ospf6d/ospf6_lsa.h
index c9ac27d..4fc2f0d 100644
--- a/ospf6d/ospf6_lsa.h
+++ b/ospf6d/ospf6_lsa.h
@@ -87,10 +87,21 @@ struct ospf6_lsa_header {
uint16_t length; /* LSA length */
};
-#define OSPF6_LSA_HEADER_END(h) ((caddr_t)(h) + sizeof(struct ospf6_lsa_header))
-#define OSPF6_LSA_SIZE(h) (ntohs(((struct ospf6_lsa_header *)(h))->length))
-#define OSPF6_LSA_END(h) \
- ((caddr_t)(h) + ntohs(((struct ospf6_lsa_header *)(h))->length))
+static inline char *ospf6_lsa_header_end(struct ospf6_lsa_header *header)
+{
+ return (char *)header + sizeof(struct ospf6_lsa_header);
+}
+
+static inline char *ospf6_lsa_end(struct ospf6_lsa_header *header)
+{
+ return (char *)header + ntohs(header->length);
+}
+
+static inline uint16_t ospf6_lsa_size(struct ospf6_lsa_header *header)
+{
+ return ntohs(header->length);
+}
+
#define OSPF6_LSA_IS_TYPE(t, L) \
((L)->header->type == htons(OSPF6_LSTYPE_##t) ? 1 : 0)
#define OSPF6_LSA_IS_SAME(L1, L2) \
diff --git a/ospf6d/ospf6_lsdb.c b/ospf6d/ospf6_lsdb.c
index c9cbdf8..9aca555 100644
--- a/ospf6d/ospf6_lsdb.c
+++ b/ospf6d/ospf6_lsdb.c
@@ -229,9 +229,8 @@ struct ospf6_lsa *ospf6_find_inter_prefix_lsa(struct ospf6 *ospf6,
struct ospf6_inter_prefix_lsa *prefix_lsa;
struct prefix prefix;
- prefix_lsa =
- (struct ospf6_inter_prefix_lsa *)OSPF6_LSA_HEADER_END(
- lsa->header);
+ prefix_lsa = (struct ospf6_inter_prefix_lsa *)
+ ospf6_lsa_header_end(lsa->header);
prefix.family = AF_INET6;
prefix.prefixlen = prefix_lsa->prefix.prefix_length;
ospf6_prefix_in6_addr(&prefix.u.prefix6, prefix_lsa,
diff --git a/ospf6d/ospf6_main.c b/ospf6d/ospf6_main.c
index 17966e7..8320f11 100644
--- a/ospf6d/ospf6_main.c
+++ b/ospf6d/ospf6_main.c
@@ -24,6 +24,7 @@
#include "vrf.h"
#include "bfd.h"
#include "libfrr.h"
+#include "libagentx.h"
#include "ospf6d.h"
#include "ospf6_top.h"
@@ -110,9 +111,10 @@ static void __attribute__((noreturn)) ospf6_exit(int status)
ospf6_master_delete();
+ keychain_terminate();
+
frr_fini();
- keychain_terminate();
exit(status);
}
@@ -169,6 +171,8 @@ static const struct frr_yang_module_info *const ospf6d_yang_modules[] = {
&frr_vrf_info,
&frr_ospf_route_map_info,
&frr_ospf6_route_map_info,
+ &ietf_key_chain_info,
+ &ietf_key_chain_deviation_info,
};
/* actual paths filled in main() */
@@ -182,19 +186,19 @@ static char *state_paths[] = {
/* clang-format off */
FRR_DAEMON_INFO(ospf6d, OSPF6,
- .vty_port = OSPF6_VTY_PORT,
- .proghelp = "Implementation of the OSPFv3 routing protocol.",
+ .vty_port = OSPF6_VTY_PORT,
+ .proghelp = "Implementation of the OSPFv3 routing protocol.",
- .signals = ospf6_signals,
- .n_signals = array_size(ospf6_signals),
+ .signals = ospf6_signals,
+ .n_signals = array_size(ospf6_signals),
- .privs = &ospf6d_privs,
+ .privs = &ospf6d_privs,
- .yang_modules = ospf6d_yang_modules,
- .n_yang_modules = array_size(ospf6d_yang_modules),
+ .yang_modules = ospf6d_yang_modules,
+ .n_yang_modules = array_size(ospf6d_yang_modules),
- .state_paths = state_paths,
-);
+ .state_paths = state_paths,
+ );
/* clang-format on */
/* Max wait time for config to load before accepting hellos */
@@ -263,6 +267,7 @@ int main(int argc, char *argv[], char *envp[])
/* thread master */
master = om6->master;
+ libagentx_init();
keychain_init();
ospf6_vrf_init();
access_list_init();
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index d13799c..a6ee8d8 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -221,12 +221,12 @@ void ospf6_lsupdate_print(struct ospf6_header *oh, int action)
&& action == OSPF6_ACTION_RECV)
|| (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
&& action == OSPF6_ACTION_SEND)) {
-
- for (p = (char *)((caddr_t)lsupdate
- + sizeof(struct ospf6_lsupdate));
- p < OSPF6_MESSAGE_END(oh)
- && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
- p += OSPF6_LSA_SIZE(p)) {
+ for (p = (char *)((caddr_t)lsupdate +
+ sizeof(struct ospf6_lsupdate));
+ p < OSPF6_MESSAGE_END(oh) &&
+ p + ospf6_lsa_size((struct ospf6_lsa_header *)p) <=
+ OSPF6_MESSAGE_END(oh);
+ p += ospf6_lsa_size((struct ospf6_lsa_header *)p)) {
ospf6_lsa_header_print_raw(
(struct ospf6_lsa_header *)p);
}
@@ -1414,7 +1414,7 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
return MSG_NG;
}
/* save on ntohs() calls here and in the LSA validator */
- lsalen = OSPF6_LSA_SIZE(lsah);
+ lsalen = ospf6_lsa_size(lsah);
if (lsalen < OSPF6_LSA_HEADER_SIZE) {
zlog_warn(
"%s: malformed LSA header #%u, declared length is %u B",
@@ -1646,9 +1646,10 @@ static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst,
/* Process LSAs */
for (p = (char *)((caddr_t)lsupdate + sizeof(struct ospf6_lsupdate));
- p < OSPF6_MESSAGE_END(oh)
- && p + OSPF6_LSA_SIZE(p) <= OSPF6_MESSAGE_END(oh);
- p += OSPF6_LSA_SIZE(p)) {
+ p < OSPF6_MESSAGE_END(oh) &&
+ p + ospf6_lsa_size((struct ospf6_lsa_header *)p) <=
+ OSPF6_MESSAGE_END(oh);
+ p += ospf6_lsa_size((struct ospf6_lsa_header *)p)) {
ospf6_receive_lsa(on, (struct ospf6_lsa_header *)p);
}
@@ -2702,7 +2703,7 @@ static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor *on,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
for (ALL_LSDB(on->lsupdate_list, lsa, lsanext)) {
- if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
+ if ((length + ospf6_lsa_size(lsa->header) + OSPF6_HEADER_SIZE) >
ospf6_packet_max(on->ospf6_if)) {
ospf6_fill_header(on->ospf6_if, (*op)->s,
length + OSPF6_HEADER_SIZE);
@@ -2719,9 +2720,9 @@ static uint16_t ospf6_make_lsupdate_list(struct ospf6_neighbor *on,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
}
ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
- stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
+ stream_put((*op)->s, lsa->header, ospf6_lsa_size(lsa->header));
(*lsa_cnt)++;
- length += OSPF6_LSA_SIZE(lsa->header);
+ length += ospf6_lsa_size(lsa->header);
assert(lsa->lock == 2);
ospf6_lsdb_remove(lsa, on->lsupdate_list);
}
@@ -2739,7 +2740,7 @@ static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
for (ALL_LSDB(on->retrans_list, lsa, lsanext)) {
- if ((length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE) >
+ if ((length + ospf6_lsa_size(lsa->header) + OSPF6_HEADER_SIZE) >
ospf6_packet_max(on->ospf6_if)) {
ospf6_fill_header(on->ospf6_if, (*op)->s,
length + OSPF6_HEADER_SIZE);
@@ -2763,9 +2764,9 @@ static uint16_t ospf6_make_ls_retrans_list(struct ospf6_neighbor *on,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
}
ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
- stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
+ stream_put((*op)->s, lsa->header, ospf6_lsa_size(lsa->header));
(*lsa_cnt)++;
- length += OSPF6_LSA_SIZE(lsa->header);
+ length += ospf6_lsa_size(lsa->header);
}
return length;
}
@@ -2849,9 +2850,9 @@ int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
/* skip over fixed header */
stream_forward_endp(op->s, OSPF6_LS_UPD_MIN_SIZE);
ospf6_lsa_age_update_to_send(lsa, on->ospf6_if->transdelay);
- stream_put(op->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
- length = OSPF6_HEADER_SIZE + OSPF6_LS_UPD_MIN_SIZE
- + OSPF6_LSA_SIZE(lsa->header);
+ stream_put(op->s, lsa->header, ospf6_lsa_size(lsa->header));
+ length = OSPF6_HEADER_SIZE + OSPF6_LS_UPD_MIN_SIZE +
+ ospf6_lsa_size(lsa->header);
ospf6_fill_header(on->ospf6_if, op->s, length);
ospf6_fill_lsupdate_header(op->s, 1);
op->length = length;
@@ -2877,7 +2878,7 @@ static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface *oi,
stream_forward_endp((*op)->s, OSPF6_LS_UPD_MIN_SIZE);
for (ALL_LSDB(oi->lsupdate_list, lsa, lsanext)) {
- if (length + OSPF6_LSA_SIZE(lsa->header) + OSPF6_HEADER_SIZE >
+ if (length + ospf6_lsa_size(lsa->header) + OSPF6_HEADER_SIZE >
ospf6_packet_max(oi)) {
ospf6_fill_header(oi, (*op)->s,
length + OSPF6_HEADER_SIZE);
@@ -2895,9 +2896,9 @@ static uint16_t ospf6_make_lsupdate_interface(struct ospf6_interface *oi,
}
ospf6_lsa_age_update_to_send(lsa, oi->transdelay);
- stream_put((*op)->s, lsa->header, OSPF6_LSA_SIZE(lsa->header));
+ stream_put((*op)->s, lsa->header, ospf6_lsa_size(lsa->header));
(*lsa_cnt)++;
- length += OSPF6_LSA_SIZE(lsa->header);
+ length += ospf6_lsa_size(lsa->header);
assert(lsa->lock == 2);
ospf6_lsdb_remove(lsa, oi->lsupdate_list);
diff --git a/ospf6d/ospf6_neighbor.c b/ospf6d/ospf6_neighbor.c
index cb65ed2..0e44f2a 100644
--- a/ospf6d/ospf6_neighbor.c
+++ b/ospf6d/ospf6_neighbor.c
@@ -1015,6 +1015,8 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
on->ospf6_if->interface->ifindex);
json_object_int_add(json_neighbor, "neighborInterfaceIndex",
on->ifindex);
+ json_object_string_addf(json_neighbor, "localLinkLocalAddress",
+ "%pI6", on->ospf6_if->linklocal_addr);
json_object_string_add(json_neighbor, "linkLocalAddress",
linklocal_addr);
json_object_string_add(json_neighbor, "neighborState",
diff --git a/ospf6d/ospf6_nssa.c b/ospf6d/ospf6_nssa.c
index 405ae90..ea2be20 100644
--- a/ospf6d/ospf6_nssa.c
+++ b/ospf6d/ospf6_nssa.c
@@ -52,10 +52,8 @@ static int ospf6_abr_nssa_am_elected(struct ospf6_area *oa)
/* Verify all the router LSA to compare the router ID */
for (ALL_LSDB_TYPED(oa->lsdb, type, lsa)) {
-
- router_lsa = (struct ospf6_router_lsa
- *)((caddr_t)lsa->header
- + sizeof(struct ospf6_lsa_header));
+ router_lsa = (struct ospf6_router_lsa *)ospf6_lsa_header_end(
+ lsa->header);
/* ignore non-ABR routers */
if (!CHECK_FLAG(router_lsa->bits, OSPF6_ROUTER_BIT_B))
@@ -416,7 +414,7 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
}
/* find the translated Type-5 for this Type-7 */
- nssa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ nssa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
type7->header);
prefix.family = AF_INET6;
prefix.prefixlen = nssa->prefix.prefix_length;
@@ -437,12 +435,10 @@ static struct ospf6_lsa *ospf6_lsa_translated_nssa_new(struct ospf6_area *area,
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- extnew = (struct ospf6_as_external_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
- ext = (struct ospf6_as_external_lsa
- *)((caddr_t)(type7->header)
- + sizeof(struct ospf6_lsa_header));
+ extnew = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ lsa_header);
+ ext = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ type7->header);
old_ptr =
(caddr_t)((caddr_t)ext + sizeof(struct ospf6_as_external_lsa));
new_ptr = (caddr_t)((caddr_t)extnew
@@ -550,7 +546,7 @@ struct ospf6_lsa *ospf6_translated_nssa_refresh(struct ospf6_area *area,
"%s: try to find translated Type-5 LSA for %s",
__func__, type7->name);
- ext_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ ext_lsa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
type7->header);
prefix.family = AF_INET6;
prefix.prefixlen = ext_lsa->prefix.prefix_length;
@@ -618,7 +614,7 @@ static void ospf6_abr_translate_nssa(struct ospf6_area *area,
struct ospf6 *ospf6;
ospf6 = area->ospf6;
- nssa_lsa = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ nssa_lsa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
if (!CHECK_FLAG(nssa_lsa->prefix.prefix_options,
@@ -1244,9 +1240,8 @@ void ospf6_nssa_lsa_originate(struct ospf6_route *route,
/* prepare buffer */
memset(buffer, 0, sizeof(buffer));
lsa_header = (struct ospf6_lsa_header *)buffer;
- as_external_lsa = (struct ospf6_as_external_lsa
- *)((caddr_t)lsa_header
- + sizeof(struct ospf6_lsa_header));
+ as_external_lsa = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
+ lsa_header);
p = (caddr_t)((caddr_t)as_external_lsa
+ sizeof(struct ospf6_as_external_lsa));
diff --git a/ospf6d/ospf6_route.h b/ospf6d/ospf6_route.h
index c9486bc..8881349 100644
--- a/ospf6d/ospf6_route.h
+++ b/ospf6d/ospf6_route.h
@@ -115,6 +115,7 @@ struct ospf6_path {
/* Cost */
uint8_t metric_type;
uint32_t cost;
+ uint32_t redistribute_cost;
struct prefix ls_prefix;
@@ -139,6 +140,8 @@ struct ospf6_path {
#define OSPF6_PATH_COST_IS_CONFIGURED(path) (path.u.cost_config != OSPF_AREA_RANGE_COST_UNSPEC)
+#define OSPF6_EXT_PATH_METRIC_MAX 0x00ffffff
+
#include "prefix.h"
#include "table.h"
#include "bitfield.h"
diff --git a/ospf6d/ospf6_snmp.c b/ospf6d/ospf6_snmp.c
index 17cdcda..36864d2 100644
--- a/ospf6d/ospf6_snmp.c
+++ b/ospf6d/ospf6_snmp.c
@@ -1017,7 +1017,7 @@ static uint8_t *ospfv3WwLsdbEntry(struct variable *v, oid *name, size_t *length,
case OSPFv3WWLSDBCHECKSUM:
return SNMP_INTEGER(ntohs(lsa->header->checksum));
case OSPFv3WWLSDBADVERTISEMENT:
- *var_len = ntohs(lsa->header->length);
+ *var_len = ospf6_lsa_size(lsa->header);
return (uint8_t *)lsa->header;
case OSPFv3WWLSDBTYPEKNOWN:
return SNMP_INTEGER(OSPF6_LSA_IS_KNOWN(lsa->header->type)
diff --git a/ospf6d/ospf6_spf.c b/ospf6d/ospf6_spf.c
index e39ae50..7879dae 100644
--- a/ospf6d/ospf6_spf.c
+++ b/ospf6d/ospf6_spf.c
@@ -130,10 +130,10 @@ static struct ospf6_vertex *ospf6_vertex_create(struct ospf6_lsa *lsa)
v->lsa = lsa;
/* capability bits + options */
- v->capability = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header));
- v->options[0] = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header) + 1);
- v->options[1] = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header) + 2);
- v->options[2] = *(uint8_t *)(OSPF6_LSA_HEADER_END(lsa->header) + 3);
+ v->capability = *(uint8_t *)(ospf6_lsa_header_end(lsa->header));
+ v->options[0] = *(uint8_t *)(ospf6_lsa_header_end(lsa->header) + 1);
+ v->options[1] = *(uint8_t *)(ospf6_lsa_header_end(lsa->header) + 2);
+ v->options[2] = *(uint8_t *)(ospf6_lsa_header_end(lsa->header) + 3);
v->nh_list = list_new();
v->nh_list->cmp = (int (*)(void *, void *))ospf6_nexthop_cmp;
@@ -187,7 +187,7 @@ static struct ospf6_lsa *ospf6_lsdesc_lsa(caddr_t lsdesc,
inet_ntop(AF_INET, &adv_router, abuf, sizeof(abuf));
if (lsa)
zlog_debug(" Link to: %s len %u, V %s", lsa->name,
- ntohs(lsa->header->length), v->name);
+ ospf6_lsa_size(lsa->header), v->name);
else
zlog_debug(" Link to: [%s Id:%s Adv:%s] No LSA , V %s",
ospf6_lstype_name(type), ibuf, abuf,
@@ -206,8 +206,8 @@ static char *ospf6_lsdesc_backlink(struct ospf6_lsa *lsa, caddr_t lsdesc,
size = (OSPF6_LSA_IS_TYPE(ROUTER, lsa)
? sizeof(struct ospf6_router_lsdesc)
: sizeof(struct ospf6_network_lsdesc));
- for (backlink = OSPF6_LSA_HEADER_END(lsa->header) + 4;
- backlink + size <= OSPF6_LSA_END(lsa->header); backlink += size) {
+ for (backlink = ospf6_lsa_header_end(lsa->header) + 4;
+ backlink + size <= ospf6_lsa_end(lsa->header); backlink += size) {
assert(!(OSPF6_LSA_IS_TYPE(NETWORK, lsa)
&& VERTEX_IS_TYPE(NETWORK, v)));
@@ -290,7 +290,7 @@ static void ospf6_nexthop_calc(struct ospf6_vertex *w, struct ospf6_vertex *v,
!= lsa->header->id)
continue;
- link_lsa = (struct ospf6_link_lsa *)OSPF6_LSA_HEADER_END(
+ link_lsa = (struct ospf6_link_lsa *)ospf6_lsa_header_end(
lsa->header);
if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
inet_ntop(AF_INET6, &link_lsa->linklocal_addr, buf,
@@ -510,8 +510,8 @@ void ospf6_spf_calculation(uint32_t router_id,
size = (VERTEX_IS_TYPE(ROUTER, v)
? sizeof(struct ospf6_router_lsdesc)
: sizeof(struct ospf6_network_lsdesc));
- for (lsdesc = OSPF6_LSA_HEADER_END(v->lsa->header) + 4;
- lsdesc + size <= OSPF6_LSA_END(v->lsa->header);
+ for (lsdesc = ospf6_lsa_header_end(v->lsa->header) + 4;
+ lsdesc + size <= ospf6_lsa_end(v->lsa->header);
lsdesc += size) {
lsa = ospf6_lsdesc_lsa(lsdesc, v);
if (lsa == NULL)
@@ -1011,7 +1011,7 @@ struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
continue;
}
lsa_header = rtr_lsa->header;
- total_lsa_length += (ntohs(lsa_header->length) - lsa_length);
+ total_lsa_length += (ospf6_lsa_size(lsa_header) - lsa_length);
num_lsa++;
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
}
@@ -1044,11 +1044,11 @@ struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
if (!OSPF6_LSA_IS_MAXAGE(rtr_lsa)) {
/* Append first Link State ID LSA */
lsa_header = rtr_lsa->header;
- memcpy(new_header, lsa_header, ntohs(lsa_header->length));
+ memcpy(new_header, lsa_header, ospf6_lsa_size(lsa_header));
/* Assign new lsa length as aggregated length. */
((struct ospf6_lsa_header *)new_header)->length =
htons(total_lsa_length);
- new_header += ntohs(lsa_header->length);
+ new_header += ospf6_lsa_size(lsa_header);
num_lsa--;
}
@@ -1063,20 +1063,19 @@ struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
}
if (IS_OSPF6_DEBUG_SPF(PROCESS)) {
- lsd = OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4;
+ lsd = ospf6_lsa_header_end(rtr_lsa->header) + 4;
interface_id = ROUTER_LSDESC_GET_IFID(lsd);
inet_ntop(AF_INET, &interface_id, ifbuf, sizeof(ifbuf));
- zlog_debug(
- "%s: Next Router LSA %s to aggreat with len %u interface_id %s",
- __func__, rtr_lsa->name,
- ntohs(lsa_header->length), ifbuf);
+ zlog_debug("%s: Next Router LSA %s to aggreat with len %u interface_id %s",
+ __func__, rtr_lsa->name,
+ ospf6_lsa_size(lsa_header), ifbuf);
}
/* Append Next Link State ID LSA */
lsa_header = rtr_lsa->header;
- memcpy(new_header, (OSPF6_LSA_HEADER_END(rtr_lsa->header) + 4),
- (ntohs(lsa_header->length) - lsa_length));
- new_header += (ntohs(lsa_header->length) - lsa_length);
+ memcpy(new_header, (ospf6_lsa_header_end(rtr_lsa->header) + 4),
+ (ospf6_lsa_size(lsa_header) - lsa_length));
+ new_header += (ospf6_lsa_size(lsa_header) - lsa_length);
num_lsa--;
rtr_lsa = ospf6_lsdb_next(end, rtr_lsa);
@@ -1091,8 +1090,8 @@ struct ospf6_lsa *ospf6_create_single_router_lsa(struct ospf6_area *area,
if (IS_OSPF6_DEBUG_SPF(PROCESS))
zlog_debug("%s: LSA %s id %u type 0%x len %u num_lsa %u",
__func__, lsa->name, ntohl(lsa->header->id),
- ntohs(lsa->header->type), ntohs(lsa->header->length),
- num_lsa);
+ ntohs(lsa->header->type),
+ ospf6_lsa_size(lsa->header), num_lsa);
return lsa;
}
@@ -1137,7 +1136,7 @@ int ospf6_ase_calculate_route(struct ospf6 *ospf6, struct ospf6_lsa *lsa,
return 0;
}
- external = (struct ospf6_as_external_lsa *)OSPF6_LSA_HEADER_END(
+ external = (struct ospf6_as_external_lsa *)ospf6_lsa_header_end(
lsa->header);
prefix.family = AF_INET6;
prefix.prefixlen = external->prefix.prefix_length;
diff --git a/ospf6d/ospf6_zebra.c b/ospf6d/ospf6_zebra.c
index 3245578..911f356 100644
--- a/ospf6d/ospf6_zebra.c
+++ b/ospf6d/ospf6_zebra.c
@@ -289,7 +289,7 @@ static int ospf6_zebra_read_route(ZAPI_CALLBACK_ARGS)
if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_ADD)
ospf6_asbr_redistribute_add(api.type, ifindex, &api.prefix,
api.nexthop_num, nexthop, api.tag,
- ospf6);
+ ospf6, api.metric);
else
ospf6_asbr_redistribute_remove(api.type, ifindex, &api.prefix,
ospf6);
diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c
index 419113e..fcc28c6 100644
--- a/ospfd/ospf_apiserver.c
+++ b/ospfd/ospf_apiserver.c
@@ -62,6 +62,11 @@ DEFINE_MTYPE_STATIC(OSPFD, APISERVER_MSGFILTER, "API Server Message Filter");
/* List of all active connections. */
struct list *apiserver_list;
+/* Indicates that API the server socket local addresss has been
+ * specified.
+ */
+struct in_addr ospf_apiserver_addr;
+
/* -----------------------------------------------------------
* Functions to lookup interfaces
* -----------------------------------------------------------
@@ -109,7 +114,21 @@ struct ospf_interface *ospf_apiserver_if_lookup_by_ifp(struct interface *ifp)
unsigned short ospf_apiserver_getport(void)
{
- struct servent *sp = getservbyname("ospfapi", "tcp");
+ struct servent *sp = NULL;
+ char sbuf[16];
+
+ /*
+ * Allow the OSPF API server port to be specified per-instance by
+ * including the instance ID in the /etc/services name. Use the
+ * prior name if no per-instance service is specified.
+ */
+ if (ospf_instance) {
+ snprintfrr(sbuf, sizeof(sbuf), "ospfapi-%d", ospf_instance);
+ sp = getservbyname(sbuf, "tcp");
+ }
+
+ if (!sp)
+ sp = getservbyname("ospfapi", "tcp");
return sp ? ntohs(sp->s_port) : OSPF_API_SYNC_PORT;
}
@@ -557,8 +576,10 @@ int ospf_apiserver_serv_sock_family(unsigned short port, int family)
sockopt_reuseaddr(accept_sock);
sockopt_reuseport(accept_sock);
- /* Bind socket to address and given port. */
- rc = sockunion_bind(accept_sock, &su, port, NULL);
+ /* Bind socket to optional lcoal address and port. */
+ if (ospf_apiserver_addr.s_addr)
+ sockunion2ip(&su) = ospf_apiserver_addr.s_addr;
+ rc = sockunion_bind(accept_sock, &su, port, &su);
if (rc < 0) {
close(accept_sock); /* Close socket */
return rc;
diff --git a/ospfd/ospf_apiserver.h b/ospfd/ospf_apiserver.h
index 0aaf67c..4341a9d 100644
--- a/ospfd/ospf_apiserver.h
+++ b/ospfd/ospf_apiserver.h
@@ -67,6 +67,14 @@ enum ospf_apiserver_event {
};
/* -----------------------------------------------------------
+ * External definitions for OSPF API ospfd parameters.
+ * -----------------------------------------------------------
+ */
+
+extern int ospf_apiserver_enable;
+extern struct in_addr ospf_apiserver_addr;
+
+/* -----------------------------------------------------------
* Following are functions to manage client connections.
* -----------------------------------------------------------
*/
diff --git a/ospfd/ospf_asbr.c b/ospfd/ospf_asbr.c
index 5baad17..9b62f36 100644
--- a/ospfd/ospf_asbr.c
+++ b/ospfd/ospf_asbr.c
@@ -110,7 +110,8 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance,
new = rn->info;
if ((new->ifindex == ifindex)
&& (new->nexthop.s_addr == nexthop.s_addr)
- && (new->tag == tag)) {
+ && (new->tag == tag)
+ && (new->metric == metric)) {
route_unlock_node(rn);
return NULL; /* NULL => no LSA to refresh */
}
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index 610b5fc..9e26a2a 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -480,7 +480,7 @@ static int ospf_ase_route_match_same(struct route_table *rt,
assert(or);
- if (or->path_type != newor->path_type)
+ if (or->changed || (or->path_type != newor->path_type))
return 0;
switch (or->path_type) {
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 95a593a..e15871a 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -765,8 +765,9 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
packets must be sent, as unicasts, to each adjacent neighbor
(i.e., those in state Exchange or greater). The destination
IP addresses for these packets are the neighbors' IP
- addresses. */
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ addresses. This behavior is extended to P2MP networks which
+ don't support broadcast. */
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_neighbor *nbr;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 173dafb..11ac7af 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -19,6 +19,7 @@
#include "zclient.h"
#include "bfd.h"
#include "ldp_sync.h"
+#include "plist.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_bfd.h"
@@ -67,6 +68,34 @@ int ospf_interface_neighbor_count(struct ospf_interface *oi)
return count;
}
+
+void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi)
+{
+ struct route_node *rn;
+ struct ospf_neighbor *nbr = NULL;
+ struct prefix nbr_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } };
+
+ if (!oi->nbr_filter)
+ return;
+
+ /*
+ * Kill neighbors that don't match the neighbor filter prefix-list
+ * excluding the neighbor for the router itself and any neighbors
+ * that are already down.
+ */
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+ if (nbr && nbr != oi->nbr_self && nbr->state != NSM_Down) {
+ nbr_src_prefix.u.prefix4 = nbr->src;
+ if (prefix_list_apply(oi->nbr_filter,
+ (struct prefix *)&(
+ nbr_src_prefix)) !=
+ PREFIX_PERMIT)
+ OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
+ }
+ }
+}
+
int ospf_if_get_output_cost(struct ospf_interface *oi)
{
/* If all else fails, use default OSPF cost */
@@ -147,17 +176,11 @@ void ospf_if_reset(struct interface *ifp)
}
}
-void ospf_if_reset_variables(struct ospf_interface *oi)
+static void ospf_if_default_variables(struct ospf_interface *oi)
{
/* Set default values. */
- /* don't clear this flag. oi->flag = OSPF_IF_DISABLE; */
- if (oi->vl_data)
- oi->type = OSPF_IFTYPE_VIRTUALLINK;
- else
- /* preserve network-type */
- if (oi->type != OSPF_IFTYPE_NBMA)
- oi->type = OSPF_IFTYPE_BROADCAST;
+ oi->type = OSPF_IFTYPE_BROADCAST;
oi->state = ISM_Down;
@@ -254,7 +277,7 @@ struct ospf_interface *ospf_if_new(struct ospf *ospf, struct interface *ifp,
oi->ls_ack_direct.ls_ack = list_new();
/* Set default values. */
- ospf_if_reset_variables(oi);
+ ospf_if_default_variables(oi);
/* Set pseudo neighbor to Null */
oi->nbr_self = NULL;
@@ -532,6 +555,7 @@ static struct ospf_if_params *ospf_new_if_params(void)
UNSET_IF_PARAM(oip, if_area);
UNSET_IF_PARAM(oip, opaque_capable);
UNSET_IF_PARAM(oip, keychain_name);
+ UNSET_IF_PARAM(oip, nbr_filter_name);
oip->auth_crypt = list_new();
@@ -550,6 +574,7 @@ static void ospf_del_if_params(struct interface *ifp,
{
list_delete(&oip->auth_crypt);
XFREE(MTYPE_OSPF_IF_PARAMS, oip->keychain_name);
+ XFREE(MTYPE_OSPF_IF_PARAMS, oip->nbr_filter_name);
ospf_interface_disable_bfd(ifp, oip);
ldp_sync_info_free(&(oip->ldp_sync_info));
XFREE(MTYPE_OSPF_IF_PARAMS, oip);
@@ -585,7 +610,8 @@ void ospf_free_if_params(struct interface *ifp, struct in_addr addr)
!OSPF_IF_PARAM_CONFIGURED(oip, if_area) &&
!OSPF_IF_PARAM_CONFIGURED(oip, opaque_capable) &&
!OSPF_IF_PARAM_CONFIGURED(oip, prefix_suppression) &&
- !OSPF_IF_PARAM_CONFIGURED(oip, keychain_name) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, keychain_name) &&
+ !OSPF_IF_PARAM_CONFIGURED(oip, nbr_filter_name) &&
listcount(oip->auth_crypt) == 0) {
ospf_del_if_params(ifp, oip);
rn->info = NULL;
@@ -821,14 +847,41 @@ int ospf_if_up(struct ospf_interface *oi)
return 1;
}
-int ospf_if_down(struct ospf_interface *oi)
+/* This function will mark routes with next-hops matching the down
+ * OSPF interface as changed. It is used to assure routes that get
+ * removed from the zebra RIB when an interface goes down are
+ * reinstalled if the interface comes back up prior to an intervening
+ * SPF calculation.
+ */
+static void ospf_if_down_mark_routes_changed(struct route_table *table,
+ struct ospf_interface *oi)
{
- struct ospf *ospf;
struct route_node *rn;
struct ospf_route *or;
struct listnode *nh;
struct ospf_path *op;
+ for (rn = route_top(table); rn; rn = route_next(rn)) {
+ or = rn->info;
+
+ if (or == NULL)
+ continue;
+
+ for (nh = listhead(or->paths); nh;
+ nh = listnextnode_unchecked(nh)) {
+ op = listgetdata(nh);
+ if (op->ifindex == oi->ifp->ifindex) {
+ or->changed = true;
+ break;
+ }
+ }
+ }
+}
+
+int ospf_if_down(struct ospf_interface *oi)
+{
+ struct ospf *ospf;
+
if (oi == NULL)
return 0;
@@ -864,23 +917,11 @@ int ospf_if_down(struct ospf_interface *oi)
/* Shutdown packet reception and sending */
ospf_if_stream_unset(oi);
- if (!ospf->new_table)
- return 1;
- for (rn = route_top(ospf->new_table); rn; rn = route_next(rn)) {
- or = rn->info;
-
- if (!or)
- continue;
+ if (ospf->new_table)
+ ospf_if_down_mark_routes_changed(ospf->new_table, oi);
- for (nh = listhead(or->paths); nh;
- nh = listnextnode_unchecked(nh)) {
- op = listgetdata(nh);
- if (op->ifindex == oi->ifp->ifindex) {
- or->changed = true;
- break;
- }
- }
- }
+ if (ospf->new_external_route)
+ ospf_if_down_mark_routes_changed(ospf->new_external_route, oi);
return 1;
}
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index 39dc951..45d0b79 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -120,8 +120,14 @@ struct ospf_if_params {
/* point-to-multipoint delayed reflooding configuration */
bool p2mp_delay_reflood;
+ /* point-to-multipoint doesn't support broadcast */
+ bool p2mp_non_broadcast;
+
/* Opaque LSA capability at interface level (see RFC5250) */
DECLARE_IF_PARAM(bool, opaque_capable);
+
+ /* Name of prefix-list name for packet source address filtering. */
+ DECLARE_IF_PARAM(char *, nbr_filter_name);
};
enum { MEMBER_ALLROUTERS = 0,
@@ -186,6 +192,10 @@ struct ospf_interface {
/* OSPF Network Type. */
uint8_t type;
+#define OSPF_IF_NON_BROADCAST(O) \
+ (((O)->type == OSPF_IFTYPE_NBMA) || \
+ ((((O)->type == OSPF_IFTYPE_POINTOMULTIPOINT) && \
+ (O)->p2mp_non_broadcast)))
/* point-to-point DMVPN configuration */
uint8_t ptp_dmvpn;
@@ -193,6 +203,9 @@ struct ospf_interface {
/* point-to-multipoint delayed reflooding */
bool p2mp_delay_reflood;
+ /* point-to-multipoint doesn't support broadcast */
+ bool p2mp_non_broadcast;
+
/* State of Interface State Machine. */
uint8_t state;
@@ -233,6 +246,9 @@ struct ospf_interface {
/* List of configured NBMA neighbor. */
struct list *nbr_nbma;
+ /* Configured prefix-list for filtering neighbors. */
+ struct prefix_list *nbr_filter;
+
/* Graceful-Restart data. */
struct {
struct {
@@ -327,7 +343,6 @@ extern void ospf_if_update_params(struct interface *ifp, struct in_addr addr);
extern int ospf_if_new_hook(struct interface *ifp);
extern void ospf_if_init(void);
extern void ospf_if_stream_unset(struct ospf_interface *oi);
-extern void ospf_if_reset_variables(struct ospf_interface *oi);
extern int ospf_if_is_enable(struct ospf_interface *oi);
extern int ospf_if_get_output_cost(struct ospf_interface *oi);
extern void ospf_if_recalculate_output_cost(struct interface *ifp);
@@ -359,6 +374,7 @@ extern void ospf_crypt_key_add(struct list *list, struct crypt_key *key);
extern int ospf_crypt_key_delete(struct list *list, uint8_t key_id);
extern uint8_t ospf_default_iftype(struct interface *ifp);
extern int ospf_interface_neighbor_count(struct ospf_interface *oi);
+extern void ospf_intf_neighbor_filter_apply(struct ospf_interface *oi);
/* Set all multicast memberships appropriately based on the type and
state of the interface. */
diff --git a/ospfd/ospf_ism.c b/ospfd/ospf_ism.c
index 2516fa7..878ab72 100644
--- a/ospfd/ospf_ism.c
+++ b/ospfd/ospf_ism.c
@@ -367,7 +367,7 @@ static int ism_interface_up(struct ospf_interface *oi)
/* Otherwise, the state transitions to Waiting. */
next_state = ISM_Waiting;
- if (oi->type == OSPF_IFTYPE_NBMA)
+ if (OSPF_IF_NON_BROADCAST(oi))
ospf_nbr_nbma_if_update(oi->ospf, oi);
/* ospf_ism_event (t); */
diff --git a/ospfd/ospf_ldp_sync.c b/ospfd/ospf_ldp_sync.c
index 4aab880..496ae5b 100644
--- a/ospfd/ospf_ldp_sync.c
+++ b/ospfd/ospf_ldp_sync.c
@@ -774,7 +774,7 @@ DEFPY (no_ospf_mpls_ldp_sync,
"Disable MPLS LDP-IGP Sync\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- ospf_ldp_sync_gbl_exit(ospf, false);
+ ospf_ldp_sync_gbl_exit(ospf, true);
return CMD_SUCCESS;
}
@@ -901,7 +901,7 @@ DEFPY (no_mpls_ldp_sync,
* stop holddown timer if running
* restore ospf cost
*/
- SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
+ UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
ldp_sync_info->enabled = LDP_IGP_SYNC_DEFAULT;
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
EVENT_OFF(ldp_sync_info->t_holddown);
diff --git a/ospfd/ospf_main.c b/ospfd/ospf_main.c
index 6a4a9a1..fdb4e5c 100644
--- a/ospfd/ospf_main.c
+++ b/ospfd/ospf_main.c
@@ -28,6 +28,7 @@
#include "libfrr.h"
#include "routemap.h"
#include "keychain.h"
+#include "libagentx.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_interface.h"
@@ -44,6 +45,7 @@
#include "ospfd/ospf_errors.h"
#include "ospfd/ospf_ldp_sync.h"
#include "ospfd/ospf_routemap_nb.h"
+#include "ospfd/ospf_apiserver.h"
#define OSPFD_STATE_NAME "%s/ospfd.json", frr_libstatedir
#define OSPFD_INST_STATE_NAME(i) "%s/ospfd-%d.json", frr_runstatedir, i
@@ -75,6 +77,7 @@ struct zebra_privs_t ospfd_privs = {
const struct option longopts[] = {
{"instance", required_argument, NULL, 'n'},
{"apiserver", no_argument, NULL, 'a'},
+ {"apiserver_addr", required_argument, NULL, 'l'},
{0}
};
@@ -83,10 +86,6 @@ const struct option longopts[] = {
/* Master of threads. */
struct event_loop *master;
-#ifdef SUPPORT_OSPF_API
-extern int ospf_apiserver_enable;
-#endif /* SUPPORT_OSPF_API */
-
/* SIGHUP handler. */
static void sighup(void)
{
@@ -134,6 +133,8 @@ static const struct frr_yang_module_info *const ospfd_yang_modules[] = {
&frr_route_map_info,
&frr_vrf_info,
&frr_ospf_route_map_info,
+ &ietf_key_chain_info,
+ &ietf_key_chain_deviation_info,
};
/* actual paths filled in main() */
@@ -191,15 +192,11 @@ static void ospf_config_end(void)
/* OSPFd main routine. */
int main(int argc, char **argv)
{
-#ifdef SUPPORT_OSPF_API
- /* OSPF apiserver is disabled by default. */
- ospf_apiserver_enable = 0;
-#endif /* SUPPORT_OSPF_API */
-
frr_preinit(&ospfd_di, argc, argv);
- frr_opt_add("n:a", longopts,
+ frr_opt_add("n:al:", longopts,
" -n, --instance Set the instance id\n"
- " -a, --apiserver Enable OSPF apiserver\n");
+ " -a, --apiserver Enable OSPF apiserver\n"
+ " -l, --apiserver_addr Set OSPF apiserver bind address\n");
while (1) {
int opt;
@@ -221,6 +218,14 @@ int main(int argc, char **argv)
case 'a':
ospf_apiserver_enable = 1;
break;
+ case 'l':
+ if (inet_pton(AF_INET, optarg, &ospf_apiserver_addr) <=
+ 0) {
+ zlog_err("OSPF: Invalid API Server IPv4 address %s specified",
+ optarg);
+ exit(0);
+ }
+ break;
#endif /* SUPPORT_OSPF_API */
default:
frr_help_exit(1);
@@ -252,6 +257,7 @@ int main(int argc, char **argv)
master = om->master;
/* Library inits. */
+ libagentx_init();
ospf_debug_init();
ospf_vrf_init();
diff --git a/ospfd/ospf_neighbor.c b/ospfd/ospf_neighbor.c
index c238f05..d47d581 100644
--- a/ospfd/ospf_neighbor.c
+++ b/ospfd/ospf_neighbor.c
@@ -431,7 +431,7 @@ static struct ospf_neighbor *ospf_nbr_add(struct ospf_interface *oi,
memcpy(&nbr->address, p, sizeof(struct prefix));
nbr->nbr_nbma = NULL;
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_nbr_nbma *nbr_nbma;
struct listnode *node;
@@ -485,7 +485,7 @@ struct ospf_neighbor *ospf_nbr_get(struct ospf_interface *oi,
route_unlock_node(rn);
nbr = rn->info;
- if (oi->type == OSPF_IFTYPE_NBMA && nbr->state == NSM_Attempt) {
+ if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->state == NSM_Attempt) {
nbr->src = iph->ip_src;
memcpy(&nbr->address, p, sizeof(struct prefix));
}
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index 08aa103..c466ddc 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -166,7 +166,7 @@ static int nsm_hello_received(struct ospf_neighbor *nbr)
OSPF_NSM_TIMER_ON(nbr->t_inactivity, ospf_inactivity_timer,
nbr->v_inactivity);
- if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma)
+ if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->nbr_nbma != NULL)
EVENT_OFF(nbr->nbr_nbma->t_poll);
/* Send proactive ARP requests */
@@ -377,7 +377,7 @@ static int nsm_kill_nbr(struct ospf_neighbor *nbr)
return 0;
}
- if (nbr->oi->type == OSPF_IFTYPE_NBMA && nbr->nbr_nbma != NULL) {
+ if (OSPF_IF_NON_BROADCAST(nbr->oi) && nbr->nbr_nbma != NULL) {
struct ospf_nbr_nbma *nbr_nbma = nbr->nbr_nbma;
nbr_nbma->nbr = NULL;
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 4bf4ae9..87aacca 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -23,6 +23,7 @@
#endif
#include "vrf.h"
#include "lib_errors.h"
+#include "plist.h"
#include "ospfd/ospfd.h"
#include "ospfd/ospf_network.h"
@@ -1486,12 +1487,8 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh,
/* Packet overflows MTU size, send immediately. */
if (length + ntohs(find->data->length) > ospf_packet_max(oi)) {
- if (oi->type == OSPF_IFTYPE_NBMA)
- ospf_ls_upd_send(nbr, ls_upd,
- OSPF_SEND_PACKET_DIRECT, 0);
- else
- ospf_ls_upd_send(nbr, ls_upd,
- OSPF_SEND_PACKET_INDIRECT, 0);
+ ospf_ls_upd_send(nbr, ls_upd,
+ OSPF_SEND_PACKET_DIRECT, 0);
/* Only remove list contents. Keep ls_upd. */
list_delete_all_node(ls_upd);
@@ -1508,12 +1505,7 @@ static void ospf_ls_req(struct ip *iph, struct ospf_header *ospfh,
/* Send rest of Link State Update. */
if (listcount(ls_upd) > 0) {
- if (oi->type == OSPF_IFTYPE_NBMA)
- ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_DIRECT,
- 0);
- else
- ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_INDIRECT,
- 0);
+ ospf_ls_upd_send(nbr, ls_upd, OSPF_SEND_PACKET_DIRECT, 0);
list_delete(&ls_upd);
} else
@@ -2756,6 +2748,20 @@ static enum ospf_read_return_enum ospf_read_helper(struct ospf *ospf)
oi = ospf_if_lookup_recv_if(ospf, iph->ip_src, ifp);
/*
+ * If a neighbor filter prefix-list is configured, apply it to the IP
+ * source address and ignore the packet if it doesn't match.
+ */
+ if (oi && oi->nbr_filter) {
+ struct prefix ip_src_prefix = { AF_INET, IPV4_MAX_BITLEN, { 0 } };
+
+ ip_src_prefix.u.prefix4 = iph->ip_src;
+ if (prefix_list_apply(oi->nbr_filter,
+ (struct prefix *)&(ip_src_prefix)) !=
+ PREFIX_PERMIT)
+ return OSPF_READ_CONTINUE;
+ }
+
+ /*
* ospf_verify_header() relies on a valid "oi" and thus can be called
* only after the passive/backbone/other checks below are passed.
* These checks in turn access the fields of unverified "ospfh"
@@ -3404,17 +3410,19 @@ static void ospf_poll_send(struct ospf_nbr_nbma *nbr_nbma)
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
return;
- if (oi->type != OSPF_IFTYPE_NBMA)
- return;
-
if (nbr_nbma->nbr != NULL && nbr_nbma->nbr->state != NSM_Down)
return;
- if (PRIORITY(oi) == 0)
- return;
+ if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (PRIORITY(oi) == 0)
+ return;
+
+ if (nbr_nbma->priority == 0 && oi->state != ISM_DR &&
+ oi->state != ISM_Backup)
+ return;
- if (nbr_nbma->priority == 0 && oi->state != ISM_DR
- && oi->state != ISM_Backup)
+ } else if (oi->type != OSPF_IFTYPE_POINTOMULTIPOINT ||
+ !oi->p2mp_non_broadcast)
return;
ospf_hello_send_sub(oi, nbr_nbma->addr.s_addr);
@@ -3460,7 +3468,7 @@ void ospf_hello_send(struct ospf_interface *oi)
if (OSPF_IF_PASSIVE_STATUS(oi) == OSPF_IF_PASSIVE)
return;
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_neighbor *nbr;
struct route_node *rn;
@@ -3476,31 +3484,44 @@ void ospf_hello_send(struct ospf_interface *oi)
continue;
/*
- * RFC 2328 Section 9.5.1
- * If the router is not eligible to become Designated
- * Router, it must periodically send Hello Packets to
- * both the Designated Router and the Backup
- * Designated Router (if they exist).
+ * Always send to all neighbors on Point-to-Multipoint
+ * non-braodcast networks.
*/
- if (PRIORITY(oi) == 0 &&
- IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
- IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
- continue;
+ if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
+ ospf_hello_send_sub(oi, nbr->address.u.prefix4
+ .s_addr);
+ else {
+ /*
+ * RFC 2328 Section 9.5.1
+ * If the router is not eligible to become Designated
+ * Router, it must periodically send Hello Packets to
+ * both the Designated Router and the Backup
+ * Designated Router (if they exist).
+ */
+ if (PRIORITY(oi) == 0 &&
+ IPV4_ADDR_CMP(&DR(oi),
+ &nbr->address.u.prefix4) &&
+ IPV4_ADDR_CMP(&BDR(oi),
+ &nbr->address.u.prefix4))
+ continue;
- /*
- * If the router is eligible to become Designated
- * Router, it must periodically send Hello Packets to
- * all neighbors that are also eligible. In addition,
- * if the router is itself the Designated Router or
- * Backup Designated Router, it must also send periodic
- * Hello Packets to all other neighbors.
- */
- if (nbr->priority == 0 && oi->state == ISM_DROther)
- continue;
+ /*
+ * If the router is eligible to become Designated
+ * Router, it must periodically send Hello Packets to
+ * all neighbors that are also eligible. In addition,
+ * if the router is itself the Designated Router or
+ * Backup Designated Router, it must also send periodic
+ * Hello Packets to all other neighbors.
+ */
+ if (nbr->priority == 0 &&
+ oi->state == ISM_DROther)
+ continue;
- /* if oi->state == Waiting, send
- * hello to all neighbors */
- ospf_hello_send_sub(oi, nbr->address.u.prefix4.s_addr);
+ /* if oi->state == Waiting, send
+ * hello to all neighbors */
+ ospf_hello_send_sub(oi, nbr->address.u.prefix4
+ .s_addr);
+ }
}
} else {
/* Decide destination address. */
@@ -3857,11 +3878,10 @@ void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag,
else
p.prefix.s_addr = htonl(OSPF_ALLDROUTERS);
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
if (flag == OSPF_SEND_PACKET_INDIRECT)
- flog_warn(
- EC_OSPF_PACKET,
- "* LS-Update is directly sent on NBMA network.");
+ flog_warn(EC_OSPF_PACKET,
+ "* LS-Update is directly sent on non-broadcast network.");
if (IPV4_ADDR_SAME(&oi->address->u.prefix4, &p.prefix))
flog_warn(EC_OSPF_PACKET,
"* LS-Update is sent to myself.");
@@ -3919,7 +3939,8 @@ static void ospf_ls_ack_send_list(struct ospf_interface *oi, struct list *ack,
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_POINTOPOINT ||
- oi->type == OSPF_IFTYPE_POINTOMULTIPOINT)
+ (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT &&
+ !oi->p2mp_non_broadcast))
op->dst.s_addr = htonl(OSPF_ALLSPFROUTERS);
else
op->dst.s_addr = dst.s_addr;
@@ -3971,7 +3992,7 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi)
networks, delayed Link State Acknowledgment packets must be
unicast separately over each adjacency (i.e., neighbor whose
state is >= Exchange). */
- if (oi->type == OSPF_IFTYPE_NBMA) {
+ if (OSPF_IF_NON_BROADCAST(oi)) {
struct ospf_neighbor *nbr;
struct route_node *rn;
diff --git a/ospfd/ospf_ri.c b/ospfd/ospf_ri.c
index 99326b4..dbe44f7 100644
--- a/ospfd/ospf_ri.c
+++ b/ospfd/ospf_ri.c
@@ -1784,11 +1784,10 @@ static void ospf_router_info_schedule(enum lsa_opcode opcode)
DEFUN (router_info,
router_info_area_cmd,
- "router-info <as|area [A.B.C.D]>",
+ "router-info <as|area>",
OSPF_RI_STR
"Enable the Router Information functionality with AS flooding scope\n"
- "Enable the Router Information functionality with Area flooding scope\n"
- "OSPF area ID in IP format (deprecated)\n")
+ "Enable the Router Information functionality with Area flooding scope\n")
{
int idx_mode = 1;
uint8_t scope;
@@ -1844,6 +1843,15 @@ DEFUN (router_info,
return CMD_SUCCESS;
}
+#if CONFDATE > 20240809
+CPP_NOTICE("Drop deprecated router_info_area_id_cmd")
+#endif
+ALIAS_HIDDEN (router_info,
+ router_info_area_id_cmd,
+ "router-info area A.B.C.D",
+ OSPF_RI_STR
+ "Enable the Router Information functionality with Area flooding scope\n"
+ "OSPF area ID in IP format (deprecated)\n")
DEFUN (no_router_info,
no_router_info_cmd,
@@ -2239,6 +2247,7 @@ static void ospf_router_info_register_vty(void)
install_element(VIEW_NODE, &show_ip_ospf_router_info_pce_cmd);
install_element(OSPF_NODE, &router_info_area_cmd);
+ install_element(OSPF_NODE, &router_info_area_id_cmd);
install_element(OSPF_NODE, &no_router_info_cmd);
install_element(OSPF_NODE, &pce_address_cmd);
install_element(OSPF_NODE, &no_pce_address_cmd);
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index e26fe6f..198309c 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -2740,9 +2740,9 @@ static void show_sr_node(struct vty *vty, struct json_object *json,
if (srn->algo[i] == SR_ALGORITHM_UNSET)
continue;
json_obj = json_object_new_object();
- char tmp[2];
+ char tmp[12];
- snprintf(tmp, sizeof(tmp), "%u", i);
+ snprintf(tmp, sizeof(tmp), "%d", i);
json_object_string_add(json_obj, tmp,
srn->algo[i] == SR_ALGORITHM_SPF
? "SPF"
diff --git a/ospfd/ospf_te.c b/ospfd/ospf_te.c
index b1563b5..d57990e 100644
--- a/ospfd/ospf_te.c
+++ b/ospfd/ospf_te.c
@@ -4016,7 +4016,6 @@ static void ospf_mpls_te_show_info(struct vty *vty, struct json_object *json,
json_object *jobj = NULL;
sum = 0;
- sub = 0;
total = lsa->size - OSPF_LSA_HEADER_SIZE;
for (tlvh = TLV_HDR_TOP(lsah); sum < total && tlvh;
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 4f30d52..7cb5197 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -2406,130 +2406,30 @@ DEFUN (no_ospf_timers_lsa_min_arrival,
return CMD_SUCCESS;
}
-DEFUN (ospf_neighbor,
- ospf_neighbor_cmd,
- "neighbor A.B.C.D [priority (0-255) [poll-interval (1-65535)]]",
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Neighbor Priority\n"
- "Priority\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 1;
- int idx_pri = 3;
- int idx_poll = 5;
- struct in_addr nbr_addr;
- unsigned int priority = OSPF_NEIGHBOR_PRIORITY_DEFAULT;
- unsigned int interval = OSPF_POLL_INTERVAL_DEFAULT;
-
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- if (argc > 2)
- priority = strtoul(argv[idx_pri]->arg, NULL, 10);
-
- if (argc > 4)
- interval = strtoul(argv[idx_poll]->arg, NULL, 10);
-
- ospf_nbr_nbma_set(ospf, nbr_addr);
-
- if (argc > 2)
- ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority);
-
- if (argc > 4)
- ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (ospf_neighbor_poll_interval,
- ospf_neighbor_poll_interval_cmd,
- "neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]",
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n"
- "OSPF priority of non-broadcast neighbor\n"
- "Priority\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 1;
- int idx_poll = 3;
- int idx_pri = 5;
- struct in_addr nbr_addr;
- unsigned int priority;
- unsigned int interval;
-
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- interval = strtoul(argv[idx_poll]->arg, NULL, 10);
-
- priority = argc > 4 ? strtoul(argv[idx_pri]->arg, NULL, 10)
- : OSPF_NEIGHBOR_PRIORITY_DEFAULT;
-
- ospf_nbr_nbma_set(ospf, nbr_addr);
- ospf_nbr_nbma_poll_interval_set(ospf, nbr_addr, interval);
-
- if (argc > 4)
- ospf_nbr_nbma_priority_set(ospf, nbr_addr, priority);
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf_neighbor,
- no_ospf_neighbor_cmd,
- "no neighbor A.B.C.D [priority (0-255) [poll-interval (1-65525)]]",
- NO_STR
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Neighbor Priority\n"
- "Priority\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n")
+DEFPY(ospf_neighbor, ospf_neighbor_cmd,
+ "[no] neighbor A.B.C.D$nbr_address [{priority (0-255)$priority | poll-interval (1-65535)$interval}]",
+ NO_STR
+ NEIGHBOR_STR
+ "Neighbor IP address\n"
+ "Neighbor Priority\n"
+ "Priority\n"
+ "Dead Neighbor Polling interval\n"
+ "Seconds\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 2;
- struct in_addr nbr_addr;
-
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- (void)ospf_nbr_nbma_unset(ospf, nbr_addr);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_ospf_neighbor_poll,
- no_ospf_neighbor_poll_cmd,
- "no neighbor A.B.C.D poll-interval (1-65535) [priority (0-255)]",
- NO_STR
- NEIGHBOR_STR
- "Neighbor IP address\n"
- "Dead Neighbor Polling interval\n"
- "Seconds\n"
- "Neighbor Priority\n"
- "Priority\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- int idx_ipv4 = 2;
- struct in_addr nbr_addr;
+ if (no)
+ ospf_nbr_nbma_unset(ospf, nbr_address);
+ else {
+ ospf_nbr_nbma_set(ospf, nbr_address);
+ if (priority_str)
+ ospf_nbr_nbma_priority_set(ospf, nbr_address, priority);
- if (!inet_aton(argv[idx_ipv4]->arg, &nbr_addr)) {
- vty_out(vty, "Please specify Neighbor ID by A.B.C.D\n");
- return CMD_WARNING_CONFIG_FAILED;
+ if (interval_str)
+ ospf_nbr_nbma_poll_interval_set(ospf, nbr_address,
+ interval);
}
- (void)ospf_nbr_nbma_unset(ospf, nbr_addr);
-
return CMD_SUCCESS;
}
@@ -2680,7 +2580,7 @@ DEFUN (no_ospf_write_multiplier,
}
ALIAS(no_ospf_write_multiplier, no_write_multiplier_cmd,
- "no write-multiplier (1-100)", NO_STR
+ "no write-multiplier [(1-100)]", NO_STR
"Write multiplier\n"
"Maximum number of interface serviced per write\n")
@@ -2754,9 +2654,10 @@ DEFUN (ospf_max_multipath,
DEFUN (no_ospf_max_multipath,
no_ospf_max_multipath_cmd,
- "no maximum-paths",
+ "no maximum-paths [" CMD_RANGE_STR(1, MULTIPATH_NUM)"]",
NO_STR
- "Max no of multiple paths for ECMP support\n")
+ "Max no of multiple paths for ECMP support\n"
+ "Number of paths\n")
{
VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
uint16_t maxpaths = MULTIPATH_NUM;
@@ -4148,6 +4049,8 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
ospf_interface_auth_show(vty, oi, json_interface_sub, use_json);
ospf_interface_auth_show(vty, oi, json_oi, use_json);
+
+ /* Point-to-Multipoint Interface options. */
if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT) {
if (use_json) {
json_object_boolean_add(json_interface_sub,
@@ -4162,6 +4065,19 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
" %sDelay reflooding LSAs received on P2MP interface\n",
oi->p2mp_delay_reflood ? "" : "Don't ");
}
+ if (use_json) {
+ json_object_boolean_add(json_interface_sub,
+ "p2mpNonBroadcast",
+ oi->p2mp_non_broadcast);
+
+ json_object_boolean_add(json_oi,
+ "p2mpNonBroadcast",
+ oi->p2mp_non_broadcast);
+ } else {
+ vty_out(vty,
+ " P2MP interface does %ssupport broadcast\n",
+ oi->p2mp_non_broadcast ? "not " : "");
+ }
}
/* Add ospf_interface object to main json blob using SIP as key
@@ -4169,6 +4085,31 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
if (use_json)
json_object_object_addf(json_ois, json_oi, "%pI4",
&oi->address->u.prefix4);
+
+ if (oi->nbr_filter) {
+ if (use_json) {
+ json_object_string_add(json_interface_sub,
+ "nbrFilterPrefixList",
+ prefix_list_name(
+ oi->nbr_filter));
+ json_object_string_add(json_oi,
+ "nbrFilterPrefixList",
+ prefix_list_name(
+ oi->nbr_filter));
+ } else
+ vty_out(vty,
+ " Neighbor filter prefix-list: %s\n",
+ prefix_list_name(oi->nbr_filter));
+ } else {
+ if (use_json) {
+ json_object_string_add(json_interface_sub,
+ "nbrFilterPrefixList",
+ "N/A");
+ json_object_string_add(json_oi,
+ "nbrFilterPrefixList",
+ "N/A");
+ }
+ }
}
}
@@ -5970,7 +5911,7 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty,
prev_nbr = nbr;
}
- if (oi->type != OSPF_IFTYPE_NBMA)
+ if (!OSPF_IF_NON_BROADCAST(oi))
continue;
struct listnode *nd;
@@ -8550,7 +8491,7 @@ DEFUN_HIDDEN (no_ospf_hello_interval,
DEFUN(ip_ospf_network, ip_ospf_network_cmd,
"ip ospf network <broadcast|"
"non-broadcast|"
- "point-to-multipoint [delay-reflood]|"
+ "point-to-multipoint [delay-reflood|non-broadcast]|"
"point-to-point [dmvpn]>",
"IP Information\n"
"OSPF interface commands\n"
@@ -8559,6 +8500,7 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
"Specify OSPF NBMA network\n"
"Specify OSPF point-to-multipoint network\n"
"Specify OSPF delayed reflooding of LSAs received on P2MP interface\n"
+ "Specify OSPF point-to-multipoint network doesn't support broadcast\n"
"Specify OSPF point-to-point network\n"
"Specify OSPF point-to-point DMVPN network\n")
{
@@ -8567,6 +8509,7 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
int old_type = IF_DEF_PARAMS(ifp)->type;
uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
uint8_t old_p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
+ uint8_t old_p2mp_non_broadcast = IF_DEF_PARAMS(ifp)->p2mp_non_broadcast;
struct route_node *rn;
if (old_type == OSPF_IFTYPE_LOOPBACK) {
@@ -8578,16 +8521,19 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = OSPF_P2MP_NON_BROADCAST_DEFAULT;
if (argv_find(argv, argc, "broadcast", &idx))
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_BROADCAST;
- else if (argv_find(argv, argc, "non-broadcast", &idx))
- IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
else if (argv_find(argv, argc, "point-to-multipoint", &idx)) {
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOMULTIPOINT;
if (argv_find(argv, argc, "delay-reflood", &idx))
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood = true;
- } else if (argv_find(argv, argc, "point-to-point", &idx)) {
+ if (argv_find(argv, argc, "non-broadcast", &idx))
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = true;
+ } else if (argv_find(argv, argc, "non-broadcast", &idx))
+ IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_NBMA;
+ else if (argv_find(argv, argc, "point-to-point", &idx)) {
IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
if (argv_find(argv, argc, "dmvpn", &idx))
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
@@ -8597,7 +8543,8 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
if (IF_DEF_PARAMS(ifp)->type == old_type &&
IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn &&
- IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood)
+ IF_DEF_PARAMS(ifp)->p2mp_delay_reflood == old_p2mp_delay_reflood &&
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast == old_p2mp_non_broadcast)
return CMD_SUCCESS;
SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
@@ -8611,13 +8558,16 @@ DEFUN(ip_ospf_network, ip_ospf_network_cmd,
oi->type = IF_DEF_PARAMS(ifp)->type;
oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
oi->p2mp_delay_reflood = IF_DEF_PARAMS(ifp)->p2mp_delay_reflood;
+ oi->p2mp_non_broadcast = IF_DEF_PARAMS(ifp)->p2mp_non_broadcast;
/*
* The OSPF interface only needs to be flapped if the network
* type or DMVPN parameter changes.
*/
if (IF_DEF_PARAMS(ifp)->type != old_type ||
- IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn) {
+ IF_DEF_PARAMS(ifp)->ptp_dmvpn != old_ptp_dmvpn ||
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast !=
+ old_p2mp_non_broadcast) {
if (oi->state > ISM_Down) {
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
@@ -8662,6 +8612,7 @@ DEFUN (no_ip_ospf_network,
IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
IF_DEF_PARAMS(ifp)->p2mp_delay_reflood =
OSPF_P2MP_DELAY_REFLOOD_DEFAULT;
+ IF_DEF_PARAMS(ifp)->p2mp_non_broadcast = OSPF_P2MP_NON_BROADCAST_DEFAULT;
if (IF_DEF_PARAMS(ifp)->type == old_type)
return CMD_SUCCESS;
@@ -10016,6 +9967,58 @@ DEFPY(ip_ospf_prefix_suppression, ip_ospf_prefix_suppression_addr_cmd,
return CMD_SUCCESS;
}
+DEFPY(ip_ospf_neighbor_filter, ip_ospf_neighbor_filter_addr_cmd,
+ "[no] ip ospf neighbor-filter ![PREFIXLIST4_NAME]$prefix_list [A.B.C.D]$ip_addr", NO_STR
+ "IP Information\n"
+ "OSPF interface commands\n"
+ "Filter OSPF neighbor packets\n"
+ "Prefix-List used for filtering\n"
+ "Address of interface\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct ospf_if_params *params;
+ struct prefix_list *nbr_filter = NULL;
+ struct route_node *rn;
+
+ params = IF_DEF_PARAMS(ifp);
+
+ if (ip_addr.s_addr != INADDR_ANY) {
+ params = ospf_get_if_params(ifp, ip_addr);
+ ospf_if_update_params(ifp, ip_addr);
+ }
+
+ if (params->nbr_filter_name)
+ XFREE(MTYPE_OSPF_IF_PARAMS, params->nbr_filter_name);
+
+ if (no) {
+ UNSET_IF_PARAM(params, nbr_filter_name);
+ params->nbr_filter_name = NULL;
+ } else {
+ SET_IF_PARAM(params, nbr_filter_name);
+ params->nbr_filter_name = XSTRDUP(MTYPE_OSPF_IF_PARAMS,
+ prefix_list);
+ nbr_filter = prefix_list_lookup(AFI_IP, params->nbr_filter_name);
+ }
+
+ /*
+ * Determine if there is a change in neighbor filter prefix-list for the
+ * interface.
+ */
+ for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
+ struct ospf_interface *oi = rn->info;
+
+ if (oi &&
+ (ip_addr.s_addr == INADDR_ANY ||
+ IPV4_ADDR_SAME(&oi->address->u.prefix4, &ip_addr)) &&
+ oi->nbr_filter != nbr_filter) {
+ oi->nbr_filter = nbr_filter;
+ if (oi->nbr_filter)
+ ospf_intf_neighbor_filter_apply(oi);
+ }
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (ospf_max_metric_router_lsa_admin,
ospf_max_metric_router_lsa_admin_cmd,
"max-metric router-lsa administrative",
@@ -10526,15 +10529,6 @@ static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
json_object_string_add(json_vrf, "strictLsaCheck",
(ospf->strict_lsa_check) ? "Enabled"
: "Disabled");
-#if CONFDATE > 20240401
- CPP_NOTICE("Remove deprecated json key: restartSupoort")
-#endif
- json_object_string_add(
- json_vrf, "restartSupoort",
- (ospf->only_planned_restart)
- ? "Planned Restart only"
- : "Planned and Unplanned Restarts");
-
json_object_string_add(
json_vrf, "restartSupport",
(ospf->only_planned_restart)
@@ -10761,10 +10755,11 @@ DEFUN (ospf_route_aggregation_timer,
DEFPY (show_ip_ospf_gr_helper,
show_ip_ospf_gr_helper_cmd,
- "show ip ospf [vrf <NAME|all>] graceful-restart helper [detail] [json]",
+ "show ip ospf [{(1-65535)$instance|vrf <NAME|all>}] graceful-restart helper [detail] [json]",
SHOW_STR
IP_STR
"OSPF information\n"
+ "Instance ID\n"
VRF_CMD_HELP_STR
"All VRFs\n"
"OSPF Graceful Restart\n"
@@ -10785,8 +10780,20 @@ DEFPY (show_ip_ospf_gr_helper,
int inst = 0;
bool detail = false;
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ ospf = ospf_lookup_instance(instance);
+ if (!ospf || !ospf->oi_running)
+ return CMD_SUCCESS;
+
OSPF_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+ if (instance && vrf_name) {
+ vty_out(vty, "%% VRF is not supported in instance mode\n");
+ return CMD_WARNING;
+ }
+
if (argv_find(argv, argc, "detail", &idx))
detail = true;
@@ -12228,6 +12235,10 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
OSPF_IFTYPE_POINTOMULTIPOINT &&
params->p2mp_delay_reflood)
vty_out(vty, " delay-reflood");
+ if (params->type ==
+ OSPF_IFTYPE_POINTOMULTIPOINT &&
+ params->p2mp_non_broadcast)
+ vty_out(vty, " non-broadcast");
if (params != IF_DEF_PARAMS(ifp) && rn)
vty_out(vty, " %pI4", &rn->p.u.prefix4);
vty_out(vty, "\n");
@@ -12440,6 +12451,15 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
vty_out(vty, "\n");
}
+ /* neighbor-filter print. */
+ if (OSPF_IF_PARAM_CONFIGURED(params, nbr_filter_name)) {
+ vty_out(vty, " ip ospf neighbor-filter %s",
+ params->nbr_filter_name);
+ if (params != IF_DEF_PARAMS(ifp) && rn)
+ vty_out(vty, " %pI4", &rn->p.u.prefix4);
+ vty_out(vty, "\n");
+ }
+
while (1) {
if (rn == NULL)
rn = route_top(IF_OIFS_PARAMS(ifp));
@@ -13256,6 +13276,9 @@ static void ospf_vty_if_init(void)
/* "ip ospf prefix-suppression" commands. */
install_element(INTERFACE_NODE, &ip_ospf_prefix_suppression_addr_cmd);
+ /* "ip ospf neighbor-filter" commands. */
+ install_element(INTERFACE_NODE, &ip_ospf_neighbor_filter_addr_cmd);
+
/* These commands are compatibitliy for previous version. */
install_element(INTERFACE_NODE, &ospf_authentication_key_cmd);
install_element(INTERFACE_NODE, &ospf_message_digest_key_cmd);
@@ -13754,11 +13777,8 @@ void ospf_vty_init(void)
install_element(OSPF_NODE, &ospf_auto_cost_reference_bandwidth_cmd);
install_element(OSPF_NODE, &no_ospf_auto_cost_reference_bandwidth_cmd);
- /* "neighbor" commands. */
+ /* "neighbor" command. */
install_element(OSPF_NODE, &ospf_neighbor_cmd);
- install_element(OSPF_NODE, &ospf_neighbor_poll_interval_cmd);
- install_element(OSPF_NODE, &no_ospf_neighbor_cmd);
- install_element(OSPF_NODE, &no_ospf_neighbor_poll_cmd);
/* write multiplier commands */
install_element(OSPF_NODE, &ospf_write_multiplier_cmd);
diff --git a/ospfd/ospf_zebra.c b/ospfd/ospf_zebra.c
index bb6cc3a..2c518f2 100644
--- a/ospfd/ospf_zebra.c
+++ b/ospfd/ospf_zebra.c
@@ -1769,6 +1769,7 @@ static void ospf_prefix_list_update(struct prefix_list *plist)
int type;
int abr_inv = 0;
struct ospf_area *area;
+ struct ospf_interface *oi;
struct listnode *node, *n1;
/* If OSPF instatnce does not exist, return right now. */
@@ -1824,6 +1825,19 @@ static void ospf_prefix_list_update(struct prefix_list *plist)
}
}
+ /* Update interface neighbor-filter lists. */
+ for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
+ if (OSPF_IF_PARAM(oi, nbr_filter_name) &&
+ strcmp(OSPF_IF_PARAM(oi, nbr_filter_name),
+ prefix_list_name(plist)) == 0) {
+ oi->nbr_filter = prefix_list_lookup(
+ AFI_IP,
+ OSPF_IF_PARAM(oi, nbr_filter_name));
+ if (oi->nbr_filter)
+ ospf_intf_neighbor_filter_apply(oi);
+ }
+ }
+
/* Schedule ABR task. */
if (IS_OSPF_ABR(ospf) && abr_inv)
ospf_schedule_abr_task(ospf);
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 4c4666d..1d013b2 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -1096,6 +1096,7 @@ struct ospf_interface *add_ospf_interface(struct connected *co,
oi->type = IF_DEF_PARAMS(co->ifp)->type;
oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
oi->p2mp_delay_reflood = IF_DEF_PARAMS(co->ifp)->p2mp_delay_reflood;
+ oi->p2mp_non_broadcast = IF_DEF_PARAMS(co->ifp)->p2mp_non_broadcast;
/* Add pseudo neighbor. */
ospf_nbr_self_reset(oi, oi->ospf->router_id);
@@ -1989,7 +1990,7 @@ static void ospf_nbr_nbma_add(struct ospf_nbr_nbma *nbr_nbma,
struct route_node *rn;
struct prefix p;
- if (oi->type != OSPF_IFTYPE_NBMA)
+ if (!OSPF_IF_NON_BROADCAST(oi))
return;
if (nbr_nbma->nbr != NULL)
@@ -2036,7 +2037,7 @@ void ospf_nbr_nbma_if_update(struct ospf *ospf, struct ospf_interface *oi)
struct route_node *rn;
struct prefix_ipv4 p;
- if (oi->type != OSPF_IFTYPE_NBMA)
+ if (!OSPF_IF_NON_BROADCAST(oi))
return;
for (rn = route_top(ospf->nbr_nbma); rn; rn = route_next(rn))
@@ -2095,7 +2096,7 @@ int ospf_nbr_nbma_set(struct ospf *ospf, struct in_addr nbr_addr)
rn->info = nbr_nbma;
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
- if (oi->type == OSPF_IFTYPE_NBMA)
+ if (OSPF_IF_NON_BROADCAST(oi))
if (prefix_match(oi->address, (struct prefix *)&p)) {
ospf_nbr_nbma_add(nbr_nbma, oi);
break;
diff --git a/pathd/path_main.c b/pathd/path_main.c
index fe636c5..23cbb9c 100644
--- a/pathd/path_main.c
+++ b/pathd/path_main.c
@@ -58,7 +58,7 @@ static void sighup(void)
static void sigint(void)
{
zlog_notice("Terminating on signal");
- zlog_notice("Unregisterfrom opaque,etc ");
+ zlog_notice("Unregister from opaque,etc ");
pathd_shutdown();
exit(0);
diff --git a/pathd/path_zebra.c b/pathd/path_zebra.c
index 645fa50..ba03315 100644
--- a/pathd/path_zebra.c
+++ b/pathd/path_zebra.c
@@ -29,6 +29,17 @@ static int path_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS);
struct zclient *zclient;
static struct zclient *zclient_sync;
+/* Event to retry synch zapi setup for label-manager */
+static struct event *t_sync_connect;
+
+enum path_sync_level {
+ PATH_SYNC_NONE = 0,
+ PATH_SYNC_CONN,
+ PATH_SYNC_HELLO,
+ PATH_SYNC_DONE
+};
+static enum path_sync_level path_sync_client_level;
+
/* Global Variables */
bool g_has_router_id_v4 = false;
bool g_has_router_id_v6 = false;
@@ -236,26 +247,48 @@ void path_zebra_release_label(mpls_label_t label)
zlog_warn("%s: error releasing label range!", __func__);
}
-static void path_zebra_label_manager_connect(void)
+/*
+ * Initialize and connect the synchronous zclient session for the
+ * label-manager. This is prepared to retry on error.
+ */
+static void path_zebra_label_manager_connect(struct event *event)
{
- /* Connect to label manager. */
- while (zclient_socket_connect(zclient_sync) < 0) {
- zlog_warn("%s: error connecting synchronous zclient!",
- __func__);
- sleep(1);
+ if (path_sync_client_level == PATH_SYNC_NONE) {
+ /* Connect to label manager. */
+ if (zclient_socket_connect(zclient_sync) < 0) {
+ zlog_warn("%s: error connecting synchronous zclient!",
+ __func__);
+ event_add_timer(master, path_zebra_label_manager_connect,
+ NULL, 1, &t_sync_connect);
+ return;
+ }
+ set_nonblocking(zclient_sync->sock);
+
+ path_sync_client_level = PATH_SYNC_CONN;
}
- set_nonblocking(zclient_sync->sock);
/* Send hello to notify zebra this is a synchronous client */
- while (zclient_send_hello(zclient_sync) < 0) {
- zlog_warn("%s: Error sending hello for synchronous zclient!",
- __func__);
- sleep(1);
+ if (path_sync_client_level == PATH_SYNC_CONN) {
+ if (zclient_send_hello(zclient_sync) == ZCLIENT_SEND_FAILURE) {
+ zlog_warn("%s: Error sending hello for synchronous zclient!",
+ __func__);
+ event_add_timer(master, path_zebra_label_manager_connect,
+ NULL, 1, &t_sync_connect);
+ return;
+ }
+
+ path_sync_client_level = PATH_SYNC_HELLO;
}
- while (lm_label_manager_connect(zclient_sync, 0) != 0) {
- zlog_warn("%s: error connecting to label manager!", __func__);
- sleep(1);
+ if (path_sync_client_level == PATH_SYNC_HELLO) {
+ if (lm_label_manager_connect(zclient_sync, 0) != 0) {
+ zlog_warn("%s: error connecting to label manager!",
+ __func__);
+ event_add_timer(master, path_zebra_label_manager_connect,
+ NULL, 1, &t_sync_connect);
+ return;
+ }
+ path_sync_client_level = PATH_SYNC_DONE;
}
}
@@ -334,13 +367,15 @@ void path_zebra_init(struct event_loop *master)
zclient_sync->privs = &pathd_privs;
/* Connect to the LM. */
- path_zebra_label_manager_connect();
+ t_sync_connect = NULL;
+ path_zebra_label_manager_connect(NULL);
}
void path_zebra_stop(void)
{
zclient_stop(zclient);
zclient_free(zclient);
+ event_cancel(&t_sync_connect);
zclient_stop(zclient_sync);
zclient_free(zclient_sync);
}
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index c3528e2..a2d756a 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1941,12 +1941,15 @@ DEFUN (show_ip_pim_mlag_summary,
json_object *json_stat = NULL;
json = json_object_new_object();
- if (router->mlag_flags & PIM_MLAGF_LOCAL_CONN_UP)
- json_object_boolean_true_add(json, "mlagConnUp");
- if (router->mlag_flags & PIM_MLAGF_PEER_CONN_UP)
- json_object_boolean_true_add(json, "mlagPeerConnUp");
- if (router->mlag_flags & PIM_MLAGF_PEER_ZEBRA_UP)
- json_object_boolean_true_add(json, "mlagPeerZebraUp");
+ json_object_boolean_add(json, "mlagConnUp",
+ CHECK_FLAG(router->mlag_flags,
+ PIM_MLAGF_LOCAL_CONN_UP));
+ json_object_boolean_add(json, "mlagPeerConnUp",
+ CHECK_FLAG(router->mlag_flags,
+ PIM_MLAGF_PEER_CONN_UP));
+ json_object_boolean_add(json, "mlagPeerZebraUp",
+ CHECK_FLAG(router->mlag_flags,
+ PIM_MLAGF_PEER_ZEBRA_UP));
json_object_string_add(json, "mlagRole",
mlag_role2str(router->mlag_role,
role_buf, sizeof(role_buf)));
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 5d7132c..dcb6116 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -1677,7 +1677,9 @@ static int pim_ifp_up(struct interface *ifp)
__func__, vrf->name);
return 0;
}
+
pim_zebra_interface_set_master(master, ifp);
+ break;
}
}
}
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index c63e0f3..adc47e7 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -56,10 +56,14 @@ int pim_mroute_set(struct pim_instance *pim, int enable)
err = setsockopt(pim->mroute_socket, PIM_IPPROTO,
MRT_TABLE, &data, data_len);
if (err) {
- zlog_warn(
- "%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO, MRT_TABLE=%d): errno=%d: %s",
- __FILE__, __func__, pim->mroute_socket,
- data, errno, safe_strerror(errno));
+ if (err == ENOPROTOOPT)
+ zlog_err("%s Kernel is not compiled with CONFIG_IP_MROUTE_MULTIPLE_TABLES and vrf's will not work",
+ __func__);
+ else
+ zlog_warn("%s %s: failure: setsockopt(fd=%d,PIM_IPPROTO, MRT_TABLE=%d): errno=%d: %s",
+ __FILE__, __func__,
+ pim->mroute_socket, data,
+ errno, safe_strerror(errno));
return -1;
}
}
diff --git a/pimd/pim_msdp.c b/pimd/pim_msdp.c
index 623c14b..ea8c84c 100644
--- a/pimd/pim_msdp.c
+++ b/pimd/pim_msdp.c
@@ -411,12 +411,10 @@ void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
pim_addr_to_prefix(&grp, sa->sg.grp);
rp_info = pim_rp_find_match_group(pim, &grp);
if (rp_info) {
- sa->rp = rp_info->rp.rpf_addr;
- } else
- {
- sa->rp = pim->msdp.originator_id;
+ sa->rp = rp_info->rp.rpf_addr;
+ } else {
+ sa->rp = pim->msdp.originator_id;
}
- sa->rp = pim->msdp.originator_id;
pim_msdp_pkt_sa_tx_one(sa);
}
sa->flags &= ~PIM_MSDP_SAF_STALE;
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index 4f1a4a1..be0be85 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -1504,11 +1504,19 @@ int routing_control_plane_protocols_control_plane_protocol_pim_address_family_re
*/
int lib_interface_pim_address_family_create(struct nb_cb_create_args *args)
{
+ struct interface *ifp;
+
switch (args->event) {
case NB_EV_VALIDATE:
- case NB_EV_PREPARE:
- case NB_EV_ABORT:
case NB_EV_APPLY:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_PREPARE:
+ ifp = nb_running_get_entry(args->dnode, NULL, true);
+ if (ifp->info)
+ return NB_OK;
+
+ pim_if_new(ifp, false, false, false, false);
break;
}
diff --git a/python/clippy/__init__.py b/python/clippy/__init__.py
index 60119fb..668724a 100644
--- a/python/clippy/__init__.py
+++ b/python/clippy/__init__.py
@@ -20,6 +20,7 @@ from _clippy import (
CMD_ATTR_HIDDEN,
CMD_ATTR_DEPRECATED,
CMD_ATTR_NOSH,
+ elf_notes,
)
diff --git a/python/clippy/elf.py b/python/clippy/elf.py
index cc442ee..fd34842 100644
--- a/python/clippy/elf.py
+++ b/python/clippy/elf.py
@@ -458,7 +458,16 @@ class ELFSubset(object):
- `this[123:str]` - extract until null byte. The slice stop value is
the `str` type (or, technically, `unicode`.)
"""
- return self._obj[k]
+ if k.start < getattr(self._obj, "len", float("+Inf")):
+ return self._obj[k]
+
+ real_sect = self._elffile.get_section_addr(self._obj.sh_addr + k.start)
+ offs = self._obj.sh_addr - real_sect.sh_addr
+ if k.stop is str:
+ new_k = slice(k.start + offs, str)
+ else:
+ new_k = slice(k.start + offs, k.stop + offs)
+ return real_sect[new_k]
def getreloc(self, offset):
"""
diff --git a/python/tsexpand.py b/python/tsexpand.py
new file mode 100644
index 0000000..5d60997
--- /dev/null
+++ b/python/tsexpand.py
@@ -0,0 +1,131 @@
+#!/usr/bin/python3
+# SPDX-License-Identifier: MIT
+#
+# 2024 by David Lamparter
+#
+# this tool edits an FRR source .c file to expand the typesafe DECLARE_DLIST
+# et al. definitions. This can be helpful to get better warnings/errors from
+# GCC when something re. a typesafe container is involved. You can also use
+# it on .h files.
+# The actual expansions created by this tool are written to separate files
+# called something like "lib/cspf__visited_tsexpand.h" (for a container named
+# "visited")
+#
+# THIS TOOL EDITS THE FILE IN PLACE. MAKE A BACKUP IF YOU HAVE UNSAVED WORK
+# IN PROGRESS (which is likely because you're debugging a typesafe container
+# problem!)
+#
+# The PREDECL_XYZ is irrelevant for this tool, it needs to be run on the file
+# that has the DECLARE_XYZ (can be .c or .h)
+#
+# the lines added by this tool all have /* $ts_expand: remove$ */ at the end
+# you can undo the effects of this tool by calling sed:
+#
+# sed -e '/\$ts_expand: remove\$/ d' -i.orig filename.c
+
+import os
+import sys
+import re
+import subprocess
+import shlex
+
+decl_re = re.compile(
+ r"""(?<=\n)[ \t]*DECLARE_(LIST|ATOMLIST|DLIST|HEAP|HASH|(SORTLIST|SKIPLIST|RBTREE|ATOMSORT)_(NON)?UNIQ)\(\s*(?P<name>[^, \t\n]+)\s*,[^)]+\)\s*;[ \t]*\n"""
+)
+kill_re = re.compile(r"""(?<=\n)[^\n]*/\* \$ts_expand: remove\$ \*/\n""")
+
+src_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+# some files may be compiled with different CPPFLAGS, that's not supported
+# here...
+cpp = subprocess.check_output(
+ ["make", "var-CPP", "var-AM_CPPFLAGS", "var-DEFS"], cwd=src_root
+)
+cpp = shlex.split(cpp.decode("UTF-8"))
+
+
+def process_file(filename):
+ with open(filename, "r") as ifd:
+ data = ifd.read()
+
+ data = kill_re.sub("", data)
+
+ before = 0
+
+ dirname = os.path.dirname(filename)
+ basename = os.path.basename(filename).removesuffix(".c").removesuffix(".h")
+
+ xname = filename + ".exp"
+ with open(filename + ".exp", "w") as ofd:
+ for m in decl_re.finditer(data):
+ s = m.start()
+ e = m.end()
+ ofd.write(data[before:s])
+
+ # start gcc/clang with some "magic" options to make it expand the
+ # typesafe macros, but nothing else.
+ # -P removes the "#line" markers (which are useless because
+ # everything ends up on one line anyway)
+ # -D_TYPESAFE_EXPAND_MACROS prevents the system header files
+ # (stddef.h, stdint.h, etc.) from being included and expanded
+ # -imacros loads the macro definitions from typesafe.h, but
+ # doesn't include any of the "plain text" (i.e. prototypes
+ # and outside-macro struct definitions) from it
+ # atomlist.h is sufficient because it includes typesafe.h which
+ # includes typerb.h, that's all of them
+ p_expand = subprocess.Popen(
+ cpp
+ + [
+ "-P",
+ "-D_TYPESAFE_EXPAND_MACROS",
+ "-imacros",
+ "lib/atomlist.h",
+ "-",
+ ],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ cwd=src_root,
+ )
+ # the output will look like shit, all on one line. format it.
+ p_format = subprocess.Popen(
+ ["clang-format", "-"],
+ stdin=p_expand.stdout,
+ stdout=subprocess.PIPE,
+ cwd=src_root,
+ )
+ # pipe between cpp & clang-format needs to be closed
+ p_expand.stdout.close()
+
+ # ... and finally, write the DECLARE_XYZ statement, and ONLY that
+ # statements. No headers, no other definitions.
+ p_expand.stdin.write(data[s:e].encode("UTF-8"))
+ p_expand.stdin.close()
+
+ odata = b""
+ while rd := p_format.stdout.read():
+ odata = odata + rd
+
+ p_expand.wait()
+ p_format.wait()
+
+ # and now that we have the expanded text, write it out, put an
+ # #include in the .c file, and put "#if 0" around the original
+ # DECLARE_XYZ statement (otherwise it'll be duplicate...)
+ newname = os.path.join(dirname, f"{basename}__{m.group('name')}_tsexpand.h")
+ with open(newname, "wb") as nfd:
+ nfd.write(odata)
+
+ ofd.write(f'#include "{newname}" /* $ts_expand: remove$ */\n')
+ ofd.write("#if 0 /* $ts_expand: remove$ */\n")
+ ofd.write(data[s:e])
+ ofd.write("#endif /* $ts_expand: remove$ */\n")
+ before = e
+
+ ofd.write(data[before:])
+
+ os.rename(xname, filename)
+
+
+if __name__ == "__main__":
+ for filename in sys.argv[1:]:
+ process_file(filename)
diff --git a/python/xref2vtysh.py b/python/xref2vtysh.py
index 91ccba6..75d9ccf 100644
--- a/python/xref2vtysh.py
+++ b/python/xref2vtysh.py
@@ -32,11 +32,11 @@ frr_top_src = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
# not quite obvious...
daemon_flags = {
- "lib/agentx.c": "VTYSH_ISISD|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA",
+ "lib/libagentx.c": "VTYSH_ISISD|VTYSH_RIPD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ZEBRA",
"lib/filter.c": "VTYSH_ACL_SHOW",
"lib/filter_cli.c": "VTYSH_ACL_CONFIG",
"lib/if.c": "VTYSH_INTERFACE",
- "lib/keychain.c": "VTYSH_KEYS",
+ "lib/keychain_cli.c": "VTYSH_KEYS",
"lib/mgmt_be_client.c": "VTYSH_MGMT_BACKEND",
"lib/mgmt_fe_client.c": "VTYSH_MGMT_FRONTEND",
"lib/lib_vty.c": "VTYSH_ALL",
diff --git a/python/xrelfo.py b/python/xrelfo.py
index a40b19e..07cd740 100644
--- a/python/xrelfo.py
+++ b/python/xrelfo.py
@@ -22,7 +22,7 @@ import argparse
from clippy.uidhash import uidhash
from clippy.elf import *
-from clippy import frr_top_src, CmdAttr
+from clippy import frr_top_src, CmdAttr, elf_notes
from tiabwarfo import FieldApplicator
from xref2vtysh import CommandEntry
@@ -327,6 +327,7 @@ class Xrelfo(dict):
}
)
self._xrefs = []
+ self.note_warn = False
def load_file(self, filename):
orig_filename = filename
@@ -395,6 +396,15 @@ class Xrelfo(dict):
ptrs = edf.iter_data(XrefPtr, slice(start, end))
else:
+ if elf_notes:
+ self.note_warn = True
+ sys.stderr.write(
+ """%s: warning: binary has no FRRouting.XREF note
+%s- one of FRR_MODULE_SETUP, FRR_DAEMON_INFO or XREF_SETUP must be used
+"""
+ % (orig_filename, orig_filename)
+ )
+
xrefarray = edf.get_section("xref_array")
if xrefarray is None:
raise ValueError("file has neither xref note nor xref_array section")
@@ -471,6 +481,9 @@ def _main(args):
sys.stderr.write("while processing %s:\n" % (fn))
traceback.print_exc()
+ if xrelfo.note_warn and args.Werror:
+ errors += 1
+
for option in dir(args):
if option.startswith("W") and option != "Werror":
checks = sorted(xrelfo.check(args))
diff --git a/qpb/qpb.c b/qpb/qpb.c
index 63454f1..6258178 100644
--- a/qpb/qpb.c
+++ b/qpb/qpb.c
@@ -10,3 +10,8 @@
/*
* Main file for the qpb library.
*/
+
+#include "config.h"
+#include "xref.h"
+
+XREF_SETUP();
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index 13d5b86..9f15885 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -677,6 +677,7 @@ fi
%{_sbindir}/mgmtd_testc
%endif
%exclude %{_sbindir}/ssd
+%exclude %{_sbindir}/fpm_listener
%if %{with_watchfrr}
%{_sbindir}/watchfrr
%endif
@@ -804,81 +805,22 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons
%changelog
-* Thu Jun 06 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - %{version}
-
-* Thu Jun 06 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - 10.0.1
-- bgpd
-- Fix route leaking from the default l3vrf
-- Allow using optional table id for negative `no set table x` command
-- Apply noop when doing negative commands for gr operations
-- Drop newline in json output for `show bgp afi safi json detail`
-- Fix `match peer` when switching between ipv4/ipv6/interface
-- Fix `no set as-path prepend asnum...`
-- Fix crash when deleting the srv6 locator
-- Fix display when using `missing-as-worst`
-- Fix dynamic peer graceful restart race condition
-- Fix logging message when receiving a software version capability
-- Fix show run of network route-distinguisher
-- Fix srv6 memory leaks spotted by asan
-- Fix the order of null check and zapi decode
-- Ignore validating the attribute flags if path-attribute is configured
-- Inherit `capability software-version` flag from the peer-group
-- Inherit `enforce-first-as` flag from the peer-group
-- Move srv6 cleanup functions
-- Print old/new states of graceful restart fsm
-- Revert "Fix pointer arithmetic in bgp snmp module"
-- debian, redhat, snapcraft
-- Libyang min version is 2.1.128
-- isisd
-- Fix heap-after-free with prefix sid
-- Fix ip/ipv6 reachability tlvs
-- lib
-- Check for not being a blackhole route
-- Fix exit commands
-- Remove nb/yang memory cleanup when daemonizing
-- Replace deprecated ares_gethostbyname
-- Replace deprecated ares_process()
-- nhrpd
-- Fix race condition
-- Fix core dump on shutdown
-- Clean up shortcut cache entries on termination
-- ospf6d
-- Accept cli `no` for point-to-multipoint
-- Fix defun formatting wrecked by clang
-- Fix loopback/ptp/ptmp conn. route checks
-- Force recalculate on interface_up
-- Prevent heap-buffer-overflow with unknown
-- Ospfv3 route change comparision fixed for asbr-only change
-- ospfd
-- Correct opaque lsa extended parser
-- Fix the bug where ip_ospf_dead-interval_minimal_hello-multiplier did not reset hello timer
-- Protect call to get_edge() in ospf_te.c
-- Solved crash in ri parsing with ospf te
-- Revert "Fix some dicey pointer arith in snmp module"
-- pimd
-- Fix crash unconfiguring rp keepalive timer
-- Fix dr-priority range
-- Fix null register before aging out reg-stop
-- Fix order of operations for evaluating join
-- Fix crash when mixing ssm/any-source joins
-- tests
-- Check if ibgp session can drop invalid aigp attribute
-- tools
-- Frr-reload strip interface vrf ctx line
-- Handle seq num for bgp as-path in frr-reload.py
-- topotests
-- Do not check table version
-- vtysh
-- Check if bgpd is enabled before installing vtysh commands for rpki
-- Fix `show route-map` command when calling via `do`
-- Show `ip ospf network ...` even if it's not the same as the interface type
-- zebra
-- Deny the routes if ip protocol cli refers to an undefined rmap
-- Fix encoded dnssl length
-- Fix evpn svd based remote nh neigh del
-- Fix mpls command
+* Fri Jul 26 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - %{version}
-* Mon Apr 08 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - 10.0
+* Fri Jul 26 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - 10.1
+- Breaking changes
+- Enable BGP dynamic capability by default for datacenter profile
+- Split BGP `rpki cache` command into separate per SSH/TCP
+- Add deprecation cycle for OSPF `router-info X [A.B.C.D]` command
+- Major highlights:
+- BGP dampening per-neighbor support
+- BMP send-experimental stats
+- Implement extended link-bandwidth for BGP
+- Paths Limit for Multiple Paths in BGP
+- New command for OSPFv2 `ip ospf neighbor-filter NAME [A.B.C.D]`
+- Implement non-broadcast support for point-to-multipoint networks
+
+* Mon Mar 25 2024 Jafar Al-Gharaibeh <jafar@atcorp.com> - 10.0
- Major highlights:
- Introduce local host routes
- Require libyang 2.1.128
diff --git a/ripd/rip_cli.c b/ripd/rip_cli.c
index 4d4349b..7066485 100644
--- a/ripd/rip_cli.c
+++ b/ripd/rip_cli.c
@@ -1233,6 +1233,23 @@ DEFPY_YANG(no_rip_distribute_list_prefix,
return nb_cli_apply_changes(vty, NULL);
}
+/*
+ * XPath: /frr-ripd:clear-rip-route
+ */
+DEFPY_YANG (clear_ip_rip,
+ clear_ip_rip_cmd,
+ "clear ip rip [vrf WORD]",
+ CLEAR_STR
+ IP_STR
+ "Clear IP RIP database\n"
+ VRF_CMD_HELP_STR)
+{
+ if (vrf)
+ nb_cli_rpc_enqueue(vty, "vrf", vrf);
+
+ return nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", NULL);
+}
+
/* RIP node structure. */
static struct cmd_node rip_node = {
.name = "rip",
@@ -1295,6 +1312,8 @@ void rip_cli_init(void)
install_element(INTERFACE_NODE, &ip_rip_bfd_profile_cmd);
install_element(INTERFACE_NODE, &no_ip_rip_bfd_profile_cmd);
+ install_element(ENABLE_NODE, &clear_ip_rip_cmd);
+
if_rmap_init(RIP_NODE);
}
/* clang-format off */
diff --git a/ripd/rip_main.c b/ripd/rip_main.c
index 845c507..67469f5 100644
--- a/ripd/rip_main.c
+++ b/ripd/rip_main.c
@@ -23,6 +23,7 @@
#include "routemap.h"
#include "bfd.h"
#include "mgmt_be_client.h"
+#include "libagentx.h"
#include "ripd/ripd.h"
#include "ripd/rip_bfd.h"
@@ -131,6 +132,8 @@ static const struct frr_yang_module_info *const ripd_yang_modules[] = {
&frr_ripd_info,
&frr_route_map_info,
&frr_vrf_info,
+ &ietf_key_chain_info,
+ &ietf_key_chain_deviation_info,
};
/* clang-format off */
@@ -188,8 +191,9 @@ int main(int argc, char **argv)
master = frr_init();
/* Library initialization. */
+ libagentx_init();
rip_error_init();
- keychain_init();
+ keychain_init_new(true);
rip_vrf_init();
/* RIP related initialization. */
diff --git a/ripd/rip_nb_rpcs.c b/ripd/rip_nb_rpcs.c
index bbe3d0f..5d3d714 100644
--- a/ripd/rip_nb_rpcs.c
+++ b/ripd/rip_nb_rpcs.c
@@ -68,12 +68,11 @@ static void clear_rip_route(struct rip *rip)
int clear_rip_route_rpc(struct nb_cb_rpc_args *args)
{
struct rip *rip;
- struct yang_data *yang_vrf;
- yang_vrf = yang_data_list_find(args->input, "%s/%s", args->xpath,
- "input/vrf");
- if (yang_vrf) {
- rip = rip_lookup_by_vrf_name(yang_vrf->value);
+ if (args->input && yang_dnode_exists(args->input, "vrf")) {
+ const char *name = yang_dnode_get_string(args->input, "vrf");
+
+ rip = rip_lookup_by_vrf_name(name);
if (rip)
clear_rip_route(rip);
} else {
diff --git a/ripd/ripd.c b/ripd/ripd.c
index e3220a9..ab4ffe5 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -1051,7 +1051,7 @@ static size_t rip_auth_md5_ah_write(struct stream *s, struct rip_interface *ri,
/* RFC2080: The value used in the sequence number is
arbitrary, but two suggestions are the time of the
message's creation or a simple message counter. */
- stream_putl(s, ++seq);
+ stream_putl(s, seq++);
/* Reserved field must be zero. */
stream_putl(s, 0);
@@ -3254,38 +3254,6 @@ DEFUN (show_ip_rip_status,
return CMD_SUCCESS;
}
-#include "ripd/ripd_clippy.c"
-
-/*
- * XPath: /frr-ripd:clear-rip-route
- */
-DEFPY_YANG (clear_ip_rip,
- clear_ip_rip_cmd,
- "clear ip rip [vrf WORD]",
- CLEAR_STR
- IP_STR
- "Clear IP RIP database\n"
- VRF_CMD_HELP_STR)
-{
- struct list *input;
- int ret;
-
- input = list_new();
- if (vrf) {
- struct yang_data *yang_vrf;
-
- yang_vrf = yang_data_new("/frr-ripd:clear-rip-route/input/vrf",
- vrf);
- listnode_add(input, yang_vrf);
- }
-
- ret = nb_cli_rpc(vty, "/frr-ripd:clear-rip-route", input, NULL);
-
- list_delete(&input);
-
- return ret;
-}
-
/* Distribute-list update functions. */
static void rip_distribute_update(struct distribute_ctx *ctx,
struct distribute *dist)
@@ -3660,7 +3628,6 @@ void rip_init(void)
/* Install rip commands. */
install_element(VIEW_NODE, &show_ip_rip_cmd);
install_element(VIEW_NODE, &show_ip_rip_status_cmd);
- install_element(ENABLE_NODE, &clear_ip_rip_cmd);
/* Debug related init. */
rip_debug_init();
diff --git a/ripd/subdir.am b/ripd/subdir.am
index 7fb3726..aed8d24 100644
--- a/ripd/subdir.am
+++ b/ripd/subdir.am
@@ -33,7 +33,6 @@ ripd_ripd_SOURCES = \
clippy_scan += \
ripd/rip_bfd.c \
ripd/rip_cli.c \
- ripd/ripd.c \
# end
noinst_HEADERS += \
diff --git a/ripngd/ripng_cli.c b/ripngd/ripng_cli.c
index 4806861..99cb68e 100644
--- a/ripngd/ripng_cli.c
+++ b/ripngd/ripng_cli.c
@@ -624,6 +624,23 @@ DEFPY_YANG(no_ripng_ipv6_distribute_list_prefix,
return nb_cli_apply_changes(vty, NULL);
}
+/*
+ * XPath: /frr-ripngd:clear-ripng-route
+ */
+DEFPY_YANG (clear_ipv6_rip,
+ clear_ipv6_rip_cmd,
+ "clear ipv6 ripng [vrf WORD]",
+ CLEAR_STR
+ IPV6_STR
+ "Clear IPv6 RIP database\n"
+ VRF_CMD_HELP_STR)
+{
+ if (vrf)
+ nb_cli_rpc_enqueue(vty, "vrf", vrf);
+
+ return nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", NULL);
+}
+
/* RIPng node structure. */
static struct cmd_node cmd_ripng_node = {
.name = "ripng",
@@ -663,6 +680,8 @@ void ripng_cli_init(void)
install_element(INTERFACE_NODE, &ipv6_ripng_split_horizon_cmd);
+ install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
+
if_rmap_init(RIPNG_NODE);
}
diff --git a/ripngd/ripng_nb_rpcs.c b/ripngd/ripng_nb_rpcs.c
index b23572d..5498bbf 100644
--- a/ripngd/ripng_nb_rpcs.c
+++ b/ripngd/ripng_nb_rpcs.c
@@ -70,12 +70,11 @@ static void clear_ripng_route(struct ripng *ripng)
int clear_ripng_route_rpc(struct nb_cb_rpc_args *args)
{
struct ripng *ripng;
- struct yang_data *yang_vrf;
- yang_vrf = yang_data_list_find(args->input, "%s/%s", args->xpath,
- "input/vrf");
- if (yang_vrf) {
- ripng = ripng_lookup_by_vrf_name(yang_vrf->value);
+ if (args->input && yang_dnode_exists(args->input, "vrf")) {
+ const char *name = yang_dnode_get_string(args->input, "vrf");
+
+ ripng = ripng_lookup_by_vrf_name(name);
if (ripng)
clear_ripng_route(ripng);
} else {
diff --git a/ripngd/ripngd.c b/ripngd/ripngd.c
index 80b9013..f4dadf3 100644
--- a/ripngd/ripngd.c
+++ b/ripngd/ripngd.c
@@ -2231,38 +2231,6 @@ DEFUN (show_ipv6_ripng_status,
return CMD_SUCCESS;
}
-#include "ripngd/ripngd_clippy.c"
-
-/*
- * XPath: /frr-ripngd:clear-ripng-route
- */
-DEFPY_YANG (clear_ipv6_rip,
- clear_ipv6_rip_cmd,
- "clear ipv6 ripng [vrf WORD]",
- CLEAR_STR
- IPV6_STR
- "Clear IPv6 RIP database\n"
- VRF_CMD_HELP_STR)
-{
- struct list *input;
- int ret;
-
- input = list_new();
- if (vrf) {
- struct yang_data *yang_vrf;
-
- yang_vrf = yang_data_new(
- "/frr-ripngd:clear-ripng-route/input/vrf", vrf);
- listnode_add(input, yang_vrf);
- }
-
- ret = nb_cli_rpc(vty, "/frr-ripngd:clear-ripng-route", input, NULL);
-
- list_delete(&input);
-
- return ret;
-}
-
/* Update ECMP routes to zebra when ECMP is disabled. */
void ripng_ecmp_disable(struct ripng *ripng)
{
@@ -2680,7 +2648,6 @@ void ripng_init(void)
/* Install ripng commands. */
install_element(VIEW_NODE, &show_ipv6_ripng_cmd);
install_element(VIEW_NODE, &show_ipv6_ripng_status_cmd);
- install_element(ENABLE_NODE, &clear_ipv6_rip_cmd);
ripng_if_init();
ripng_debug_init();
diff --git a/ripngd/subdir.am b/ripngd/subdir.am
index a881144..83e376b 100644
--- a/ripngd/subdir.am
+++ b/ripngd/subdir.am
@@ -27,7 +27,6 @@ ripngd_ripngd_SOURCES = \
clippy_scan += \
ripngd/ripng_cli.c \
- ripngd/ripngd.c \
# end
noinst_HEADERS += \
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 07050ab..21c596b 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -448,6 +448,7 @@ DEFPY (install_seg6local_routes,
End_X$seg6l_endx X:X::X:X$seg6l_endx_nh6|\
End_T$seg6l_endt (1-4294967295)$seg6l_endt_table|\
End_DX4$seg6l_enddx4 A.B.C.D$seg6l_enddx4_nh4|\
+ End_DX6$seg6l_enddx6 X:X::X:X$seg6l_enddx6_nh6|\
End_DT6$seg6l_enddt6 (1-4294967295)$seg6l_enddt6_table|\
End_DT4$seg6l_enddt4 (1-4294967295)$seg6l_enddt4_table|\
End_DT46$seg6l_enddt46 (1-4294967295)$seg6l_enddt46_table>\
@@ -467,6 +468,8 @@ DEFPY (install_seg6local_routes,
"Redirect table id to use\n"
"SRv6 End.DX4 function to use\n"
"V4 Nexthop address to use\n"
+ "SRv6 End.DX6 function to use\n"
+ "V6 Nexthop address to use\n"
"SRv6 End.DT6 function to use\n"
"Redirect table id to use\n"
"SRv6 End.DT4 function to use\n"
@@ -516,6 +519,9 @@ DEFPY (install_seg6local_routes,
if (seg6l_enddx4) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_DX4;
ctx.nh4 = seg6l_enddx4_nh4;
+ } else if (seg6l_enddx6) {
+ action = ZEBRA_SEG6_LOCAL_ACTION_END_DX6;
+ ctx.nh6 = seg6l_enddx6_nh6;
} else if (seg6l_endx) {
action = ZEBRA_SEG6_LOCAL_ACTION_END_X;
ctx.nh6 = seg6l_endx_nh6;
diff --git a/staticd/static_zebra.c b/staticd/static_zebra.c
index c4efc14..420ed79 100644
--- a/staticd/static_zebra.c
+++ b/staticd/static_zebra.c
@@ -341,7 +341,8 @@ void static_zebra_nht_register(struct static_nexthop *nh, bool reg)
/* refresh with existing data */
afi_t afi = prefix_afi(&lookup.nh);
- if (nh->state == STATIC_NOT_INSTALLED)
+ if (nh->state == STATIC_NOT_INSTALLED ||
+ nh->state == STATIC_SENT_TO_ZEBRA)
nh->state = STATIC_START;
static_nht_update(&rn->p, &nhtd->nh, nhtd->nh_num, afi,
si->safi, nh->nh_vrf_id);
diff --git a/tests/bgpd/test_mp_attr.c b/tests/bgpd/test_mp_attr.c
index cebdda9..44a2104 100644
--- a/tests/bgpd/test_mp_attr.c
+++ b/tests/bgpd/test_mp_attr.c
@@ -23,6 +23,7 @@
#include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_label.h"
#define VT100_RESET "\x1b[0m"
#define VT100_RED "\x1b[31m"
@@ -1075,6 +1076,7 @@ int main(void)
vrf_init(NULL, NULL, NULL, NULL);
bgp_option_set(BGP_OPT_NO_LISTEN);
bgp_attr_init();
+ bgp_labels_init();
if (fileno(stdout) >= 0)
tty = isatty(fileno(stdout));
diff --git a/tests/bgpd/test_peer_attr.c b/tests/bgpd/test_peer_attr.c
index 12c2f11..767c41c 100644
--- a/tests/bgpd/test_peer_attr.c
+++ b/tests/bgpd/test_peer_attr.c
@@ -18,6 +18,7 @@
#include "bgpd/bgp_vty.h"
#include "bgpd/bgp_zebra.h"
#include "bgpd/bgp_network.h"
+#include "bgpd/bgp_label.h"
#ifdef ENABLE_BGP_VNC
#include "bgpd/rfapi/rfapi_backend.h"
@@ -1374,6 +1375,7 @@ static void bgp_shutdown(void)
bgp_route_finish();
bgp_route_map_terminate();
bgp_attr_finish();
+ bgp_labels_finish();
bgp_pthreads_finish();
access_list_add_hook(NULL);
access_list_delete_hook(NULL);
diff --git a/tests/lib/northbound/test_oper_data.c b/tests/lib/northbound/test_oper_data.c
index 8f7e7c5..321f158 100644
--- a/tests/lib/northbound/test_oper_data.c
+++ b/tests/lib/northbound/test_oper_data.c
@@ -14,6 +14,7 @@
#include "lib_vty.h"
#include "log.h"
#include "northbound.h"
+#include "northbound_cli.h"
static struct event_loop *master;
@@ -200,6 +201,19 @@ static struct yang_data *frr_test_module_vrfs_vrf_routes_route_active_get_elem(
return NULL;
}
+/*
+ * XPath: /frr-test-module:frr-test-module/vrfs/vrf/ping
+ */
+static int frr_test_module_vrfs_vrf_ping(struct nb_cb_rpc_args *args)
+{
+ const char *vrf = yang_dnode_get_string(args->input, "../name");
+ const char *data = yang_dnode_get_string(args->input, "data");
+
+ yang_dnode_rpc_output_add(args->output, "vrf", vrf);
+ yang_dnode_rpc_output_add(args->output, "data-out", data);
+
+ return NB_OK;
+}
/*
* XPath: /frr-test-module:frr-test-module/c1value
@@ -263,6 +277,10 @@ const struct frr_yang_module_info frr_test_module_info = {
.cbs.get_elem = frr_test_module_vrfs_vrf_routes_route_active_get_elem,
},
{
+ .xpath = "/frr-test-module:frr-test-module/vrfs/vrf/ping",
+ .cbs.rpc = frr_test_module_vrfs_vrf_ping,
+ },
+ {
.xpath = "/frr-test-module:frr-test-module/c1value",
.cbs.get_elem = frr_test_module_c1value_get_elem,
},
@@ -277,6 +295,33 @@ const struct frr_yang_module_info frr_test_module_info = {
};
/* clang-format on */
+DEFUN(test_rpc, test_rpc_cmd, "test rpc",
+ "Test\n"
+ "RPC\n")
+{
+ struct lyd_node *output = NULL;
+ char xpath[XPATH_MAXLEN];
+ int ret;
+
+ snprintf(xpath, sizeof(xpath),
+ "/frr-test-module:frr-test-module/vrfs/vrf[name='testname']/ping");
+
+ nb_cli_rpc_enqueue(vty, "data", "testdata");
+
+ ret = nb_cli_rpc(vty, xpath, &output);
+ if (ret != CMD_SUCCESS) {
+ vty_out(vty, "RPC failed\n");
+ return ret;
+ }
+
+ vty_out(vty, "vrf %s data %s\n", yang_dnode_get_string(output, "vrf"),
+ yang_dnode_get_string(output, "data-out"));
+
+ yang_dnode_free(output);
+
+ return CMD_SUCCESS;
+}
+
static const struct frr_yang_module_info *const modules[] = {
&frr_test_module_info,
};
@@ -416,6 +461,8 @@ int main(int argc, char **argv)
lib_cmd_init();
nb_init(master, modules, array_size(modules), false);
+ install_element(ENABLE_NODE, &test_rpc_cmd);
+
/* Create artificial data. */
create_data(num_vrfs, num_interfaces, num_routes);
diff --git a/tests/lib/northbound/test_oper_data.in b/tests/lib/northbound/test_oper_data.in
index a6c4f87..f7c44ca 100644
--- a/tests/lib/northbound/test_oper_data.in
+++ b/tests/lib/northbound/test_oper_data.in
@@ -1 +1,2 @@
show yang operational-data /frr-test-module:frr-test-module
+test rpc
diff --git a/tests/lib/northbound/test_oper_data.refout b/tests/lib/northbound/test_oper_data.refout
index aa930fe..7c56564 100644
--- a/tests/lib/northbound/test_oper_data.refout
+++ b/tests/lib/northbound/test_oper_data.refout
@@ -119,5 +119,7 @@ test# show yang operational-data /frr-test-module:frr-test-module
}
}
}
+test# test rpc
+vrf testname data testdata
test#
end.
diff --git a/tests/lib/subdir.am b/tests/lib/subdir.am
index 94df362..185b895 100644
--- a/tests/lib/subdir.am
+++ b/tests/lib/subdir.am
@@ -34,6 +34,10 @@ tests_lib_test_grpc_CXXFLAGS = $(WERROR) $(TESTS_CXXFLAGS)
tests_lib_test_grpc_CPPFLAGS = $(TESTS_CPPFLAGS)
tests_lib_test_grpc_LDADD = $(GRPC_TESTS_LDADD)
tests_lib_test_grpc_SOURCES = tests/lib/test_grpc.cpp
+nodist_tests_lib_test_grpc_SOURCES = \
+ yang/frr-bfdd.yang.c \
+ yang/frr-staticd.yang.c \
+ # end
##############################################################################
diff --git a/tests/lib/test_printfrr.c b/tests/lib/test_printfrr.c
index 66699ec..a81ebcd 100644
--- a/tests/lib/test_printfrr.c
+++ b/tests/lib/test_printfrr.c
@@ -143,6 +143,8 @@ int main(int argc, char **argv)
NAN,
};
uint64_t ui64 = 0xfeed1278cafef00d;
+ uint16_t i16 = -23456;
+ int_fast8_t if8 = 123;
struct in_addr ip;
char *p;
char buf[256];
@@ -169,6 +171,16 @@ int main(int argc, char **argv)
FMT_NSTD(printchk("11110000000011111010010111000011", "%b", 0xf00fa5c3));
FMT_NSTD(printchk("0b01011010", "%#010b", 0x5a));
+/* FMT_NSTD is conditional on the frr-format plugin being NOT enabled.
+ * However, the frr-format plugin does not support %wd/%wfd yet, so this needs
+ * to be unconditional.
+ */
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat"
+ printchk("123 -23456 feed1278cafef00d 9876", "%wf8d %w16d %w64x %d",
+ if8, i16, ui64, 9876);
+#pragma GCC diagnostic pop
+
inet_aton("192.168.1.2", &ip);
printchk("192.168.1.2", "%pI4", &ip);
printchk(" 192.168.1.2", "%20pI4", &ip);
@@ -218,19 +230,25 @@ int main(int argc, char **argv)
printchk("02:ca:fe:f0:0d:1e", "%pFXh", &pfx);
struct prefix_sg sg;
- sg.src.s_addr = INADDR_ANY;
+ SET_IPADDR_V4(&sg.src);
+ sg.src.ipaddr_v4.s_addr = INADDR_ANY;
sg.grp.s_addr = INADDR_ANY;
printchk("(*,*)", "%pPSG4", &sg);
- inet_aton("192.168.1.2", &sg.src);
+ inet_aton("192.168.1.2", &sg.src.ipaddr_v4);
printchk("(192.168.1.2,*)", "%pPSG4", &sg);
inet_aton("224.1.2.3", &sg.grp);
printchk("(192.168.1.2,224.1.2.3)", "%pPSG4", &sg);
- sg.src.s_addr = INADDR_ANY;
+ SET_IPADDR_NONE(&sg.src);
+ sg.src.ipaddr_v4.s_addr = INADDR_ANY;
printchk("(*,224.1.2.3)", "%pPSG4", &sg);
+ SET_IPADDR_V6(&sg.src);
+ inet_pton(AF_INET6, "1:2:3:4::5", &sg.src.ipaddr_v6);
+ printchk("(1:2:3:4::5,224.1.2.3)", "%pPSG4", &sg);
+
uint8_t randhex[] = { 0x12, 0x34, 0x00, 0xca, 0xfe, 0x00, 0xaa, 0x55 };
FMT_NSTD(printchk("12 34 00 ca fe 00 aa 55", "%.8pHX", randhex));
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
index b2e8de5..eb4e51a 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post4.1.ref
@@ -1,9 +1,9 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
index 7bee704..8fe3ea4 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post5.0.ref
@@ -1,9 +1,9 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0/24 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0/24 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
index 31071e7..67b9071 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4-post6.1.ref
@@ -1,10 +1,10 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
Default local pref 100, local AS 100
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0/24 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0/24 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
index 53c4793..4f21a57 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv4.ref
@@ -1,7 +1,7 @@
BGP table version is 1, local router ID is 192.168.0.1
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
- Network Next Hop Metric LocPrf Weight Path
- *> 192.168.0.0 0.0.0.0 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> 192.168.0.0 0.0.0.0 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
index fe3f072..69e44e7 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6-post4.1.ref
@@ -1,9 +1,9 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> fc00::/64 :: 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
index 363b4f5..77aab38 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6.ref
@@ -1,7 +1,7 @@
BGP table version is 1, local router ID is 192.168.0.1
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Origin codes: i - IGP, e - EGP, ? - incomplete
- Network Next Hop Metric LocPrf Weight Path
- *> fc00::/64 :: 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
index 8c3229b..a99400a 100644
--- a/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_bgp_ipv6_post6.1.ref
@@ -1,10 +1,10 @@
BGP table version is 1, local router ID is 192.168.0.1, vrf id 0
Default local pref 100, local AS 100
-Status codes: s suppressed, d damped, h history, * valid, > best, = multipath,
+Status codes: s suppressed, d damped, h history, u unsorted, * valid, > best, = multipath,
i internal, r RIB-failure, S Stale, R Removed
Nexthop codes: @NNN nexthop's vrf id, < announce-nh-self
Origin codes: i - IGP, e - EGP, ? - incomplete
RPKI validation codes: V valid, I invalid, N Not found
- Network Next Hop Metric LocPrf Weight Path
- *> fc00::/64 :: 0 32768 i
+ Network Next Hop Metric LocPrf Weight Path
+ *> fc00::/64 :: 0 32768 i
diff --git a/tests/topotests/all_protocol_startup/r1/show_ip_ospf_interface.ref b/tests/topotests/all_protocol_startup/r1/show_ip_ospf_interface.ref
index 7e28f04..f52b51d 100644
--- a/tests/topotests/all_protocol_startup/r1/show_ip_ospf_interface.ref
+++ b/tests/topotests/all_protocol_startup/r1/show_ip_ospf_interface.ref
@@ -1,5 +1,5 @@
r1-eth0 is up
- ifindex X, MTU 1500 bytes, BW XX Mbit <UP,BROADCAST,RUNNING,MULTICAST>
+ ifindex X, MTU 1500 bytes, BW XX Mbit <UP,LOWER_UP,BROADCAST,RUNNING,MULTICAST>
Internet Address 192.168.0.1/24, Broadcast 192.168.0.255, Area 0.0.0.0
MTU mismatch detection: enabled
Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10
@@ -12,7 +12,7 @@ r1-eth0 is up
Neighbor Count is 0, Adjacent neighbor count is 0
Graceful Restart hello delay: 10s
r1-eth3 is up
- ifindex X, MTU 1500 bytes, BW XX Mbit <UP,BROADCAST,RUNNING,MULTICAST>
+ ifindex X, MTU 1500 bytes, BW XX Mbit <UP,LOWER_UP,BROADCAST,RUNNING,MULTICAST>
Internet Address 192.168.3.1/26, Broadcast 192.168.3.63, Area 0.0.0.0
MTU mismatch detection: enabled
Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10
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 e067cdb..b4bc1e1 100644
--- a/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
+++ b/tests/topotests/all_protocol_startup/test_all_protocol_startup.py
@@ -54,7 +54,7 @@ fatal_error = ""
def build_topo(tgen):
router = tgen.add_router("r1")
for i in range(0, 10):
- tgen.add_switch("sw%d" % i).add_link(router)
+ tgen.add_switch("sw{}".format(i)).add_link(router)
#####################################################
@@ -67,7 +67,7 @@ def build_topo(tgen):
def setup_module(module):
global fatal_error
- print("\n\n** %s: Setup Topology" % module.__name__)
+ print("\n\n** {}: Setup Topology".format(module.__name__))
print("******************************************\n")
thisDir = os.path.dirname(os.path.realpath(__file__))
@@ -85,34 +85,36 @@ def setup_module(module):
#
# Main router
for i in range(1, 2):
- net["r%s" % i].loadConf("mgmtd", "%s/r%s/zebra.conf" % (thisDir, i))
- net["r%s" % i].loadConf("zebra", "%s/r%s/zebra.conf" % (thisDir, i))
- net["r%s" % i].loadConf("ripd", "%s/r%s/ripd.conf" % (thisDir, i))
- net["r%s" % i].loadConf("ripngd", "%s/r%s/ripngd.conf" % (thisDir, i))
- net["r%s" % i].loadConf("ospfd", "%s/r%s/ospfd.conf" % (thisDir, i))
+ net["r{}".format(i)].loadConf("mgmtd", "{}/r{}/zebra.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("zebra", "{}/r{}/zebra.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("ripd", "{}/r{}/ripd.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("ripngd", "{}/r{}/ripngd.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("ospfd", "{}/r{}/ospfd.conf".format(thisDir, i))
if net["r1"].checkRouterVersion("<", "4.0"):
- net["r%s" % i].loadConf(
- "ospf6d", "%s/r%s/ospf6d.conf-pre-v4" % (thisDir, i)
+ net["r{}".format(i)].loadConf(
+ "ospf6d", "{}/r{}/ospf6d.conf-pre-v4".format(thisDir, i)
)
else:
- net["r%s" % i].loadConf("ospf6d", "%s/r%s/ospf6d.conf" % (thisDir, i))
- net["r%s" % i].loadConf("isisd", "%s/r%s/isisd.conf" % (thisDir, i))
- net["r%s" % i].loadConf("bgpd", "%s/r%s/bgpd.conf" % (thisDir, i))
- if net["r%s" % i].daemon_available("ldpd"):
+ net["r{}".format(i)].loadConf(
+ "ospf6d", "{}/r{}/ospf6d.conf".format(thisDir, i)
+ )
+ net["r{}".format(i)].loadConf("isisd", "{}/r{}/isisd.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("bgpd", "{}/r{}/bgpd.conf".format(thisDir, i))
+ if net["r{}".format(i)].daemon_available("ldpd"):
# Only test LDPd if it's installed and Kernel >= 4.5
- net["r%s" % i].loadConf("ldpd", "%s/r%s/ldpd.conf" % (thisDir, i))
- net["r%s" % i].loadConf("sharpd")
- net["r%s" % i].loadConf("nhrpd", "%s/r%s/nhrpd.conf" % (thisDir, i))
- net["r%s" % i].loadConf("babeld", "%s/r%s/babeld.conf" % (thisDir, i))
- net["r%s" % i].loadConf("pbrd", "%s/r%s/pbrd.conf" % (thisDir, i))
- tgen.gears["r%s" % i].start()
+ net["r{}".format(i)].loadConf("ldpd", "{}/r{}/ldpd.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("sharpd")
+ net["r{}".format(i)].loadConf("nhrpd", "{}/r{}/nhrpd.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("babeld", "{}/r{}/babeld.conf".format(thisDir, i))
+ net["r{}".format(i)].loadConf("pbrd", "{}/r{}/pbrd.conf".format(thisDir, i))
+ tgen.gears["r{}".format(i)].start()
# For debugging after starting FRR daemons, uncomment the next line
# tgen.mininet_cli()
def teardown_module(module):
- print("\n\n** %s: Shutdown Topology" % module.__name__)
+ print("\n\n** {}: Shutdown Topology".format(module.__name__))
print("******************************************\n")
tgen = get_topogen()
tgen.stop_topology()
@@ -133,7 +135,7 @@ def test_router_running():
# Starting Routers
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
# For debugging after starting FRR daemons, uncomment the next line
@@ -158,7 +160,9 @@ def test_error_messages_vtysh():
#
# VTYSH output from router
- vtystdout = net["r%s" % i].cmd('vtysh -c "show version" 2> /dev/null').rstrip()
+ vtystdout = (
+ net["r{}".format(i)].cmd('vtysh -c "show version" 2> /dev/null').rstrip()
+ )
# Fix newlines (make them all the same)
vtystdout = ("\n".join(vtystdout.splitlines()) + "\n").rstrip()
@@ -166,16 +170,20 @@ def test_error_messages_vtysh():
vtystdout = re.sub(r"FRRouting [0-9]+.*", "", vtystdout, flags=re.DOTALL)
if vtystdout == "":
- print("r%s StdOut ok" % i)
+ print("r{} StdOut ok".format(i))
- assert vtystdout == "", "Vtysh StdOut Output check failed for router r%s" % i
+ assert (
+ vtystdout == ""
+ ), "Vtysh StdOut Output check failed for router r{}".format(i)
#
# Second checking Standard Error
#
# VTYSH StdErr output from router
- vtystderr = net["r%s" % i].cmd('vtysh -c "show version" > /dev/null').rstrip()
+ vtystderr = (
+ net["r{}".format(i)].cmd('vtysh -c "show version" > /dev/null').rstrip()
+ )
# Fix newlines (make them all the same)
vtystderr = ("\n".join(vtystderr.splitlines()) + "\n").rstrip()
@@ -183,13 +191,15 @@ def test_error_messages_vtysh():
# vtystderr = re.sub(r"FRRouting [0-9]+.*", "", vtystderr, flags=re.DOTALL)
if vtystderr == "":
- print("r%s StdErr ok" % i)
+ print("r{} StdErr ok".format(i))
- assert vtystderr == "", "Vtysh StdErr Output check failed for router r%s" % i
+ assert (
+ vtystderr == ""
+ ), "Vtysh StdErr Output check failed for router r{}".format(i)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -213,37 +223,37 @@ def test_error_messages_daemons():
error_logs = ""
for i in range(1, 2):
- log = net["r%s" % i].getStdErr("ripd")
+ log = net["r{}".format(i)].getStdErr("ripd")
if log:
- error_logs += "r%s RIPd StdErr Output:\n" % i
+ error_logs += "r{} RIPd StdErr Output:\n".format(i)
error_logs += log
- log = net["r%s" % i].getStdErr("ripngd")
+ log = net["r{}".format(i)].getStdErr("ripngd")
if log:
- error_logs += "r%s RIPngd StdErr Output:\n" % i
+ error_logs += "r{} RIPngd StdErr Output:\n".format(i)
error_logs += log
- log = net["r%s" % i].getStdErr("ospfd")
+ log = net["r{}".format(i)].getStdErr("ospfd")
if log:
- error_logs += "r%s OSPFd StdErr Output:\n" % i
+ error_logs += "r{} OSPFd StdErr Output:\n".format(i)
error_logs += log
- log = net["r%s" % i].getStdErr("ospf6d")
+ log = net["r{}".format(i)].getStdErr("ospf6d")
if log:
- error_logs += "r%s OSPF6d StdErr Output:\n" % i
+ error_logs += "r{} OSPF6d StdErr Output:\n".format(i)
error_logs += log
- log = net["r%s" % i].getStdErr("isisd")
+ log = net["r{}".format(i)].getStdErr("isisd")
# ISIS shows debugging enabled status on StdErr
# Remove these messages
log = re.sub(r"^IS-IS .* debugging is on.*", "", log).rstrip()
if log:
- error_logs += "r%s ISISd StdErr Output:\n" % i
+ error_logs += "r{} ISISd StdErr Output:\n".format(i)
error_logs += log
- log = net["r%s" % i].getStdErr("bgpd")
+ log = net["r{}".format(i)].getStdErr("bgpd")
if log:
- error_logs += "r%s BGPd StdErr Output:\n" % i
+ error_logs += "r{} BGPd StdErr Output:\n".format(i)
error_logs += log
- if net["r%s" % i].daemon_available("ldpd"):
- log = net["r%s" % i].getStdErr("ldpd")
+ if net["r{}".format(i)].daemon_available("ldpd"):
+ log = net["r{}".format(i)].getStdErr("ldpd")
if log:
- error_logs += "r%s LDPd StdErr Output:\n" % i
+ error_logs += "r{} LDPd StdErr Output:\n".format(i)
error_logs += log
log = net["r1"].getStdErr("nhrpd")
@@ -251,27 +261,27 @@ def test_error_messages_daemons():
# Ignore these
log = re.sub(r".*YANG model.*not embedded.*", "", log).rstrip()
if log:
- error_logs += "r%s NHRPd StdErr Output:\n" % i
+ error_logs += "r{} NHRPd StdErr Output:\n".format(i)
error_logs += log
log = net["r1"].getStdErr("babeld")
if log:
- error_logs += "r%s BABELd StdErr Output:\n" % i
+ error_logs += "r{} BABELd StdErr Output:\n".format(i)
error_logs += log
log = net["r1"].getStdErr("pbrd")
if log:
- error_logs += "r%s PBRd StdErr Output:\n" % i
+ error_logs += "r{} PBRd StdErr Output:\n".format(i)
error_logs += log
- log = net["r%s" % i].getStdErr("zebra")
+ log = net["r{}".format(i)].getStdErr("zebra")
if log:
- error_logs += "r%s Zebra StdErr Output:\n" % i
+ error_logs += "r{} Zebra StdErr Output:\n".format(i)
error_logs += log
if error_logs:
sys.stderr.write(
- "Failed check for StdErr Output on daemons:\n%s\n" % error_logs
+ "Failed check for StdErr Output on daemons:\n{}\n".format(error_logs)
)
# Ignoring the issue if told to ignore (ie not yet fixed)
@@ -317,18 +327,20 @@ def test_converge_protocols():
# Make sure that all daemons are running
failures = 0
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
print("Show that v4 routes are right\n")
- v4_routesFile = "%s/r%s/ipv4_routes.ref" % (thisDir, i)
+ v4_routesFile = "{}/r{}/ipv4_routes.ref".format(thisDir, i)
expected = (
- net["r%s" % i].cmd("sort {} 2> /dev/null".format(v4_routesFile)).rstrip()
+ net["r{}".format(i)]
+ .cmd("sort {} 2> /dev/null".format(v4_routesFile))
+ .rstrip()
)
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd(
"vtysh -c \"show ip route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null"
)
@@ -344,24 +356,26 @@ def test_converge_protocols():
title2="Expected IP RoutingTable",
)
if diff:
- sys.stderr.write("r%s failed IP Routing table check:\n%s\n" % (i, diff))
+ sys.stderr.write("r{} failed IP Routing table check:\n{}\n".format(i, diff))
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
- assert failures == 0, "IP Routing table failed for r%s\n%s" % (i, diff)
+ assert failures == 0, "IP Routing table failed for r{}\n{}".format(i, diff)
failures = 0
print("Show that v6 routes are right\n")
- v6_routesFile = "%s/r%s/ipv6_routes.ref" % (thisDir, i)
+ v6_routesFile = "{}/r{}/ipv6_routes.ref".format(thisDir, i)
expected = (
- net["r%s" % i].cmd("sort {} 2> /dev/null".format(v6_routesFile)).rstrip()
+ net["r{}".format(i)]
+ .cmd("sort {} 2> /dev/null".format(v6_routesFile))
+ .rstrip()
)
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd(
"vtysh -c \"show ipv6 route\" | sed -e '/^Codes: /,/^\\s*$/d' | sort 2> /dev/null"
)
@@ -377,20 +391,24 @@ def test_converge_protocols():
title2="Expected IPv6 RoutingTable",
)
if diff:
- sys.stderr.write("r%s failed IPv6 Routing table check:\n%s\n" % (i, diff))
+ sys.stderr.write(
+ "r{} failed IPv6 Routing table check:\n{}\n".format(i, diff)
+ )
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
- assert failures == 0, "IPv6 Routing table failed for r%s\n%s" % (i, diff)
+ assert failures == 0, "IPv6 Routing table failed for r{}\n{}".format(i, diff)
def route_get_nhg_id(route_str):
net = get_topogen().net
- output = net["r1"].cmd('vtysh -c "show ip route %s nexthop-group"' % route_str)
+ output = net["r1"].cmd(
+ 'vtysh -c "show ip route {} nexthop-group"'.format(route_str)
+ )
match = re.search(r"Nexthop Group ID: (\d+)", output)
- assert match is not None, (
- "Nexthop Group ID not found for sharpd route %s" % route_str
+ assert match is not None, "Nexthop Group ID not found for sharpd route {}".format(
+ route_str
)
nhg_id = int(match.group(1))
@@ -410,7 +428,7 @@ def verify_nexthop_group(nhg_id, recursive=False, ecmp=0):
while not found and count < 10:
count += 1
# Verify NHG is valid/installed
- output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
+ output = net["r1"].cmd('vtysh -c "show nexthop-group rib {}"'.format(nhg_id))
valid = re.search(r"Valid", output)
if valid is None:
found = False
@@ -449,20 +467,24 @@ def verify_nexthop_group(nhg_id, recursive=False, ecmp=0):
continue
found = True
- assert valid is not None, "Nexthop Group ID=%d not marked Valid" % nhg_id
+ assert valid is not None, "Nexthop Group ID={} not marked Valid".format(nhg_id)
if ecmp or recursive:
- assert ecmpcount is not None, "Nexthop Group ID=%d has no depends" % nhg_id
+ assert ecmpcount is not None, "Nexthop Group ID={} has no depends".format(
+ nhg_id
+ )
if ecmp:
- assert len(depends) == ecmp, (
- "Nexthop Group ID=%d doesn't match ecmp size" % nhg_id
- )
+ assert (
+ len(depends) == ecmp
+ ), "Nexthop Group ID={} doesn't match ecmp size".format(nhg_id)
else:
- assert len(depends) == 1, (
- "Nexthop Group ID=%d should only have one recursive depend" % nhg_id
+ assert (
+ len(depends) == 1
+ ), "Nexthop Group ID={} should only have one recursive depend".format(
+ nhg_id
)
else:
- assert installed is not None, (
- "Nexthop Group ID=%d not marked Installed" % nhg_id
+ assert installed is not None, "Nexthop Group ID={} not marked Installed".format(
+ nhg_id
)
@@ -600,7 +622,7 @@ def test_nexthop_groups():
dups = []
nhg_id = route_get_nhg_id("6.6.6.1/32")
while (len(dups) != 4) and count < 10:
- output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
+ output = net["r1"].cmd('vtysh -c "show nexthop-group rib {}"'.format(nhg_id))
dups = re.findall(r"(via 1\.1\.1\.1)", output)
if len(dups) != 4:
@@ -608,9 +630,10 @@ def test_nexthop_groups():
sleep(1)
# Should find 3, itself is inactive
- assert len(dups) == 4, (
- "Route 6.6.6.1/32 with Nexthop Group ID=%d has wrong number of resolved nexthops"
- % nhg_id
+ assert (
+ len(dups) == 4
+ ), "Route 6.6.6.1/32 with Nexthop Group ID={} has wrong number of resolved nexthops".format(
+ nhg_id
)
## Remove all NHG routes
@@ -640,7 +663,7 @@ def test_rip_status():
print("******************************************\n")
failures = 0
for i in range(1, 2):
- refTableFile = "%s/r%s/rip_status.ref" % (thisDir, i)
+ refTableFile = "{}/r{}/rip_status.ref".format(thisDir, i)
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -649,7 +672,7 @@ def test_rip_status():
# Actual output from router
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd('vtysh -c "show ip rip status" 2> /dev/null')
.rstrip()
)
@@ -670,16 +693,20 @@ def test_rip_status():
# Empty string if it matches, otherwise diff contains unified diff
if diff:
- sys.stderr.write("r%s failed IP RIP status check:\n%s\n" % (i, diff))
+ sys.stderr.write(
+ "r{} failed IP RIP status check:\n{}\n".format(i, diff)
+ )
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
- assert failures == 0, "IP RIP status failed for router r%s:\n%s" % (i, diff)
+ assert failures == 0, "IP RIP status failed for router r{}:\n{}".format(
+ i, diff
+ )
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -697,7 +724,7 @@ def test_ripng_status():
print("******************************************\n")
failures = 0
for i in range(1, 2):
- refTableFile = "%s/r%s/ripng_status.ref" % (thisDir, i)
+ refTableFile = "{}/r{}/ripng_status.ref".format(thisDir, i)
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -706,7 +733,7 @@ def test_ripng_status():
# Actual output from router
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd('vtysh -c "show ipv6 ripng status" 2> /dev/null')
.rstrip()
)
@@ -730,20 +757,19 @@ def test_ripng_status():
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
- "r%s failed IPv6 RIPng status check:\n%s\n" % (i, diff)
+ "r{} failed IPv6 RIPng status check:\n{}\n".format(i, diff)
)
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
- assert failures == 0, "IPv6 RIPng status failed for router r%s:\n%s" % (
- i,
- diff,
+ assert failures == 0, "IPv6 RIPng status failed for router r{}:\n{}".format(
+ i, diff
)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -761,7 +787,7 @@ def test_ospfv2_interfaces():
print("******************************************\n")
failures = 0
for i in range(1, 2):
- refTableFile = "%s/r%s/show_ip_ospf_interface.ref" % (thisDir, i)
+ refTableFile = "{}/r{}/show_ip_ospf_interface.ref".format(thisDir, i)
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -770,7 +796,7 @@ def test_ospfv2_interfaces():
# Actual output from router
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd('vtysh -c "show ip ospf interface" 2> /dev/null')
.rstrip()
)
@@ -803,11 +829,11 @@ def test_ospfv2_interfaces():
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
- "r%s failed SHOW IP OSPF INTERFACE check:\n%s\n" % (i, diff)
+ "r{} failed SHOW IP OSPF INTERFACE check:\n{}\n".format(i, diff)
)
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
# Ignoring the issue if told to ignore (ie not yet fixed)
if failures != 0:
@@ -821,11 +847,11 @@ def test_ospfv2_interfaces():
assert (
failures == 0
- ), "SHOW IP OSPF INTERFACE failed for router r%s:\n%s" % (i, diff)
+ ), "SHOW IP OSPF INTERFACE failed for router r{}:\n{}".format(i, diff)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -843,7 +869,7 @@ def test_isis_interfaces():
print("******************************************\n")
failures = 0
for i in range(1, 2):
- refTableFile = "%s/r%s/show_isis_interface_detail.ref" % (thisDir, i)
+ refTableFile = "{}/r{}/show_isis_interface_detail.ref".format(thisDir, i)
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -852,7 +878,7 @@ def test_isis_interfaces():
# Actual output from router
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd('vtysh -c "show isis interface detail" 2> /dev/null')
.rstrip()
)
@@ -876,19 +902,19 @@ def test_isis_interfaces():
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
- "r%s failed SHOW ISIS INTERFACE DETAIL check:\n%s\n" % (i, diff)
+ "r{} failed SHOW ISIS INTERFACE DETAIL check:\n{}\n".format(i, diff)
)
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
assert (
failures == 0
- ), "SHOW ISIS INTERFACE DETAIL failed for router r%s:\n%s" % (i, diff)
+ ), "SHOW ISIS INTERFACE DETAIL failed for router r{}:\n{}".format(i, diff)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -906,7 +932,7 @@ def test_bgp_summary():
print("******************************************\n")
failures = 0
for i in range(1, 2):
- refTableFile = "%s/r%s/show_ip_bgp_summary.ref" % (thisDir, i)
+ refTableFile = "{}/r{}/show_ip_bgp_summary.ref".format(thisDir, i)
if os.path.isfile(refTableFile):
# Read expected result from file
expected_original = open(refTableFile).read().rstrip()
@@ -933,7 +959,7 @@ def test_bgp_summary():
]:
# Actual output from router
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd(
'vtysh -c "show ip bgp summary ' + arguments + '" 2> /dev/null'
)
@@ -1049,22 +1075,19 @@ def test_bgp_summary():
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
- "r%s failed SHOW IP BGP SUMMARY check:\n%s\n" % (i, diff)
+ "r{} failed SHOW IP BGP SUMMARY check:\n{}\n".format(i, diff)
)
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
assert (
failures == 0
- ), "SHOW IP BGP SUMMARY failed for router r%s:\n%s" % (
- i,
- diff,
- )
+ ), "SHOW IP BGP SUMMARY failed for router r{}:\n{}".format(i, diff)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -1082,7 +1105,7 @@ def test_bgp_ipv6_summary():
print("******************************************\n")
failures = 0
for i in range(1, 2):
- refTableFile = "%s/r%s/show_bgp_ipv6_summary.ref" % (thisDir, i)
+ refTableFile = "{}/r{}/show_bgp_ipv6_summary.ref".format(thisDir, i)
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -1091,7 +1114,7 @@ def test_bgp_ipv6_summary():
# Actual output from router
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd('vtysh -c "show bgp ipv6 summary" 2> /dev/null')
.rstrip()
)
@@ -1147,20 +1170,19 @@ def test_bgp_ipv6_summary():
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
- "r%s failed SHOW BGP IPv6 SUMMARY check:\n%s\n" % (i, diff)
+ "r{} failed SHOW BGP IPv6 SUMMARY check:\n{}\n".format(i, diff)
)
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
- assert failures == 0, "SHOW BGP IPv6 SUMMARY failed for router r%s:\n%s" % (
- i,
- diff,
- )
+ assert (
+ failures == 0
+ ), "SHOW BGP IPv6 SUMMARY failed for router r{}:\n{}".format(i, diff)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -1177,11 +1199,13 @@ def test_nht():
thisDir = os.path.dirname(os.path.realpath(__file__))
for i in range(1, 2):
- nhtFile = "%s/r%s/ip_nht.ref" % (thisDir, i)
+ nhtFile = "{}/r{}/ip_nht.ref".format(thisDir, i)
expected = open(nhtFile).read().rstrip()
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
- actual = net["r%s" % i].cmd('vtysh -c "show ip nht" 2> /dev/null').rstrip()
+ actual = (
+ net["r{}".format(i)].cmd('vtysh -c "show ip nht" 2> /dev/null').rstrip()
+ )
actual = re.sub(r"fd [0-9]+", "fd XX", actual)
actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
@@ -1193,15 +1217,17 @@ def test_nht():
)
if diff:
- assert 0, "r%s failed ip nht check:\n%s\n" % (i, diff)
+ assert 0, "r{} failed ip nht check:\n{}\n".format(i, diff)
else:
print("show ip nht is ok\n")
- nhtFile = "%s/r%s/ipv6_nht.ref" % (thisDir, i)
+ nhtFile = "{}/r{}/ipv6_nht.ref".format(thisDir, i)
expected = open(nhtFile).read().rstrip()
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
- actual = net["r%s" % i].cmd('vtysh -c "show ipv6 nht" 2> /dev/null').rstrip()
+ actual = (
+ net["r{}".format(i)].cmd('vtysh -c "show ipv6 nht" 2> /dev/null').rstrip()
+ )
actual = re.sub(r"fd [0-9]+", "fd XX", actual)
actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
@@ -1213,7 +1239,7 @@ def test_nht():
)
if diff:
- assert 0, "r%s failed ipv6 nht check:\n%s\n" % (i, diff)
+ assert 0, "r{} failed ipv6 nht check:\n{}\n".format(i, diff)
else:
print("show ipv6 nht is ok\n")
@@ -1233,7 +1259,7 @@ def test_bgp_ipv4():
diffresult = {}
for i in range(1, 2):
success = 0
- for refTableFile in glob.glob("%s/r%s/show_bgp_ipv4*.ref" % (thisDir, i)):
+ for refTableFile in glob.glob("{}/r{}/show_bgp_ipv4*.ref".format(thisDir, i)):
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -1242,7 +1268,9 @@ def test_bgp_ipv4():
# Actual output from router
actual = (
- net["r%s" % i].cmd('vtysh -c "show bgp ipv4" 2> /dev/null').rstrip()
+ net["r{}".format(i)]
+ .cmd('vtysh -c "show bgp ipv4" 2> /dev/null')
+ .rstrip()
)
# Remove summary line (changed recently)
actual = re.sub(r"Total number.*", "", actual)
@@ -1264,24 +1292,26 @@ def test_bgp_ipv4():
diffresult[refTableFile] = diff
else:
success = 1
- print("template %s matched: r%s ok" % (refTableFile, i))
+ print("template {} matched: r{} ok".format(refTableFile, i))
break
if not success:
resultstr = "No template matched.\n"
for f in diffresult.keys():
- resultstr += "template %s: r%s failed SHOW BGP IPv4 check:\n%s\n" % (
- f,
- i,
- diffresult[f],
+ resultstr += (
+ "template {}: r{} failed SHOW BGP IPv4 check:\n{}\n".format(
+ f,
+ i,
+ diffresult[f],
+ )
)
raise AssertionError(
- "SHOW BGP IPv4 failed for router r%s:\n%s" % (i, resultstr)
+ "SHOW BGP IPv4 failed for router r{}:\n{}".format(i, resultstr)
)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -1300,7 +1330,7 @@ def test_bgp_ipv6():
diffresult = {}
for i in range(1, 2):
success = 0
- for refTableFile in glob.glob("%s/r%s/show_bgp_ipv6*.ref" % (thisDir, i)):
+ for refTableFile in glob.glob("{}/r{}/show_bgp_ipv6*.ref".format(thisDir, i)):
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -1309,7 +1339,9 @@ def test_bgp_ipv6():
# Actual output from router
actual = (
- net["r%s" % i].cmd('vtysh -c "show bgp ipv6" 2> /dev/null').rstrip()
+ net["r{}".format(i)]
+ .cmd('vtysh -c "show bgp ipv6" 2> /dev/null')
+ .rstrip()
)
# Remove summary line (changed recently)
actual = re.sub(r"Total number.*", "", actual)
@@ -1331,23 +1363,25 @@ def test_bgp_ipv6():
diffresult[refTableFile] = diff
else:
success = 1
- print("template %s matched: r%s ok" % (refTableFile, i))
+ print("template {} matched: r{} ok".format(refTableFile, i))
if not success:
resultstr = "No template matched.\n"
for f in diffresult.keys():
- resultstr += "template %s: r%s failed SHOW BGP IPv6 check:\n%s\n" % (
- f,
- i,
- diffresult[f],
+ resultstr += (
+ "template {}: r{} failed SHOW BGP IPv6 check:\n{}\n".format(
+ f,
+ i,
+ diffresult[f],
+ )
)
raise AssertionError(
- "SHOW BGP IPv6 failed for router r%s:\n%s" % (i, resultstr)
+ "SHOW BGP IPv6 failed for router r{}:\n{}".format(i, resultstr)
)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -1364,13 +1398,15 @@ def test_route_map():
print("*******************************************************\n")
failures = 0
for i in range(1, 2):
- refroutemap = "%s/r%s/show_route_map.ref" % (thisDir, i)
+ refroutemap = "{}/r{}/show_route_map.ref".format(thisDir, i)
if os.path.isfile(refroutemap):
expected = open(refroutemap).read().rstrip()
expected = ("\n".join(expected.splitlines()) + "\n").splitlines(1)
actual = (
- net["r%s" % i].cmd('vtysh -c "show route-map" 2> /dev/null').rstrip()
+ net["r{}".format(i)]
+ .cmd('vtysh -c "show route-map" 2> /dev/null')
+ .rstrip()
)
actual = ("\n".join(actual.splitlines()) + "\n").splitlines(1)
@@ -1383,15 +1419,15 @@ def test_route_map():
if diff:
sys.stderr.write(
- "r%s failed show route-map command Check:\n%s\n" % (i, diff)
+ "r{} failed show route-map command Check:\n{}\n".format(i, diff)
)
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
assert (
failures == 0
- ), "Show route-map command failed for router r%s:\n%s" % (i, diff)
+ ), "Show route-map command failed for router r{}:\n{}".format(i, diff)
def test_nexthop_groups_with_route_maps():
@@ -1418,28 +1454,34 @@ def test_nexthop_groups_with_route_maps():
src_str = "192.168.0.1"
net["r1"].cmd(
- 'vtysh -c "c t" -c "route-map NH-SRC permit 111" -c "set src %s"' % src_str
+ 'vtysh -c "c t" -c "route-map NH-SRC permit 111" -c "set src {}"'.format(
+ src_str
+ )
)
net["r1"].cmd('vtysh -c "c t" -c "ip protocol sharp route-map NH-SRC"')
- net["r1"].cmd('vtysh -c "sharp install routes %s nexthop-group test 1"' % route_str)
+ net["r1"].cmd(
+ 'vtysh -c "sharp install routes {} nexthop-group test 1"'.format(route_str)
+ )
- verify_route_nexthop_group("%s/32" % route_str)
+ verify_route_nexthop_group("{}/32".format(route_str))
# Only a valid test on linux using nexthop objects
if sys.platform.startswith("linux"):
- output = net["r1"].cmd("ip route show %s/32" % route_str)
- match = re.search(r"src %s" % src_str, output)
- assert match is not None, "Route %s/32 not installed with src %s" % (
+ output = net["r1"].cmd("ip route show {}/32".format(route_str))
+ match = re.search(r"src {}".format(src_str), output)
+ assert match is not None, "Route {}/32 not installed with src {}".format(
route_str,
src_str,
)
# Remove NHG routes and route-map
- net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % route_str)
+ net["r1"].cmd('vtysh -c "sharp remove routes {} 1"'.format(route_str))
net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NH-SRC"')
net["r1"].cmd(
- 'vtysh -c "c t" -c "no route-map NH-SRC permit 111" # -c "set src %s"' % src_str
+ 'vtysh -c "c t" -c "no route-map NH-SRC permit 111" # -c "set src {}"'.format(
+ src_str
+ )
)
net["r1"].cmd('vtysh -c "c t" -c "no route-map NH-SRC"')
@@ -1449,7 +1491,9 @@ def test_nexthop_groups_with_route_maps():
deny_route_str = "3.3.3.2"
net["r1"].cmd(
- 'vtysh -c "c t" -c "ip prefix-list NOPE seq 5 permit %s/32"' % permit_route_str
+ 'vtysh -c "c t" -c "ip prefix-list NOPE seq 5 permit {}/32"'.format(
+ permit_route_str
+ )
)
net["r1"].cmd(
'vtysh -c "c t" -c "route-map NOPE permit 111" -c "match ip address prefix-list NOPE"'
@@ -1459,35 +1503,42 @@ def test_nexthop_groups_with_route_maps():
# This route should be permitted
net["r1"].cmd(
- 'vtysh -c "sharp install routes %s nexthop-group test 1"' % permit_route_str
+ 'vtysh -c "sharp install routes {} nexthop-group test 1"'.format(
+ permit_route_str
+ )
)
- verify_route_nexthop_group("%s/32" % permit_route_str)
+ verify_route_nexthop_group("{}/32".format(permit_route_str))
# This route should be denied
net["r1"].cmd(
- 'vtysh -c "sharp install routes %s nexthop-group test 1"' % deny_route_str
+ 'vtysh -c "sharp install routes {} nexthop-group test 1"'.format(deny_route_str)
)
nhg_id = route_get_nhg_id(deny_route_str)
- output = net["r1"].cmd('vtysh -c "show nexthop-group rib %d"' % nhg_id)
+ output = net["r1"].cmd('vtysh -c "show nexthop-group rib {}"'.format(nhg_id))
match = re.search(r"Valid", output)
- assert match is None, "Nexthop Group ID=%d should not be marked Valid" % nhg_id
+ assert match is None, "Nexthop Group ID={} should not be marked Valid".format(
+ nhg_id
+ )
match = re.search(r"Installed", output)
- assert match is None, "Nexthop Group ID=%d should not be marked Installed" % nhg_id
+ assert match is None, "Nexthop Group ID={} should not be marked Installed".format(
+ nhg_id
+ )
# Remove NHG routes and route-map
- net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % permit_route_str)
- net["r1"].cmd('vtysh -c "sharp remove routes %s 1"' % deny_route_str)
+ net["r1"].cmd('vtysh -c "sharp remove routes {} 1"'.format(permit_route_str))
+ net["r1"].cmd('vtysh -c "sharp remove routes {} 1"'.format(deny_route_str))
net["r1"].cmd('vtysh -c "c t" -c "no ip protocol sharp route-map NOPE"')
net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE permit 111"')
net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE deny 222"')
net["r1"].cmd('vtysh -c "c t" -c "no route-map NOPE"')
net["r1"].cmd(
- 'vtysh -c "c t" -c "no ip prefix-list NOPE seq 5 permit %s/32"'
- % permit_route_str
+ 'vtysh -c "c t" -c "no ip prefix-list NOPE seq 5 permit {}/32"'.format(
+ permit_route_str
+ )
)
@@ -1550,7 +1601,7 @@ def test_mpls_interfaces():
print("******************************************\n")
failures = 0
for i in range(1, 2):
- refTableFile = "%s/r%s/show_mpls_ldp_interface.ref" % (thisDir, i)
+ refTableFile = "{}/r{}/show_mpls_ldp_interface.ref".format(thisDir, i)
if os.path.isfile(refTableFile):
# Read expected result from file
expected = open(refTableFile).read().rstrip()
@@ -1559,7 +1610,7 @@ def test_mpls_interfaces():
# Actual output from router
actual = (
- net["r%s" % i]
+ net["r{}".format(i)]
.cmd('vtysh -c "show mpls ldp interface" 2> /dev/null')
.rstrip()
)
@@ -1579,22 +1630,22 @@ def test_mpls_interfaces():
# Empty string if it matches, otherwise diff contains unified diff
if diff:
sys.stderr.write(
- "r%s failed MPLS LDP Interface status Check:\n%s\n" % (i, diff)
+ "r{} failed MPLS LDP Interface status Check:\n{}\n".format(i, diff)
)
failures += 1
else:
- print("r%s ok" % i)
+ print("r{} ok".format(i))
if failures > 0:
fatal_error = "MPLS LDP Interface status failed"
assert (
failures == 0
- ), "MPLS LDP Interface status failed for router r%s:\n%s" % (i, diff)
+ ), "MPLS LDP Interface status failed for router r{}:\n{}".format(i, diff)
# Make sure that all daemons are running
for i in range(1, 2):
- fatal_error = net["r%s" % i].checkRouterRunning()
+ fatal_error = net["r{}".format(i)].checkRouterRunning()
assert fatal_error == "", fatal_error
@@ -1707,8 +1758,8 @@ def test_shutdown_check_memleak():
thisDir = os.path.dirname(os.path.realpath(__file__))
for i in range(1, 2):
- net["r%s" % i].stopRouter()
- net["r%s" % i].report_memory_leaks(
+ net["r{}".format(i)].stopRouter()
+ net["r{}".format(i)].report_memory_leaks(
os.environ.get("TOPOTESTS_CHECK_MEMLEAK"), os.path.basename(__file__)
)
diff --git a/tests/topotests/analyze.py b/tests/topotests/analyze.py
index 690786a..a1ac9a2 100755
--- a/tests/topotests/analyze.py
+++ b/tests/topotests/analyze.py
@@ -262,7 +262,7 @@ def main():
capture_output=True,
)
except subprocess.CalledProcessError:
- print(f"{docker_bin} container '{contid}' does not exist")
+ logging.critical(f"{docker_bin} container '{contid}' does not exist")
sys.exit(1)
# If you need container info someday...
# cont_info = json.loads(p.stdout)
@@ -278,7 +278,7 @@ def main():
if scount and args.results and not os.path.exists(args.results):
if not contid:
if not os.path.exists(cppath):
- print(f"'{cppath}' doesn't exist to save")
+ logging.critical(f"'{cppath}' doesn't exist to save")
sys.exit(1)
if args.save_xml:
subprocess.run(["cp", cppath, args.results])
@@ -294,7 +294,7 @@ def main():
capture_output=True,
)
except subprocess.CalledProcessError as error:
- print(f"Can't {docker_bin} cp '{cppath}': %s", str(error))
+ logging.critical(f"Can't {docker_bin} cp '{cppath}': %s", str(error))
sys.exit(1)
if "SUDO_USER" in os.environ:
@@ -303,7 +303,7 @@ def main():
# User doesn't want to save results just use them inplace
if not contid:
if not os.path.exists(cppath):
- print(f"'{cppath}' doesn't exist")
+ logging.critical(f"'{cppath}' doesn't exist")
sys.exit(1)
args.results = cppath
else:
@@ -321,7 +321,7 @@ def main():
capture_output=True,
)
except subprocess.CalledProcessError as error:
- print(f"Can't {docker_bin} cp '{cppath}': %s", str(error))
+ logging.critical(f"Can't {docker_bin} cp '{cppath}': %s", str(error))
sys.exit(1)
args.results = tresname
diff --git a/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json b/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json
index 5cba71e..61be1df 100644
--- a/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json
+++ b/tests/topotests/bfd_bgp_cbit_topo3/r1/bgp_ipv6_routes_down.json
@@ -4,51 +4,6 @@
"localAS": 101,
"routes":
{
- "2001:db8:6::/64": [
- {
- "stale": true,
- "valid": true,
- "bestpath": true,
- "pathFrom": "external",
- "prefix": "2001:db8:6::",
- "prefixLen": 64,
- "network": "2001:db8:6::\/64",
- "metric": 0,
- "weight": 0,
- "peerId": "2001:db8:4::1",
- "origin": "IGP",
- "nexthops": [
- { "ip": "2001:db8:4::1",
- "afi": "ipv6",
- "scope": "global",
- "used": true
- }
- ]
- }
- ],
- "2001:db8:7::/64": [
- {
- "stale": true,
- "valid": true,
- "bestpath": true,
- "pathFrom": "external",
- "prefix": "2001:db8:7::",
- "prefixLen": 64, "network":
- "2001:db8:7::\/64",
- "metric": 0,
- "weight": 0,
- "peerId": "2001:db8:4::1",
- "origin": "IGP",
- "nexthops": [
- {
- "ip": "2001:db8:4::1",
- "afi": "ipv6",
- "scope": "global",
- "used": true
- }
- ]
- }
- ],
"2001:db8:8::/64": [
{
"valid": true,
diff --git a/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json b/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json
index 8eea183..36cdcc3 100644
--- a/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json
+++ b/tests/topotests/bfd_bgp_cbit_topo3/r1/ipv6_routes.json
@@ -32,49 +32,5 @@
}
]
}
- ],
- "2001:db8:6::/64": [{
- "distance": 20,
- "protocol": "bgp",
- "metric": 0,
- "selected": true,
- "destSelected": true,
- "prefix": "2001:db8:6::/64",
- "nexthops": [{
- "ip":"2001:db8:4::1",
- "active": true,
- "afi": "ipv6",
- "recursive":true
- },
- {
- "fib":true,
- "ip":"2001:db8:1::2",
- "afi": "ipv6",
- "interfaceName": "r1-eth0"
- }
- ]
- }
- ],
- "2001:db8:7::/64": [{
- "distance": 20,
- "protocol": "bgp",
- "metric": 0,
- "selected": true,
- "destSelected": true,
- "prefix": "2001:db8:7::/64",
- "nexthops": [{
- "ip":"2001:db8:4::1",
- "active": true,
- "afi": "ipv6",
- "recursive": true
- },
- {
- "fib":true,
- "ip":"2001:db8:1::2",
- "afi": "ipv6",
- "interfaceName":"r1-eth0"
- }
- ]
- }
]
}
diff --git a/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py b/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py
index 906687d..d478e99 100644
--- a/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py
+++ b/tests/topotests/bfd_bgp_cbit_topo3/test_bfd_bgp_cbit_topo3.py
@@ -122,21 +122,23 @@ def test_bfd_connection():
def test_bfd_loss_intermediate():
"""
- Assert that BFD notices the bfd link down failure.
- but BGP entries should still be present
+ Assert that BGP notices the BFD link down failure.
+ The BGP entries should be flushed as the C-bit is set in both directions.
"""
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
r1 = tgen.gears["r1"]
- expected = { "as":101, "peers":{ "2001:db8:4::1": { "state":"Established" } } }
- test_func = partial(topotest.router_json_cmp, r1, "show bgp ipv6 uni summ json", expected)
+ expected = {"as": 101, "peers": {"2001:db8:4::1": {"state": "Established"}}}
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show bgp ipv6 uni summ json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
- assertmsg ='"r1" has not established bgp peering yet'
+ assertmsg = '"r1" has not established bgp peering yet'
assert result is None, assertmsg
- #assert False
+ # assert False
logger.info("removing IPv6 address from r2 to simulate loss of connectivity")
# Disable r2-eth0 ipv6 address
cmd = 'vtysh -c "configure terminal" -c "interface r2-eth1" -c "no ipv6 address 2001:db8:4::2/64"'
@@ -160,7 +162,7 @@ def test_bfd_loss_intermediate():
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
- logger.info("waiting for BGP entries to become stale")
+ logger.info("waiting for BGP entries to be removed")
for router in tgen.routers().values():
if router.name == "r2":
continue
diff --git a/tests/topotests/bfd_topo3/test_bfd_topo3.py b/tests/topotests/bfd_topo3/test_bfd_topo3.py
index f767b0e..d7b2542 100644
--- a/tests/topotests/bfd_topo3/test_bfd_topo3.py
+++ b/tests/topotests/bfd_topo3/test_bfd_topo3.py
@@ -189,7 +189,7 @@ def test_wait_bfd_convergence():
"show bfd peers json",
bfd_config,
)
- _, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=200, wait=1)
assertmsg = '"{}" BFD configuration failure'.format(router)
assert result is None, assertmsg
diff --git a/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
index 30f4a2f..fee5f2d 100644
--- a/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
+++ b/tests/topotests/bfd_vrflite_topo1/test_bfd_vrflite_topo1.py
@@ -81,8 +81,7 @@ def setup_module(mod):
for rname, router in router_list.items():
router.load_config(
- TopoRouter.RD_ZEBRA,
- os.path.join(CWD, "{}/zebra.conf".format(rname))
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
router.load_config(
TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
@@ -114,8 +113,8 @@ def test_bfd_connection():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("waiting for bfd peers to go up")
- router = tgen.gears['r1']
- json_file = "{}/{}/bfd_peers_status.json".format(CWD, 'r1')
+ router = tgen.gears["r1"]
+ json_file = "{}/{}/bfd_peers_status.json".format(CWD, "r1")
expected = json.loads(open(json_file).read())
test_func = partial(
diff --git a/eigrpd/eigrp_pkt_tlv1.c b/tests/topotests/bgp_6vpe_ebgp_topo1/__init__.py
index e69de29..e69de29 100644
--- a/eigrpd/eigrp_pkt_tlv1.c
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/__init__.py
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/h1/zebra.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/h1/zebra.conf
new file mode 100644
index 0000000..06a23bb
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/h1/zebra.conf
@@ -0,0 +1,4 @@
+ipv6 route fd00:200::/64 fd00:100::2
+interface eth-pe1
+ ipv6 address fd00:100::1/64
+!
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/h2/zebra.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/h2/zebra.conf
new file mode 100644
index 0000000..2dadfc4
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/h2/zebra.conf
@@ -0,0 +1,8 @@
+ipv6 route fd00:100::/64 fd00:200::5
+interface eth-pe2
+ ipv6 address fd00:200::6/64
+ ipv6 address fd00:201::6/64
+ ipv6 address fd00:300::6/64
+ ipv6 address fd00:400::6/64
+ ipv6 address fd01:200::6/64
+!
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_summary.json b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_summary.json
new file mode 100644
index 0000000..c2100ad
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_summary.json
@@ -0,0 +1,13 @@
+{
+ "ipv6Vpn": {
+ "routerId": "198.51.100.2",
+ "as": 65500,
+ "peers": {
+ "192.0.2.5": {
+ "remoteAs": 65501,
+ "state": "Established",
+ "peerState": "OK"
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_vrf_ipv6.json b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_vrf_ipv6.json
new file mode 100644
index 0000000..c6e776d
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgp_vrf_ipv6.json
@@ -0,0 +1,116 @@
+{
+ "vrfName": "vrf1",
+ "routerId": "198.51.100.2",
+ "defaultLocPrf": 100,
+ "localAS": 65500,
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:100::/64",
+ "metric": 0,
+ "weight": 32768,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:200::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:200::/64",
+ "metric": 0,
+ "weight": 0,
+ "path": "65501",
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:201::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:201::/64",
+ "metric": 0,
+ "weight": 0,
+ "path": "65501",
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:300::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:300::/64",
+ "metric": 0,
+ "weight": 0,
+ "path": "65501",
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:400::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:400::/64",
+ "metric": 0,
+ "weight": 0,
+ "path": "65501",
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd01:200::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd01:200::/64",
+ "metric": 0,
+ "weight": 0,
+ "path": "65501",
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgpd.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgpd.conf
new file mode 100644
index 0000000..26e94d4
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/bgpd.conf
@@ -0,0 +1,32 @@
+!
+!debug bgp zebra
+router bgp 65500
+ bgp router-id 198.51.100.2
+ no bgp ebgp-requires-policy
+ neighbor 192.0.2.5 remote-as 65501
+ neighbor 192.0.2.5 capability extended-nexthop
+ address-family ipv4 unicast
+ no neighbor 192.0.2.5 activate
+ exit-address-family
+ address-family ipv6 vpn
+ neighbor 192.0.2.5 activate
+ neighbor 192.0.2.5 route-map rmap in
+ exit-address-family
+exit
+router bgp 65500 vrf vrf1
+ bgp router-id 198.51.100.2
+ address-family ipv6 unicast
+ redistribute connected
+ label vpn export 101
+ rd vpn export 444:1
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+!
+interface eth-pe2
+ mpls bgp forwarding
+!
+route-map rmap permit 1
+ set ipv6 next-hop prefer-global
+!
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/ipv6_routes_vrf.json b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/ipv6_routes_vrf.json
new file mode 100644
index 0000000..1545749
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/ipv6_routes_vrf.json
@@ -0,0 +1,142 @@
+{
+ "fd00:100::/64": [
+ {
+ "prefix": "fd00:100::/64",
+ "protocol": "connected",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "nexthops": [
+ {
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "eth-h1",
+ "active": true
+ }
+ ]
+ }
+ ],
+ "fd00:200::/64": [
+ {
+ "prefix": "fd00:200::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "vrf": "default",
+ "active": true,
+ "labels": [
+ 102
+ ],
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "fd00:201::/64": [
+ {
+ "prefix": "fd00:201::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "vrf": "default",
+ "active": true,
+ "labels": [
+ 102
+ ],
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "fd00:300::/64": [
+ {
+ "prefix": "fd00:300::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "vrf": "default",
+ "active": true,
+ "labels": [
+ 102
+ ],
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "fd00:400::/64": [
+ {
+ "prefix": "fd00:400::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "vrf": "default",
+ "active": true,
+ "labels": [
+ 102
+ ],
+ "weight": 1
+ }
+ ]
+ }
+ ],
+ "fd01:200::/64": [
+ {
+ "prefix": "fd01:200::/64",
+ "protocol": "bgp",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "installed": true,
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:205",
+ "afi": "ipv6",
+ "vrf": "default",
+ "active": true,
+ "labels": [
+ 102
+ ],
+ "weight": 1
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/isisd.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/isisd.conf
new file mode 100644
index 0000000..61f2fe7
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/isisd.conf
@@ -0,0 +1,23 @@
+!
+interface lo
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+interface eth-pe2
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+router isis 1
+ net 49.0000.0007.e901.2222.00
+ is-type level-1
+ lsp-gen-interval 1
+ mpls-te on
+ mpls-te router-address 198.51.100.2
+ segment-routing on
+ segment-routing node-msd 8
+ segment-routing global-block 1000 10000 local-block 30000 30999
+ segment-routing prefix 198.51.100.2/32 index 22
+!
+
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/zebra.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/zebra.conf
new file mode 100644
index 0000000..7ddd98f
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe1/zebra.conf
@@ -0,0 +1,11 @@
+!
+interface eth-h1
+ ipv6 address fd00:100::2/64
+!
+interface eth-pe2
+ ip address 192.0.2.2/24
+ ipv6 address ::ffff:192.0.2.2/120
+!
+interface lo
+ ip address 198.51.100.2/32
+!
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_summary.json b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_summary.json
new file mode 100644
index 0000000..d740794
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_summary.json
@@ -0,0 +1,13 @@
+{
+ "ipv6Vpn": {
+ "routerId": "198.51.100.5",
+ "as": 65501,
+ "peers": {
+ "192.0.2.2": {
+ "remoteAs": 65500,
+ "state": "Established",
+ "peerState": "OK"
+ }
+ }
+ }
+}
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_vrf_ipv6.json b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_vrf_ipv6.json
new file mode 100644
index 0000000..ec42999
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgp_vrf_ipv6.json
@@ -0,0 +1,116 @@
+{
+ "vrfName": "vrf1",
+ "routerId": "198.51.100.5",
+ "defaultLocPrf": 100,
+ "localAS": 65501,
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:100::/64",
+ "metric": 0,
+ "weight": 0,
+ "path": "65500",
+ "nexthops": [
+ {
+ "ip": "::ffff:c000:202",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:200::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:200::/64",
+ "metric": 0,
+ "weight": 32768,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:201::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:201::/64",
+ "metric": 0,
+ "weight": 32768,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:300::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:300::/64",
+ "metric": 0,
+ "weight": 32768,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:400::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd00:400::/64",
+ "metric": 0,
+ "weight": 32768,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd01:200::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "network": "fd01:200::/64",
+ "metric": 0,
+ "weight": 32768,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgpd.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgpd.conf
new file mode 100644
index 0000000..03b63af
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/bgpd.conf
@@ -0,0 +1,31 @@
+!
+router bgp 65501
+ bgp router-id 198.51.100.5
+ no bgp ebgp-requires-policy
+ neighbor 192.0.2.2 remote-as 65500
+ neighbor 192.0.2.2 capability extended-nexthop
+ address-family ipv4 unicast
+ no neighbor 192.0.2.2 activate
+ exit-address-family
+ address-family ipv6 vpn
+ neighbor 192.0.2.2 activate
+ neighbor 192.0.2.2 route-map rmap in
+ exit-address-family
+exit
+router bgp 65501 vrf vrf1
+ bgp router-id 198.51.100.5
+ address-family ipv6 unicast
+ redistribute connected
+ label vpn export 102
+ rd vpn export 444:2
+ rt vpn both 52:100
+ export vpn
+ import vpn
+exit-address-family
+!
+interface eth-pe1
+ mpls bgp forwarding
+!
+route-map rmap permit 1
+ set ipv6 next-hop prefer-global
+! \ No newline at end of file
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/isisd.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/isisd.conf
new file mode 100644
index 0000000..f210554
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/isisd.conf
@@ -0,0 +1,22 @@
+!
+interface lo
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+interface eth-pe1
+ ip router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+router isis 1
+ net 49.0000.0007.e901.5555.00
+ is-type level-1
+ lsp-gen-interval 1
+ mpls-te on
+ mpls-te router-address 198.51.100.5
+ segment-routing on
+ segment-routing node-msd 8
+ segment-routing global-block 1000 10000 local-block 33000 33999
+ segment-routing prefix 198.51.100.5/32 index 55
+!
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/zebra.conf b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/zebra.conf
new file mode 100644
index 0000000..bf20638
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/pe2/zebra.conf
@@ -0,0 +1,15 @@
+!
+interface eth-h2
+ ipv6 address fd00:200::5/64
+ ipv6 address fd00:201::5/64
+ ipv6 address fd00:300::5/64
+ ipv6 address fd00:400::5/64
+ ipv6 address fd01:200::5/64
+!
+interface eth-pe1
+ ip address 192.0.2.5/24
+ ipv6 address ::ffff:192.0.2.5/120
+!
+interface lo
+ ip address 198.51.100.5/32
+!
diff --git a/tests/topotests/bgp_6vpe_ebgp_topo1/test_bgp_6vpe_ebgp_topo1.py b/tests/topotests/bgp_6vpe_ebgp_topo1/test_bgp_6vpe_ebgp_topo1.py
new file mode 100644
index 0000000..cbed8f0
--- /dev/null
+++ b/tests/topotests/bgp_6vpe_ebgp_topo1/test_bgp_6vpe_ebgp_topo1.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2023 by 6WIND
+#
+
+"""
+Test the FRR BGP 6VPE functionality
+"""
+
+import os
+import sys
+import json
+import functools
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# 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.checkping import check_ping
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.isisd]
+
+
+def build_topo(tgen):
+ """
+ +---+ +---+ +---+ +---+
+ | h1|----|pe1|----|pe2|----| h2|
+ +---+ +---+ +---+ +---+
+ """
+
+ def connect_routers(tgen, left, right):
+ pe = None
+ host = None
+ for rname in [left, right]:
+ if rname not in tgen.routers().keys():
+ tgen.add_router(rname)
+ if "pe" in rname:
+ pe = tgen.gears[rname]
+ if "h" in rname:
+ host = tgen.gears[rname]
+
+ switch = tgen.add_switch("s-{}-{}".format(left, right))
+ switch.add_link(tgen.gears[left], nodeif="eth-{}".format(right))
+ switch.add_link(tgen.gears[right], nodeif="eth-{}".format(left))
+
+ if pe and host:
+ pe.cmd("ip link add vrf1 type vrf table 10")
+ pe.cmd("ip link set vrf1 up")
+ pe.cmd("ip link set dev eth-{} master vrf1".format(host.name))
+
+ if "p" in left and "p" in right:
+ # PE <-> P or P <-> P
+ tgen.gears[left].run("sysctl -w net.mpls.conf.eth-{}.input=1".format(right))
+ tgen.gears[right].run("sysctl -w net.mpls.conf.eth-{}.input=1".format(left))
+
+ connect_routers(tgen, "h1", "pe1")
+ connect_routers(tgen, "pe1", "pe2")
+ connect_routers(tgen, "pe2", "h2")
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+ logger.info("setup_module")
+
+ for rname, router in tgen.routers().items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ if "h" in rname:
+ # hosts
+ continue
+
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_convergence():
+ "Assert that BGP is converging."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for bgp peers to go up")
+
+ router_list = ["pe1", "pe2"]
+
+ for name in router_list:
+ router = tgen.gears[name]
+ ref_file = "{}/{}/bgp_summary.json".format(CWD, router.name)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, router, "show bgp summary json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=90, wait=1)
+ assertmsg = "{}: bgp did not converge".format(router.name)
+ assert res is None, assertmsg
+
+
+def test_bgp_ipv6_vpn():
+ "Assert that BGP is exchanging BGP route."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for bgp peers exchanging UPDATES")
+
+ router_list = ["pe1", "pe2"]
+
+ for name in router_list:
+ router = tgen.gears[name]
+ ref_file = "{}/{}/bgp_vrf_ipv6.json".format(CWD, router.name)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp vrf vrf1 ipv6 unicast json",
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = "{}: BGP UPDATE exchange failure".format(router.name)
+ assert res is None, assertmsg
+
+
+def test_zebra_ipv6_installed():
+ "Assert that routes are installed."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+ pe1 = tgen.gears["pe1"]
+ logger.info("check ipv6 routes installed on pe1")
+
+ ref_file = "{}/{}/ipv6_routes_vrf.json".format(CWD, pe1.name)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp, pe1, "show ipv6 route vrf vrf1 json", expected
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = "{}: Zebra Installation failure on vrf vrf1".format(pe1.name)
+ assert res is None, assertmsg
+
+
+def test_bgp_ping6_ok():
+ "Check that h1 pings h2"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ check_ping("h1", "fd00:200::6", True, 5, 1)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/eigrpd/eigrp_pkt_tlv2.c b/tests/topotests/bgp_addpath_paths_limit/__init__.py
index e69de29..e69de29 100644
--- a/eigrpd/eigrp_pkt_tlv2.c
+++ b/tests/topotests/bgp_addpath_paths_limit/__init__.py
diff --git a/tests/topotests/bgp_addpath_paths_limit/r1/frr.conf b/tests/topotests/bgp_addpath_paths_limit/r1/frr.conf
new file mode 100644
index 0000000..65beb7f
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/r1/frr.conf
@@ -0,0 +1,13 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+router bgp 65001
+ timers bgp 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers connect 5
+ address-family ipv4 unicast
+ neighbor 192.168.1.2 addpath-rx-paths-limit 2
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_addpath_paths_limit/r2/frr.conf b/tests/topotests/bgp_addpath_paths_limit/r2/frr.conf
new file mode 100644
index 0000000..796b4d0
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/r2/frr.conf
@@ -0,0 +1,37 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+int r2-eth1
+ ip address 192.168.2.2/24
+!
+int r2-eth2
+ ip address 192.168.7.2/24
+!
+router bgp 65002
+ timers bgp 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.7.7 remote-as external
+ neighbor 192.168.7.7 timers connect 5
+ neighbor 192.168.2.3 remote-as external
+ neighbor 192.168.2.3 timers connect 5
+ neighbor 192.168.2.3 weight 3
+ neighbor 192.168.2.4 remote-as external
+ neighbor 192.168.2.4 timers connect 5
+ neighbor 192.168.2.4 weight 4
+ neighbor 192.168.2.5 remote-as external
+ neighbor 192.168.2.5 timers connect 5
+ neighbor 192.168.2.5 weight 5
+ neighbor 192.168.2.6 remote-as external
+ neighbor 192.168.2.6 timers connect 5
+ neighbor 192.168.2.6 weight 6
+ address-family ipv4 unicast
+ neighbor 192.168.1.1 addpath-tx-all-paths
+ neighbor 192.168.1.1 prefix-list announce out
+ neighbor 192.168.7.7 addpath-tx-all-paths
+ neighbor 192.168.7.7 prefix-list announce out
+ exit-address-family
+!
+ip prefix-list announce seq 5 permit 172.16.16.254/32
+!
diff --git a/tests/topotests/bgp_addpath_paths_limit/r3/frr.conf b/tests/topotests/bgp_addpath_paths_limit/r3/frr.conf
new file mode 100644
index 0000000..4d834d3
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/r3/frr.conf
@@ -0,0 +1,16 @@
+!
+int lo
+ ip address 172.16.16.254/32
+!
+int r3-eth0
+ ip address 192.168.2.3/24
+!
+router bgp 65003
+ timers bgp 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers connect 5
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_addpath_paths_limit/r4/frr.conf b/tests/topotests/bgp_addpath_paths_limit/r4/frr.conf
new file mode 100644
index 0000000..01e0aa9
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/r4/frr.conf
@@ -0,0 +1,16 @@
+!
+int lo
+ ip address 172.16.16.254/32
+!
+int r4-eth0
+ ip address 192.168.2.4/24
+!
+router bgp 65004
+ timers bgp 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers connect 5
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_addpath_paths_limit/r5/frr.conf b/tests/topotests/bgp_addpath_paths_limit/r5/frr.conf
new file mode 100644
index 0000000..02bb847
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/r5/frr.conf
@@ -0,0 +1,16 @@
+!
+int lo
+ ip address 172.16.16.254/32
+!
+int r5-eth0
+ ip address 192.168.2.5/24
+!
+router bgp 65005
+ timers bgp 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers connect 5
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_addpath_paths_limit/r6/frr.conf b/tests/topotests/bgp_addpath_paths_limit/r6/frr.conf
new file mode 100644
index 0000000..39fdbcc
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/r6/frr.conf
@@ -0,0 +1,16 @@
+!
+int lo
+ ip address 172.16.16.254/32
+!
+int r6-eth0
+ ip address 192.168.2.6/24
+!
+router bgp 65006
+ timers bgp 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers connect 5
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_addpath_paths_limit/r7/frr.conf b/tests/topotests/bgp_addpath_paths_limit/r7/frr.conf
new file mode 100644
index 0000000..8c44566
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/r7/frr.conf
@@ -0,0 +1,13 @@
+!
+int r7-eth0
+ ip address 192.168.7.7/24
+!
+router bgp 65007
+ timers bgp 3 10
+ no bgp ebgp-requires-policy
+ neighbor 192.168.7.2 remote-as external
+ neighbor 192.168.7.2 timers connect 5
+ address-family ipv4 unicast
+ neighbor 192.168.7.2 addpath-rx-paths-limit 3
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_addpath_paths_limit/test_bgp_addpath_paths_limit.py b/tests/topotests/bgp_addpath_paths_limit/test_bgp_addpath_paths_limit.py
new file mode 100644
index 0000000..b7a1cfb
--- /dev/null
+++ b/tests/topotests/bgp_addpath_paths_limit/test_bgp_addpath_paths_limit.py
@@ -0,0 +1,128 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+"""
+Test if Paths-Limit capability works as expected.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 8):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+ switch.add_link(tgen.gears["r5"])
+ switch.add_link(tgen.gears["r6"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r7"])
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_addpath_paths_limit():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+ r7 = tgen.gears["r7"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.7.7": {
+ "neighborCapabilities": {
+ "pathsLimit": {
+ "ipv4Unicast": {
+ "advertisedAndReceived": True,
+ "advertisedPathsLimit": 0,
+ "receivedPathsLimit": 3,
+ }
+ }
+ }
+ },
+ "192.168.1.1": {
+ "neighborCapabilities": {
+ "pathsLimit": {
+ "ipv4Unicast": {
+ "advertisedAndReceived": True,
+ "advertisedPathsLimit": 0,
+ "receivedPathsLimit": 2,
+ }
+ }
+ }
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge initially"
+
+ def _bgp_check_received_routes(router, expected):
+ output = json.loads(
+ router.vtysh_cmd("show bgp ipv4 unicast 172.16.16.254/32 json")
+ )
+
+ if "paths" not in output:
+ return "No paths received"
+
+ return topotest.json_cmp(len(output["paths"]), expected)
+
+ test_func = functools.partial(_bgp_check_received_routes, r1, 2)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Received routes count is not as expected"
+
+ test_func = functools.partial(_bgp_check_received_routes, r7, 3)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Received routes count is not as expected"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py
index 5d5f165..4883e84 100644
--- a/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py
+++ b/tests/topotests/bgp_asdot_regex/test_bgp_asdot_regex.py
@@ -44,8 +44,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/bgp_bmp/r1/bgpd.conf b/tests/topotests/bgp_bmp/r1/bgpd.conf
index 69acf6e..24505de 100644
--- a/tests/topotests/bgp_bmp/r1/bgpd.conf
+++ b/tests/topotests/bgp_bmp/r1/bgpd.conf
@@ -6,9 +6,17 @@ router bgp 65501
neighbor 192:168::2 remote-as 65502
!
bmp targets bmp1
- bmp connect 192.0.178.10 port 1789 min-retry 100 max-retry 10000
+ bmp connect 192.0.2.10 port 1789 min-retry 100 max-retry 10000
exit
!
+ address-family ipv4 vpn
+ neighbor 192.168.0.2 activate
+ neighbor 192.168.0.2 soft-reconfiguration inbound
+ exit-address-family
+ address-family ipv6 vpn
+ neighbor 192:168::2 activate
+ neighbor 192:168::2 soft-reconfiguration inbound
+ exit-address-family
address-family ipv4 unicast
neighbor 192.168.0.2 activate
neighbor 192.168.0.2 soft-reconfiguration inbound
@@ -20,3 +28,21 @@ router bgp 65501
neighbor 192:168::2 soft-reconfiguration inbound
exit-address-family
!
+router bgp 65502 vrf vrf1
+ bgp router_id 192.168.0.1
+ bgp log-neighbor-changes
+ address-family ipv4 unicast
+ label vpn export 101
+ rd vpn export 444:1
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+ address-family ipv6 unicast
+ label vpn export 103
+ rd vpn export 555:1
+ rt vpn both 54:200
+ export vpn
+ import vpn
+ exit-address-family
+exit
diff --git a/tests/topotests/bgp_bmp/r1/zebra.conf b/tests/topotests/bgp_bmp/r1/zebra.conf
index 6a25a6f..0b523c9 100644
--- a/tests/topotests/bgp_bmp/r1/zebra.conf
+++ b/tests/topotests/bgp_bmp/r1/zebra.conf
@@ -1,5 +1,5 @@
interface r1-eth0
- ip address 192.0.178.1/24
+ ip address 192.0.2.1/24
!
interface r1-eth1
ip address 192.168.0.1/24
diff --git a/tests/topotests/bgp_bmp/r2/bgpd.conf b/tests/topotests/bgp_bmp/r2/bgpd.conf
index 7c8255a..40e2cd5 100644
--- a/tests/topotests/bgp_bmp/r2/bgpd.conf
+++ b/tests/topotests/bgp_bmp/r2/bgpd.conf
@@ -12,8 +12,35 @@ router bgp 65502
redistribute connected
exit-address-family
!
+ address-family ipv4 vpn
+ neighbor 192.168.0.1 activate
+ exit-address-family
+!
+ address-family ipv6 vpn
+ neighbor 192:168::1 activate
+ exit-address-family
+!
address-family ipv6 unicast
neighbor 192:168::1 activate
redistribute connected
exit-address-family
!
+router bgp 65502 vrf vrf1
+ bgp router-id 192.168.0.2
+ bgp log-neighbor-changes
+ no bgp network import-check
+ address-family ipv4 unicast
+ label vpn export 102
+ rd vpn export 444:2
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+ address-family ipv6 unicast
+ label vpn export 105
+ rd vpn export 555:2
+ rt vpn both 54:200
+ export vpn
+ import vpn
+ exit-address-family
+exit
diff --git a/tests/topotests/bgp_bmp/test_bgp_bmp.py b/tests/topotests/bgp_bmp/test_bgp_bmp.py
index 250f1cb..02de805 100644
--- a/tests/topotests/bgp_bmp/test_bgp_bmp.py
+++ b/tests/topotests/bgp_bmp/test_bgp_bmp.py
@@ -55,7 +55,7 @@ LOC_RIB = "loc-rib"
def build_topo(tgen):
tgen.add_router("r1")
tgen.add_router("r2")
- tgen.add_bmp_server("bmp1", ip="192.0.178.10", defaultRoute="via 192.0.178.1")
+ tgen.add_bmp_server("bmp1", ip="192.0.2.10", defaultRoute="via 192.0.2.1")
switch = tgen.add_switch("s1")
switch.add_link(tgen.gears["r1"])
@@ -81,8 +81,8 @@ def setup_module(mod):
tgen.start_router()
logger.info("starting BMP servers")
- for _, server in tgen.get_bmp_servers().items():
- server.start()
+ for bmp_name, server in tgen.get_bmp_servers().items():
+ server.start(log_file=os.path.join(tgen.logdir, bmp_name, "bmp.log"))
def teardown_module(_mod):
@@ -105,7 +105,9 @@ def get_bmp_messages():
"""
messages = []
tgen = get_topogen()
- text_output = tgen.gears["bmp1"].run("cat /var/log/bmp.log")
+ text_output = tgen.gears["bmp1"].run(
+ "cat {}".format(os.path.join(tgen.logdir, "bmp1", "bmp.log"))
+ )
for m in text_output.splitlines():
# some output in the bash can break the message decoding
@@ -121,7 +123,7 @@ def get_bmp_messages():
return messages
-def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
+def check_for_prefixes(expected_prefixes, bmp_log_type, policy, labels=None):
"""
Check for the presence of the given prefixes in the BMP server logs with
the given message type and the set policy.
@@ -140,6 +142,12 @@ def check_for_prefixes(expected_prefixes, bmp_log_type, policy):
and "bmp_log_type" in m.keys()
and m["bmp_log_type"] == bmp_log_type
and m["policy"] == policy
+ and (
+ labels is None
+ or (
+ m["ip_prefix"] in labels.keys() and m["label"] == labels[m["ip_prefix"]]
+ )
+ )
]
# check for prefixes
@@ -174,7 +182,7 @@ def configure_prefixes(tgen, node, asn, safi, prefixes, vrf=None, update=True):
Configure the bgp prefixes.
"""
withdraw = "no " if not update else ""
- vrf = " vrf {}" if vrf else ""
+ vrf = " vrf {}".format(vrf) if vrf else ""
for p in prefixes:
ip = ip_network(p)
cmd = [
@@ -216,6 +224,45 @@ def unicast_prefixes(policy):
assert success, "Checking the withdrawed prefixes has been failed !."
+def vpn_prefixes(policy):
+ """
+ Setup the BMP monitor policy, Add and withdraw ipv4/v6 prefixes.
+ Check if the previous actions are logged in the BMP server with the right
+ message type and the right policy.
+ """
+ tgen = get_topogen()
+ set_bmp_policy(tgen, "r1", 65501, "bmp1", "vpn", policy)
+
+ prefixes = ["172.31.10.1/32", "2001::2222/128"]
+
+ if policy == PRE_POLICY:
+ # labels are not yet supported in adj-RIB-in. Do not test for the moment
+ labels = None
+ else:
+ # "label vpn export" value in r2/bgpd.conf
+ labels = {
+ "172.31.10.1/32": 102,
+ "2001::2222/128": 105,
+ }
+
+ # add prefixes
+ configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, vrf="vrf1")
+
+ logger.info("checking for updated prefixes")
+ # check
+ test_func = partial(check_for_prefixes, prefixes, "update", policy, labels=labels)
+ success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
+ assert success, "Checking the updated prefixes has been failed !."
+
+ # withdraw prefixes
+ configure_prefixes(tgen, "r2", 65502, "unicast", prefixes, vrf="vrf1", update=False)
+ logger.info("checking for withdrawed prefixes")
+ # check
+ test_func = partial(check_for_prefixes, prefixes, "withdraw", policy)
+ success, _ = topotest.run_and_expect(test_func, True, wait=0.5)
+ assert success, "Checking the withdrawed prefixes has been failed !."
+
+
def test_bmp_server_logging():
"""
Assert the logging of the bmp server.
@@ -223,7 +270,9 @@ def test_bmp_server_logging():
def check_for_log_file():
tgen = get_topogen()
- output = tgen.gears["bmp1"].run("ls /var/log/")
+ output = tgen.gears["bmp1"].run(
+ "ls {}".format(os.path.join(tgen.logdir, "bmp1"))
+ )
if "bmp.log" not in output:
return False
return True
@@ -244,6 +293,16 @@ def test_bmp_bgp_unicast():
unicast_prefixes(LOC_RIB)
+def test_bmp_bgp_vpn():
+ # check for the prefixes in the BMP server logging file
+ logger.info("***** VPN prefixes pre-policy logging *****")
+ vpn_prefixes(PRE_POLICY)
+ logger.info("***** VPN prefixes post-policy logging *****")
+ vpn_prefixes(POST_POLICY)
+ logger.info("***** VPN prefixes loc-rib logging *****")
+ vpn_prefixes(LOC_RIB)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py
index 6d17cdb..e0c1b49 100644
--- a/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py
+++ b/tests/topotests/bgp_color_extcommunities/test_bgp_color_extcommunities.py
@@ -117,7 +117,9 @@ def test_bgp_color_extended_communities():
test_func = functools.partial(_bgp_check_route, r2, True)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
- assert result is None, "10.10.10.0/24 ext community is correctly not installed, but SHOULD be"
+ assert (
+ result is None
+ ), "10.10.10.0/24 ext community is correctly not installed, but SHOULD be"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py
index 000ea60..fdae9a3 100644
--- a/tests/topotests/bgp_community_alias/test_bgp-community-alias.py
+++ b/tests/topotests/bgp_community_alias/test_bgp-community-alias.py
@@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py b/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py
index 4180bfc..e9114bd 100644
--- a/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py
+++ b/tests/topotests/bgp_conditional_advertisement_static_route/test_bgp_conditional_advertisement_static_route.py
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2"), "s2": ("r2", "r3")}
diff --git a/tests/topotests/bgp_confed1/r2/bgpd.conf b/tests/topotests/bgp_confed1/r2/bgpd.conf
index fe13dfe..ba2da41 100644
--- a/tests/topotests/bgp_confed1/r2/bgpd.conf
+++ b/tests/topotests/bgp_confed1/r2/bgpd.conf
@@ -4,7 +4,6 @@
!debug bgp updates out
!
router bgp 200
- no bgp ebgp-requires-policy
bgp confederation identifier 300
bgp confederation peers 300
neighbor 192.0.2.1 remote-as 100
@@ -12,7 +11,9 @@ router bgp 200
!
address-family ipv4 unicast
network 203.0.113.16/28
+ neighbor 192.0.2.1 route-map any in
+ neighbor 192.0.2.1 route-map any out
neighbor 192.0.2.18 default-originate
exit-address-family
!
-
+route-map any permit 10
diff --git a/tests/topotests/bgp_confed1/test_bgp_confed1.py b/tests/topotests/bgp_confed1/test_bgp_confed1.py
index 57a8522..7b37f4f 100644
--- a/tests/topotests/bgp_confed1/test_bgp_confed1.py
+++ b/tests/topotests/bgp_confed1/test_bgp_confed1.py
@@ -32,7 +32,7 @@ pytestmark = [pytest.mark.bgpd]
def build_topo(tgen):
- for routern in range(1, 5):
+ for routern in range(1, 5):
tgen.add_router("r{}".format(routern))
switch = tgen.add_switch("s1")
@@ -47,8 +47,8 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r3"])
-def setup_module(mod):
+def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
@@ -67,6 +67,7 @@ def setup_module(mod):
# Initialize all routers.
tgen.start_router()
+
def teardown_module(_mod):
"Teardown the pytest environment"
tgen = get_topogen()
diff --git a/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py b/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py
index 5310d3b..7bc0050 100644
--- a/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py
+++ b/tests/topotests/bgp_confederation_astype/test_bgp_confederation_astype.py
@@ -18,7 +18,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r3")}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step10/show_ip_route.ref.diff b/tests/topotests/bgp_dampening_per_peer/__init__.py
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step10/show_ip_route.ref.diff
+++ b/tests/topotests/bgp_dampening_per_peer/__init__.py
diff --git a/tests/topotests/bgp_dampening_per_peer/r1/frr.conf b/tests/topotests/bgp_dampening_per_peer/r1/frr.conf
new file mode 100644
index 0000000..4589955
--- /dev/null
+++ b/tests/topotests/bgp_dampening_per_peer/r1/frr.conf
@@ -0,0 +1,15 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ neighbor 192.168.1.2 capability dynamic
+ !
+ address-family ipv4 unicast
+ neighbor 192.168.1.2 dampening 1 1 1 1
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_dampening_per_peer/r2/frr.conf b/tests/topotests/bgp_dampening_per_peer/r2/frr.conf
new file mode 100644
index 0000000..d68d13d
--- /dev/null
+++ b/tests/topotests/bgp_dampening_per_peer/r2/frr.conf
@@ -0,0 +1,17 @@
+!
+int lo
+ ip address 10.10.10.10/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_dampening_per_peer/test_bgp_dampening_per_peer.py b/tests/topotests/bgp_dampening_per_peer/test_bgp_dampening_per_peer.py
new file mode 100644
index 0000000..2066d84
--- /dev/null
+++ b/tests/topotests/bgp_dampening_per_peer/test_bgp_dampening_per_peer.py
@@ -0,0 +1,177 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = [pytest.mark.bgpd]
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, get_topogen
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_dampening_per_peer():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _converge():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 10.10.10.10/32 json"))
+ expected = {
+ "paths": [
+ {
+ "valid": True,
+ "nexthops": [
+ {
+ "hostname": "r2",
+ "accessible": True,
+ }
+ ],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't converge"
+
+ ####
+ # Withdraw 10.10.10.10/32, and check if it's flagged as history.
+ ####
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ address-family ipv4 unicast
+ no redistribute connected
+ """
+ )
+
+ def _check_bgp_dampening_history():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 10.10.10.10/32 json"))
+ expected = {
+ "paths": [
+ {
+ "dampeningHistoryEntry": True,
+ "nexthops": [
+ {
+ "hostname": "r2",
+ "accessible": True,
+ }
+ ],
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _check_bgp_dampening_history,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "10.10.10.10/32 is not flagged as history entry"
+
+ ####
+ # Reannounce 10.10.10.10/32, and check if it's flagged as dampened.
+ ####
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ address-family ipv4 unicast
+ redistribute connected
+ """
+ )
+
+ def _check_bgp_dampening_dampened():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 10.10.10.10/32 json"))
+ expected = {
+ "paths": [
+ {
+ "valid": True,
+ "dampeningSuppressed": True,
+ "nexthops": [
+ {
+ "hostname": "r2",
+ "accessible": True,
+ }
+ ],
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _check_bgp_dampening_dampened,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "10.10.10.10/32 is not flagged as dampened entry"
+
+ ####
+ # Check if the route becomes non-dampened again after some time.
+ ####
+ def _check_bgp_dampening_undampened():
+ output = json.loads(r1.vtysh_cmd("show bgp ipv4 unicast 10.10.10.10/32 json"))
+ expected = {
+ "paths": [
+ {
+ "valid": True,
+ "dampeningHistoryEntry": None,
+ "dampeningSuppressed": None,
+ "nexthops": [
+ {
+ "hostname": "r2",
+ "accessible": True,
+ }
+ ],
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _check_bgp_dampening_undampened,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=120, wait=10)
+ assert result is None, "10.10.10.10/32 is flagged as history/dampened"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
index a0014c7..05e0748 100644
--- a/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
+++ b/tests/topotests/bgp_default_afi_safi/test_bgp-default-afi-safi.py
@@ -30,8 +30,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 5):
diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py
index 6156968..50a1938 100644
--- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py
+++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_1.py
@@ -325,12 +325,14 @@ def teardown_module():
)
logger.info("=" * 40)
+
#####################################################
#
# Testcases
#
#####################################################
+
def test_verify_bgp_default_originate_in_IBGP_p0(request):
"""
Verify BGP default-originate route with IBGP peer
@@ -396,7 +398,9 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
step("After changing the BGP AS Path Verify the BGP Convergence")
BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, " Complete Convergence is expected after changing the ASN but failed to converge --> :Failed \n Error: {}".format(
+ assert (
+ BGP_CONVERGENCE is True
+ ), " Complete Convergence is expected after changing the ASN but failed to converge --> :Failed \n Error: {}".format(
BGP_CONVERGENCE
)
@@ -413,8 +417,10 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Failed to configure the static routes {} on router R1 \n Error: {}".format(
- tc_name,static_routes_input, result
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the static routes {} on router R1 \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step("verify IPv4 and IPv6 static route are configured and up on R1")
for addr_type in ADDR_TYPES:
@@ -429,8 +435,10 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r1", static_routes_input)
- assert result is True, "Testcase {} : Failed \n After configuring the static routes {} , the routes are not found in FIB \n Error: {}".format(
- tc_name,static_routes_input, result
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n After configuring the static routes {} , the routes are not found in FIB \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -483,7 +491,11 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
},
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure the redistribute static configuration \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the redistribute static configuration \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring redistribute command , verify static and connected routes ( loopback connected routes) are advertised on R2"
@@ -517,13 +529,17 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : After redistributing static routes the routes {} expected in FIB but NOT FOUND ......! \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : After redistributing static routes the routes {} expected in FIB but NOT FOUND ......! \n Error: {}".format(
+ tc_name, static_routes_input, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : After redistributing static routes the routes {} expected in RIB but NOT FOUND ......! \n Error: {}".format(
- tc_name, static_routes_input , result
+ assert (
+ result is True
+ ), "Testcase {} : After redistributing static routes the routes {} expected in RIB but NOT FOUND ......! \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -547,7 +563,11 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed Configuring default originate configuration. \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed Configuring default originate configuration. \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring default-originate command , verify default routes are advertised on R2 "
@@ -574,12 +594,16 @@ def test_verify_bgp_default_originate_in_IBGP_p0(request):
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : post configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on FIB .......! FAILED \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : post configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on FIB .......! FAILED \n Error: {}".format(
tc_name, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : Failedpost configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on RIB......! FAILED \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failedpost configuring the BGP Default originate configuration static and connected routes should not be effected but impacted on RIB......! FAILED \n Error: {}".format(
tc_name, result
)
step(
@@ -686,7 +710,9 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
step("After changing the BGP AS Path Verify the BGP Convergence")
BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, "Complete convergence is expeceted after changing the ASN os the routes ..! :Failed \n Error: {}".format(
+ assert (
+ BGP_CONVERGENCE is True
+ ), "Complete convergence is expeceted after changing the ASN os the routes ..! :Failed \n Error: {}".format(
BGP_CONVERGENCE
)
@@ -703,7 +729,9 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Failed to configure the static routes ....! Failed \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the static routes ....! Failed \n Error: {}".format(
tc_name, result
)
step("verify IPv4 and IPv6 static route are configured and up on R1")
@@ -719,8 +747,10 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input)
- assert result is True, "Testcase {} : Route is not found in {} in FIB ......! Failed \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : Route is not found in {} in FIB ......! Failed \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -773,7 +803,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
},
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure redistribute configuratin \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure redistribute configuratin \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring redistribute command , verify static and connected routes ( loopback connected routes) are advertised on R2"
@@ -806,11 +840,15 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static & and connected routes are expected but not found in FIB .... ! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : static & and connected routes are expected but not found in FIB .... ! \n Error: {}".format(
tc_name, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static & and connected routes are expected but not found in RIB .... ! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : static & and connected routes are expected but not found in RIB .... ! \n Error: {}".format(
tc_name, result
)
snapshot1 = get_prefix_count_route(tgen, topo, dut="r2", peer="r3")
@@ -830,7 +868,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure the default originate configuration \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the default originate configuration \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring default-originate command , verify default routes are advertised on R2 on both BGP RIB and FIB"
@@ -853,13 +895,17 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
}
result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 FIB .....! NOT FOUND \n Error: {}".format(
- tc_name, NETWORK1_1,result
+ assert (
+ result is True
+ ), "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 FIB .....! NOT FOUND \n Error: {}".format(
+ tc_name, NETWORK1_1, result
)
result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input)
- assert result is True, "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 RIB .....! NOT FOUND \n Error: {}".format(
- tc_name,NETWORK1_1, result
+ assert (
+ result is True
+ ), "Testcase {} : static route from R1 {} and default route from R3 is expected in R2 RIB .....! NOT FOUND \n Error: {}".format(
+ tc_name, NETWORK1_1, result
)
step(
@@ -875,7 +921,11 @@ def test_verify_bgp_default_originate_in_EBGP_p0(request):
metric=0,
expected_aspath="4000",
)
- assert result is True, "Testcase {} : Default route from R3 is expected with attributes in R2 RIB .....! NOT FOUND Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Default route from R3 is expected with attributes in R2 RIB .....! NOT FOUND Error: {}".format(
+ tc_name, result
+ )
step(
"Taking the snapshot2 of the prefix count after configuring the default originate"
@@ -968,7 +1018,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
step("After changing the BGP AS Path Verify the BGP Convergence")
BGP_CONVERGENCE = verify_bgp_convergence(tgen, topo)
- assert BGP_CONVERGENCE is True, "Complete convergence is expected after changing ASN ....! ERROR :Failed \n Error: {}".format(
+ assert (
+ BGP_CONVERGENCE is True
+ ), "Complete convergence is expected after changing ASN ....! ERROR :Failed \n Error: {}".format(
BGP_CONVERGENCE
)
@@ -989,7 +1041,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Static Configuration is Failed \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Static Configuration is Failed \n Error: {}".format(
tc_name, result
)
@@ -1010,8 +1064,10 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r0", static_routes_input)
- assert result is True, "Testcase {} : routes {} unable is not found in R0 FIB \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : routes {} unable is not found in R0 FIB \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -1028,7 +1084,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure redistribute static configuration....! \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure redistribute static configuration....! \n Error: {}".format(
+ tc_name, result
+ )
step("verify IPv4 and IPv6 static route are configured and up on R1")
for addr_type in ADDR_TYPES:
@@ -1047,13 +1107,17 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r1", static_routes_input)
- assert result is True, "Testcase {} : Failed... Routes {} expected in r0 FIB after configuring the redistribute config \n Error: {}".format(
- tc_name,static_routes_input, result
+ assert (
+ result is True
+ ), "Testcase {} : Failed... Routes {} expected in r0 FIB after configuring the redistribute config \n Error: {}".format(
+ tc_name, static_routes_input, result
)
result = verify_bgp_rib(tgen, addr_type, "r1", static_routes_input)
- assert result is True, "Testcase {} : Failed... Routes {} expected in r0 RIB after configuring the redistribute config \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : Failed... Routes {} expected in r0 RIB after configuring the redistribute config \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -1094,7 +1158,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix list \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix list \n Error: {}".format(
+ tc_name, result
+ )
step(
"Configure IPV4 and IPv6 route-map (RMv4 and RMv6 ) matching prefix-list (Pv4 and Pv6) respectively on R1"
@@ -1120,7 +1188,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the route map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the route map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Configure default-originate with route-map (RMv4 and RMv6) on R1, on BGP IPv4 and IPv6 address family "
@@ -1142,7 +1214,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure the default originate \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the default originate \n Error: {}".format(
+ tc_name, result
+ )
step("Verify the default route is received in BGP RIB and FIB")
step(
@@ -1167,7 +1243,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed...! Expected default route from R1 not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed...! Expected default route from R1 not found in FIB \n Error: {}".format(
tc_name, result
)
@@ -1178,7 +1256,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed...! Expected default route from R1 not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed...! Expected default route from R1 not found in RIB \n Error: {}".format(
tc_name, result
)
step("Remove route-map RMv4 and RMv6 from default-originate command in R1")
@@ -1196,7 +1276,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to remove the default originate conditional route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to remove the default originate conditional route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Verify BGP RIB and FIB After removing route-map , default route still present on R2"
@@ -1221,7 +1305,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default route from R1 is not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is not found in FIB \n Error: {}".format(
tc_name, result
)
@@ -1232,7 +1318,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default route from R1 is not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is not found in RIB \n Error: {}".format(
tc_name, result
)
@@ -1266,7 +1354,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure the Default originate route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the Default originate route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring default-originate command , verify default routes are advertised on R2 "
@@ -1290,7 +1382,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default Route from R1 is not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default Route from R1 is not found in FIB \n Error: {}".format(
tc_name, result
)
@@ -1301,7 +1395,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
)
- assert result is True, "Testcase {} : Failed Default Route from R1 is not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default Route from R1 is not found in RIB \n Error: {}".format(
tc_name, result
)
@@ -1345,7 +1441,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to delete the prefix list Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to delete the prefix list Error: {}".format(
+ tc_name, result
+ )
step(
"Verify BGP RIB and FIB After deleting prefix-list , verify IPv4 and IPv6 default route got removed from DUT "
@@ -1426,7 +1526,11 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix lists Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix lists Error: {}".format(
+ tc_name, result
+ )
step(
"After configuring the Prefixlist cross checking the BGP Default route is configured again , before deleting the route map"
@@ -1452,7 +1556,9 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
expected=True,
)
- assert result is True, "Testcase {} : Failed Default route from R1 is expected in FIB but not found \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is expected in FIB but not found \n Error: {}".format(
tc_name, result
)
@@ -1464,14 +1570,20 @@ def test_verify_bgp_default_originate_in_IBGP_with_route_map_p0(request):
next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
expected=True,
)
- assert result is True, "Testcase {} : Failed Default route from R1 is expected in RIB but not found \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default route from R1 is expected in RIB but not found \n Error: {}".format(
tc_name, result
)
step("Deleting the routemap")
input_dict = {"r1": {"route_maps": ["RMv4", "RMv6"]}}
result = delete_route_maps(tgen, input_dict)
- assert result is True, "Testcase {} : Failed to delete the Route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to delete the Route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Verify BGP RIB and FIB ,After deleting route-map , verify IPv4 and IPv6 default route got removed from DUT"
@@ -1605,7 +1717,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_static_routes(tgen, static_routes_input)
- assert result is True, "Testcase {} : Failed to configure the static routes \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the static routes \n Error: {}".format(
tc_name, result
)
step("verify IPv4 and IPv6 static route are configured and up on R4")
@@ -1625,8 +1739,10 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input)
- assert result is True, "Testcase {} : Failed Static route {} is not found in R4 FIB \n Error: {}".format(
- tc_name, static_routes_input,result
+ assert (
+ result is True
+ ), "Testcase {} : Failed Static route {} is not found in R4 FIB \n Error: {}".format(
+ tc_name, static_routes_input, result
)
step(
@@ -1643,7 +1759,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, redistribute_static)
- assert result is True, "Testcase {} : Failed to configure the redistribute static \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the redistribute static \n Error: {}".format(
+ tc_name, result
+ )
step("verify IPv4 and IPv6 static route are configured and up on R3")
for addr_type in ADDR_TYPES:
@@ -1662,11 +1782,15 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = verify_fib_routes(tgen, addr_type, "r3", static_routes_input)
- assert result is True, "Testcase {} : Failed static routes from R1 and R3 is not found in FIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed static routes from R1 and R3 is not found in FIB \n Error: {}".format(
tc_name, result
)
result = verify_bgp_rib(tgen, addr_type, "r3", static_routes_input)
- assert result is True, "Testcase {} : Failed static routes from R1 and R3 is not found in RIB \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed static routes from R1 and R3 is not found in RIB \n Error: {}".format(
tc_name, result
)
@@ -1698,12 +1822,20 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix lists \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix lists \n Error: {}".format(
+ tc_name, result
+ )
step("verify IPv4 and IPv6 Prefix list got configured on R3")
input_dict = {"r3": {"prefix_lists": ["Pv4", "Pv6"]}}
result = verify_prefix_lists(tgen, input_dict)
- assert result is True, "Testcase {} : Failed ..! configured prefix lists {} are not found \n Error: {}".format(tc_name,input_dict, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed ..! configured prefix lists {} are not found \n Error: {}".format(
+ tc_name, input_dict, result
+ )
step(
"Configure IPv4 and IPv6 route-map ( RMv4 and RMv6 ) matching prefix-list (Pv4 and Pv6 ) respectively on R3"
@@ -1729,7 +1861,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_route_maps(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the route-map \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the route-map \n Error: {}".format(
+ tc_name, result
+ )
step(
"Taking the snapshot of the prefix count before configuring the default originate"
)
@@ -1754,7 +1890,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed to configure default-originate \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure default-originate \n Error: {}".format(
+ tc_name, result
+ )
step("Verify the default route is NOT received in BGP RIB and FIB on R2 ")
step(
@@ -1836,7 +1976,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to configure the prefix lists Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to configure the prefix lists Error: {}".format(
+ tc_name, result
+ )
step("Verify BGP default route for IPv4 and IPv6 is received on R2")
@@ -1859,7 +2003,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R3[addr_type],
)
- assert result is True, "Testcase {} : Failed Default routes are expected in R2 FIB from R3 but not found ....! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default routes are expected in R2 FIB from R3 but not found ....! \n Error: {}".format(
tc_name, result
)
@@ -1870,7 +2016,9 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
static_routes_input,
next_hop=DEFAULT_ROUTE_NXT_HOP_R3[addr_type],
)
- assert result is True, "Testcase {} : Failed Default routes are expected in R2 RIB from R3 but not found ....! \n Error: {}".format(
+ assert (
+ result is True
+ ), "Testcase {} : Failed Default routes are expected in R2 RIB from R3 but not found ....! \n Error: {}".format(
tc_name, result
)
@@ -1914,7 +2062,11 @@ def test_verify_bgp_default_originate_in_EBGP_with_route_map_p0(request):
}
}
result = create_prefix_lists(tgen, input_dict_3)
- assert result is True, "Testcase {} : Failed to remove prefix-lists from R3 Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Failed to remove prefix-lists from R3 Error: {}".format(
+ tc_name, result
+ )
step(
"After Removing route BGP default route for IPv4 and IPv6 is NOT received on R2"
diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py
index 59f833b..4e8bda5 100644
--- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py
+++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_topo1_2.py
@@ -955,6 +955,7 @@ def test_verify_bgp_default_originate_route_map_in_OUT_p1(request):
write_test_footer(tc_name)
+
def test_verify_bgp_default_originate_route_map_in_IN_p1(request):
"""Verify BGP default originate route-map with IN route-map"""
tgen = get_topogen()
@@ -1472,6 +1473,7 @@ def test_verify_bgp_default_originate_route_map_in_IN_p1(request):
)
write_test_footer(tc_name)
+
def test_verify_default_originate_after_removing_default_originate_p1(request):
"""Verify BGP default route after removing default-originate"""
@@ -2232,9 +2234,9 @@ def test_verify_default_originate_after_removing_default_originate_p1(request):
)
write_test_footer(tc_name)
+
def test_verify_default_originate_route_with_GR_p1(request):
- """ "Verify default-originate route with GR "
- """
+ """ "Verify default-originate route with GR " """
tgen = get_topogen()
global BGP_CONVERGENCE
global topo
@@ -2250,14 +2252,13 @@ def test_verify_default_originate_route_with_GR_p1(request):
if BGP_CONVERGENCE != True:
pytest.skip("skipped because of BGP Convergence failure")
-
step("Configure IPV4 and IPV6 IBGP between R1 and R2 ")
step("Configure IPV4 and IPV6 EBGP between R2 to R3 ")
- r0_local_as = topo['routers']['r0']['bgp']['local_as']
- r1_local_as = topo['routers']['r1']['bgp']['local_as']
- r2_local_as = topo['routers']['r2']['bgp']['local_as']
- r3_local_as = topo['routers']['r3']['bgp']['local_as']
- r4_local_as = topo['routers']['r4']['bgp']['local_as']
+ r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"]
+ r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"]
+ r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"]
+ r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"]
+ r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"]
input_dict = {
"r0": {
"bgp": {
@@ -2336,33 +2337,14 @@ def test_verify_default_originate_route_with_GR_p1(request):
"bgp": {
"local_as": local_as,
"address_family": {
- "ipv4": {
- "unicast": {
- "default_originate":{
- "r2":{
-
- }
-
- }
-
- }
- }, "ipv6": {
- "unicast": {
- "default_originate":{
- "r2":{
-
- }
-
- }
- }
- }
- }
+ "ipv4": {"unicast": {"default_originate": {"r2": {}}}},
+ "ipv6": {"unicast": {"default_originate": {"r2": {}}}},
+ },
}
}
}
result = create_router_bgp(tgen, topo, default_originate_config)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step(
"R2 received default-originate routes and advertised it to R3 , verify on R2 and R3"
@@ -2383,17 +2365,28 @@ def test_verify_default_originate_route_with_GR_p1(request):
}
}
- result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_fib_routes(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_bgp_rib(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
-
step(" Kill BGPd session on R2")
kill_router_daemons(tgen, "r2", ["bgpd"])
start_router_daemons(tgen, "r2", ["bgpd"])
@@ -2411,17 +2404,30 @@ def test_verify_default_originate_route_with_GR_p1(request):
}
}
- result = verify_fib_routes(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_fib_routes(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r2", static_routes_input,next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type])
+ result = verify_bgp_rib(
+ tgen,
+ addr_type,
+ "r2",
+ static_routes_input,
+ next_hop=DEFAULT_ROUTE_NXT_HOP_R1[addr_type],
+ )
assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
write_test_footer(tc_name)
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py
index 82c4e7e..f67a431 100644
--- a/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py
+++ b/tests/topotests/bgp_default_originate/test_default_originate_conditional_routemap.py
@@ -75,6 +75,7 @@ NETWORK1_1 = {"ipv4": "198.51.1.1/32", "ipv6": "2001:DB8::1:1/128"}
DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"}
NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
+
def setup_module(mod):
"""
Sets up the pytest environment
@@ -818,11 +819,11 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
step("Configure IPv4 and IPv6 , EBGP neighbor between R3 and R2")
step("Configure IPv4 and IPv6 IBGP neighbor between R3 and R4")
- r0_local_as = topo['routers']['r0']['bgp']['local_as']
- r1_local_as = topo['routers']['r1']['bgp']['local_as']
- r2_local_as = topo['routers']['r2']['bgp']['local_as']
- r3_local_as = topo['routers']['r3']['bgp']['local_as']
- r4_local_as = topo['routers']['r4']['bgp']['local_as']
+ r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"]
+ r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"]
+ r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"]
+ r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"]
+ r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"]
input_dict = {
"r0": {
"bgp": {
@@ -1026,22 +1027,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "200",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "200",
+ "as_action": "prepend",
}
-
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "300",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "300",
+ "as_action": "prepend",
}
+ },
},
],
"RMv6": [
@@ -1049,21 +1049,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "200",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "200",
+ "as_action": "prepend",
}
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "300",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "300",
+ "as_action": "prepend",
}
+ },
},
],
}
@@ -1122,22 +1122,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "500",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "500",
+ "as_action": "prepend",
}
-
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "600",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "600",
+ "as_action": "prepend",
}
+ },
},
],
"RMv6": [
@@ -1145,21 +1144,21 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"action": "permit",
"seq_id": "1",
"set": {
- "path": {
- "as_num": "500",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "500",
+ "as_action": "prepend",
}
+ },
},
{
"action": "permit",
"seq_id": "2",
"set": {
- "path": {
- "as_num": "600",
- "as_action": "prepend",
- }
+ "path": {
+ "as_num": "600",
+ "as_action": "prepend",
}
+ },
},
],
}
@@ -1170,7 +1169,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
assert result is True, "Test case {} : Failed \n Error: {}".format(tc_name, result)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
-
step("As path 500 added to IPv4 and IPv6 default -originate route received on R2")
result = verify_rib_default_route(
tgen,
@@ -1232,7 +1230,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes "
)
-
DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"}
result = verify_rib_default_route(
tgen,
@@ -1244,7 +1241,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
expected_aspath="4000 500",
)
-
step(
"Modify route-map seq1 configure metric 50 and route-map seq2 configure metric 100 IPv4 and IPv6 route-map "
)
@@ -1294,7 +1290,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes "
)
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1314,7 +1309,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
{
"action": "permit",
"seq_id": "1",
-
"set": {
"path": {
"as_num": "500",
@@ -1374,9 +1368,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify AS-prepend is deleted from default originate route and metric value only present on R2 for IPv4 and IPv6 default routes "
)
-
-
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1388,7 +1379,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
-
step("Delete metric value from IP4 and IPv6 route-map configured on R3 ")
route_map = {
"r3": {
@@ -1428,8 +1418,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Metric value deleted from IPv4 and IPv6 default route on R2 ,verify default routes "
)
-
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1443,11 +1431,11 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
step("Change IPv4 and IPv6 , EBGP to IBGP neighbor between R3 and R2")
step("Change IPv4 and IPv6 IBGP to EBGP neighbor between R3 and R4")
- r0_local_as = topo['routers']['r0']['bgp']['local_as']
- r1_local_as = topo['routers']['r1']['bgp']['local_as']
- r2_local_as = topo['routers']['r2']['bgp']['local_as']
- r3_local_as = topo['routers']['r3']['bgp']['local_as']
- r4_local_as = topo['routers']['r4']['bgp']['local_as']
+ r0_local_as = topo["routers"]["r0"]["bgp"]["local_as"]
+ r1_local_as = topo["routers"]["r1"]["bgp"]["local_as"]
+ r2_local_as = topo["routers"]["r2"]["bgp"]["local_as"]
+ r3_local_as = topo["routers"]["r3"]["bgp"]["local_as"]
+ r4_local_as = topo["routers"]["r4"]["bgp"]["local_as"]
input_dict = {
"r0": {
"bgp": {
@@ -1459,7 +1447,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"local_as": r1_local_as,
}
},
-
"r2": {
"bgp": {
"local_as": 1111,
@@ -1645,8 +1632,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Configured metric value received on R2 along with as-path for IPv4 and IPv6 default routes "
)
-
-
result = verify_rib_default_route(
tgen,
topo,
@@ -1656,7 +1641,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
locPrf=50,
)
-
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
step(
@@ -1708,9 +1692,6 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"Verify Modified local-preference value received on R2 for IPv4 and IPv6 default routes "
)
-
-
-
DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"}
result = verify_rib_default_route(
tgen,
@@ -1724,13 +1705,15 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
# updating the topology with the updated AS-Number to avoid conflict in con configuring the AS
updated_topo = topo
- updated_topo['routers']['r0']['bgp']['local_as']=get_dut_as_number(tgen,"r0")
- updated_topo['routers']['r1']['bgp']['local_as']=get_dut_as_number(tgen,"r1")
- updated_topo['routers']['r2']['bgp']['local_as']=get_dut_as_number(tgen,"r2")
- updated_topo['routers']['r3']['bgp']['local_as']=get_dut_as_number(tgen,"r3")
- updated_topo['routers']['r4']['bgp']['local_as']=get_dut_as_number(tgen,"r4")
+ updated_topo["routers"]["r0"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r0")
+ updated_topo["routers"]["r1"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r1")
+ updated_topo["routers"]["r2"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r2")
+ updated_topo["routers"]["r3"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r3")
+ updated_topo["routers"]["r4"]["bgp"]["local_as"] = get_dut_as_number(tgen, "r4")
- step("Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ")
+ step(
+ "Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command "
+ )
local_as = get_dut_as_number(tgen, dut="r4")
shut_neighbor = {
"r4": {
@@ -1740,46 +1723,41 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"ipv4": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":True}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": True}}}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":True}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": True}}}
}
}
- }
- }
+ },
+ },
}
}
}
result = create_router_bgp(tgen, updated_topo, shut_neighbor)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- interface = topo['routers']['r3']['links']['r4']['interface']
- input_dict = {
- "r1": {
- "interface_list": [interface],
- "status": "down"
- }
- }
+ interface = topo["routers"]["r3"]["links"]["r4"]["interface"]
+ input_dict = {"r1": {"interface_list": [interface], "status": "down"}}
result = interface_status(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Shut down the interface failed ! \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Shut down the interface failed ! \n Error: {}".format(
+ tc_name, result
+ )
step("After shutting the interface verify the BGP convergence")
- result = verify_bgp_convergence(tgen,topo,expected=False)
- assert result is not True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result)
+ result = verify_bgp_convergence(tgen, topo, expected=False)
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(
+ tc_name, result
+ )
step("verify default route deleted from R2 ")
result = verify_rib_default_route(
@@ -1788,8 +1766,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in RIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1797,11 +1780,17 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in FIB -> {}".format( tc_name, result)
-
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Shut down interface the default route is NOT expected but found in FIB -> {}".format(
+ tc_name, result
+ )
- step("no Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command ")
+ step(
+ "no Shut IPv4/IPv6 BGP neighbor from R4 ( R4-R3) using 'neighbor x.x.x.x shut' command "
+ )
local_as = get_dut_as_number(tgen, dut="r4")
shut_neighbor = {
"r4": {
@@ -1811,46 +1800,39 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"ipv4": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":False}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": False}}}
}
}
},
"ipv6": {
"unicast": {
"neighbor": {
- "r3": {
- "dest_link": {
- "r4": {"shutdown":False}
- }
- }
+ "r3": {"dest_link": {"r4": {"shutdown": False}}}
}
}
- }
- }
+ },
+ },
}
}
}
result = create_router_bgp(tgen, updated_topo, shut_neighbor)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
- interface = topo['routers']['r3']['links']['r4']['interface']
- input_dict = {
- "r1": {
- "interface_list": [interface],
- "status": "up"
- }
- }
+ interface = topo["routers"]["r3"]["links"]["r4"]["interface"]
+ input_dict = {"r1": {"interface_list": [interface], "status": "up"}}
result = interface_status(tgen, topo, input_dict)
- assert result is True, "Testcase {} : Bring up interface failed ! \n Error: {}".format(tc_name, result)
+ assert (
+ result is True
+ ), "Testcase {} : Bring up interface failed ! \n Error: {}".format(tc_name, result)
step("After no shutting the interface verify the BGP convergence")
- result = verify_bgp_convergence(tgen,topo,expected=True)
- assert result is True, "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(tc_name, result)
+ result = verify_bgp_convergence(tgen, topo, expected=True)
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n After shutting Down BGP convergence should Fail and return False \n Error: {}".format(
+ tc_name, result
+ )
step("After no shut neighbor , verify default route relearn on R2")
result = verify_rib_default_route(
@@ -1859,8 +1841,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=True)
- assert result is True, "Testcase {} : Failed \n Error: After no Shut down interface the default route is expected but found in RIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After no Shut down interface the default route is expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1868,10 +1855,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected=True)
- assert result is True, "Testcase {} : Failed \n Error: After Shut down interface the default route is expected but found in FIB -> {}".format( tc_name, result)
-
-
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After Shut down interface the default route is expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Remove IPv4/IPv6 static route configure on R4")
for addr_type in ADDR_TYPES:
@@ -1881,7 +1871,7 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
{
"network": [NETWORK1_1[addr_type]],
"next_hop": NEXT_HOP_IP[addr_type],
- "delete": True
+ "delete": True,
}
]
}
@@ -1902,12 +1892,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
]
}
}
- result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_fib_routes(
+ tgen, addr_type, "r4", static_routes_input, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=False)
- assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_bgp_rib(
+ tgen, addr_type, "r4", static_routes_input, expected=False
+ )
+ assert result is not True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
@@ -1918,8 +1912,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in RIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1927,9 +1926,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in FIB -> {}".format( tc_name, result)
-
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is NOT expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Configuring the static route back in r4")
for addr_type in ADDR_TYPES:
@@ -1959,12 +1962,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
]
}
}
- result = verify_fib_routes(tgen, addr_type, "r4", static_routes_input, expected=True)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_fib_routes(
+ tgen, addr_type, "r4", static_routes_input, expected=True
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
- result = verify_bgp_rib(tgen, addr_type, "r4", static_routes_input, expected=True)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ result = verify_bgp_rib(
+ tgen, addr_type, "r4", static_routes_input, expected=True
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, result
)
@@ -1975,8 +1982,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in RIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -1984,8 +1996,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After removing static the default route is expected but found in FIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After removing static the default route is expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Deactivate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)")
@@ -1999,15 +2016,14 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"r3": {"dest_link": {"r4": {"deactivate": "ipv4"}}}
}
},
-
- },"ipv6": {
+ },
+ "ipv6": {
"unicast": {
"neighbor": {
"r3": {"dest_link": {"r4": {"deactivate": "ipv6"}}}
}
},
-
- }
+ },
}
}
}
@@ -2022,8 +2038,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in RIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -2031,8 +2052,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= False)
- assert result is not True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in FIB -> {}".format( tc_name, result)
+ expected=False,
+ )
+ assert (
+ result is not True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is NOT expected but found in FIB -> {}".format(
+ tc_name, result
+ )
step("Activate IPv4 and IPv6 neighbor configured from R4 ( R4-R3)")
@@ -2046,15 +2072,14 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
"r3": {"dest_link": {"r4": {"activate": "ipv4"}}}
}
},
-
- },"ipv6": {
+ },
+ "ipv6": {
"unicast": {
"neighbor": {
"r3": {"dest_link": {"r4": {"activate": "ipv6"}}}
}
},
-
- }
+ },
}
}
}
@@ -2064,7 +2089,7 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
step("Verify bgp convergence.")
bgp_convergence = verify_bgp_convergence(tgen, updated_topo)
- assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+ assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
tc_name, bgp_convergence
)
step("After Activating the BGP neighbor , verify default route learned on R2")
@@ -2074,8 +2099,13 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in RIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in RIB -> {}".format(
+ tc_name, result
+ )
result = verify_fib_default_route(
tgen,
@@ -2083,10 +2113,16 @@ def test_verify_default_originate_after_BGP_attributes_p1(request):
dut="r2",
routes=DEFAULT_ROUTES,
expected_nexthop=DEFAULT_ROUTE_NXT_HOP_R3,
- expected= True)
- assert result is True, "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in FIB -> {}".format( tc_name, result)
+ expected=True,
+ )
+ assert (
+ result is True
+ ), "Testcase {} : Failed \n Error: After Deactivating the BGP neighbor the default route is expected but found in FIB -> {}".format(
+ tc_name, result
+ )
write_test_footer(tc_name)
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
index 9a0f562..8269322 100644
--- a/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
+++ b/tests/topotests/bgp_dont_capability_negotiate/test_bgp_dont_capability_negotiate.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
@@ -194,6 +192,7 @@ def test_bgp_check_fqdn():
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
assert result is None, "FQDN capability disabled, but we still have a hostname"
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_dynamic_capability/r1/frr.conf b/tests/topotests/bgp_dynamic_capability/r1/frr.conf
index aa5c3db..c959462 100644
--- a/tests/topotests/bgp_dynamic_capability/r1/frr.conf
+++ b/tests/topotests/bgp_dynamic_capability/r1/frr.conf
@@ -15,6 +15,7 @@ router bgp 65001
!
address-family ipv4 unicast
neighbor 192.168.1.2 addpath-tx-all-paths
+ neighbor 192.168.1.2 addpath-rx-paths-limit 10
exit-address-family
!
ip prefix-list r2 seq 5 permit 10.10.10.10/32
diff --git a/tests/topotests/bgp_dynamic_capability/r2/frr.conf b/tests/topotests/bgp_dynamic_capability/r2/frr.conf
index 7f25665..3cc1f1f 100644
--- a/tests/topotests/bgp_dynamic_capability/r2/frr.conf
+++ b/tests/topotests/bgp_dynamic_capability/r2/frr.conf
@@ -16,6 +16,7 @@ router bgp 65002
neighbor 192.168.1.1 timers 1 3
neighbor 192.168.1.1 timers connect 1
neighbor 192.168.1.1 capability dynamic
+ neighbor 192.168.1.1 addpath-rx-paths-limit 20
!
address-family ipv4 unicast
redistribute connected
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py
index 5202f51..4d7d46c 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_addpath.py
@@ -6,7 +6,11 @@
#
"""
-Test if Addpath capability is adjusted dynamically.
+Test if Addpath/Paths-Limit capabilities are adjusted dynamically.
+T1: Enable Addpath/Paths-Limit capabilities and check if they are exchanged dynamically
+T2: Disable paths limit and check if it's exchanged dynamically
+T3: Disable Addpath capability RX and check if it's exchanged dynamically
+T4: Disable Addpath capability and check if it's exchanged dynamically
"""
import os
@@ -16,7 +20,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -24,9 +28,6 @@ sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-from lib.common_config import step
-
-pytestmark = [pytest.mark.bgpd]
def setup_module(mod):
@@ -47,7 +48,7 @@ def teardown_module(mod):
tgen.stop_topology()
-def test_bgp_dynamic_capability_addpath():
+def test_bgp_addpath_paths_limit():
tgen = get_topogen()
if tgen.routers_have_failure():
@@ -56,7 +57,7 @@ def test_bgp_dynamic_capability_addpath():
r1 = tgen.gears["r1"]
r2 = tgen.gears["r2"]
- def _bgp_converge():
+ def _converge():
output = json.loads(r1.vtysh_cmd("show bgp neighbor json"))
expected = {
"192.168.1.2": {
@@ -65,8 +66,19 @@ def test_bgp_dynamic_capability_addpath():
"dynamic": "advertisedAndReceived",
"addPath": {
"ipv4Unicast": {
+ "txAdvertisedAndReceived": False,
"txAdvertised": True,
+ "txReceived": False,
"rxAdvertisedAndReceived": True,
+ "rxAdvertised": True,
+ "rxReceived": True,
+ }
+ },
+ "pathsLimit": {
+ "ipv4Unicast": {
+ "advertisedAndReceived": True,
+ "advertisedPathsLimit": 10,
+ "receivedPathsLimit": 20,
}
},
},
@@ -80,26 +92,26 @@ def test_bgp_dynamic_capability_addpath():
return topotest.json_cmp(output, expected)
test_func = functools.partial(
- _bgp_converge,
+ _converge,
)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
assert result is None, "Can't converge"
- step("Enable Addpath capability and check if it's exchanged dynamically")
-
- # Clear message stats to check if we receive a notification or not after we
- # change the settings fo LLGR.
+ ####
+ # T1: Enable Addpath/Paths-Limit capabilities and check if they are exchanged dynamically
+ ####
r1.vtysh_cmd("clear bgp 192.168.1.2 message-stats")
r2.vtysh_cmd(
"""
configure terminal
- router bgp
- address-family ipv4 unicast
- neighbor 192.168.1.1 addpath-tx-all-paths
+ router bgp
+ address-family ipv4 unicast
+ neighbor 192.168.1.1 addpath-tx-all-paths
+ neighbor 192.168.1.1 addpath-rx-paths-limit 21
"""
)
- def _bgp_check_if_addpath_rx_tx_and_session_not_reset():
+ def _enable_addpath_paths_limit():
output = json.loads(r1.vtysh_cmd("show bgp neighbor json"))
expected = {
"192.168.1.2": {
@@ -109,7 +121,18 @@ def test_bgp_dynamic_capability_addpath():
"addPath": {
"ipv4Unicast": {
"txAdvertisedAndReceived": True,
+ "txAdvertised": True,
+ "txReceived": True,
"rxAdvertisedAndReceived": True,
+ "rxAdvertised": True,
+ "rxReceived": True,
+ }
+ },
+ "pathsLimit": {
+ "ipv4Unicast": {
+ "advertisedAndReceived": True,
+ "advertisedPathsLimit": 10,
+ "receivedPathsLimit": 21,
}
},
},
@@ -120,23 +143,76 @@ def test_bgp_dynamic_capability_addpath():
},
"messageStats": {
"notificationsRecv": 0,
- "capabilityRecv": 1,
+ "notificationsSent": 0,
+ "capabilityRecv": 2,
},
}
}
return topotest.json_cmp(output, expected)
test_func = functools.partial(
- _bgp_check_if_addpath_rx_tx_and_session_not_reset,
+ _enable_addpath_paths_limit,
)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
- assert result is None, "Session was reset after enabling Addpath capability"
+ assert (
+ result is None
+ ), "Something went wrong when enabling Addpath/Paths-Limit capabilities"
- step("Disable Addpath capability RX and check if it's exchanged dynamically")
+ ###
+ # T2: Disable paths limit and check if it's exchanged dynamically
+ ###
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp
+ address-family ipv4 unicast
+ no neighbor 192.168.1.1 addpath-rx-paths-limit
+ """
+ )
- # Clear message stats to check if we receive a notification or not after we
- # disable addpath-rx.
- r1.vtysh_cmd("clear bgp 192.168.1.2 message-stats")
+ def _disable_paths_limit():
+ output = json.loads(r1.vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.1.2": {
+ "bgpState": "Established",
+ "neighborCapabilities": {
+ "dynamic": "advertisedAndReceived",
+ "addPath": {
+ "ipv4Unicast": {
+ "txAdvertisedAndReceived": True,
+ "txAdvertised": True,
+ "txReceived": True,
+ "rxAdvertisedAndReceived": True,
+ "rxAdvertised": True,
+ "rxReceived": True,
+ }
+ },
+ "pathsLimit": {
+ "ipv4Unicast": {
+ "advertisedAndReceived": True,
+ "advertisedPathsLimit": 10,
+ "receivedPathsLimit": 0,
+ }
+ },
+ },
+ "messageStats": {
+ "notificationsRecv": 0,
+ "notificationsSent": 0,
+ "capabilityRecv": 3,
+ },
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _disable_paths_limit,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Something went wrong after disabling paths limit"
+
+ ###
+ # T3: Disable Addpath capability RX and check if it's exchanged dynamically
+ ###
r2.vtysh_cmd(
"""
configure terminal
@@ -146,7 +222,7 @@ def test_bgp_dynamic_capability_addpath():
"""
)
- def _bgp_check_if_addpath_tx_and_session_not_reset():
+ def _disable_addpath_rx():
output = json.loads(r1.vtysh_cmd("show bgp neighbor json"))
expected = {
"192.168.1.2": {
@@ -156,27 +232,39 @@ def test_bgp_dynamic_capability_addpath():
"addPath": {
"ipv4Unicast": {
"txAdvertisedAndReceived": True,
+ "txAdvertised": True,
+ "txReceived": True,
+ "rxAdvertisedAndReceived": False,
"rxAdvertised": True,
+ "rxReceived": False,
+ }
+ },
+ "pathsLimit": {
+ "ipv4Unicast": {
+ "advertisedAndReceived": True,
+ "advertisedPathsLimit": 10,
+ "receivedPathsLimit": 0,
}
},
},
"messageStats": {
"notificationsRecv": 0,
- "capabilityRecv": 1,
+ "notificationsSent": 0,
+ "capabilityRecv": 4,
},
}
}
return topotest.json_cmp(output, expected)
test_func = functools.partial(
- _bgp_check_if_addpath_tx_and_session_not_reset,
+ _disable_addpath_rx,
)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
- assert result is None, "Session was reset after disabling Addpath RX flags"
+ assert result is None, "Something went wrong after disabling Addpath RX flags"
- # Clear message stats to check if we receive a notification or not after we
- # disable Addpath capability.
- r1.vtysh_cmd("clear bgp 192.168.1.2 message-stats")
+ ###
+ # T4: Disable Addpath capability and check if it's exchanged dynamically
+ ###
r1.vtysh_cmd(
"""
configure terminal
@@ -186,7 +274,7 @@ def test_bgp_dynamic_capability_addpath():
"""
)
- def _bgp_check_if_addpath_capability_is_absent():
+ def _disable_addpath():
output = json.loads(r1.vtysh_cmd("show bgp neighbor json"))
expected = {
"192.168.1.2": {
@@ -195,24 +283,30 @@ def test_bgp_dynamic_capability_addpath():
"dynamic": "advertisedAndReceived",
"addPath": {
"ipv4Unicast": {
- "txAdvertisedAndReceived": None,
- "txAdvertised": None,
+ "txAdvertisedAndReceived": False,
+ "txAdvertised": False,
+ "txReceived": True,
+ "rxAdvertisedAndReceived": False,
"rxAdvertised": True,
+ "rxReceived": False,
}
},
},
"messageStats": {
"notificationsRecv": 0,
+ "notificationsSent": 0,
+ "capabilitySent": 1,
+ "capabilityRecv": 4,
},
}
}
return topotest.json_cmp(output, expected)
test_func = functools.partial(
- _bgp_check_if_addpath_capability_is_absent,
+ _disable_addpath,
)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
- assert result is None, "Failed to disable Addpath capability"
+ assert result is None, "Something went wrong when disabling Addpath capability"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py
index 338886d..26fae17 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_fqdn.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py
index 4644ef3..d67bfea 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_graceful_restart.py
@@ -18,7 +18,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -28,8 +28,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py
index ba95bd1..9e1f26f 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_orf.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
index aa9ad5f..f6c1e25 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_role.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
index 737e694..128283b 100644
--- a/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
+++ b/tests/topotests/bgp_dynamic_capability/test_bgp_dynamic_capability_software_version.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
index 34f7dc8..d9ccd69 100644
--- a/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
+++ b/tests/topotests/bgp_ebgp_common_subnet_nexthop_unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
@@ -35,8 +35,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 4):
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step10/show_ipv6_route.ref.diff b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step10/show_ipv6_route.ref.diff
+++ b/tests/topotests/bgp_evpn_maximum_prefix/__init__.py
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf
new file mode 100644
index 0000000..7476a37
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/c1/frr.conf
@@ -0,0 +1,4 @@
+!
+int c1-eth0
+ ip address 192.168.0.1/24
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf
new file mode 100644
index 0000000..a203daa
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/c2/frr.conf
@@ -0,0 +1,4 @@
+!
+int c2-eth0
+ ip address 192.168.0.2/24
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf
new file mode 100644
index 0000000..0534518
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/r1/frr.conf
@@ -0,0 +1,30 @@
+!
+!debug bgp neighbor
+!debug route-map detail
+!
+vni 10
+!
+int lo
+ ip address 10.10.10.1/32
+!
+int r1-eth1
+ ip address 192.168.1.1/24
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ network 10.10.10.10/32
+ exit-address-family
+ !
+ address-family l2vpn evpn
+ neighbor 192.168.1.2 activate
+ advertise-all-vni
+ advertise ipv4 unicast
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf
new file mode 100644
index 0000000..353302b
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/r2/frr.conf
@@ -0,0 +1,25 @@
+!
+!debug bgp neighbor
+!
+int lo
+ ip address 10.10.10.2/32
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+ !
+ address-family l2vpn evpn
+ neighbor 192.168.1.1 activate
+ neighbor 192.168.1.1 maximum-prefix 2
+ advertise-all-vni
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py
new file mode 100644
index 0000000..5469eff
--- /dev/null
+++ b/tests/topotests/bgp_evpn_maximum_prefix/test_bgp_evpn_maximum_prefix.py
@@ -0,0 +1,92 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ tgen.net["r1"].cmd(
+ """
+ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.1 nolearning
+ip link add name br10 type bridge
+ip link set dev vxlan10 master br10
+ip link set dev r1-eth0 master br10
+ip link set up dev br10
+ip link set up dev vxlan10"""
+ )
+
+ tgen.net["r2"].cmd(
+ """
+ip link add vxlan10 type vxlan id 10 dstport 4789 local 10.10.10.2 nolearning
+ip link add name br10 type bridge
+ip link set dev vxlan10 master br10
+ip link set dev r2-eth1 master br10
+ip link set up dev br10
+ip link set up dev vxlan10"""
+ )
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_evpn_maximum_prefix():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp l2vpn evpn summary failed json"))
+ expected = {
+ "peers": {
+ "192.168.1.1": {
+ "lastNotificationReason": "Cease/Maximum Number of Prefixes Reached",
+ "lastResetDueTo": "BGP Notification send",
+ }
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert result is None, "Can't limit maximum-prefixes for EVPN routes"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
index 33b6d08..d246517 100644
--- a/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/leaf1/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65101
+ timers bgp 3 10
bgp router-id 192.168.100.13
no bgp ebgp-requires-policy
neighbor 192.168.50.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
index 428998b..6855a43 100644
--- a/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/leaf2/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65101
+ timers bgp 3 10
bgp router-id 192.168.100.14
no bgp ebgp-requires-policy
neighbor 192.168.61.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
index b9fce46..7d6fef6 100644
--- a/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/spine1/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65001
+ timers bgp 3 10
bgp router-id 192.168.100.13
no bgp ebgp-requires-policy
neighbor 192.168.50.2 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
index 1430e10..c651ada 100644
--- a/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/spine2/evpn.conf
@@ -1,6 +1,7 @@
frr defaults datacenter
!
router bgp 65001
+ timers bgp 3 10
bgp router-id 192.168.100.14
no bgp ebgp-requires-policy
neighbor 192.168.60.2 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py
index 945c038..b033e9c 100644
--- a/tests/topotests/bgp_evpn_mh/test_evpn_mh.py
+++ b/tests/topotests/bgp_evpn_mh/test_evpn_mh.py
@@ -37,8 +37,6 @@ from lib import topotest
# Required to instantiate the topology builder class.
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd, pytest.mark.pimd]
-
#####################################################
##
## Network Topology Definition
@@ -389,13 +387,6 @@ def setup_module(module):
tors.append("torm22")
config_tors(tgen, tors)
- hosts = []
- hosts.append("hostd11")
- hosts.append("hostd12")
- hosts.append("hostd21")
- hosts.append("hostd22")
- config_hosts(tgen, hosts)
-
# tgen.mininet_cli()
# This is a sample of configuration loading.
router_list = tgen.routers()
@@ -410,6 +401,13 @@ def setup_module(module):
TopoRouter.RD_BGP, os.path.join(CWD, "{}/evpn.conf".format(rname))
)
tgen.start_router()
+
+ hosts = []
+ hosts.append("hostd11")
+ hosts.append("hostd12")
+ hosts.append("hostd21")
+ hosts.append("hostd22")
+ config_hosts(tgen, hosts)
# tgen.mininet_cli()
@@ -634,6 +632,7 @@ def check_mac(dut, vni, mac, m_type, esi, intf, ping_gw=False, tgen=None):
out = dut.vtysh_cmd("show evpn mac vni %d mac %s json" % (vni, mac))
+ tmp_esi = None
mac_js = json.loads(out)
for mac, info in mac_js.items():
tmp_esi = info.get("esi", "")
@@ -642,7 +641,15 @@ def check_mac(dut, vni, mac, m_type, esi, intf, ping_gw=False, tgen=None):
if tmp_esi == esi and tmp_m_type == m_type and intf == intf:
return None
- return "invalid vni %d mac %s out %s" % (vni, mac, mac_js)
+ return "invalid vni %d mac %s expected esi %s, %s m_type %s and intf %s out %s" % (
+ vni,
+ mac,
+ tmp_esi,
+ esi,
+ m_type,
+ intf,
+ mac_js,
+ )
def test_evpn_mac():
diff --git a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
index 2c1c695..62b7ec5 100644
--- a/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm11/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65002
+ timers bgp 3 10
bgp router-id 192.168.100.15
no bgp ebgp-requires-policy
neighbor 192.168.1.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
index 8b0ce1d..3ceb974 100644
--- a/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm12/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65003
+ timers bgp 3 10
bgp router-id 192.168.100.16
no bgp ebgp-requires-policy
neighbor 192.168.2.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
index 5247dc1..ecaf85d 100644
--- a/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm21/evpn.conf
@@ -7,6 +7,7 @@ frr defaults datacenter
!
!
router bgp 65004
+ timers bgp 3 10
bgp router-id 192.168.100.17
no bgp ebgp-requires-policy
neighbor 192.168.3.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
index ec56360..c7e1524 100644
--- a/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
+++ b/tests/topotests/bgp_evpn_mh/torm22/evpn.conf
@@ -6,6 +6,7 @@ frr defaults datacenter
! debug bgp zebra
!
router bgp 65005
+ timers bgp 3 10
bgp router-id 192.168.100.18
no bgp ebgp-requires-policy
neighbor 192.168.4.1 remote-as external
diff --git a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
index 2041a40..603f069 100755
--- a/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
+++ b/tests/topotests/bgp_evpn_overlay_index_gateway/test_bgp_evpn_overlay_index_gateway.py
@@ -179,7 +179,7 @@ def setup_module(mod):
pe.cmd_raises("sysctl -w net.ipv4.tcp_l3mdev_accept={}".format(l3mdev_accept))
# For all registered routers, load the zebra configuration file
- for (name, router) in tgen.routers().items():
+ for name, router in tgen.routers().items():
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(name))
)
@@ -230,11 +230,11 @@ def evpn_gateway_ip_show_op_check(trigger=" "):
"zebra_vrf_ipv6": "show ipv6 route vrf vrf-blue json",
}
- for (name, pe) in tgen.gears.items():
+ for name, pe in tgen.gears.items():
if name not in PES:
continue
- for (cmd_key, command) in show_commands.items():
+ for cmd_key, command in show_commands.items():
expected_op_file = "{0}/{1}/{2}_{3}.json".format(
CWD, name, cmd_key, trigger
)
diff --git a/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py b/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py
index 5781684..2df0fd0 100644
--- a/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py
+++ b/tests/topotests/bgp_evpn_route_map_match/test_bgp_evpn_route_map_match.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("c1", "r1"), "s2": ("r1", "r2"), "s3": ("r2", "c2")}
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/evpn.vni.json b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/evpn.vni.json
index 98ae92c..45d00c6 100644
--- a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/evpn.vni.json
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE1/evpn.vni.json
@@ -1,7 +1,7 @@
{
"vni":101,
"type":"L2",
- "vrf":"default",
+ "tenantVrf":"default",
"vxlanInterface":"vxlan0",
"vtepIp":"10.10.10.10",
"mcastGroup":"0.0.0.0",
diff --git a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE2/evpn.vni.json b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE2/evpn.vni.json
index 5c05978..f480b56 100644
--- a/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE2/evpn.vni.json
+++ b/tests/topotests/bgp_evpn_vxlan_svd_topo1/PE2/evpn.vni.json
@@ -1,7 +1,7 @@
{
"vni":101,
"type":"L2",
- "vrf":"default",
+ "tenantVrf":"default",
"vxlanInterface":"vxlan0",
"vtepIp":"10.30.30.30",
"mcastGroup":"0.0.0.0",
diff --git a/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py b/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py
index eb05986..a5e5bdc 100644
--- a/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py
+++ b/tests/topotests/bgp_extcomm_list_delete/test_bgp_extcomm-list_delete.py
@@ -124,7 +124,8 @@ def test_rt_extcomm_list_delete():
# check for the deletion of the extended community
test_func = functools.partial(
- _bgp_extcomm_list_del_check, r2, "10.10.10.1/32", r"1.1.1.1:1")
+ _bgp_extcomm_list_del_check, r2, "10.10.10.1/32", r"1.1.1.1:1"
+ )
_, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5)
assert result, "RT extended community 1.1.1.1:1 was not stripped."
@@ -138,7 +139,8 @@ def test_soo_extcomm_list_delete():
# check for the deletion of the extended community
test_func = functools.partial(
- _bgp_extcomm_list_del_check, r2, "10.10.10.2/32", r"2.2.2.2:2")
+ _bgp_extcomm_list_del_check, r2, "10.10.10.2/32", r"2.2.2.2:2"
+ )
_, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5)
assert result, "SoO extended community 2.2.2.2:2 was not stripped."
@@ -152,7 +154,8 @@ def test_nt_extcomm_list_delete():
# check for the deletion of the extended community
test_func = functools.partial(
- _bgp_extcomm_list_del_check, r2, "10.10.10.3/32", r"3.3.3.3")
+ _bgp_extcomm_list_del_check, r2, "10.10.10.3/32", r"3.3.3.3"
+ )
_, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5)
assert result, "NT extended community 3.3.3.3:0 was not stripped."
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step10/show_mpls_table.ref.diff b/tests/topotests/bgp_extended_link_bandwidth/__init__.py
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step10/show_mpls_table.ref.diff
+++ b/tests/topotests/bgp_extended_link_bandwidth/__init__.py
diff --git a/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf
new file mode 100644
index 0000000..d0c0813
--- /dev/null
+++ b/tests/topotests/bgp_extended_link_bandwidth/r1/frr.conf
@@ -0,0 +1,32 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
+router bgp 65000
+ no bgp ebgp-requires-policy
+ no bgp network import-check
+ neighbor 192.168.1.2 remote-as internal
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ neighbor 192.168.1.2 extended-link-bandwidth
+ address-family ipv4 unicast
+ network 10.10.10.40/32
+ network 10.10.10.100/32
+ network 10.10.10.200/32
+ neighbor 192.168.1.2 route-map r2 out
+ exit-address-family
+!
+ip prefix-list p40 seq 5 permit 10.10.10.40/32
+ip prefix-list p100 seq 5 permit 10.10.10.100/32
+ip prefix-list p200 seq 5 permit 10.10.10.200/32
+!
+route-map r2 permit 10
+ match ip address prefix-list p40
+ set extcommunity bandwidth 40000
+route-map r2 permit 20
+ match ip address prefix-list p100
+ set extcommunity bandwidth 100000
+route-map r2 permit 30
+ match ip address prefix-list p200
+ set extcommunity bandwidth 200000
+exit
diff --git a/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf
new file mode 100644
index 0000000..5cad150
--- /dev/null
+++ b/tests/topotests/bgp_extended_link_bandwidth/r2/frr.conf
@@ -0,0 +1,10 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
+router bgp 65000
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as internal
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+!
diff --git a/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py
new file mode 100644
index 0000000..e7058f5
--- /dev/null
+++ b/tests/topotests/bgp_extended_link_bandwidth/test_bgp_extended_link_bandwidth.py
@@ -0,0 +1,95 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import re
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_dynamic_capability_role():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json detail"))
+ expected = {
+ "routes": {
+ "10.10.10.40/32": {
+ "paths": [
+ {
+ "extendedIpv6Community": {
+ "string": "LB:65000:5000000000 (40.000 Gbps)",
+ }
+ }
+ ]
+ },
+ "10.10.10.100/32": {
+ "paths": [
+ {
+ "extendedIpv6Community": {
+ "string": "LB:65000:12500000000 (100.000 Gbps)",
+ }
+ }
+ ]
+ },
+ "10.10.10.200/32": {
+ "paths": [
+ {
+ "extendedIpv6Community": {
+ "string": "LB:65000:25000000000 (200.000 Gbps)",
+ }
+ }
+ ]
+ },
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(
+ _bgp_converge,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see link bandwidths as expected"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py
index eef122b..a5db20e 100644
--- a/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py
+++ b/tests/topotests/bgp_extended_optional_parameters_length/test_bgp_extended_optional_parameters_length.py
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf
index 50d1583..3d4d3a8 100644
--- a/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r1/frr.conf
@@ -1,3 +1,10 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
router bgp 65001
no bgp ebgp-requires-policy
bgp graceful-restart
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf
deleted file mode 100644
index e65bfb2..0000000
--- a/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf
+++ /dev/null
@@ -1,7 +0,0 @@
-!
-interface lo
- ip address 172.16.255.1/32
-!
-interface r1-eth0
- ip address 192.168.255.1/24
-!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf
index 97418ca..f5ba4ea 100644
--- a/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r2/frr.conf
@@ -1,3 +1,8 @@
+no zebra nexthop kernel enable
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
router bgp 65002
no bgp ebgp-requires-policy
bgp graceful-restart
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf
deleted file mode 100644
index 758d797..0000000
--- a/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-no zebra nexthop kernel enable
-!
-interface r2-eth0
- ip address 192.168.255.2/24
-!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf b/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf
new file mode 100644
index 0000000..1d84ec6
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r3/frr.conf
@@ -0,0 +1,19 @@
+no zebra nexthop kernel enable
+!
+interface lo
+ ip address 172.16.255.3/32
+!
+interface r3-eth0
+ ip address 192.168.34.3/24
+!
+router bgp 65003
+ no bgp ebgp-requires-policy
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.34.4 remote-as external
+ neighbor 192.168.34.4 timers 1 3
+ neighbor 192.168.34.4 timers connect 1
+ neighbor 192.168.34.4 graceful-restart
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf b/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf
new file mode 100644
index 0000000..5890791
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r4/frr.conf
@@ -0,0 +1,13 @@
+no zebra nexthop kernel enable
+!
+interface r4-eth0
+ ip address 192.168.34.4/24
+!
+router bgp 65004
+ no bgp ebgp-requires-policy
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.34.3 remote-as external
+ neighbor 192.168.34.3 timers 1 3
+ neighbor 192.168.34.3 timers connect 1
+ neighbor 192.168.34.3 graceful-restart
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py
new file mode 100644
index 0000000..2354c0c
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_per_neighbor_restart_retain_routes.py
@@ -0,0 +1,108 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+"""
+Test if routes are retained during BGP restarts using
+ Graceful Restart per-neighbor.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step, stop_router
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 5):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_gr_restart_retain_routes():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r4 = tgen.gears["r4"]
+
+ def _bgp_converge():
+ output = json.loads(r4.vtysh_cmd("show bgp ipv4 neighbors 192.168.34.3 json"))
+ expected = {
+ "192.168.34.3": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_bgp_retained_routes():
+ output = json.loads(r4.vtysh_cmd("show bgp ipv4 unicast 172.16.255.3/32 json"))
+ expected = {"paths": [{"stale": True}]}
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_kernel_retained_routes():
+ output = json.loads(
+ r4.cmd("ip -j route show 172.16.255.3/32 proto bgp dev r4-eth0")
+ )
+ expected = [{"dst": "172.16.255.3", "gateway": "192.168.34.3", "metric": 20}]
+ return topotest.json_cmp(output, expected)
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R4"
+
+ step("Restart R3")
+ stop_router(tgen, "r3")
+
+ step("Check if routes (BGP) are retained at R4")
+ test_func = functools.partial(_bgp_check_bgp_retained_routes)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP retained routes on R4"
+
+ step("Check if routes (Kernel) are retained at R4")
+ assert (
+ _bgp_check_kernel_retained_routes() is None
+ ), "Failed to retain BGP routes in kernel on R4"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
index a820b4b..abf737f 100644
--- a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
+++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
@@ -42,13 +42,8 @@ def setup_module(mod):
router_list = tgen.routers()
- for i, (rname, router) in enumerate(router_list.items(), 1):
- router.load_config(
- TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
- )
- router.load_config(
- TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
- )
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
tgen.start_router()
@@ -83,8 +78,10 @@ def test_bgp_gr_restart_retain_routes():
return topotest.json_cmp(output, expected)
def _bgp_check_kernel_retained_routes():
- output = json.loads(r2.cmd("ip -j route show 172.16.255.1/32 proto bgp dev r2-eth0"))
- expected = [{"dst":"172.16.255.1","gateway":"192.168.255.1","metric":20}]
+ output = json.loads(
+ r2.cmd("ip -j route show 172.16.255.1/32 proto bgp dev r2-eth0")
+ )
+ expected = [{"dst": "172.16.255.1", "gateway": "192.168.255.1", "metric": 20}]
return topotest.json_cmp(output, expected)
step("Initial BGP converge")
@@ -101,7 +98,9 @@ def test_bgp_gr_restart_retain_routes():
assert result is None, "Failed to see BGP retained routes on R2"
step("Check if routes (Kernel) are retained at R2")
- assert _bgp_check_kernel_retained_routes() is None, "Failed to retain BGP routes in kernel on R2"
+ assert (
+ _bgp_check_kernel_retained_routes() is None
+ ), "Failed to retain BGP routes in kernel on R2"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py
index 0deb181..489c59f 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/add_routes.py
@@ -1,17 +1,17 @@
from lib.lutil import luCommand
luCommand(
- "r1", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH"
+ "r1", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH"
)
luCommand(
- "r3", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH"
+ "r3", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH"
)
luCommand(
- "r4", 'vtysh -c "show bgp next"', "99.0.0.. valid", "wait", "See CE static NH"
+ "r4", 'vtysh -c "show bgp nexthop"', "99.0.0.. valid", "wait", "See CE static NH"
)
-luCommand("r1", 'vtysh -c "show bgp ipv4 uni"', "i5.*i5", "wait", "See CE routes")
-luCommand("r3", 'vtysh -c "show bgp ipv4 uni"', "i5.*i5", "wait", "See CE routes")
-luCommand("r4", 'vtysh -c "show bgp ipv4 uni"', "i5.*i5", "wait", "See CE routes")
+luCommand("r1", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes")
+luCommand("r3", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes")
+luCommand("r4", 'vtysh -c "show bgp ipv4 uni"', "i 5.*i 5", "wait", "See CE routes")
luCommand("ce1", 'vtysh -c "show bgp ipv4 uni 5.1.0.0/24"', "", "none", "See CE routes")
luCommand("r1", 'vtysh -c "show bgp ipv4 uni 5.1.0.0/24"', "", "none", "See CE routes")
luCommand("ce2", 'vtysh -c "show bgp ipv4 uni 5.1.0.0/24"', "", "none", "See CE routes")
@@ -39,22 +39,22 @@ luCommand(
luCommand(
"r3",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.1/32",
+ "i 99.0.0.1/32",
"wait",
"See R1s static address",
)
luCommand(
"r4",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.1/32",
+ "i 99.0.0.1/32",
"wait",
"See R1s static address",
)
luCommand(
- "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i5.*i5", "wait", "See R1s imports"
+ "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i 5.*i 5", "wait", "See R1s imports"
)
luCommand(
- "r4", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i5.*i5", "wait", "See R1s imports"
+ "r4", 'vtysh -c "show bgp ipv4 vpn rd 10:1"', "i 5.*i 5", "wait", "See R1s imports"
)
luCommand(
@@ -86,14 +86,14 @@ if have2ndImports:
luCommand(
"r1",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.2/32",
+ "i 99.0.0.2/32",
"wait",
"See R3s static address",
)
luCommand(
"r4",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.2/32",
+ "i 99.0.0.2/32",
"wait",
"See R3s static address",
)
@@ -101,14 +101,14 @@ if have2ndImports:
luCommand(
"r1",
'vtysh -c "show bgp ipv4 vpn rd 10:3"',
- "i5.*i5",
+ "i 5.*i 5",
"none",
"See R3s imports",
)
luCommand(
"r4",
'vtysh -c "show bgp ipv4 vpn rd 10:3"',
- "i5.*i5",
+ "i 5.*i 5",
"none",
"See R3s imports",
)
@@ -133,22 +133,22 @@ luCommand(
luCommand(
"r1",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.3/32",
+ "i 99.0.0.3/32",
"wait",
"See R4s static address",
)
luCommand(
"r3",
'vtysh -c "show bgp ipv4 vpn"',
- "i99.0.0.3/32",
+ "i 99.0.0.3/32",
"wait",
"See R4s static address",
)
luCommand(
- "r1", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i5.*i5", "wait", "See R4s imports"
+ "r1", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i 5.*i 5", "wait", "See R4s imports"
)
luCommand(
- "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i5.*i5", "wait", "See R4s imports"
+ "r3", 'vtysh -c "show bgp ipv4 vpn rd 10:4"', "i 5.*i 5", "wait", "See R4s imports"
)
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
index 6cd92e2..c966660 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/scripts/adjacencies.py
@@ -7,18 +7,36 @@ luCommand("ce1", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up
luCommand("ce2", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)
luCommand("ce3", 'vtysh -c "show bgp summary"', " 00:0", "wait", "Adjacencies up", 180)
luCommand(
- "r1", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+ "r1",
+ 'vtysh -c "show ip route ospf"',
+ "2.2.2.2",
+ "wait",
+ "OSPF Route has Arrived",
+ 60,
+)
luCommand(
"r1", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
luCommand(
- "r3", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+ "r3",
+ 'vtysh -c "show ip route ospf"',
+ "2.2.2.2",
+ "wait",
+ "OSPF Route has Arrived",
+ 60,
+)
luCommand(
"r3", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
luCommand(
- "r4", 'vtysh -c "show ip route ospf"', "2.2.2.2", "wait", "OSPF Route has Arrived", 60)
+ "r4",
+ 'vtysh -c "show ip route ospf"',
+ "2.2.2.2",
+ "wait",
+ "OSPF Route has Arrived",
+ 60,
+)
luCommand(
"r4", "ping 2.2.2.2 -c 1", " 0. packet loss", "wait", "PE->P2 (loopback) ping", 60
)
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
index e05bf21..2ce4bc5 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_vrf/scripts/scale_up.py
@@ -70,7 +70,7 @@ else:
"See all sharp routes in rib on ce1",
wait,
wait_time=10,
- )
+ )
luCommand(
"ce2",
'vtysh -c "show ip route summ" | grep "sharp" | cut -d " " -f 33',
@@ -79,7 +79,7 @@ else:
"See all sharp routes in rib on ce2",
wait,
wait_time=10,
- )
+ )
rtrs = ["ce1", "ce2", "ce3"]
for rtr in rtrs:
diff --git a/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
index 483c048..7023e3a 100644
--- a/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
+++ b/tests/topotests/bgp_large_comm_list_match/test_bgp_large_comm_list_match.py
@@ -137,7 +137,9 @@ def test_bgp_large_comm_list_match_any():
step("BGP filtering check with large-community-list on R3")
test_func = functools.partial(_bgp_converge)
_, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
- assert result is None, "Failed to filter BGP UPDATES with large-community-list on R3"
+ assert (
+ result is None
+ ), "Failed to filter BGP UPDATES with large-community-list on R3"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
index dfc4171..6289a2e 100644
--- a/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
+++ b/tests/topotests/bgp_link_bw_ip/r2/bgp-route-3.json
@@ -4,7 +4,7 @@
{
"valid":true,
"multipath":true,
- "extendedCommunity":{
+ "extendedIpv6Community":{
"string":"LB:65302:125000 (1.000 Mbps)"
},
"nexthops":[
diff --git a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
index 4014bfb..e4ed92d 100644
--- a/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
+++ b/tests/topotests/bgp_link_bw_ip/r5/bgpd.conf
@@ -13,6 +13,7 @@ router bgp 65302
bgp bestpath as-path multipath-relax
no bgp ebgp-requires-policy
neighbor 11.1.2.5 remote-as external
+ neighbor 11.1.2.5 extended-link-bandwidth
neighbor 11.1.2.5 timers 3 10
neighbor 11.1.5.2 remote-as external
neighbor 11.1.5.2 timers 3 10
diff --git a/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
index af6976b..fd67b2e 100644
--- a/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
+++ b/tests/topotests/bgp_link_bw_ip/test_bgp_linkbw_ip.py
@@ -53,7 +53,39 @@ anycast IP (VIP) addresses via BGP.
def build_topo(tgen):
- "Build function"
+ """
+ Build function
+
+ +------+
+ | |
+ /| r7 |---
+ / | 65351|
+ / +------+
+ /
+ +------+ / +------+
+ | |/ | |
+ /| r4 | | r8 |---
+ / | 65301|------| 65352|
+ / +------+ +------+
+ /
+ +------+ / +------+ +------+
+ | |/ | | | |
+ | r2 | | r5 | | r9 |---
+ | 65201|------| 65302|------| 65353|
+ +------+ +------+ +------+
+ |
+ +------+ |
+ | |----------
+ | r1 |
+ | 65101|----------
+ +------+ |
+ |
+ +------+ +------+ +------+
+ | | | | | |
+ | r3 |------| r6 |------| r10 |---
+ | 65202| | 65303| | 65354|
+ +------+ +------+ +------+
+ """
# Create 10 routers - 1 super-spine, 2 spines, 3 leafs
# and 4 servers
diff --git a/tests/topotests/bgp_llgr/test_bgp_llgr.py b/tests/topotests/bgp_llgr/test_bgp_llgr.py
index d604871..d7897cf 100644
--- a/tests/topotests/bgp_llgr/test_bgp_llgr.py
+++ b/tests/topotests/bgp_llgr/test_bgp_llgr.py
@@ -36,8 +36,6 @@ from lib.common_config import (
step,
)
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(0, 6):
diff --git a/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py b/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py
index 26e8fe9..c84fce6 100644
--- a/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py
+++ b/tests/topotests/bgp_local_asn/test_bgp_local_asn_agg.py
@@ -35,7 +35,7 @@ from lib.common_config import (
verify_rib,
step,
check_address_types,
- check_router_status
+ check_router_status,
)
from lib.topolog import logger
diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py
index cb8fa1e..cfaab9b 100644
--- a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py
+++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_agg.py
@@ -48,7 +48,7 @@ from lib.common_config import (
verify_rib,
step,
check_address_types,
- check_router_status
+ check_router_status,
)
from lib.topolog import logger
@@ -163,7 +163,9 @@ def test_verify_bgp_local_as_agg_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -190,7 +192,9 @@ def test_verify_bgp_local_as_agg_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
diff --git a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py
index e9234f5..bacef47 100644
--- a/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py
+++ b/tests/topotests/bgp_local_asn_dot/test_bgp_local_asn_dot_topo1.py
@@ -229,7 +229,9 @@ def test_verify_bgp_local_as_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -256,7 +258,9 @@ def test_verify_bgp_local_as_in_EBGP_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -832,7 +836,9 @@ def test_verify_bgp_local_as_GR_EBGP_p0(request):
"neighbor": {
"r2": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -861,7 +867,9 @@ def test_verify_bgp_local_as_GR_EBGP_p0(request):
"neighbor": {
"r4": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -1395,7 +1403,9 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -1422,7 +1432,9 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -1593,7 +1605,10 @@ def test_verify_bgp_local_as_in_EBGP_aspath_p0(request):
{
"action": "permit",
"set": {
- "path": {"as_num": "1.1000 1.1000", "as_action": "prepend"}
+ "path": {
+ "as_num": "1.1000 1.1000",
+ "as_action": "prepend",
+ }
},
}
]
@@ -1778,7 +1793,9 @@ def test_verify_bgp_local_as_in_iBGP_p0(request):
"neighbor": {
"r4": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2137,7 +2154,9 @@ def test_verify_bgp_local_as_allow_as_in_iBGP_p0(request):
"neighbor": {
"r2": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2166,7 +2185,9 @@ def test_verify_bgp_local_as_allow_as_in_iBGP_p0(request):
"neighbor": {
"r4": {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2484,7 +2505,9 @@ def test_verify_bgp_local_as_in_EBGP_port_reset_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2511,7 +2534,9 @@ def test_verify_bgp_local_as_in_EBGP_port_reset_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -2824,7 +2849,9 @@ def test_verify_bgp_local_as_in_EBGP_negative2_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -2851,7 +2878,9 @@ def test_verify_bgp_local_as_in_EBGP_negative2_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -3164,7 +3193,9 @@ def test_verify_bgp_local_as_in_EBGP_negative3_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -3191,7 +3222,9 @@ def test_verify_bgp_local_as_in_EBGP_negative3_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
@@ -3354,7 +3387,9 @@ def test_verify_bgp_local_as_in_EBGP_restart_daemons_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- "r3": {"local_asn": {"local_as": "1.110"}}
+ "r3": {
+ "local_asn": {"local_as": "1.110"}
+ }
}
}
}
@@ -3381,7 +3416,9 @@ def test_verify_bgp_local_as_in_EBGP_restart_daemons_p0(request):
"neighbor": {
neighbor: {
"dest_link": {
- dut: {"local_asn": {"remote_as": "1.110"}}
+ dut: {
+ "local_asn": {"remote_as": "1.110"}
+ }
}
}
}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step11/show_ip_route.ref.diff b/tests/topotests/bgp_nexthop_mp_ipv4_6/__init__.py
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step11/show_ip_route.ref.diff
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/__init__.py
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/h1/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/h1/zebra.conf
new file mode 100644
index 0000000..9b19b2c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/h1/zebra.conf
@@ -0,0 +1,6 @@
+ipv6 route ::/0 fd00:100::2
+ip route 0.0.0.0/0 192.168.1.2
+interface eth-r1
+ ip address 192.168.1.1/24
+ ipv6 address fd00:100::1/64
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/h2/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/h2/zebra.conf
new file mode 100644
index 0000000..2bf4a66
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/h2/zebra.conf
@@ -0,0 +1,6 @@
+ipv6 route ::/0 fd00:700::2
+ip route 0.0.0.0/0 192.168.7.2
+interface eth-r7
+ ip address 192.168.7.1/24
+ ipv6 address fd00:700::1/64
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/h3/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/h3/zebra.conf
new file mode 100644
index 0000000..e8b6ac6
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/h3/zebra.conf
@@ -0,0 +1,6 @@
+ipv6 route ::/0 fd00:800::2
+ip route 0.0.0.0/0 192.168.8.2
+interface eth-r8
+ ip address 192.168.8.1/24
+ ipv6 address fd00:800::1/64
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv4.json
new file mode 100755
index 0000000..12fecee
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv4.json
@@ -0,0 +1,70 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "0.0.0.0",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65000 65700",
+ "nexthops": [
+ {
+ "ip": "172.16.1.3",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65700",
+ "nexthops": [
+ {
+ "ip": "172.16.0.2",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65000 65800",
+ "nexthops": [
+ {
+ "ip": "172.16.1.3",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65800",
+ "nexthops": [
+ {
+ "ip": "172.16.0.2",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step1.json
new file mode 100755
index 0000000..f7c5c7c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step1.json
@@ -0,0 +1,90 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65000 65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:2::3",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::2",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65000 65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:2::3",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::2",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step2.json
new file mode 100755
index 0000000..f7c5c7c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgp_ipv6_step2.json
@@ -0,0 +1,90 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65000 65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:2::3",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::2",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65000 65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:2::3",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::2",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgpd.conf
new file mode 100644
index 0000000..23b986d
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/bgpd.conf
@@ -0,0 +1,23 @@
+router bgp 65100
+ no bgp ebgp-requires-policy
+ neighbor 172.16.0.2 remote-as external
+ neighbor 172.16.1.3 remote-as external
+ ! neighbor 172.16.0.2 capability extended-nexthop
+ !
+ address-family ipv4 unicast
+ redistribute connected route-map RMAP4
+ !
+ address-family ipv6 unicast
+ redistribute connected route-map RMAP6
+ neighbor 172.16.0.2 activate
+ neighbor 172.16.1.3 activate
+ !
+
+ip prefix-list RANGE4 seq 10 permit 192.168.0.0/16 le 24
+ipv6 prefix-list RANGE6 seq 10 permit fd00:100::0/64
+
+route-map RMAP4 permit 10
+ match ip address prefix-list RANGE4
+!
+route-map RMAP6 permit 10
+ match ipv6 address prefix-list RANGE6
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/zebra.conf
new file mode 100644
index 0000000..79cbafb
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r1/zebra.conf
@@ -0,0 +1,16 @@
+!
+interface eth-h1
+ ip address 192.168.1.2/24
+ ipv6 address fd00:100::2/64
+!
+interface eth-r2
+ ip address 172.16.0.1/24
+ ipv6 address fd00:0:1::1/64
+!
+interface eth-r3
+ ip address 172.16.1.1/24
+ ipv6 address fd00:0:2::1/64
+!
+interface lo
+ ip address 192.0.2.1/32
+ ipv6 address 2001:db8::1/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv4.json
new file mode 100755
index 0000000..64dadf6
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv4.json
@@ -0,0 +1,46 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "172.16.0.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "172.17.0.7",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "172.17.0.8",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step1.json
new file mode 100644
index 0000000..4f86a1a
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step1.json
@@ -0,0 +1,53 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::1",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json
new file mode 100644
index 0000000..21f3608
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgp_ipv6_step2.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgpd.conf
new file mode 100644
index 0000000..badb11c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/bgpd.conf
@@ -0,0 +1,11 @@
+router bgp 65000
+ no bgp ebgp-requires-policy
+ neighbor 172.16.0.1 remote-as external
+ ! neighbor 172.16.0.1 capability extended-nexthop
+ neighbor 192.0.2.101 remote-as internal
+ neighbor 192.0.2.101 update-source 192.0.2.2
+ !
+ address-family ipv6 unicast
+ neighbor 172.16.0.1 activate
+ neighbor 192.0.2.101 activate
+ !
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/isisd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/isisd.conf
new file mode 100644
index 0000000..1696379
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/isisd.conf
@@ -0,0 +1,24 @@
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-rr1
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r1
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+router isis 1
+ net 49.0000.0000.0000.0002.00
+ is-type level-1
+ lsp-gen-interval 1
+ topology ipv6-unicast
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/zebra.conf
new file mode 100644
index 0000000..8997115
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r2/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface eth-r1
+ ip address 172.16.0.2/24
+ ipv6 address fd00:0:1::2/64
+!
+interface eth-rr1
+ ip address 10.0.0.2/24
+ ipv6 address fd00:0:3::2/64
+!
+interface lo
+ ip address 192.0.2.2/32
+ ipv6 address 2001:db8::2/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv4.json
new file mode 100644
index 0000000..0f18a43
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv4.json
@@ -0,0 +1,46 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "172.16.1.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "172.17.0.7",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "172.17.0.8",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step1.json
new file mode 100644
index 0000000..f44121c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step1.json
@@ -0,0 +1,53 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:2::1",
+ "afi": "ipv6",
+ "scope": "global"
+ },
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json
new file mode 100644
index 0000000..21f3608
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgp_ipv6_step2.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "afi": "ipv6",
+ "scope": "link-local",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgpd.conf
new file mode 100644
index 0000000..4dec311
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/bgpd.conf
@@ -0,0 +1,11 @@
+router bgp 65000
+ no bgp ebgp-requires-policy
+ neighbor 172.16.1.1 remote-as external
+ ! neighbor 172.16.1.1 capability extended-nexthop
+ neighbor 192.0.2.101 remote-as internal
+ neighbor 192.0.2.101 update-source 192.0.2.3
+ !
+ address-family ipv6 unicast
+ neighbor 172.16.1.1 activate
+ neighbor 192.0.2.101 activate
+ !
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/isisd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/isisd.conf
new file mode 100644
index 0000000..fe3e307
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/isisd.conf
@@ -0,0 +1,24 @@
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-rr1
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r1
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+router isis 1
+ net 49.0000.0000.0000.0003.00
+ is-type level-1
+ lsp-gen-interval 1
+ topology ipv6-unicast
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/zebra.conf
new file mode 100644
index 0000000..8074bbd
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r3/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface eth-r1
+ ip address 172.16.1.3/24
+ ipv6 address fd00:0:2::3/64
+!
+interface eth-rr1
+ ip address 10.0.1.3/24
+ ipv6 address fd00:0:4::3/64
+!
+interface lo
+ ip address 192.0.2.3/32
+ ipv6 address 2001:db8::3/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv4.json
new file mode 100755
index 0000000..64dadf6
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv4.json
@@ -0,0 +1,46 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "172.16.0.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "172.17.0.7",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "172.17.0.8",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step1.json
new file mode 100755
index 0000000..756a78e
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step1.json
@@ -0,0 +1,49 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::1",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step2.json
new file mode 100755
index 0000000..7d0786c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgp_ipv6_step2.json
@@ -0,0 +1,49 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "2001:db8::2",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgpd.conf
new file mode 100644
index 0000000..2dbc4ac
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/bgpd.conf
@@ -0,0 +1,13 @@
+router bgp 65000
+ neighbor 192.0.2.5 remote-as internal
+ neighbor 192.0.2.6 remote-as internal
+ neighbor 192.0.2.101 remote-as internal
+ neighbor 192.0.2.5 update-source 192.0.2.4
+ neighbor 192.0.2.6 update-source 192.0.2.4
+ neighbor 192.0.2.101 update-source 192.0.2.4
+ !
+ address-family ipv6 unicast
+ neighbor 192.0.2.5 activate
+ neighbor 192.0.2.6 activate
+ neighbor 192.0.2.101 activate
+ !
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/isisd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/isisd.conf
new file mode 100644
index 0000000..21eb80f
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/isisd.conf
@@ -0,0 +1,26 @@
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-rr1
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r6
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+router isis 1
+ net 49.0000.0000.0000.0004.00
+ is-type level-1
+ lsp-gen-interval 1
+ topology ipv6-unicast
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/zebra.conf
new file mode 100644
index 0000000..c598b34
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r4/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface eth-r6
+ ip address 10.0.4.4/24
+ ipv6 address fd00:0:7::4/64
+!
+interface eth-rr1
+ ip address 10.0.2.4/24
+ ipv6 address fd00:0:5::4/64
+!
+interface lo
+ ip address 192.0.2.4/32
+ ipv6 address 2001:db8::4/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv4.json
new file mode 100755
index 0000000..64dadf6
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv4.json
@@ -0,0 +1,46 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "172.16.0.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "172.17.0.7",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "172.17.0.8",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step1.json
new file mode 100755
index 0000000..756a78e
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step1.json
@@ -0,0 +1,49 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::1",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step2.json
new file mode 100755
index 0000000..7d0786c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgp_ipv6_step2.json
@@ -0,0 +1,49 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "2001:db8::2",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgpd.conf
new file mode 100644
index 0000000..101edbd
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/bgpd.conf
@@ -0,0 +1,13 @@
+router bgp 65000
+ neighbor 192.0.2.4 remote-as internal
+ neighbor 192.0.2.6 remote-as internal
+ neighbor 192.0.2.101 remote-as internal
+ neighbor 192.0.2.4 update-source 192.0.2.5
+ neighbor 192.0.2.6 update-source 192.0.2.5
+ neighbor 192.0.2.101 update-source 192.0.2.5
+ !
+ address-family ipv6 unicast
+ neighbor 192.0.2.4 activate
+ neighbor 192.0.2.6 activate
+ neighbor 192.0.2.101 activate
+ !
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/isisd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/isisd.conf
new file mode 100644
index 0000000..f998e80
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/isisd.conf
@@ -0,0 +1,26 @@
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-rr1
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r6
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+router isis 1
+ net 49.0000.0000.0000.0005.00
+ is-type level-1
+ lsp-gen-interval 1
+ topology ipv6-unicast
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/zebra.conf
new file mode 100644
index 0000000..7b43db0
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r5/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface eth-r6
+ ip address 10.0.5.5/24
+ ipv6 address fd00:0:8::5/64
+!
+interface eth-rr1
+ ip address 10.0.3.5/24
+ ipv6 address fd00:0:6::5/64
+!
+interface lo
+ ip address 192.0.2.5/32
+ ipv6 address 2001:db8::5/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv4.json
new file mode 100644
index 0000000..64dadf6
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv4.json
@@ -0,0 +1,46 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "172.16.0.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "172.17.0.7",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "172.17.0.8",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step1.json
new file mode 100644
index 0000000..1a01ead
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step1.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::1",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step2.json
new file mode 100644
index 0000000..55912dd
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgp_ipv6_step2.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "nexthops": [
+ {
+ "ip": "2001:db8::2",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgpd.conf
new file mode 100644
index 0000000..e036a77
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/bgpd.conf
@@ -0,0 +1,17 @@
+router bgp 65000
+ no bgp ebgp-requires-policy
+ no bgp enforce-first-as
+ neighbor 192.0.2.4 remote-as internal
+ neighbor 192.0.2.5 remote-as internal
+ neighbor 192.0.2.101 remote-as internal
+ neighbor 172.17.0.201 remote-as external
+ neighbor 192.0.2.4 update-source 192.0.2.6
+ neighbor 192.0.2.5 update-source 192.0.2.6
+ neighbor 192.0.2.101 update-source 192.0.2.6
+ !
+ address-family ipv6 unicast
+ neighbor 192.0.2.4 activate
+ neighbor 192.0.2.5 activate
+ neighbor 192.0.2.101 activate
+ neighbor 172.17.0.201 activate
+ !
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/isisd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/isisd.conf
new file mode 100644
index 0000000..b575290
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/isisd.conf
@@ -0,0 +1,31 @@
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-r4
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r5
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-sw1
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+router isis 1
+ net 49.0000.0000.0000.0006.00
+ is-type level-1
+ lsp-gen-interval 1
+ topology ipv6-unicast
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/zebra.conf
new file mode 100644
index 0000000..fce74c1
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r6/zebra.conf
@@ -0,0 +1,16 @@
+!
+interface eth-r4
+ ip address 10.0.4.6/24
+ ipv6 address fd00:0:7::6/64
+!
+interface eth-r5
+ ip address 10.0.5.6/24
+ ipv6 address fd00:0:8::6/64
+!
+interface eth-sw1
+ ip address 172.17.0.6/24
+ ipv6 address fd00:0:9::6/64
+!
+interface lo
+ ip address 192.0.2.6/32
+ ipv6 address 2001:db8::6/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv4.json
new file mode 100644
index 0000000..72b0f03
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv4.json
@@ -0,0 +1,46 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65100",
+ "nexthops": [
+ {
+ "ip": "172.17.0.6",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "0.0.0.0",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "172.17.0.8",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step1.json
new file mode 100644
index 0000000..8fe5f7c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step1.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::6",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step2.json
new file mode 100644
index 0000000..8fe5f7c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgp_ipv6_step2.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::6",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgpd.conf
new file mode 100644
index 0000000..a707b23
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/bgpd.conf
@@ -0,0 +1,21 @@
+router bgp 65700
+ no bgp ebgp-requires-policy
+ no bgp enforce-first-as
+ neighbor 172.17.0.201 remote-as external
+ !
+ address-family ipv4 unicast
+ redistribute connected route-map RMAP4
+ !
+ address-family ipv6 unicast
+ redistribute connected route-map RMAP6
+ neighbor 172.17.0.201 activate
+ !
+
+ip prefix-list RANGE4 seq 10 permit 192.168.0.0/16 le 24
+ipv6 prefix-list RANGE6 seq 10 permit fd00:700::0/64
+
+route-map RMAP4 permit 10
+ match ip address prefix-list RANGE4
+!
+route-map RMAP6 permit 10
+ match ipv6 address prefix-list RANGE6
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/zebra.conf
new file mode 100644
index 0000000..7544829
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r7/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface eth-h2
+ ip address 192.168.7.2/24
+ ipv6 address fd00:700::2/64
+!
+interface eth-sw1
+ ip address 172.17.0.7/24
+ ipv6 address fd00:0:9::7/64
+!
+interface lo
+ ip address 192.0.2.7/32
+ ipv6 address 2001:db8::7/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv4.json
new file mode 100644
index 0000000..596ee4b
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv4.json
@@ -0,0 +1,46 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65100",
+ "nexthops": [
+ {
+ "ip": "172.17.0.6",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "172.17.0.7",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "0.0.0.0",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step1.json
new file mode 100644
index 0000000..20f4940
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step1.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::6",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step2.json
new file mode 100644
index 0000000..20f4940
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgp_ipv6_step2.json
@@ -0,0 +1,48 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65000 65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::6",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "",
+ "nexthops": [
+ {
+ "ip": "::",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgpd.conf
new file mode 100644
index 0000000..d57712d
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/bgpd.conf
@@ -0,0 +1,21 @@
+router bgp 65800
+ no bgp ebgp-requires-policy
+ no bgp enforce-first-as
+ neighbor 172.17.0.201 remote-as external
+ !
+ address-family ipv4 unicast
+ redistribute connected route-map RMAP4
+ !
+ address-family ipv6 unicast
+ redistribute connected route-map RMAP6
+ neighbor 172.17.0.201 activate
+ !
+
+ip prefix-list RANGE4 seq 10 permit 192.168.0.0/16 le 24
+ipv6 prefix-list RANGE6 seq 10 permit fd00:800::0/64
+
+route-map RMAP4 permit 10
+ match ip address prefix-list RANGE4
+!
+route-map RMAP6 permit 10
+ match ipv6 address prefix-list RANGE6
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/zebra.conf
new file mode 100644
index 0000000..7e2479b
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/r8/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface eth-h3
+ ip address 192.168.8.2/24
+ ipv6 address fd00:800::2/64
+!
+interface eth-sw1
+ ip address 172.17.0.8/24
+ ipv6 address fd00:0:9::8/64
+!
+interface lo
+ ip address 192.0.2.8/32
+ ipv6 address 2001:db8::8/128
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv4.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv4.json
new file mode 100644
index 0000000..ac67fe0
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv4.json
@@ -0,0 +1,58 @@
+{
+ "routes": {
+ "192.168.1.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "172.16.0.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "172.16.1.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.7.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "172.17.0.7",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "192.168.8.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "172.17.0.8",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step1.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step1.json
new file mode 100644
index 0000000..4e359fd
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step1.json
@@ -0,0 +1,62 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:1::1",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "fd00:0:2::1",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "scope": "global",
+ "afi": "ipv6",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step2.json b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step2.json
new file mode 100644
index 0000000..4ab0e1c
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgp_ipv6_step2.json
@@ -0,0 +1,62 @@
+{
+ "routes": {
+ "fd00:100::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "2001:db8::2",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ },
+ {
+ "valid": true,
+ "multipath": true,
+ "path": "65100",
+ "nexthops": [
+ {
+ "ip": "2001:db8::3",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:700::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65700",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::7",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "fd00:800::/64": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "path": "65800",
+ "nexthops": [
+ {
+ "ip": "fd00:0:9::8",
+ "afi": "ipv6",
+ "scope": "global",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgpd.conf
new file mode 100644
index 0000000..9bbac8b
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/bgpd.conf
@@ -0,0 +1,26 @@
+router bgp 65000
+ neighbor 192.0.2.2 remote-as internal
+ neighbor 192.0.2.3 remote-as internal
+ neighbor 192.0.2.4 remote-as internal
+ neighbor 192.0.2.5 remote-as internal
+ neighbor 192.0.2.6 remote-as internal
+ neighbor 192.0.2.2 update-source 192.0.2.101
+ neighbor 192.0.2.3 update-source 192.0.2.101
+ neighbor 192.0.2.4 update-source 192.0.2.101
+ neighbor 192.0.2.5 update-source 192.0.2.101
+ neighbor 192.0.2.6 update-source 192.0.2.101
+ !
+ address-family ipv4 unicast
+ neighbor 192.0.2.2 route-reflector-client
+ neighbor 192.0.2.3 route-reflector-client
+
+ !
+ address-family ipv6 unicast
+ neighbor 192.0.2.2 activate
+ neighbor 192.0.2.3 activate
+ neighbor 192.0.2.4 activate
+ neighbor 192.0.2.5 activate
+ neighbor 192.0.2.6 activate
+ neighbor 192.0.2.2 route-reflector-client
+ neighbor 192.0.2.3 route-reflector-client
+ !
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/isisd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/isisd.conf
new file mode 100644
index 0000000..fe5bcfb
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/isisd.conf
@@ -0,0 +1,40 @@
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-r2
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r3
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r4
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+interface eth-r5
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+ isis network point-to-point
+!
+router isis 1
+ net 49.0000.0000.0000.0101.00
+ is-type level-1
+ lsp-gen-interval 1
+ topology ipv6-unicast
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/zebra.conf
new file mode 100644
index 0000000..7f5c8d1
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rr1/zebra.conf
@@ -0,0 +1,21 @@
+!
+interface eth-r2
+ ip address 10.0.0.101/24
+ ipv6 address fd00:0:3::101/64
+!
+interface eth-r3
+ ip address 10.0.1.101/24
+ ipv6 address fd00:0:4::101/64
+!
+interface eth-r4
+ ip address 10.0.2.101/24
+ ipv6 address fd00:0:5::101/64
+!
+interface eth-r5
+ ip address 10.0.3.101/24
+ ipv6 address fd00:0:6::101/64
+!
+interface lo
+ ip address 192.0.2.101/32
+ ipv6 address 2001:db8::101/128
+
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/bgpd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/bgpd.conf
new file mode 100644
index 0000000..596cc3e
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/bgpd.conf
@@ -0,0 +1,21 @@
+router bgp 65200 view RS
+ bgp router-id 192.0.2.201
+ no bgp ebgp-requires-policy
+ neighbor 172.17.0.6 remote-as external
+ neighbor 172.17.0.7 remote-as external
+ neighbor 172.17.0.8 remote-as external
+ !
+ address-family ipv4 unicast
+ neighbor 172.17.0.6 route-server-client
+ neighbor 172.17.0.7 route-server-client
+ neighbor 172.17.0.8 route-server-client
+
+ !
+ address-family ipv6 unicast
+ neighbor 172.17.0.6 activate
+ neighbor 172.17.0.7 activate
+ neighbor 172.17.0.8 activate
+ neighbor 172.17.0.6 route-server-client
+ neighbor 172.17.0.7 route-server-client
+ neighbor 172.17.0.8 route-server-client
+ !
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/isisd.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/isisd.conf
new file mode 100644
index 0000000..892b4e7
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/isisd.conf
@@ -0,0 +1,36 @@
+!
+interface lo
+ ip router isis 1
+ ipv6 router isis 1
+ isis passive
+!
+interface eth-r2
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+interface eth-r3
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+interface eth-r4
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+interface eth-r5
+ ip router isis 1
+ ipv6 router isis 1
+ isis hello-interval 1
+ isis hello-multiplier 3
+!
+router isis 1
+ net 49.0000.0000.0000.0101.00
+ is-type level-1
+ lsp-gen-interval 1
+ topology ipv6-unicast
+!
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/zebra.conf b/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/zebra.conf
new file mode 100644
index 0000000..75ee083
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/rs1/zebra.conf
@@ -0,0 +1,8 @@
+interface eth-sw1
+ ip address 172.17.0.201/24
+ ipv6 address fd00:0:9::201/64
+!
+interface lo
+ ip address 192.0.2.201/32
+ ipv6 address 2001:db8::201/128
+
diff --git a/tests/topotests/bgp_nexthop_mp_ipv4_6/test_nexthop_mp_ipv4_6.py b/tests/topotests/bgp_nexthop_mp_ipv4_6/test_nexthop_mp_ipv4_6.py
new file mode 100644
index 0000000..911a6d7
--- /dev/null
+++ b/tests/topotests/bgp_nexthop_mp_ipv4_6/test_nexthop_mp_ipv4_6.py
@@ -0,0 +1,283 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2024 by 6WIND
+#
+
+"""
+Test BGP nexthop conformity with IPv4,6 MP-BGP over IPv4 peering
+"""
+
+import os
+import sys
+import json
+import functools
+from functools import partial
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# 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.checkping import check_ping
+from lib.bgp import verify_bgp_convergence_from_running_config
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.isisd]
+
+
+def build_topo(tgen):
+ r"""
+ +---+
+ | h1|
+ +---+
+ |
+ +---+
+ | r1| AS 65100
+ +---+
+ / \ _____________
+ / \
+ +---+ +---+
+ | r2| | r3| rr1 is route-reflector
+ +---+ +---+ for r2 and r3
+ \ /
+ \ /
+ +---+
+ |rr1| AS 65000
+ +---+
+ / \
+ / \
+ +---+ +---+
+ | r4| | r5| iBGP full-mesh between
+ +---+ +---+ rr1, r4, r5 and r6
+ \ /
+ \ /
+ +---+
+ | r6|
+ +---+
+ | _____________
+ |
+ | +---+
+ [sw1]-----|rs1| AS 65200
+ /\ +---+ rs1: route-server
+ / \
+ / \ _____________
+ +---+ +---+
+ | r7| | r8| AS 65700 (r7)
+ +---+ +---+ AS 65800 (r8)
+ | |
+ +---+ +---+
+ | h2| | h3|
+ +---+ +---+
+ """
+
+ def connect_routers(tgen, left, right):
+ for rname in [left, right]:
+ if rname not in tgen.routers().keys():
+ tgen.add_router(rname)
+
+ switch = tgen.add_switch("s-{}-{}".format(left, right))
+ switch.add_link(tgen.gears[left], nodeif="eth-{}".format(right))
+ switch.add_link(tgen.gears[right], nodeif="eth-{}".format(left))
+
+ def connect_switchs(tgen, rname, switch):
+ if rname not in tgen.routers().keys():
+ tgen.add_router(rname)
+
+ switch.add_link(tgen.gears[rname], nodeif="eth-{}".format(switch.name))
+
+ connect_routers(tgen, "h1", "r1")
+ connect_routers(tgen, "r1", "r2")
+ connect_routers(tgen, "r1", "r3")
+ connect_routers(tgen, "r2", "rr1")
+ connect_routers(tgen, "r3", "rr1")
+ connect_routers(tgen, "rr1", "r4")
+ connect_routers(tgen, "rr1", "r5")
+ connect_routers(tgen, "r4", "r6")
+ connect_routers(tgen, "r5", "r6")
+
+ sw1 = tgen.add_switch("sw1")
+ connect_switchs(tgen, "r6", sw1)
+ connect_switchs(tgen, "rs1", sw1)
+ connect_switchs(tgen, "r7", sw1)
+ connect_switchs(tgen, "r8", sw1)
+
+ connect_routers(tgen, "r7", "h2")
+ connect_routers(tgen, "r8", "h3")
+
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+ logger.info("setup_module")
+
+ for rname, router in tgen.routers().items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ if "h" in rname:
+ # hosts
+ continue
+
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ if rname in ["r1", "r7", "r8", "rs1"]:
+ # external routers
+ continue
+
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_convergence():
+ "Assert that BGP is converging."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("waiting for bgp peers to go up")
+
+ for rname in tgen.routers().keys():
+ if "h" in rname:
+ # hosts
+ continue
+ result = verify_bgp_convergence_from_running_config(tgen, dut=rname)
+ assert result is True, "BGP is not converging on {}".format(rname)
+
+
+def test_bgp_ipv4_nexthop_step1():
+ "Assert that BGP has correct ipv4 nexthops."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname, router in tgen.routers().items():
+ if "h" in rname:
+ # hosts
+ continue
+ if "rs1" in rname:
+ continue
+ ref_file = "{}/{}/bgp_ipv4.json".format(CWD, rname)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp ipv4 unicast json",
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = "{}: BGP IPv4 Nexthop failure".format(rname)
+ assert res is None, assertmsg
+
+
+def test_bgp_ipv6_nexthop_step1():
+ "Assert that BGP has correct ipv6 nexthops."
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ for rname, router in tgen.routers().items():
+ if "h" in rname:
+ # hosts
+ continue
+ if "rs1" in rname:
+ continue
+ ref_file = "{}/{}/bgp_ipv6_step1.json".format(CWD, rname)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp ipv6 unicast json",
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = "{}: BGP IPv6 Nexthop failure".format(rname)
+ assert res is None, assertmsg
+
+
+def test_bgp_ping_ok_step1():
+ "Check that h1 pings h2 and h3"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ check_ping("h1", "192.168.7.1", True, 5, 1)
+ check_ping("h1", "fd00:700::1", True, 5, 1)
+ check_ping("h1", "192.168.8.1", True, 5, 1)
+ check_ping("h1", "fd00:800::1", True, 5, 1)
+
+
+def test_bgp_ipv6_nexthop_step2():
+ """
+ Remove IPv6 global on r1 and r7
+ Assert that BGP has correct ipv6 nexthops.
+ """
+
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ tgen.gears["r1"].vtysh_cmd(
+ """
+configure
+interface eth-r2
+ no ipv6 address fd00:0:1::1/64
+!
+interface eth-r3
+ no ipv6 address fd00:0:2::1/64
+"""
+ )
+
+ for rname, router in tgen.routers().items():
+ if "h" in rname:
+ # hosts
+ continue
+ if "rs1" in rname:
+ continue
+ ref_file = "{}/{}/bgp_ipv6_step2.json".format(CWD, rname)
+ expected = json.loads(open(ref_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp ipv6 unicast json",
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assertmsg = "{}: BGP IPv6 Nexthop failure".format(rname)
+ assert res is None, assertmsg
+
+
+def test_bgp_ping_ok_step2():
+ "Check that h1 pings h2 and h3"
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ check_ping("h1", "192.168.7.1", True, 5, 1)
+ check_ping("h1", "fd00:700::1", True, 5, 1)
+ check_ping("h1", "192.168.8.1", True, 5, 1)
+ check_ping("h1", "fd00:800::1", True, 5, 1)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_oad/test_bgp_oad.py b/tests/topotests/bgp_oad/test_bgp_oad.py
index b26c548..a2ca37a 100644
--- a/tests/topotests/bgp_oad/test_bgp_oad.py
+++ b/tests/topotests/bgp_oad/test_bgp_oad.py
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2", "r4"), "s2": ("r2", "r3"), "s3": ("r4", "r5")}
diff --git a/tests/topotests/bgp_orf/test_bgp_orf.py b/tests/topotests/bgp_orf/test_bgp_orf.py
index 7f45a24..47c0556 100644
--- a/tests/topotests/bgp_orf/test_bgp_orf.py
+++ b/tests/topotests/bgp_orf/test_bgp_orf.py
@@ -20,7 +20,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -29,8 +29,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py
index df39032..8504737 100644
--- a/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py
+++ b/tests/topotests/bgp_path_attributes_topo1/test_bgp_path_attributes.py
@@ -78,6 +78,7 @@ pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
# Address read from env variables
ADDR_TYPES = check_address_types()
+
####
def setup_module(mod):
"""
diff --git a/tests/topotests/bgp_path_selection/test_bgp_path_selection.py b/tests/topotests/bgp_path_selection/test_bgp_path_selection.py
index bf5737b..30083b4 100644
--- a/tests/topotests/bgp_path_selection/test_bgp_path_selection.py
+++ b/tests/topotests/bgp_path_selection/test_bgp_path_selection.py
@@ -49,7 +49,11 @@ def setup_module(mod):
for routern in range(1, 4):
tgen.gears["r{}".format(routern)].cmd("ip link add vrf1 type vrf table 10")
tgen.gears["r{}".format(routern)].cmd("ip link set vrf1 up")
- tgen.gears["r{}".format(routern)].cmd("ip address add dev vrf1 {}.{}.{}.{}/32".format(routern, routern, routern,routern))
+ tgen.gears["r{}".format(routern)].cmd(
+ "ip address add dev vrf1 {}.{}.{}.{}/32".format(
+ routern, routern, routern, routern
+ )
+ )
tgen.gears["r2"].cmd("ip address add dev vrf1 192.0.2.8/32")
tgen.gears["r3"].cmd("ip address add dev vrf1 192.0.2.8/32")
@@ -74,6 +78,7 @@ def teardown_module(mod):
tgen = get_topogen()
tgen.stop_topology()
+
def test_bgp_path_selection_ecmp():
tgen = get_topogen()
@@ -97,7 +102,7 @@ def test_bgp_path_selection_ecmp():
"aspath": {"string": "65002"},
"multipath": True,
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
@@ -117,7 +122,9 @@ def test_bgp_path_selection_vpn_ecmp():
def _bgp_check_path_selection_vpn_ecmp():
output = json.loads(
- tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json")
+ tgen.gears["r1"].vtysh_cmd(
+ "show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json"
+ )
)
expected = {
"paths": [
@@ -132,7 +139,7 @@ def test_bgp_path_selection_vpn_ecmp():
"aspath": {"string": "65002"},
"multipath": True,
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
@@ -160,13 +167,13 @@ def test_bgp_path_selection_metric():
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.2", "metric": 10}],
- "bestpath":{ "selectionReason":"IGP Metric"},
+ "bestpath": {"selectionReason": "IGP Metric"},
},
{
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
@@ -189,7 +196,9 @@ def test_bgp_path_selection_vpn_metric():
def _bgp_check_path_selection_vpn_metric():
output = json.loads(
- tgen.gears["r1"].vtysh_cmd("show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json")
+ tgen.gears["r1"].vtysh_cmd(
+ "show bgp vrf vrf1 ipv4 unicast 192.0.2.8/32 json"
+ )
)
expected = {
"paths": [
@@ -197,13 +206,13 @@ def test_bgp_path_selection_vpn_metric():
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.2", "metric": 10}],
- "bestpath":{ "selectionReason":"IGP Metric"},
+ "bestpath": {"selectionReason": "IGP Metric"},
},
{
"valid": True,
"aspath": {"string": "65002"},
"nexthops": [{"ip": "192.0.2.3", "metric": 20}],
- }
+ },
]
}
diff --git a/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py b/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py
index 2eb936a..9269826 100644
--- a/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py
+++ b/tests/topotests/bgp_peer_graceful_shutdown/test_bgp_peer_graceful_shutdown.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import step
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2"), "s2": ("r2", "r3")}
diff --git a/tests/topotests/bgp_peer_group/r1/bgpd.conf b/tests/topotests/bgp_peer_group/r1/bgpd.conf
index 19b490a..68d8e61 100644
--- a/tests/topotests/bgp_peer_group/r1/bgpd.conf
+++ b/tests/topotests/bgp_peer_group/r1/bgpd.conf
@@ -5,4 +5,8 @@ router bgp 65001
neighbor PG timers 3 10
neighbor 192.168.255.3 peer-group PG
neighbor r1-eth0 interface peer-group PG
+ neighbor PG1 peer-group
+ neighbor PG1 remote-as external
+ neighbor PG1 timers 3 20
+ neighbor 192.168.251.2 peer-group PG1
!
diff --git a/tests/topotests/bgp_peer_group/r1/zebra.conf b/tests/topotests/bgp_peer_group/r1/zebra.conf
index e2c399e..16fd8c5 100644
--- a/tests/topotests/bgp_peer_group/r1/zebra.conf
+++ b/tests/topotests/bgp_peer_group/r1/zebra.conf
@@ -2,5 +2,8 @@
interface r1-eth0
ip address 192.168.255.1/24
!
+interface r1-eth1
+ ip address 192.168.251.1/30
+!
ip forwarding
!
diff --git a/tests/topotests/bgp_peer_group/r2/bgpd.conf b/tests/topotests/bgp_peer_group/r2/bgpd.conf
index 0880ee9..d0e8f01 100644
--- a/tests/topotests/bgp_peer_group/r2/bgpd.conf
+++ b/tests/topotests/bgp_peer_group/r2/bgpd.conf
@@ -4,4 +4,8 @@ router bgp 65002
neighbor PG remote-as external
neighbor PG timers 3 10
neighbor r2-eth0 interface peer-group PG
+ neighbor PG1 peer-group
+ neighbor PG1 remote-as external
+ neighbor PG1 timers 3 20
+ neighbor 192.168.251.1 peer-group PG1
!
diff --git a/tests/topotests/bgp_peer_group/r2/zebra.conf b/tests/topotests/bgp_peer_group/r2/zebra.conf
index 606c17b..c2ad956 100644
--- a/tests/topotests/bgp_peer_group/r2/zebra.conf
+++ b/tests/topotests/bgp_peer_group/r2/zebra.conf
@@ -2,5 +2,8 @@
interface r2-eth0
ip address 192.168.255.2/24
!
+interface r2-eth1
+ ip address 192.168.251.2/30
+!
ip forwarding
!
diff --git a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
index a91fade..5cbcd19 100644
--- a/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
+++ b/tests/topotests/bgp_peer_group/test_bgp_peer-group.py
@@ -22,7 +22,7 @@ sys.path.append(os.path.join(CWD, "../"))
# pylint: disable=C0413
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-
+from lib.topolog import logger
pytestmark = [pytest.mark.bgpd]
@@ -36,6 +36,10 @@ def build_topo(tgen):
switch.add_link(tgen.gears["r2"])
switch.add_link(tgen.gears["r3"])
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
@@ -70,6 +74,7 @@ def test_bgp_peer_group():
expected = {
"r1-eth0": {"peerGroup": "PG", "bgpState": "Established"},
"192.168.255.3": {"peerGroup": "PG", "bgpState": "Established"},
+ "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Established"},
}
return topotest.json_cmp(output, expected)
@@ -96,6 +101,48 @@ def test_bgp_peer_group():
assert result is None, "Failed checking advertised routes from r3"
+def test_bgp_peer_group_remote_as_del_readd():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ logger.info("Remove bgp peer-group PG1 remote-as neighbor should be retained")
+ r1.cmd(
+ 'vtysh -c "config t" -c "router bgp 65001" '
+ + ' -c "no neighbor PG1 remote-as external" '
+ )
+
+ def _bgp_peer_group_remoteas_del():
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Active"},
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_peer_group_remoteas_del)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed bgp convergence in r1"
+
+ logger.info("Re-add bgp peer-group PG1 remote-as neighbor should be established")
+ r1.cmd(
+ 'vtysh -c "config t" -c "router bgp 65001" '
+ + ' -c "neighbor PG1 remote-as external" '
+ )
+
+ def _bgp_peer_group_remoteas_add():
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp neighbor json"))
+ expected = {
+ "192.168.251.2": {"peerGroup": "PG1", "bgpState": "Established"},
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_peer_group_remoteas_add)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed bgp convergence in r1"
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py b/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py
index 9239be9..340df71 100755
--- a/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py
+++ b/tests/topotests/bgp_peer_type_multipath_relax/test_bgp_peer-type_multipath-relax.py
@@ -103,7 +103,6 @@ def setup_module(mod):
# For all registered routers, load the zebra configuration file
for rname, router in tgen.routers().items():
- router.run("/bin/bash {}/setup_vrfs".format(CWD))
router.load_config(
TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
)
diff --git a/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py b/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py
index 0eb2447..5d6440c 100644
--- a/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py
+++ b/tests/topotests/bgp_prefix_list_any/test_bgp_prefix_list_any.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py b/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py
index 2ae6f7f..d9402f2 100644
--- a/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py
+++ b/tests/topotests/bgp_remove_private_as_route_map/test_bgp_remove_private_as_route_map.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py b/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py
index 5c7cc8e..ef7c94b 100644
--- a/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py
+++ b/tests/topotests/bgp_rmap_extcommunity_none/test_bgp_rmap_extcommunity_none.py
@@ -18,7 +18,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -27,8 +27,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py
index 412ecc1..d50d67b 100644
--- a/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py
+++ b/tests/topotests/bgp_route_aggregation/test_bgp_aggregation.py
@@ -403,7 +403,6 @@ def test_route_summarisation_with_summary_only_p1(request):
)
for action, value in zip(["removed", "add"], [True, False]):
-
step(
"{} static routes as below: "
"(no) ip route 10.1.1.0/24 and (no) ip route 10.1.2.0/24"
@@ -815,7 +814,11 @@ def test_route_summarisation_with_as_set_p1(request):
)
for addr_type in ADDR_TYPES:
- for pfx, seq_id, network, in zip(
+ for (
+ pfx,
+ seq_id,
+ network,
+ ) in zip(
[1, 2, 3, 4, 5],
[10, 20, 30, 40, 50],
[NETWORK_1_1, NETWORK_1_2, NETWORK_1_3, NETWORK_1_4, NETWORK_1_5],
diff --git a/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py b/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py
index 15a077d..f7a66fd 100644
--- a/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py
+++ b/tests/topotests/bgp_route_map_delay_timer/test_bgp_route_map_delay_timer.py
@@ -15,7 +15,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
index a06e3ed..93a514b 100644
--- a/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
+++ b/tests/topotests/bgp_route_map_match_ipv6_nexthop/test_bgp_route_map_match_ipv6_nexthop.py
@@ -16,7 +16,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -25,8 +25,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step11/show_ipv6_route.ref.diff b/tests/topotests/bgp_route_map_match_tag_untagged/__init__.py
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step11/show_ipv6_route.ref.diff
+++ b/tests/topotests/bgp_route_map_match_tag_untagged/__init__.py
diff --git a/tests/topotests/bgp_route_map_match_tag_untagged/r1/frr.conf b/tests/topotests/bgp_route_map_match_tag_untagged/r1/frr.conf
new file mode 100644
index 0000000..13eced2
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_tag_untagged/r1/frr.conf
@@ -0,0 +1,19 @@
+!
+interface r1-eth0
+ ip address 192.168.1.1/24
+!
+router bgp 65001
+ address-family ipv4
+ redistribute static route-map untagged
+ exit-address-family
+!
+ip route 10.10.10.10/32 Null0
+ip route 10.10.10.20/32 Null0 tag 20
+!
+route-map untagged permit 10
+ match tag untagged
+ set tag 10
+route-map untagged permit 20
+ match tag 20
+ set tag untagged
+exit
diff --git a/tests/topotests/bgp_route_map_match_tag_untagged/test_bgp_route_map_match_tag_untagged.py b/tests/topotests/bgp_route_map_match_tag_untagged/test_bgp_route_map_match_tag_untagged.py
new file mode 100644
index 0000000..7dd63fd
--- /dev/null
+++ b/tests/topotests/bgp_route_map_match_tag_untagged/test_bgp_route_map_match_tag_untagged.py
@@ -0,0 +1,83 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 2):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_route_map_match_tag_untagged():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_check_advertised_routes_r2():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show bgp ipv4 unicast detail json")
+ )
+ expected = {
+ "routes": {
+ "10.10.10.10/32": [
+ {
+ "tag": 10,
+ }
+ ],
+ "10.10.10.20/32": [
+ {
+ "tag": None,
+ }
+ ],
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_check_advertised_routes_r2)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Tags for static routes are not as expected"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py
index 23cf041..18b7831 100644
--- a/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py
+++ b/tests/topotests/bgp_route_server_client/test_bgp_route_server_client.py
@@ -15,7 +15,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -24,8 +24,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 4):
diff --git a/tests/topotests/bgp_rpki_topo1/r2/bgpd.conf b/tests/topotests/bgp_rpki_topo1/r2/bgpd.conf
index 87d7214..4de177d 100644
--- a/tests/topotests/bgp_rpki_topo1/r2/bgpd.conf
+++ b/tests/topotests/bgp_rpki_topo1/r2/bgpd.conf
@@ -21,5 +21,5 @@ router bgp 65002 vrf vrf10
!
rpki
rpki retry_interval 5
- rpki cache 192.0.2.1 15432 preference 1
+ rpki cache tcp 192.0.2.1 15432 preference 1
exit
diff --git a/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py b/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py
index a12204f..f52b28a 100644
--- a/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py
+++ b/tests/topotests/bgp_rpki_topo1/test_bgp_rpki_topo1.py
@@ -189,7 +189,7 @@ def test_show_bgp_rpki_prefixes_no_rpki_cache():
"""
configure
rpki
- no rpki cache 192.0.2.1 15432 preference 1
+ no rpki cache tcp 192.0.2.1 15432 preference 1
exit
"""
)
@@ -219,7 +219,7 @@ def test_show_bgp_rpki_prefixes_reconnect():
"""
configure
rpki
- rpki cache 192.0.2.1 15432 preference 1
+ rpki cache tcp 192.0.2.1 15432 preference 1
exit
"""
)
@@ -319,7 +319,7 @@ def test_show_bgp_rpki_prefixes_vrf():
configure
vrf vrf10
rpki
- rpki cache 192.0.2.3 15432 preference 1
+ rpki cache tcp 192.0.2.3 15432 preference 1
exit
exit
"""
diff --git a/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py b/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py
index 3886bc1..db6dbc6 100644
--- a/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py
+++ b/tests/topotests/bgp_sender_as_path_loop_detection/test_bgp_sender-as-path-loop-detection.py
@@ -129,6 +129,83 @@ def test_bgp_sender_as_path_loop_detection():
assert result is None, "Routes should not be sent to r1 from r2"
+def test_remove_loop_detection_on_one_peer():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r2 = tgen.gears["r2"]
+
+ def _bgp_reset_route_to_r1():
+ output = json.loads(
+ r2.vtysh_cmd("show ip bgp neighbor 192.168.255.2 advertised-routes json")
+ )
+ expected = {"totalPrefixCounter": 3}
+ return topotest.json_cmp(output, expected)
+
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65002
+ no neighbor 192.168.255.2 sender-as-path-loop-detection
+ """
+ )
+
+ r2.vtysh_cmd(
+ """
+ clear bgp *
+ """
+ )
+ test_func = functools.partial(_bgp_reset_route_to_r1)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed bgp to reset route"
+
+
+def test_loop_detection_on_peer_group():
+ tgen = get_topogen()
+
+ r2 = tgen.gears["r2"]
+
+ def _bgp_suppress_route_to_r1():
+ output = json.loads(
+ r2.vtysh_cmd("show ip bgp neighbor 192.168.255.2 advertised-routes json")
+ )
+ expected = {"totalPrefixCounter": 0}
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_suppress_route_to_r3():
+ output = json.loads(
+ r2.vtysh_cmd("show ip bgp neighbor 192.168.254.2 advertised-routes json")
+ )
+ expected = {"totalPrefixCounter": 2}
+ return topotest.json_cmp(output, expected)
+
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65002
+ neighbor loop_group peer-group
+ neighbor 192.168.255.2 peer-group loop_group
+ neighbor loop_group sender-as-path-loop-detection
+ """
+ )
+
+ r2.vtysh_cmd(
+ """
+ clear bgp *
+ """
+ )
+
+ test_func = functools.partial(_bgp_suppress_route_to_r3)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Route 172.16.255.253/32 should not be sent to r3 from r2"
+
+ test_func = functools.partial(_bgp_suppress_route_to_r1)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Routes should not be sent to r1 from r2"
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_set_aspath_exclude/r1/bgpd.conf b/tests/topotests/bgp_set_aspath_exclude/r1/bgpd.conf
index 9bef24f..c70b493 100644
--- a/tests/topotests/bgp_set_aspath_exclude/r1/bgpd.conf
+++ b/tests/topotests/bgp_set_aspath_exclude/r1/bgpd.conf
@@ -8,10 +8,19 @@ router bgp 65001
exit-address-family
!
ip prefix-list p1 seq 5 permit 172.16.255.31/32
+ip prefix-list p2 seq 5 permit 172.16.255.32/32
+ip prefix-list p3 seq 5 permit 172.16.255.30/32
!
+bgp as-path access-list FIRST permit ^65
+bgp as-path access-list SECOND permit 2$
+
+route-map r2 permit 6
+ match ip address prefix-list p2
+ set as-path exclude as-path-access-list SECOND
route-map r2 permit 10
match ip address prefix-list p1
set as-path exclude 65003
route-map r2 permit 20
+ match ip address prefix-list p3
set as-path exclude all
!
diff --git a/tests/topotests/bgp_set_aspath_exclude/r3/zebra.conf b/tests/topotests/bgp_set_aspath_exclude/r3/zebra.conf
index 3fa6c64..5689315 100644
--- a/tests/topotests/bgp_set_aspath_exclude/r3/zebra.conf
+++ b/tests/topotests/bgp_set_aspath_exclude/r3/zebra.conf
@@ -1,5 +1,6 @@
!
int lo
+ ip address 172.16.255.30/32
ip address 172.16.255.31/32
ip address 172.16.255.32/32
!
diff --git a/tests/topotests/bgp_set_aspath_exclude/test_bgp_set_aspath_exclude.py b/tests/topotests/bgp_set_aspath_exclude/test_bgp_set_aspath_exclude.py
index d373a74..85e7b96 100644
--- a/tests/topotests/bgp_set_aspath_exclude/test_bgp_set_aspath_exclude.py
+++ b/tests/topotests/bgp_set_aspath_exclude/test_bgp_set_aspath_exclude.py
@@ -64,29 +64,33 @@ def teardown_module(mod):
expected_1 = {
"routes": {
+ "172.16.255.30/32": [{"path": ""}],
"172.16.255.31/32": [{"path": "65002"}],
- "172.16.255.32/32": [{"path": ""}],
+ "172.16.255.32/32": [{"path": "65003"}],
}
}
expected_2 = {
"routes": {
- "172.16.255.31/32": [{"path": ""}],
+ "172.16.255.30/32": [{"path": ""}],
+ "172.16.255.31/32": [{"path": "65002"}],
"172.16.255.32/32": [{"path": ""}],
}
}
expected_3 = {
"routes": {
- "172.16.255.31/32": [{"path": "65003"}],
- "172.16.255.32/32": [{"path": "65003"}],
+ "172.16.255.30/32": [{"path": ""}],
+ "172.16.255.31/32": [{"path": "65002"}],
+ "172.16.255.32/32": [{"path": "65002 65003"}],
}
}
expected_4 = {
"routes": {
- "172.16.255.31/32": [{"path": "65002 65003"}],
- "172.16.255.32/32": [{"path": "65002 65003"}],
+ "172.16.255.30/32": [{"path": ""}],
+ "172.16.255.31/32": [{"path": "65002"}],
+ "172.16.255.32/32": [{"path": "65002"}],
}
}
@@ -117,34 +121,42 @@ def test_bgp_set_aspath_exclude_access_list():
rname = "r1"
r1 = tgen.gears[rname]
+ # tgen.mininet_cli()
r1.vtysh_cmd(
"""
conf
bgp as-path access-list FIRST permit ^65
route-map r2 permit 6
+ no set as-path exclude as-path-access-list SECOND
set as-path exclude as-path-access-list FIRST
"""
)
+ # tgen.mininet_cli()
+ r1.vtysh_cmd(
+ """
+clear bgp *
+ """
+ )
test_func = functools.partial(bgp_converge, tgen.gears["r1"], expected_2)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
- assert result is None, "Failed overriding incoming AS-PATH with regex 1 route-map"
+ assert result is None, "Failed change of exclude rule in route map"
r1.vtysh_cmd(
"""
conf
- bgp as-path access-list SECOND permit 2
route-map r2 permit 6
+ no set as-path exclude as-path-access-list FIRST
set as-path exclude as-path-access-list SECOND
"""
)
# tgen.mininet_cli()
- test_func = functools.partial(bgp_converge, tgen.gears["r1"], expected_3)
+ test_func = functools.partial(bgp_converge, tgen.gears["r1"], expected_1)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
- assert result is None, "Failed overriding incoming AS-PATH with regex 2 route-map"
+ assert result is None, "Failed reverting exclude rule in route map"
def test_no_bgp_set_aspath_exclude_access_list():
@@ -159,15 +171,28 @@ def test_no_bgp_set_aspath_exclude_access_list():
r1.vtysh_cmd(
"""
conf
- no bgp as-path access-list SECOND permit 2
+ no bgp as-path access-list SECOND permit 2$
+ """
+ )
+
+ r1.vtysh_cmd(
+ """
+clear bgp *
"""
)
test_func = functools.partial(bgp_converge, tgen.gears["r1"], expected_3)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
- assert result is None, "Failed removing bgp as-path access-list"
+ assert result is None, "Failed to removing current accesslist"
+ # tgen.mininet_cli()
+ r1.vtysh_cmd(
+ """
+conf
+ bgp as-path access-list SECOND permit 3$
+ """
+ )
r1.vtysh_cmd(
"""
clear bgp *
@@ -177,7 +202,26 @@ clear bgp *
test_func = functools.partial(bgp_converge, tgen.gears["r1"], expected_4)
_, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
- assert result is None, "Failed to renegotiate with peers"
+ assert result is None, "Failed to renegotiate with peers 2"
+
+ r1.vtysh_cmd(
+ """
+conf
+ route-map r2 permit 6
+ no set as-path exclude as-path-access-list SECOND
+ """
+ )
+
+ r1.vtysh_cmd(
+ """
+clear bgp *
+ """
+ )
+
+ test_func = functools.partial(bgp_converge, tgen.gears["r1"], expected_3)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+
+ assert result is None, "Failed to renegotiate with peers 2"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_software_version/test_bgp_software_version.py b/tests/topotests/bgp_software_version/test_bgp_software_version.py
index 25e646c..c867208 100644
--- a/tests/topotests/bgp_software_version/test_bgp_software_version.py
+++ b/tests/topotests/bgp_software_version/test_bgp_software_version.py
@@ -17,7 +17,7 @@ import json
import pytest
import functools
-pytestmark = pytest.mark.bgpd
+pytestmark = [pytest.mark.bgpd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -26,8 +26,6 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
-pytestmark = [pytest.mark.bgpd]
-
def setup_module(mod):
topodef = {"s1": ("r1", "r2")}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step11/show_mpls_table.ref.diff b/tests/topotests/bgp_srv6_sid_reachability/c11/bgpd.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step11/show_mpls_table.ref.diff
+++ b/tests/topotests/bgp_srv6_sid_reachability/c11/bgpd.conf
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c11/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/c11/staticd.conf
new file mode 100644
index 0000000..bcf5a04
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c11/staticd.conf
@@ -0,0 +1,4 @@
+!
+ip route 0.0.0.0/0 192.168.1.254
+ipv6 route ::/0 2001:1::ffff
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c11/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/c11/zebra.conf
new file mode 100644
index 0000000..0615cf9
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c11/zebra.conf
@@ -0,0 +1,6 @@
+hostname c11
+!
+interface eth0
+ ip address 192.168.1.1/24
+ ipv6 address 2001:1::1/64
+!
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ip_route.ref.diff b/tests/topotests/bgp_srv6_sid_reachability/c12/bgpd.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ip_route.ref.diff
+++ b/tests/topotests/bgp_srv6_sid_reachability/c12/bgpd.conf
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c12/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/c12/staticd.conf
new file mode 100644
index 0000000..bcf5a04
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c12/staticd.conf
@@ -0,0 +1,4 @@
+!
+ip route 0.0.0.0/0 192.168.1.254
+ipv6 route ::/0 2001:1::ffff
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c12/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/c12/zebra.conf
new file mode 100644
index 0000000..18985aa
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c12/zebra.conf
@@ -0,0 +1,6 @@
+hostname c12
+!
+interface eth0
+ ip address 192.168.1.1/24
+ ipv6 address 2001:1::1/64
+!
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ipv6_route.ref.diff b/tests/topotests/bgp_srv6_sid_reachability/c21/bgpd.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ipv6_route.ref.diff
+++ b/tests/topotests/bgp_srv6_sid_reachability/c21/bgpd.conf
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c21/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/c21/staticd.conf
new file mode 100644
index 0000000..608e600
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c21/staticd.conf
@@ -0,0 +1,4 @@
+!
+ip route 0.0.0.0/0 192.168.2.254
+ipv6 route ::/0 2001:2::ffff
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c21/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/c21/zebra.conf
new file mode 100644
index 0000000..b8b70ac
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c21/zebra.conf
@@ -0,0 +1,6 @@
+hostname c21
+!
+interface eth0
+ ip address 192.168.2.1/24
+ ipv6 address 2001:2::1/64
+!
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_mpls_table.ref.diff b/tests/topotests/bgp_srv6_sid_reachability/c22/bgpd.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_mpls_table.ref.diff
+++ b/tests/topotests/bgp_srv6_sid_reachability/c22/bgpd.conf
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c22/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/c22/staticd.conf
new file mode 100644
index 0000000..277aae9
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c22/staticd.conf
@@ -0,0 +1,5 @@
+
+!
+ip route 0.0.0.0/0 192.168.2.254
+ipv6 route ::/0 2001:2::ffff
+! \ No newline at end of file
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c22/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/c22/zebra.conf
new file mode 100644
index 0000000..cc764cc
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c22/zebra.conf
@@ -0,0 +1,9 @@
+hostname c22
+!
+interface eth0
+ ip address 192.168.2.1/24
+ ipv6 address 2001:2::1/64
+!
+ip route 0.0.0.0/0 192.168.2.254
+ipv6 route ::/0 2001:2::ffff
+!
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ip_route.ref.diff b/tests/topotests/bgp_srv6_sid_reachability/c31/bgpd.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ip_route.ref.diff
+++ b/tests/topotests/bgp_srv6_sid_reachability/c31/bgpd.conf
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c31/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/c31/staticd.conf
new file mode 100644
index 0000000..0c88575
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c31/staticd.conf
@@ -0,0 +1,4 @@
+!
+ip route 0.0.0.0/0 192.168.3.254
+ipv6 route ::/0 2001:3::ffff
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c31/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/c31/zebra.conf
new file mode 100644
index 0000000..3f75641
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c31/zebra.conf
@@ -0,0 +1,6 @@
+hostname c31
+!
+interface eth0
+ ip address 192.168.3.1/24
+ ipv6 address 2001:3::1/64
+!
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ipv6_route.ref.diff b/tests/topotests/bgp_srv6_sid_reachability/c32/bgpd.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ipv6_route.ref.diff
+++ b/tests/topotests/bgp_srv6_sid_reachability/c32/bgpd.conf
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c32/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/c32/staticd.conf
new file mode 100644
index 0000000..0c88575
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c32/staticd.conf
@@ -0,0 +1,4 @@
+!
+ip route 0.0.0.0/0 192.168.3.254
+ipv6 route ::/0 2001:3::ffff
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/c32/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/c32/zebra.conf
new file mode 100644
index 0000000..c06a7d1
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/c32/zebra.conf
@@ -0,0 +1,6 @@
+hostname c32
+!
+interface eth0
+ ip address 192.168.3.1/24
+ ipv6 address 2001:3::1/64
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r1/bgpd.conf b/tests/topotests/bgp_srv6_sid_reachability/r1/bgpd.conf
new file mode 100644
index 0000000..573dbe0
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r1/bgpd.conf
@@ -0,0 +1,61 @@
+frr defaults traditional
+!
+hostname r1
+password zebra
+!
+log commands
+!
+router bgp 65001
+ bgp router-id 192.0.2.1
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001:db8:12::2 remote-as 65002
+ neighbor 2001:db8:12::2 timers 3 10
+ neighbor 2001:db8:12::2 timers connect 1
+ neighbor 2001:db8:12::2 capability extended-nexthop
+ neighbor 2001:db8:13::3 remote-as 65001
+ neighbor 2001:db8:13::3 timers 3 10
+ neighbor 2001:db8:13::3 timers connect 1
+ neighbor 2001:db8:13::3 capability extended-nexthop
+ !
+ segment-routing srv6
+ locator default
+ !
+ address-family ipv4 vpn
+ neighbor 2001:db8:12::2 activate
+ neighbor 2001:db8:13::3 activate
+ exit-address-family
+ !
+!
+router bgp 65001 vrf vrf10
+ bgp router-id 192.0.2.1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 1
+ rd vpn export 65001:10
+ rt vpn both 0:10
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
+router bgp 65001 vrf vrf20
+ bgp router-id 192.0.2.1
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 2
+ rd vpn export 65001:20
+ rt vpn both 0:20
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
+interface eth0
+ mpls bgp forwarding
+!
+interface eth1
+ mpls bgp forwarding
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r1/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/r1/staticd.conf
new file mode 100644
index 0000000..49b64fd
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r1/staticd.conf
@@ -0,0 +1,4 @@
+!
+ipv6 route 2001:db8:2:2::/64 2001:db8:12::2
+ipv6 route 2001:db8:3:3::/64 2001:db8:13::3
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r1/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/r1/zebra.conf
new file mode 100644
index 0000000..79dbf95
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r1/zebra.conf
@@ -0,0 +1,32 @@
+log file zebra.log
+!
+hostname r1
+!
+interface lo
+ ipv6 address 2001:db8:1:1::1/128
+!
+interface eth0
+ ipv6 address 2001:db8:12::1/64
+!
+interface eth1
+ ipv6 address 2001:db8:13::1/64
+!
+interface eth2 vrf vrf10
+ ip address 192.168.1.254/24
+!
+interface eth3 vrf vrf20
+ ip address 192.168.1.254/24
+!
+segment-routing
+ srv6
+ locators
+ locator default
+ prefix 2001:db8:1:1::/64
+ !
+ !
+!
+ip forwarding
+ipv6 forwarding
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r2/bgpd.conf b/tests/topotests/bgp_srv6_sid_reachability/r2/bgpd.conf
new file mode 100644
index 0000000..723d6fc
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r2/bgpd.conf
@@ -0,0 +1,50 @@
+frr defaults traditional
+!
+hostname r2
+password zebra
+!
+log commands
+!
+router bgp 65002
+ bgp router-id 192.0.2.2
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001:db8:12::1 remote-as 65001
+ neighbor 2001:db8:12::1 timers 3 10
+ neighbor 2001:db8:12::1 timers connect 1
+ neighbor 2001:db8:12::1 capability extended-nexthop
+ !
+ segment-routing srv6
+ locator default
+ !
+ address-family ipv4 vpn
+ neighbor 2001:db8:12::1 activate
+ exit-address-family
+ !
+!
+router bgp 65002 vrf vrf10
+ bgp router-id 192.0.2.2
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 1
+ rd vpn export 65002:10
+ rt vpn both 0:10
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
+router bgp 65002 vrf vrf20
+ bgp router-id 192.0.2.2
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 2
+ rd vpn export 65002:20
+ rt vpn both 0:20
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r2/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/r2/staticd.conf
new file mode 100644
index 0000000..8d80c1e
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r2/staticd.conf
@@ -0,0 +1,4 @@
+!
+ipv6 route 2001:db8:1:1::/64 2001:db8:12::1
+ipv6 route 2001:db8:3:3::/64 2001:db8:12::1
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r2/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/r2/zebra.conf
new file mode 100644
index 0000000..09a65b9
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r2/zebra.conf
@@ -0,0 +1,29 @@
+log file zebra.log
+!
+hostname r2
+!
+interface lo
+ ipv6 address 2001:db8:2:2::1/128
+!
+interface eth0
+ ipv6 address 2001:db8:12::2/64
+!
+interface eth1 vrf vrf10
+ ip address 192.168.2.254/24
+!
+interface eth2 vrf vrf20
+ ip address 192.168.2.254/24
+!
+segment-routing
+ srv6
+ locators
+ locator default
+ prefix 2001:db8:2:2::/64
+ !
+ !
+!
+ip forwarding
+ipv6 forwarding
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r3/bgpd.conf b/tests/topotests/bgp_srv6_sid_reachability/r3/bgpd.conf
new file mode 100644
index 0000000..c412cb6
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r3/bgpd.conf
@@ -0,0 +1,50 @@
+frr defaults traditional
+!
+hostname r2
+password zebra
+!
+log commands
+!
+router bgp 65001
+ bgp router-id 192.0.2.3
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 2001:db8:13::1 remote-as 65001
+ neighbor 2001:db8:13::1 timers 3 10
+ neighbor 2001:db8:13::1 timers connect 1
+ neighbor 2001:db8:13::1 capability extended-nexthop
+ !
+ segment-routing srv6
+ locator default
+ !
+ address-family ipv4 vpn
+ neighbor 2001:db8:13::1 activate
+ exit-address-family
+ !
+!
+router bgp 65001 vrf vrf10
+ bgp router-id 192.0.2.3
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 1
+ rd vpn export 65001:10
+ rt vpn both 0:10
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
+router bgp 65001 vrf vrf20
+ bgp router-id 192.0.2.2
+ !
+ address-family ipv4 unicast
+ redistribute connected
+ sid vpn export 2
+ rd vpn export 65001:20
+ rt vpn both 0:20
+ import vpn
+ export vpn
+ exit-address-family
+ !
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r3/staticd.conf b/tests/topotests/bgp_srv6_sid_reachability/r3/staticd.conf
new file mode 100644
index 0000000..9d672d5
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r3/staticd.conf
@@ -0,0 +1,6 @@
+!
+ipv6 route 2001:db8:12::/64 2001:db8:13::1
+!
+ipv6 route 2001:db8:1:1::/64 2001:db8:13::1
+ipv6 route 2001:db8:2:2::/64 2001:db8:13::1
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/r3/zebra.conf b/tests/topotests/bgp_srv6_sid_reachability/r3/zebra.conf
new file mode 100644
index 0000000..a20cb76
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/r3/zebra.conf
@@ -0,0 +1,29 @@
+log file zebra.log
+!
+hostname r2
+!
+interface lo
+ ipv6 address 2001:db8:3:3::1/128
+!
+interface eth0
+ ipv6 address 2001:db8:13::3/64
+!
+interface eth1 vrf vrf10
+ ip address 192.168.3.254/24
+!
+interface eth2 vrf vrf20
+ ip address 192.168.3.254/24
+!
+segment-routing
+ srv6
+ locators
+ locator default
+ prefix 2001:db8:3:3::/64
+ !
+ !
+!
+ip forwarding
+ipv6 forwarding
+!
+line vty
+!
diff --git a/tests/topotests/bgp_srv6_sid_reachability/test_bgp_srv6_sid_reachability.py b/tests/topotests/bgp_srv6_sid_reachability/test_bgp_srv6_sid_reachability.py
new file mode 100755
index 0000000..92315bc
--- /dev/null
+++ b/tests/topotests/bgp_srv6_sid_reachability/test_bgp_srv6_sid_reachability.py
@@ -0,0 +1,169 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2023 by 6WIND
+#
+
+import os
+import re
+import sys
+import json
+import functools
+import pytest
+
+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.common_config import required_linux_kernel_version
+from lib.checkping import check_ping
+
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+
+def build_topo(tgen):
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+ tgen.add_router("r3")
+
+ tgen.add_router("c11")
+ tgen.add_router("c12")
+ tgen.add_router("c21")
+ tgen.add_router("c22")
+ tgen.add_router("c31")
+ tgen.add_router("c32")
+
+ tgen.add_link(tgen.gears["r1"], tgen.gears["r2"], "eth0", "eth0")
+ tgen.add_link(tgen.gears["r1"], tgen.gears["r3"], "eth1", "eth0")
+ tgen.add_link(tgen.gears["r1"], tgen.gears["c11"], "eth2", "eth0")
+ tgen.add_link(tgen.gears["r1"], tgen.gears["c12"], "eth3", "eth0")
+ tgen.add_link(tgen.gears["r2"], tgen.gears["c21"], "eth1", "eth0")
+ tgen.add_link(tgen.gears["r2"], tgen.gears["c22"], "eth2", "eth0")
+ tgen.add_link(tgen.gears["r3"], tgen.gears["c31"], "eth1", "eth0")
+ tgen.add_link(tgen.gears["r3"], tgen.gears["c32"], "eth2", "eth0")
+
+
+def setup_module(mod):
+ result = required_linux_kernel_version("5.15")
+ if result is not True:
+ pytest.skip("Kernel requirements are not met")
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ for rname, router in tgen.routers().items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_STATIC, os.path.join(CWD, "{}/staticd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.gears["r1"].run("sysctl net.vrf.strict_mode=1")
+ tgen.gears["r1"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["r1"].run("ip link set vrf10 up")
+ tgen.gears["r1"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["r1"].run("ip link set vrf20 up")
+ tgen.gears["r1"].run("ip link set eth2 master vrf10")
+ tgen.gears["r1"].run("ip link set eth3 master vrf20")
+
+ tgen.gears["r2"].run("sysctl net.vrf.strict_mode=1")
+ tgen.gears["r2"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["r2"].run("ip link set vrf10 up")
+ tgen.gears["r2"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["r2"].run("ip link set vrf20 up")
+ tgen.gears["r2"].run("ip link set eth1 master vrf10")
+ tgen.gears["r2"].run("ip link set eth2 master vrf20")
+
+ tgen.gears["r3"].run("sysctl net.vrf.strict_mode=1")
+ tgen.gears["r3"].run("ip link add vrf10 type vrf table 10")
+ tgen.gears["r3"].run("ip link set vrf10 up")
+ tgen.gears["r3"].run("ip link add vrf20 type vrf table 20")
+ tgen.gears["r3"].run("ip link set vrf20 up")
+ tgen.gears["r3"].run("ip link set eth1 master vrf10")
+ tgen.gears["r3"].run("ip link set eth2 master vrf20")
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_ping():
+ tgen = get_topogen()
+
+ check_ping("c11", "192.168.2.1", True, 10, 1)
+ check_ping("c11", "192.168.3.1", True, 10, 1)
+ check_ping("c12", "192.168.2.1", True, 10, 1)
+ check_ping("c12", "192.168.3.1", True, 10, 1)
+ check_ping("c21", "192.168.3.1", True, 10, 1)
+ check_ping("c22", "192.168.3.1", True, 10, 1)
+
+
+def test_sid_unreachable_nht():
+ get_topogen().gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ no ipv6 route 2001:db8:2:2::/64 2001:db8:12::2
+ """
+ )
+ check_ping("c11", "192.168.2.1", False, 10, 1)
+
+
+def test_sid_reachable_again_nht():
+ get_topogen().gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ ipv6 route 2001:db8:2:2::/64 2001:db8:12::2
+ """
+ )
+ check_ping("c11", "192.168.2.1", True, 10, 1)
+
+
+def test_sid_unreachable_bgp_update():
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65002
+ no segment-routing srv6
+ exit
+ router bgp 65002 vrf vrf10
+ address-family ipv4 unicast
+ no sid vpn export 1
+ """
+ )
+ check_ping("c11", "192.168.2.1", False, 10, 1)
+
+
+def test_sid_reachable_again_bgp_update():
+ get_topogen().gears["r2"].vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65002
+ segment-routing srv6
+ locator default
+ exit
+ exit
+ router bgp 65002 vrf vrf10
+ address-family ipv4 unicast
+ sid vpn export 1
+ """
+ )
+ check_ping("c11", "192.168.2.1", True, 10, 1)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py
index 900d0c2..f0c9144 100755
--- a/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py
+++ b/tests/topotests/bgp_srv6l3vpn_route_leak/test_bgp_srv6l3vpn_route_leak.py
@@ -37,10 +37,12 @@ def setup_module(mod):
tgen.start_topology()
for rname, router in tgen.routers().items():
- router.load_config(TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname)))
- router.load_config(TopoRouter.RD_BGP,
- os.path.join(CWD, '{}/bgpd.conf'.format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
tgen.gears["pe1"].run("ip link add vrf10 type vrf table 10")
tgen.gears["pe1"].run("ip link set vrf10 up")
@@ -62,7 +64,7 @@ def open_json_file(path):
return json.load(f)
except IOError:
assert False, "Could not read file {}".format(path)
-
+
def check(name, command, checker):
tgen = get_topogen()
@@ -80,25 +82,25 @@ def check(name, command, checker):
def check_vrf10_bgp_rib(output):
- expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_default_bgp_vpn_rib(output):
- expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
+ expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_vrf20_bgp_rib(output):
- expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_vrf20_rib(output):
- expected = open_json_file("%s/pe1/results/vrf20_ipv4.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf20_ipv4.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
diff --git a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
index fd8a78b..ec14ef0 100644
--- a/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
+++ b/tests/topotests/bgp_suppress_fib/test_bgp_suppress_fib.py
@@ -217,6 +217,7 @@ def test_bgp_allow_as_in():
assertmsg = '"r2" 192.168.1.1/32 route should be gone'
assert result is None, assertmsg
+
def test_local_vs_non_local():
tgen = get_topogen()
@@ -229,7 +230,7 @@ def test_local_vs_non_local():
paths = output["paths"]
for i in range(len(paths)):
if "fibPending" in paths[i]:
- assert(False), "Route 60.0.0.0/24 should not have fibPending"
+ assert False, "Route 60.0.0.0/24 should not have fibPending"
if __name__ == "__main__":
diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py
index e7948ea..4855d5c 100644
--- a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py
+++ b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py
@@ -36,8 +36,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-pytestmark = [pytest.mark.bgpd]
-
def build_topo(tgen):
for routern in range(1, 3):
diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
index 6fe044f..aeb9bf5 100644
--- a/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
+++ b/tests/topotests/bgp_tcp_mss/test_bgp_vrf_tcp_mss.py
@@ -46,7 +46,7 @@ from lib.bgp import (
verify_bgp_rib,
verify_bgp_timers_and_functionality,
verify_router_id,
- verify_tcp_mss
+ verify_tcp_mss,
)
from lib.common_config import (
kill_router_daemons,
@@ -54,6 +54,7 @@ from lib.common_config import (
addKernelRoute,
apply_raw_config,
check_address_types,
+ check_router_status,
create_prefix_lists,
create_route_maps,
create_static_routes,
@@ -66,10 +67,9 @@ from lib.common_config import (
verify_fib_routes,
verify_rib,
write_test_footer,
- write_test_header
+ write_test_header,
)
-pytestmark = [pytest.mark.bgpd]
# Global variables
NETWORK1_1 = {"ipv4": "1.1.1.1/32", "ipv6": "1::1/128"}
NETWORK1_2 = {"ipv4": "1.1.1.2/32", "ipv6": "1::2/128"}
@@ -85,7 +85,8 @@ NETWORK5_2 = {"ipv4": "5.1.1.2/32", "ipv6": "5::2/128"}
NEXT_HOP_IP = {"ipv4": "Null0", "ipv6": "Null0"}
## File name
-TCPDUMP_FILE="test_tcp_packet_test.txt"
+TCPDUMP_FILE = "test_tcp_packet_test.txt"
+
def setup_module(mod):
"""
@@ -93,7 +94,7 @@ def setup_module(mod):
* `mod`: module name
"""
- global topo,TCPDUMP_FILE
+ global topo, TCPDUMP_FILE
# Required linux kernel version for this suite to run.
result = required_linux_kernel_version("4.15")
@@ -128,6 +129,7 @@ def setup_module(mod):
step("Running setup_module() done")
+
def teardown_module():
"""Teardown the pytest environment"""
@@ -138,9 +140,7 @@ def teardown_module():
# Stop toplogy and Remove tmp files
tgen.stop_topology()
- step(
- "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
- )
+ step("Testsuite end time: {}".format(time.asctime(time.localtime(time.time()))))
step("=" * 40)
@@ -150,6 +150,7 @@ def teardown_module():
#
#####################################################
+
def test_bgp_vrf_tcp_mss(request):
tgen = get_topogen()
tc_name = request.node.name
@@ -280,34 +281,34 @@ def test_bgp_vrf_tcp_mss(request):
step("Verify the static Routes in R2 on RED VRF")
for addr_type in ADDR_TYPES:
static_routes_input = {
- "r3": {
- "static_routes": [
- {
- "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- ]
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ ]
}
}
dut = "r2"
@@ -317,34 +318,34 @@ def test_bgp_vrf_tcp_mss(request):
step("Verify the static Routes in R1 on RED VRF")
for addr_type in ADDR_TYPES:
static_routes_input = {
- "r3": {
- "static_routes": [
- {
- "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- {
- "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
- "next_hop": NEXT_HOP_IP[addr_type],
- "vrf": "RED",
- },
- ]
+ "r3": {
+ "static_routes": [
+ {
+ "network": [NETWORK1_1[addr_type]] + [NETWORK1_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK2_1[addr_type]] + [NETWORK2_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK3_1[addr_type]] + [NETWORK3_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK4_1[addr_type]] + [NETWORK4_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ {
+ "network": [NETWORK5_1[addr_type]] + [NETWORK5_2[addr_type]],
+ "next_hop": NEXT_HOP_IP[addr_type],
+ "vrf": "RED",
+ },
+ ]
}
}
dut = "r1"
@@ -404,9 +405,6 @@ def test_bgp_vrf_tcp_mss(request):
tcp_mss_result
)
-
-
-
step("Enabling tcp-mss 500 between R2 and R3 of VRF Default")
TCP_MSS = 500
raw_config = {
@@ -440,8 +438,6 @@ def test_bgp_vrf_tcp_mss(request):
result = apply_raw_config(tgen, raw_config)
assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
-
-
step("Clear BGP at router R2 and R3")
for addr_type in ADDR_TYPES:
clear_bgp(tgen, topo, "r2", addr_type)
@@ -550,7 +546,6 @@ def test_bgp_vrf_tcp_mss(request):
tcp_mss_result is not True
), " TCP-MSS mismatch :Failed \n Error: {}".format(tcp_mss_result)
-
step("Removing tcp-mss 500 between R2 and R3 of VRF Default ")
TCP_MSS = 500
raw_config = {
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json
new file mode 100644
index 0000000..2ed7631
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_vpn_route_1723101.json
@@ -0,0 +1,50 @@
+{
+ "444:1":{
+ "prefix":"172.31.0.1/32",
+ "advertisedTo":{
+ "192.168.0.1":{
+ }
+ },
+ "paths":[
+ {
+ "aspath":{
+ "string":"65500",
+ "segments":[
+ {
+ "type":"as-sequence",
+ "list":[
+ 65500
+ ]
+ }
+ ],
+ "length":1
+ },
+ "origin":"incomplete",
+ "metric":0,
+ "valid":true,
+ "bestpath":{
+ "overall":true,
+ "selectionReason":"First path received"
+ },
+ "extendedCommunity":{
+ "string":"RT:52:101"
+ },
+ "remoteLabel":102,
+ "nexthops":[
+ {
+ "ip":"192.168.0.1",
+ "afi":"ipv4",
+ "metric":0,
+ "accessible":true,
+ "used":true
+ }
+ ],
+ "peer":{
+ "peerId":"192.168.0.1",
+ "routerId":"192.0.2.1",
+ "type":"external"
+ }
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
index 8b2e674..1898243 100644
--- a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
+++ b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
@@ -228,7 +228,12 @@ def test_export_route_target_empty():
router = tgen.gears["r1"]
logger.info("r1, Remove 'rt vpn export 52:100' command")
router.vtysh_cmd(
- "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nno rt vpn export 52:100\n"
+ """
+configure terminal
+router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ no rt vpn export 52:100
+"""
)
prefix = "172.31.0.1/32"
@@ -254,10 +259,15 @@ def test_export_route_target_with_routemap_with_export_route_target():
router = tgen.gears["r1"]
logger.info("r1, configuring route target with route-map with export route target")
router.vtysh_cmd(
- "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nroute-map vpn export rmap\n"
- )
- router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nset extcommunity rt 52:100\n"
+ """
+configure terminal
+router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ route-map vpn export RMAP
+!
+route-map RMAP permit 1
+ set extcommunity rt 52:100
+"""
)
prefix = "172.31.0.1/32"
@@ -283,7 +293,11 @@ def test_export_route_target_with_routemap_without_export_route_target():
router = tgen.gears["r1"]
logger.info("r1, removing 'set extcommunity rt 52:100.")
router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nno set extcommunity rt\n"
+ """
+configure terminal
+route-map RMAP permit 1
+ no set extcommunity rt
+"""
)
prefix = "172.31.0.1/32"
@@ -309,7 +323,12 @@ def test_export_route_target_with_default_command():
router = tgen.gears["r1"]
logger.info("r1, detach route-map and re-add route target vpn export")
router.vtysh_cmd(
- "configure terminal\nrouter bgp 65500 vrf vrf1\naddress-family ipv4 unicast\nrt vpn export 52:100\n"
+ """
+configure terminal
+router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ rt vpn export 52:100
+"""
)
prefix = "172.31.0.1/32"
logger.info("r1, check that exported prefix {} is added back".format(prefix))
@@ -334,9 +353,14 @@ def test_export_suppress_route_target_with_route_map_command():
router = tgen.gears["r1"]
logger.info("r1, add an extended comm-list to delete 52:100")
- router.vtysh_cmd("configure terminal\nbgp extcommunity-list 1 permit rt 52:100\n")
router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nset extended-comm-list 1 delete\n"
+ """
+configure terminal
+bgp extcommunity-list 1 permit rt 52:100
+!
+route-map RMAP permit 1
+ set extended-comm-list 1 delete
+"""
)
prefix = "172.31.0.1/32"
logger.info("r1, check that exported prefix {} is removed".format(prefix))
@@ -361,7 +385,11 @@ def test_export_add_route_target_to_route_map_command():
router = tgen.gears["r1"]
logger.info("r1, add an additional set extcommunity 52:101")
router.vtysh_cmd(
- "configure terminal\nroute-map rmap permit 1\nset extcommunity rt 52:101\n"
+ """
+configure terminal
+route-map RMAP permit 1
+ set extcommunity rt 52:101
+"""
)
prefix = "172.31.0.1/32"
logger.info("r1, check that exported prefix {} is added back".format(prefix))
@@ -376,6 +404,126 @@ def test_export_add_route_target_to_route_map_command():
assert success, "{}, vpnv4 update {} still not present".format(router.name, prefix)
+def test_adj_rib_out_label_change():
+ """
+ Check that changing the VPN label on r1
+ is propagated on r2
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Changing VPN label value to export")
+ dump = tgen.gears["r1"].vtysh_cmd(
+ """
+configure terminal
+ router bgp 65500 vrf vrf1
+ address-family ipv4 unicast
+ label vpn export 102
+"""
+ )
+ # Check BGP IPv4 route entry for 172.31.0.1 on r1
+ logger.info("Checking BGP IPv4 routes for convergence on r1")
+ router = tgen.gears["r2"]
+ json_file = "{}/{}/bgp_ipv4_vpn_route_1723101.json".format(CWD, router.name)
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp ipv4 vpn 172.31.0.1/32 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+
+def test_adj_rib_in_label_change():
+ """
+ Check that syncinig with ADJ-RIB-in on r2
+ permits restoring the initial label value
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Enable soft-reconfiguration inbound on r2")
+
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd(
+ """
+configure terminal
+router bgp 65501
+ address-family ipv4 vpn
+ neighbor 192.168.0.1 soft-reconfiguration inbound
+"""
+ )
+
+ logger.info("Applying a deny-all route-map to input on r2")
+ r2.vtysh_cmd(
+ """
+configure terminal
+route-map DENY-ALL deny 1
+!
+router bgp 65501
+ address-family ipv4 vpn
+ neighbor 192.168.0.1 route-map DENY-ALL in
+"""
+ )
+
+ # check that 172.31.0.1 should not be present
+ logger.info("Check that received update 172.31.0.1 is not present")
+
+ expected = {}
+ test_func = partial(
+ topotest.router_json_cmp,
+ r2,
+ "show bgp ipv4 vpn 172.31.0.1/32 json",
+ expected,
+ exact=True,
+ )
+ success, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert success, "r2, vpnv4 update 172.31.0.1 still present"
+
+
+def test_adj_rib_in_label_change_remove_rmap():
+ """
+ Check that syncinig with ADJ-RIB-in on r2
+ permits restoring the initial label value
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ logger.info("Removing the deny-all route-map from input on r2")
+
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd(
+ """
+configure terminal
+router bgp 65501
+ address-family ipv4 vpn
+ no neighbor 192.168.0.1 route-map DENY-ALL in
+"""
+ )
+ # Check BGP IPv4 route entry for 172.31.0.1 on r1
+ logger.info(
+ "Checking that 172.31.0.1 BGP update is present and has valid label on r2"
+ )
+ json_file = "{}/{}/bgp_ipv4_vpn_route_1723101.json".format(CWD, r2.name)
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ r2,
+ "show bgp ipv4 vpn 172.31.0.1/32 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assertmsg = '"{}" JSON output mismatches'.format(r2.name)
+ assert result is None, assertmsg
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
index 6f313be..31743c8 100644
--- a/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
+++ b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
@@ -52,30 +52,32 @@ def build_topo(tgen):
switch = tgen.add_switch("s3")
switch.add_link(tgen.gears["r2"])
+
def _populate_iface():
tgen = get_topogen()
cmds_list = [
- 'ip link add vrf1 type vrf table 10',
- 'echo 10 > /proc/sys/net/mpls/platform_labels',
- 'ip link set dev vrf1 up',
- 'ip link set dev {0}-eth1 master vrf1',
- 'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input',
- 'ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}',
- 'ip link set dev {0}-gre0 up',
- 'echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input',
+ "ip link add vrf1 type vrf table 10",
+ "echo 10 > /proc/sys/net/mpls/platform_labels",
+ "ip link set dev vrf1 up",
+ "ip link set dev {0}-eth1 master vrf1",
+ "echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input",
+ "ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}",
+ "ip link set dev {0}-gre0 up",
+ "echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input",
]
for cmd in cmds_list:
- input = cmd.format('r1', '1', '2')
- logger.info('input: ' + cmd)
- output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2'))
- logger.info('output: ' + output)
+ input = cmd.format("r1", "1", "2")
+ logger.info("input: " + cmd)
+ output = tgen.net["r1"].cmd(cmd.format("r1", "1", "2"))
+ logger.info("output: " + output)
for cmd in cmds_list:
- input = cmd.format('r2', '2', '1')
- logger.info('input: ' + cmd)
- output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
- logger.info('output: ' + output)
+ input = cmd.format("r2", "2", "1")
+ logger.info("input: " + cmd)
+ output = tgen.net["r2"].cmd(cmd.format("r2", "2", "1"))
+ logger.info("output: " + output)
+
def setup_module(mod):
"Sets up the pytest environment"
@@ -113,13 +115,13 @@ def test_protocols_convergence():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- router = tgen.gears['r1']
+ router = tgen.gears["r1"]
logger.info("Dump some context for r1")
router.vtysh_cmd("show bgp ipv4 vpn")
router.vtysh_cmd("show bgp summary")
router.vtysh_cmd("show bgp vrf vrf1 ipv4")
router.vtysh_cmd("show running-config")
- router = tgen.gears['r2']
+ router = tgen.gears["r2"]
logger.info("Dump some context for r2")
router.vtysh_cmd("show bgp ipv4 vpn")
router.vtysh_cmd("show bgp summary")
@@ -128,11 +130,11 @@ def test_protocols_convergence():
# Check IPv4 routing tables on r1
logger.info("Checking IPv4 routes for convergence on r1")
- router = tgen.gears['r1']
+ router = tgen.gears["r1"]
json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
logger.info("skipping file {}".format(json_file))
- assert 0, 'ipv4_routes.json file not found'
+ assert 0, "ipv4_routes.json file not found"
return
expected = json.loads(open(json_file).read())
@@ -148,10 +150,10 @@ def test_protocols_convergence():
# Check BGP IPv4 routing tables on r2 not installed
logger.info("Checking BGP IPv4 routes for convergence on r2")
- router = tgen.gears['r2']
+ router = tgen.gears["r2"]
json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
if not os.path.isfile(json_file):
- assert 0, 'bgp_ipv4_routes.json file not found'
+ assert 0, "bgp_ipv4_routes.json file not found"
expected = json.loads(open(json_file).read())
test_func = partial(
@@ -163,7 +165,8 @@ def test_protocols_convergence():
_, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
assertmsg = '"{}" JSON output mismatches'.format(router.name)
assert result is None, assertmsg
-
+
+
def test_memory_leak():
"Run the memory leak test and report results."
tgen = get_topogen()
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_mpls_table.ref.diff b/tests/topotests/bgp_vrf_different_asn/__init__.py
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_mpls_table.ref.diff
+++ b/tests/topotests/bgp_vrf_different_asn/__init__.py
diff --git a/tests/topotests/bgp_vrf_different_asn/r1/frr.conf b/tests/topotests/bgp_vrf_different_asn/r1/frr.conf
new file mode 100644
index 0000000..b325dfb
--- /dev/null
+++ b/tests/topotests/bgp_vrf_different_asn/r1/frr.conf
@@ -0,0 +1,18 @@
+!
+vrf vrf100
+ vni 10100
+exit-vrf
+!
+interface r1-eth0 vrf vrf100
+ ip address 192.168.1.1/24
+!
+router bgp 65000
+ address-family ipv4 unicast
+ import vrf vrf100
+ exit-address-family
+!
+router bgp 65100 vrf vrf100
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py b/tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py
new file mode 100644
index 0000000..9a1a9ec
--- /dev/null
+++ b/tests/topotests/bgp_vrf_different_asn/test_bgp_vrf_different_asn.py
@@ -0,0 +1,107 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2024 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 2):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ r1 = tgen.gears["r1"]
+ r1.run("ip link add vrf100 type vrf table 1001")
+ r1.run("ip link set up dev vrf100")
+ r1.run("ip link set r1-eth0 master vrf100")
+
+ router_list = tgen.routers()
+
+ for _, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_frr_config(os.path.join(CWD, "{}/frr.conf".format(rname)))
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_vrf_different_asn():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_check_instances():
+ output = json.loads(tgen.gears["r1"].vtysh_cmd("show bgp vrf all json"))
+ expected = {
+ "default": {
+ "vrfName": "default",
+ "localAS": 65000,
+ },
+ "vrf100": {
+ "vrfName": "vrf100",
+ "localAS": 65100,
+ },
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_check_instances)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see vrf100 to be under 65100 ASN"
+
+ def _bgp_check_imported_route():
+ output = json.loads(
+ tgen.gears["r1"].vtysh_cmd("show ip route 192.168.1.0/24 json")
+ )
+ expected = {
+ "192.168.1.0/24": [
+ {
+ "installed": True,
+ "selected": True,
+ "nexthops": [
+ {
+ "interfaceName": "vrf100",
+ "vrf": "vrf100",
+ "active": True,
+ }
+ ],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_check_imported_route)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=1)
+ assert result is None, "Can't see 192.168.1.0/24 being imported into a default VRF"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py
index 1787021..726afcb 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo3/test_bgp_vrf_dynamic_route_leak_topo3.py
@@ -851,23 +851,25 @@ def test_dynamic_imported_matching_prefix_based_on_community_list_p0(request):
result = verify_bgp_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
@@ -924,23 +926,25 @@ def test_dynamic_imported_matching_prefix_based_on_community_list_p0(request):
result = verify_bgp_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r3", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes["r3"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes["r3"]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, "r3", static_routes)
@@ -1153,23 +1157,25 @@ def test_dynamic_import_routes_delete_static_route_p1(request):
result = verify_bgp_rib(
tgen, addr_type, "r2", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r2"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r2"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r2", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
step("Delete static routes from vrf BLUE")
@@ -1209,21 +1215,23 @@ def test_dynamic_import_routes_delete_static_route_p1(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(tgen, addr_type, dut, static_routes, expected=False)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
step("Delete static routes from vrf default")
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
index c7fbc01..45d7b03 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-1.py
@@ -320,7 +320,6 @@ def test_dynamic_import_recursive_import_tenant_vrf_p1(request):
for dut, vrf_name, vrf_import, as_num in zip(
["r2", "r4"], ["GREEN", "BLUE"], ["RED", "default"], [2, 4]
):
-
for action, value in zip(["Delete", "Re-add"], [True, False]):
step("{} the import command on {} router".format(action, dut))
temp = {}
@@ -357,23 +356,25 @@ def test_dynamic_import_recursive_import_tenant_vrf_p1(request):
result = verify_bgp_rib(
tgen, addr_type, "r4", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes["r4"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes["r4"]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, "r4", static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes["r4"]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes["r4"]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, "r4", static_routes)
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
index 02950eb..d29edf5 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-2.py
@@ -495,23 +495,25 @@ def test_dynamic_import_routes_between_two_tenant_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
@@ -882,23 +884,25 @@ def test_dynamic_import_routes_between_two_tenant_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
diff --git a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
index 4b18903..c118ffc 100644
--- a/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
+++ b/tests/topotests/bgp_vrf_dynamic_route_leak_topo4/test_bgp_vrf_dynamic_route_leak_topo4-3.py
@@ -356,23 +356,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
@@ -503,23 +505,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
@@ -882,23 +886,25 @@ def test_dynamic_import_routes_between_tenant_to_default_vrf_p0(request):
result = verify_bgp_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed \nError {}\n" "Routes {} still in BGP table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed \nError {}\n"
+ "Routes {} still in BGP table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
result = verify_rib(
tgen, addr_type, dut, static_routes, expected=False
)
- assert (
- result is not True
- ), "Testcase {} : Failed Error {}" "Routes {} still in Route table".format(
- tc_name,
- result,
- static_routes[dut]["static_routes"][0]["network"],
+ assert result is not True, (
+ "Testcase {} : Failed Error {}"
+ "Routes {} still in Route table".format(
+ tc_name,
+ result,
+ static_routes[dut]["static_routes"][0]["network"],
+ )
)
else:
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
diff --git a/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf10_ipv4_unicast.json b/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf10_ipv4_unicast.json
index 768bffb..f664bb6 100644
--- a/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf10_ipv4_unicast.json
+++ b/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf10_ipv4_unicast.json
@@ -15,15 +15,16 @@
"origin": "incomplete",
"nexthops": [
{
+ "ip": "::ffff:c000:202",
"hostname": "ce1",
"afi": "ipv6",
- "scope": "global",
- "used": true
+ "scope": "global"
},
{
"hostname": "ce1",
"afi": "ipv6",
- "scope": "link-local"
+ "scope": "link-local",
+ "used": true
}
]
}
diff --git a/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf20_ipv4_unicast.json b/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf20_ipv4_unicast.json
index 1e93715..3498ed4 100644
--- a/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf20_ipv4_unicast.json
+++ b/tests/topotests/bgp_vrf_leaking_5549_routes/pe1/results/vrf20_ipv4_unicast.json
@@ -17,15 +17,16 @@
"nhVrfName": "vrf10",
"nexthops": [
{
+ "ip": "::ffff:c000:202",
"hostname": "pe1",
"afi": "ipv6",
- "scope": "global",
- "used": true
+ "scope": "global"
},
{
"hostname": "pe1",
"afi": "ipv6",
- "scope": "link-local"
+ "scope": "link-local",
+ "used": true
}
]
}
diff --git a/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py b/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py
index 244db6c..b208192 100755
--- a/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py
+++ b/tests/topotests/bgp_vrf_leaking_5549_routes/test_bgp_vrf_leaking.py
@@ -37,10 +37,12 @@ def setup_module(mod):
tgen.start_topology()
for rname, router in tgen.routers().items():
- router.load_config(TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname)))
- router.load_config(TopoRouter.RD_BGP,
- os.path.join(CWD, '{}/bgpd.conf'.format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
tgen.gears["pe1"].run("ip link add vrf10 type vrf table 10")
tgen.gears["pe1"].run("ip link set vrf10 up")
@@ -62,22 +64,22 @@ def open_json_file(path):
return json.load(f)
except IOError:
assert False, "Could not read file {}".format(path)
-
+
def check_vrf10_rib(output):
- expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf10_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_default_vpn_rib(output):
- expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
+ expected = open_json_file("%s/pe1/results/default_ipv4_vpn.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
def check_vrf20_rib(output):
- expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
+ expected = open_json_file("%s/pe1/results/vrf20_ipv4_unicast.json" % CWD)
actual = json.loads(output)
return topotest.json_cmp(actual, expected)
diff --git a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py
index 5d93964..3cb3180 100644
--- a/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py
+++ b/tests/topotests/bgp_vrf_lite_best_path_test/test_bgp_vrf_lite_best_path_topo2.py
@@ -43,7 +43,7 @@ from lib.common_config import (
step,
create_static_routes,
check_router_status,
- apply_raw_config
+ apply_raw_config,
)
from lib.topolog import logger
@@ -51,7 +51,7 @@ from lib.bgp import (
verify_bgp_convergence,
create_router_bgp,
verify_bgp_rib,
- verify_bgp_bestpath
+ verify_bgp_bestpath,
)
from lib.topojson import build_config_from_json
@@ -84,10 +84,8 @@ VRF_LIST = ["RED", "BLUE", "GREEN"]
COMM_VAL_1 = "100:100"
COMM_VAL_2 = "500:500"
COMM_VAL_3 = "600:600"
-BESTPATH = {
- "ipv4": "0.0.0.0",
- "ipv6": "::"
-}
+BESTPATH = {"ipv4": "0.0.0.0", "ipv6": "::"}
+
def setup_module(mod):
"""
@@ -158,6 +156,7 @@ def teardown_module():
#
#####################################################
+
def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
"""
Verify ECMP for imported routes from different VRFs.
@@ -170,136 +169,130 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
check_router_status(tgen)
reset_config_on_routers(tgen)
- step("Configure same static routes in tenant vrfs RED and GREEN on router "
- "R3 and redistribute in respective BGP process")
+ step(
+ "Configure same static routes in tenant vrfs RED and GREEN on router "
+ "R3 and redistribute in respective BGP process"
+ )
for vrf_name in ["RED", "GREEN"]:
for addr_type in ADDR_TYPES:
if vrf_name == "GREEN":
- next_hop_vrf = topo["routers"]["r1"]["links"][
- "r3-link3"][addr_type].split("/")[0]
+ next_hop_vrf = topo["routers"]["r1"]["links"]["r3-link3"][
+ addr_type
+ ].split("/")[0]
else:
- next_hop_vrf = topo["routers"]["r2"]["links"][
- "r3-link1"][addr_type].split("/")[0]
+ next_hop_vrf = topo["routers"]["r2"]["links"]["r3-link1"][
+ addr_type
+ ].split("/")[0]
static_routes = {
"r3": {
"static_routes": [
{
"network": [NETWORK1_1[addr_type]],
"next_hop": next_hop_vrf,
- "vrf": vrf_name
+ "vrf": vrf_name,
}
]
}
}
result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
step("Redistribute static route on BGP VRF : {}".format(vrf_name))
temp = {}
for addr_type in ADDR_TYPES:
- temp.update({
- addr_type: {
- "unicast": {
- "redistribute": [{
- "redist_type": "static"
- }]
- }
- }
- })
+ temp.update(
+ {addr_type: {"unicast": {"redistribute": [{"redist_type": "static"}]}}}
+ )
- redist_dict = {"r3": {"bgp": [{
- "vrf": vrf_name, "local_as": 3, "address_family": temp
- }]}}
+ redist_dict = {
+ "r3": {"bgp": [{"vrf": vrf_name, "local_as": 3, "address_family": temp}]}
+ }
result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
- step("Verify that configured static routes are installed in respective "
- "BGP table for vrf RED & GREEN")
+ step(
+ "Verify that configured static routes are installed in respective "
+ "BGP table for vrf RED & GREEN"
+ )
for vrf_name in ["RED", "GREEN"]:
for addr_type in ADDR_TYPES:
if vrf_name == "GREEN":
- next_hop_vrf = topo["routers"]["r1"]["links"][
- "r3-link3"][addr_type].split("/")[0]
+ next_hop_vrf = topo["routers"]["r1"]["links"]["r3-link3"][
+ addr_type
+ ].split("/")[0]
else:
- next_hop_vrf = topo["routers"]["r2"]["links"][
- "r3-link1"][addr_type].split("/")[0]
+ next_hop_vrf = topo["routers"]["r2"]["links"]["r3-link1"][
+ addr_type
+ ].split("/")[0]
static_routes = {
"r3": {
"static_routes": [
- {
- "network": [NETWORK1_1[addr_type]],
- "vrf": vrf_name
- }
+ {"network": [NETWORK1_1[addr_type]], "vrf": vrf_name}
]
}
}
- result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
- next_hop=next_hop_vrf)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_bgp_rib(
+ tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
- result = verify_rib(tgen, addr_type, "r3", static_routes,
- next_hop=next_hop_vrf)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_rib(
+ tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
step("Import vrf RED and GREEN into default vrf and Configure ECMP")
bgp_val = []
for vrf_name in ["RED", "GREEN"]:
temp = {}
for addr_type in ADDR_TYPES:
- temp.update({
- addr_type: {
- "unicast": {
- "import": {
- "vrf": vrf_name
- },
- "maximum_paths": {
- "ebgp": 2
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {
+ "import": {"vrf": vrf_name},
+ "maximum_paths": {"ebgp": 2},
}
}
}
- })
+ )
- bgp_val.append({
- "local_as": 3, "address_family": temp
- })
+ bgp_val.append({"local_as": 3, "address_family": temp})
import_dict = {"r3": {"bgp": bgp_val}}
result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("Configure bgp bestpath on router r3")
r3_raw_config = {
- "r3": {
- "raw_config": [
- "router bgp 3",
- "bgp bestpath as-path multipath-relax"
- ]
- }
+ "r3": {"raw_config": ["router bgp 3", "bgp bestpath as-path multipath-relax"]}
}
result = apply_raw_config(tgen, r3_raw_config)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that routes are imported with two different next-hop vrfs "
- "and IPs. Additionally R3 must do ECMP for both the routes.")
+ step(
+ "Verify that routes are imported with two different next-hop vrfs "
+ "and IPs. Additionally R3 must do ECMP for both the routes."
+ )
for addr_type in ADDR_TYPES:
next_hop_vrf = [
- topo["routers"]["r2"]["links"]["r3-link1"][addr_type]. \
- split("/")[0],
- topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \
- split("/")[0]
- ]
+ topo["routers"]["r2"]["links"]["r3-link1"][addr_type].split("/")[0],
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[0],
+ ]
static_routes = {
"r3": {
"static_routes": [
@@ -310,54 +303,61 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
}
}
- result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
- next_hop=next_hop_vrf)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_bgp_rib(
+ tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
- result = verify_rib(tgen, addr_type, "r3", static_routes,
- next_hop=next_hop_vrf)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_rib(tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
- step("Now change the next-hop of static routes in vrf RED and GREEN to "
- "same IP address")
+ step(
+ "Now change the next-hop of static routes in vrf RED and GREEN to "
+ "same IP address"
+ )
for addr_type in ADDR_TYPES:
- next_hop_vrf = topo["routers"]["r1"]["links"][
- "r3-link3"][addr_type].split("/")[0]
+ next_hop_vrf = topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[
+ 0
+ ]
static_routes = {
"r3": {
"static_routes": [
{
"network": [NETWORK1_1[addr_type]],
"next_hop": next_hop_vrf,
- "vrf": "RED"
+ "vrf": "RED",
},
{
"network": [NETWORK1_1[addr_type]],
- "next_hop": topo["routers"]["r2"]["links"][
- "r3-link1"][addr_type].split("/")[0],
+ "next_hop": topo["routers"]["r2"]["links"]["r3-link1"][
+ addr_type
+ ].split("/")[0],
"vrf": "RED",
- "delete": True
- }
+ "delete": True,
+ },
]
}
}
result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
- step("Verify that now routes are imported with two different next-hop "
- "vrfs but same IPs. Additionally R3 must do ECMP for both the routes")
+ step(
+ "Verify that now routes are imported with two different next-hop "
+ "vrfs but same IPs. Additionally R3 must do ECMP for both the routes"
+ )
for addr_type in ADDR_TYPES:
next_hop_vrf = [
- topo["routers"]["r1"]["links"]["r3-link3"][addr_type].\
- split("/")[0],
- topo["routers"]["r1"]["links"]["r3-link3"][addr_type]. \
- split("/")[0]
- ]
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[0],
+ topo["routers"]["r1"]["links"]["r3-link3"][addr_type].split("/")[0],
+ ]
static_routes = {
"r3": {
"static_routes": [
@@ -368,20 +368,24 @@ def test_dynamic_import_ecmp_imported_routed_diffrent_vrfs_p0(request):
}
}
- result = verify_bgp_rib(tgen, addr_type, "r3", static_routes,
- next_hop=next_hop_vrf)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_bgp_rib(
+ tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf
+ )
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
- result = verify_rib(tgen, addr_type, "r3", static_routes,
- next_hop=next_hop_vrf)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ result = verify_rib(tgen, addr_type, "r3", static_routes, next_hop=next_hop_vrf)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
write_test_footer(tc_name)
-def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0(request):
+def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_p0(
+ request,
+):
"""
Verify ECMP for imported routes from different VRFs.
"""
@@ -393,13 +397,15 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
check_router_status(tgen)
reset_config_on_routers(tgen)
- step("Configure same static routes on R2 and R3 vrfs and redistribute in BGP "
- "for GREEN and RED vrf instances")
- for dut, network in zip(["r2", "r3"], [
- [NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]]):
+ step(
+ "Configure same static routes on R2 and R3 vrfs and redistribute in BGP "
+ "for GREEN and RED vrf instances"
+ )
+ for dut, network in zip(
+ ["r2", "r3"], [[NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]]
+ ):
for vrf_name, network_vrf in zip(["RED", "GREEN"], network):
- step("Configure static route for VRF : {} on {}".format(vrf_name,
- dut))
+ step("Configure static route for VRF : {} on {}".format(vrf_name, dut))
for addr_type in ADDR_TYPES:
static_routes = {
dut: {
@@ -407,44 +413,50 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": [network_vrf[addr_type]],
"next_hop": "blackhole",
- "vrf": vrf_name
+ "vrf": vrf_name,
}
]
}
}
result = create_static_routes(tgen, static_routes)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
for dut, as_num in zip(["r2", "r3"], ["2", "3"]):
for vrf_name in ["RED", "GREEN"]:
step("Redistribute static route on BGP VRF : {}".format(vrf_name))
temp = {}
for addr_type in ADDR_TYPES:
- temp.update({
- addr_type: {
- "unicast": {
- "redistribute": [{
- "redist_type": "static"
- }]
+ temp.update(
+ {
+ addr_type: {
+ "unicast": {"redistribute": [{"redist_type": "static"}]}
}
}
- })
+ )
- redist_dict = {dut: {"bgp": [{
- "vrf": vrf_name, "local_as": as_num, "address_family": temp
- }]}}
+ redist_dict = {
+ dut: {
+ "bgp": [
+ {"vrf": vrf_name, "local_as": as_num, "address_family": temp}
+ ]
+ }
+ }
result = create_router_bgp(tgen, topo, redist_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
-
- step("Verify that R2 and R3 has installed redistributed routes in default "
- "and RED vrfs and GREEN respectively:")
- for dut, network in zip(["r2", "r3"],
- [[NETWORK1_1, NETWORK1_2],
- [NETWORK1_1, NETWORK1_2]]):
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that R2 and R3 has installed redistributed routes in default "
+ "and RED vrfs and GREEN respectively:"
+ )
+ for dut, network in zip(
+ ["r2", "r3"], [[NETWORK1_1, NETWORK1_2], [NETWORK1_1, NETWORK1_2]]
+ ):
for vrf_name, network_vrf in zip(["RED", "GREEN"], network):
for addr_type in ADDR_TYPES:
static_routes = {
@@ -453,38 +465,32 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": [network_vrf[addr_type]],
"next_hop": "blackhole",
- "vrf": vrf_name
+ "vrf": vrf_name,
}
]
}
}
result = verify_bgp_rib(tgen, addr_type, dut, static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
step("Import vrf RED's route in vrf GREEN on R3")
temp = {}
for addr_type in ADDR_TYPES:
- temp.update({
- addr_type: {
- "unicast": {
- "import": {
- "vrf": "RED"
- }
- }
- }
- })
+ temp.update({addr_type: {"unicast": {"import": {"vrf": "RED"}}}})
- import_dict = {"r3": {"bgp": [{
- "vrf": "GREEN", "local_as": 3, "address_family": temp
- }]}}
+ import_dict = {
+ "r3": {"bgp": [{"vrf": "GREEN", "local_as": 3, "address_family": temp}]}
+ }
result = create_router_bgp(tgen, topo, import_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that locally imported routes are installed over eBGP imported"
- " routes from VRF RED into VRF GREEN")
+ step(
+ "Verify that locally imported routes are installed over eBGP imported"
+ " routes from VRF RED into VRF GREEN"
+ )
for addr_type in ADDR_TYPES:
static_routes = {
"r3": {
@@ -492,7 +498,7 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": [NETWORK1_2[addr_type]],
"next_hop": "blackhole",
- "vrf": "GREEN"
+ "vrf": "GREEN",
}
]
}
@@ -504,19 +510,21 @@ def test_locally_imported_routes_selected_as_bestpath_over_ebgp_imported_routes_
{
"network": NETWORK1_2[addr_type],
"bestpath": BESTPATH[addr_type],
- "vrf": "GREEN"
+ "vrf": "GREEN",
}
]
}
}
result = verify_bgp_bestpath(tgen, addr_type, input_routes)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
result = verify_rib(tgen, addr_type, "r3", static_routes)
- assert result is True, "Testcase {} : Failed \n Error {}". \
- format(tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error {}".format(
+ tc_name, result
+ )
write_test_footer(tc_name)
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf b/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
index f52f56b..397f793 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
+++ b/tests/topotests/bgp_vrf_route_leak_basic/r1/bgpd.conf
@@ -12,7 +12,7 @@ router bgp 99 vrf DONNA
address-family ipv4 unicast
redistribute connected
import vrf EVA
- import vrf NOTEXISTING
+ import vrf ZITA
import vrf default
!
!
@@ -21,10 +21,10 @@ router bgp 99 vrf EVA
address-family ipv4 unicast
redistribute connected
import vrf DONNA
- import vrf NOTEXISTING
+ import vrf ZITA
!
!
-router bgp 99 vrf NOTEXISTING
+router bgp 99 vrf ZITA
no bgp ebgp-requires-policy
no bgp network import-check
address-family ipv4 unicast
diff --git a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
index 13c38a9..6d4b436 100644
--- a/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
+++ b/tests/topotests/bgp_vrf_route_leak_basic/test_bgp-vrf-route-leak-basic.py
@@ -24,7 +24,7 @@ sys.path.append(os.path.join(CWD, "../"))
from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-
+from lib.checkping import check_ping
pytestmark = [pytest.mark.bgpd]
@@ -126,11 +126,13 @@ def test_vrf_route_leak_donna():
"172.16.101.0/24": [
{
"protocol": "bgp",
+ "selected": None,
"nexthops": [
{
- "interfaceIndex": 0,
+ "fib": None,
"interfaceName": "unknown",
"vrf": "Unknown",
+ "active": None,
},
],
},
@@ -196,11 +198,13 @@ def test_vrf_route_leak_eva():
"172.16.101.0/24": [
{
"protocol": "bgp",
+ "selected": None,
"nexthops": [
{
- "interfaceIndex": 0,
+ "fib": None,
"interfaceName": "unknown",
"vrf": "Unknown",
+ "active": None,
},
],
},
@@ -214,7 +218,6 @@ def test_vrf_route_leak_eva():
assert result, "BGP VRF EVA check failed:\n{}".format(diff)
-
def test_vrf_route_leak_default():
logger.info("Ensure that routes are leaked back and forth")
tgen = get_topogen()
@@ -278,8 +281,230 @@ def test_ping():
r1 = tgen.gears["r1"]
logger.info("Ping from default to DONNA")
- output = r1.run("ping -c 4 -w 4 -I 10.0.4.1 10.0.0.1")
- assert " 0% packet loss" in output, "Ping default->DONNA FAILED"
+ check_ping("r1", "10.0.0.1", True, 10, 0.5, source_addr="10.0.4.1")
+
+
+def test_vrf_route_leak_donna_after_eva_down():
+ logger.info("Ensure that route states change after EVA interface goes down")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd(
+ """
+configure
+interface EVA
+ shutdown
+"""
+ )
+
+ # Test DONNA VRF.
+ expect = {
+ "10.0.1.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": None,
+ "nexthops": [
+ {
+ "fib": None,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": None,
+ },
+ ],
+ },
+ ],
+ "10.0.3.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": None,
+ "nexthops": [
+ {
+ "fib": None,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": None,
+ },
+ ],
+ },
+ ],
+ }
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
+ )
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+ """
+ Check that "show ip route vrf DONNA json" and the JSON at key "DONNA" of
+ "show ip route vrf all json" gives the same result.
+ """
+
+ def check_vrf_table(router, vrf, expect):
+ output = router.vtysh_cmd("show ip route vrf all json", isjson=True)
+ vrf_table = output.get(vrf, {})
+
+ return topotest.json_cmp(vrf_table, expect)
+
+ test_func = partial(check_vrf_table, r1, "DONNA", expect)
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+
+def test_vrf_route_leak_donna_after_eva_up():
+ logger.info("Ensure that route states change after EVA interface goes up")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd(
+ """
+configure
+interface EVA
+ no shutdown
+"""
+ )
+
+ # Test DONNA VRF.
+ expect = {
+ "10.0.1.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ "10.0.3.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "EVA",
+ "vrf": "EVA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ }
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
+ )
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+
+def test_vrf_route_leak_donna_add_vrf_zita():
+ logger.info("Add VRF ZITA and ensure that the route from VRF ZITA is updated")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r1.cmd("ip link add ZITA type vrf table 1003")
+
+ # Test DONNA VRF.
+ expect = {
+ "172.16.101.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": None,
+ "nexthops": [
+ {
+ "fib": None,
+ "interfaceName": "ZITA",
+ "vrf": "ZITA",
+ "active": None,
+ },
+ ],
+ },
+ ],
+ }
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
+ )
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+
+def test_vrf_route_leak_donna_set_zita_up():
+ logger.info("Set VRF ZITA up and ensure that the route from VRF ZITA is updated")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd(
+ """
+configure
+interface ZITA
+ no shutdown
+"""
+ )
+
+ # Test DONNA VRF.
+ expect = {
+ "172.16.101.0/24": [
+ {
+ "protocol": "bgp",
+ "selected": True,
+ "nexthops": [
+ {
+ "fib": True,
+ "interfaceName": "ZITA",
+ "vrf": "ZITA",
+ "active": True,
+ },
+ ],
+ },
+ ],
+ }
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
+ )
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
+
+
+def test_vrf_route_leak_donna_delete_vrf_zita():
+ logger.info("Delete VRF ZITA and ensure that the route from VRF ZITA is deleted")
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r1.cmd("ip link delete ZITA")
+
+ # Test DONNA VRF.
+ expect = {
+ "172.16.101.0/24": None,
+ }
+
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip route vrf DONNA json", expect
+ )
+ result, diff = topotest.run_and_expect(test_func, None, count=10, wait=0.5)
+ assert result, "BGP VRF DONNA check failed:\n{}".format(diff)
def test_memory_leak():
diff --git a/tests/topotests/config_timing/test_config_timing.py b/tests/topotests/config_timing/test_config_timing.py
index 5c1b972..52d196f 100644
--- a/tests/topotests/config_timing/test_config_timing.py
+++ b/tests/topotests/config_timing/test_config_timing.py
@@ -97,8 +97,8 @@ def test_static_timing():
optype = "adding" if add else "removing"
iptype = "IPv6" if do_ipv6 else "IPv4"
if super_prefix is None:
- super_prefix = u"2001::/48" if do_ipv6 else u"10.0.0.0/8"
- via = u"lo"
+ super_prefix = "2001::/48" if do_ipv6 else "10.0.0.0/8"
+ via = "lo"
optyped = "added" if add else "removed"
for rname, router in router_list.items():
@@ -161,8 +161,8 @@ def test_static_timing():
prefix_count = 50
prefix_base = [
- [u"10.0.0.0/8", u"11.0.0.0/8"],
- [u"2100:1111:2220::/44", u"2100:3333:4440::/44"],
+ ["10.0.0.0/8", "11.0.0.0/8"],
+ ["2100:1111:2220::/44", "2100:3333:4440::/44"],
]
# This apparently needed to allow for various mgmtd/staticd/zebra connections to form
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index 23eab68..a231513 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -68,6 +68,10 @@ def log_handler(basename, logpath):
topolog.logfinish(basename, logpath)
+def is_main_runner():
+ return "PYTEST_XDIST_WORKER" not in os.environ
+
+
def pytest_addoption(parser):
"""
Add topology-only option to the topology tester. This option makes pytest
@@ -86,6 +90,17 @@ def pytest_addoption(parser):
)
parser.addoption(
+ "--cov-topotest",
+ action="store_true",
+ help="Enable reporting of coverage",
+ )
+
+ parser.addoption(
+ "--cov-frr-build-dir",
+ help="Dir of coverage-enable build being run, default is the source dir",
+ )
+
+ parser.addoption(
"--gdb-breakpoints",
metavar="SYMBOL[,SYMBOL...]",
help="Comma-separated list of functions to set gdb breakpoints on",
@@ -456,6 +471,37 @@ def pytest_assertrepr_compare(op, left, right):
return json_result.gen_report()
+def setup_coverage(config):
+ commander = Commander("pytest")
+ if config.option.cov_frr_build_dir:
+ bdir = Path(config.option.cov_frr_build_dir).resolve()
+ output = commander.cmd_raises(f"find {bdir} -name zebra_nb.gcno").strip()
+ else:
+ # Support build sub-directory of main source dir
+ bdir = Path(__file__).resolve().parent.parent.parent
+ output = commander.cmd_raises(f"find {bdir} -name zebra_nb.gcno").strip()
+ m = re.match(f"({bdir}.*)/zebra/zebra_nb.gcno", output)
+ if not m:
+ logger.warning(
+ "No coverage data files (*.gcno) found, try specifying --cov-frr-build-dir"
+ )
+ return
+
+ bdir = Path(m.group(1))
+ # Save so we can get later from g_pytest_config
+ rundir = Path(config.option.rundir).resolve()
+ gcdadir = rundir / "gcda"
+ os.environ["FRR_BUILD_DIR"] = str(bdir)
+ os.environ["GCOV_PREFIX_STRIP"] = str(len(bdir.parts) - 1)
+ os.environ["GCOV_PREFIX"] = str(gcdadir)
+
+ if is_main_runner():
+ commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+r {{}} +")
+ commander.cmd_raises(f"mkdir -p {gcdadir}")
+ commander.cmd_raises(f"chown -R root:frr {gcdadir}")
+ commander.cmd_raises(f"chmod 2775 {gcdadir}")
+
+
def pytest_configure(config):
"""
Assert that the environment is correctly configured, and get extra config.
@@ -556,8 +602,6 @@ def pytest_configure(config):
if config.option.topology_only and is_xdist:
pytest.exit("Cannot use --topology-only with distributed test mode")
- pytest.exit("Cannot use --topology-only with distributed test mode")
-
# Check environment now that we have config
if not diagnose_env(rundir):
pytest.exit("environment has errors, please read the logs in %s" % rundir)
@@ -572,27 +616,25 @@ def pytest_configure(config):
if "TOPOTESTS_CHECK_STDERR" in os.environ:
del os.environ["TOPOTESTS_CHECK_STDERR"]
+ if config.option.cov_topotest:
+ setup_coverage(config)
+
@pytest.fixture(autouse=True, scope="session")
-def setup_session_auto():
+def session_autouse():
# Aligns logs nicely
logging.addLevelName(logging.WARNING, " WARN")
logging.addLevelName(logging.INFO, " INFO")
- if "PYTEST_TOPOTEST_WORKER" not in os.environ:
- is_worker = False
- elif not os.environ["PYTEST_TOPOTEST_WORKER"]:
- is_worker = False
- else:
- is_worker = True
+ is_main = is_main_runner()
- logger.debug("Before the run (is_worker: %s)", is_worker)
- if not is_worker:
+ logger.debug("Before the run (is_main: %s)", is_main)
+ if is_main:
cleanup_previous()
yield
- if not is_worker:
+ if is_main:
cleanup_current()
- logger.debug("After the run (is_worker: %s)", is_worker)
+ logger.debug("After the run (is_main: %s)", is_main)
def pytest_runtest_setup(item):
@@ -719,6 +761,49 @@ def pytest_runtest_makereport(item, call):
pause_test()
+def coverage_finish(terminalreporter, config):
+ commander = Commander("pytest")
+ rundir = Path(config.option.rundir).resolve()
+ bdir = Path(os.environ["FRR_BUILD_DIR"])
+ gcdadir = Path(os.environ["GCOV_PREFIX"])
+
+ logger.info("Creating .gcno ssymlink from '%s' to '%s'", gcdadir, bdir)
+ commander.cmd_raises(
+ f"cd {gcdadir}; bdir={bdir}"
+ + """
+for f in $(find . -name '*.gcda'); do
+ f=${f#./};
+ f=${f%.gcda}.gcno;
+ ln -fs $bdir/$f $f;
+ touch -h -r $bdir/$f $f;
+ echo $f;
+done"""
+ )
+
+ # Get the results into a summary file
+ data_file = rundir / "coverage.info"
+ logger.info("Gathering coverage data into: %s", data_file)
+ commander.cmd_raises(
+ f"lcov --directory {gcdadir} --capture --output-file {data_file}"
+ )
+
+ # Get coverage info filtered to a specific set of files
+ report_file = rundir / "coverage.info"
+ logger.debug("Generating coverage summary from: %s\n%s", report_file)
+ output = commander.cmd_raises(f"lcov --summary {data_file}")
+ logger.info("\nCOVERAGE-SUMMARY-START\n%s\nCOVERAGE-SUMMARY-END", output)
+ terminalreporter.write(
+ f"\nCOVERAGE-SUMMARY-START\n{output}\nCOVERAGE-SUMMARY-END\n"
+ )
+
+
+def pytest_terminal_summary(terminalreporter, exitstatus, config):
+ # Only run if we are the top level test runner
+ is_xdist_worker = "PYTEST_XDIST_WORKER" in os.environ
+ if config.option.cov_topotest and not is_xdist_worker:
+ coverage_finish(terminalreporter, config)
+
+
#
# Add common fixtures available to all tests as parameters
#
diff --git a/tests/topotests/eigrp_topo1/test_eigrp_topo1.py b/tests/topotests/eigrp_topo1/test_eigrp_topo1.py
index 3c9392c..b3152f4 100644
--- a/tests/topotests/eigrp_topo1/test_eigrp_topo1.py
+++ b/tests/topotests/eigrp_topo1/test_eigrp_topo1.py
@@ -193,6 +193,7 @@ if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
+
#
# Auxiliary Functions
#
diff --git a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py
index c0621d7..cfcd4a1 100644
--- a/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py
+++ b/tests/topotests/evpn_pim_1/test_evpn_pim_topo1.py
@@ -20,7 +20,7 @@ import pytest
import json
from functools import partial
-pytestmark = [pytest.mark.pimd]
+pytestmark = [pytest.mark.pimd, pytest.mark.bgpd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -32,10 +32,6 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-# Required to instantiate the topology builder class.
-
-pytestmark = [pytest.mark.bgpd, pytest.mark.bgpd]
-
#####################################################
##
diff --git a/tests/topotests/example_test/test_template.py b/tests/topotests/example_test/test_template.py
index 2797548..5728eba 100644
--- a/tests/topotests/example_test/test_template.py
+++ b/tests/topotests/example_test/test_template.py
@@ -41,6 +41,7 @@ pytestmark = [
# pytest.mark.vrrpd,
]
+
# Function we pass to Topogen to create the topology
def build_topo(tgen):
"Build function"
diff --git a/tests/topotests/fpm_testing_topo1/r1/fpm_counters.json b/tests/topotests/fpm_testing_topo1/r1/fpm_counters.json
new file mode 100644
index 0000000..05a6731
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/fpm_counters.json
@@ -0,0 +1,8 @@
+{
+ "connected":true,
+ "useNHG":true,
+ "useRouteReplace":true,
+ "disabled":false,
+ "address":"127.0.0.1",
+ "port":2620
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ip_route.ref.diff b/tests/topotests/fpm_testing_topo1/r1/fpm_stub.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ip_route.ref.diff
+++ b/tests/topotests/fpm_testing_topo1/r1/fpm_stub.conf
diff --git a/tests/topotests/fpm_testing_topo1/r1/routes_summ.json b/tests/topotests/fpm_testing_topo1/r1/routes_summ.json
new file mode 100644
index 0000000..e9157bc
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/routes_summ.json
@@ -0,0 +1,27 @@
+{
+ "routes":[
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"connected"
+ },
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"local"
+ },
+ {
+ "fib":10000,
+ "rib":10000,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"sharp"
+ }
+ ],
+ "routesTotal":10002,
+ "routesTotalFib":10002
+}
diff --git a/tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json b/tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json
new file mode 100644
index 0000000..8585b2b
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/routes_summ_removed.json
@@ -0,0 +1,20 @@
+{
+ "routes":[
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"connected"
+ },
+ {
+ "fib":1,
+ "rib":1,
+ "fibOffLoaded":0,
+ "fibTrapped":0,
+ "type":"local"
+ }
+ ],
+ "routesTotal":2,
+ "routesTotalFib":2
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ipv6_route.ref.diff b/tests/topotests/fpm_testing_topo1/r1/sharpd.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ipv6_route.ref.diff
+++ b/tests/topotests/fpm_testing_topo1/r1/sharpd.conf
diff --git a/tests/topotests/fpm_testing_topo1/r1/zebra.conf b/tests/topotests/fpm_testing_topo1/r1/zebra.conf
new file mode 100644
index 0000000..c7b1646
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/r1/zebra.conf
@@ -0,0 +1,5 @@
+fpm address 127.0.0.1
+
+interface r1-eth0
+ ip address 192.168.44.1/24
+!
diff --git a/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
new file mode 100644
index 0000000..22fc50b
--- /dev/null
+++ b/tests/topotests/fpm_testing_topo1/test_fpm_topo1.py
@@ -0,0 +1,135 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# test_route_scale1.py
+#
+# Copyright (c) 2024 by
+# Nvidia, Inc.
+# Donald Sharp
+#
+
+"""
+test_fpm_topo1.py: Testing FPM module
+
+"""
+import os
+import re
+import sys
+import pytest
+import json
+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
+
+
+pytestmark = [pytest.mark.fpm, pytest.mark.sharpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Populate routers
+ tgen.add_router("r1")
+
+ switch = tgen.add_switch("sw1")
+ switch.add_link(tgen.gears["r1"])
+
+
+def setup_module(module):
+ "Setup topology"
+
+ # fpm_stub = os.system("which fpm-stub")
+ # if fpm-stub:
+ # pytest.skip("")
+
+ tgen = Topogen(build_topo, module.__name__)
+ tgen.start_topology()
+
+ 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)),
+ "-M dplane_fpm_nl",
+ )
+ router.load_config(
+ TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_FPM_LISTENER,
+ os.path.join(CWD, "{}/fpm_stub.conf".format(rname)),
+ )
+
+ 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 test_fpm_connection_made():
+ "Test that the fpm starts up and a connection is made"
+
+ tgen = get_topogen()
+ router = tgen.gears["r1"]
+
+ fpm_counters = "{}/r1/fpm_counters.json".format(CWD)
+ expected = json.loads(open(fpm_counters).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show fpm status json", expected
+ )
+
+ success, result = topotest.run_and_expect(test_func, None, 30, 1)
+ assert success, "Unable to connect to the fpm:\n{}".format(result)
+
+
+def test_fpm_install_routes():
+ "Test that simple routes installed appears to work"
+
+ tgen = get_topogen()
+ router = tgen.gears["r1"]
+
+ # Let's install 10000 routes
+ router.vtysh_cmd("sharp install routes 10.0.0.0 nexthop 192.168.44.33 10000")
+ routes_file = "{}/r1/routes_summ.json".format(CWD)
+ expected = json.loads(open(routes_file).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route summ json", expected
+ )
+
+ success, result = topotest.run_and_expect(test_func, None, 60, 1)
+ assert success, "Unable to successfully install 10000 routes: {}".format(result)
+
+ # Let's remove 10000 routes
+ router.vtysh_cmd("sharp remove routes 10.0.0.0 10000")
+
+ routes_file_removed = "{}/r1/routes_summ_removed.json".format(CWD)
+ expected = json.loads(open(routes_file_removed).read())
+
+ test_func = partial(
+ topotest.router_json_cmp, router, "show ip route summ json", expected
+ )
+
+ success, result = topotest.run_and_expect(test_func, None, 60, 1)
+ assert success, "Unable to remove 10000 routes: {}".format(result)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/grpc_basic/test_basic_grpc.py b/tests/topotests/grpc_basic/test_basic_grpc.py
index 1ded663..cf1c6d0 100644
--- a/tests/topotests/grpc_basic/test_basic_grpc.py
+++ b/tests/topotests/grpc_basic/test_basic_grpc.py
@@ -9,16 +9,18 @@
test_basic_grpc.py: Test Basic gRPC.
"""
+import json
import logging
import os
+import re
import sys
import pytest
-
from lib.common_config import step
from lib.micronet import commander
from lib.topogen import Topogen, TopoRouter
from lib.topolog import logger
+from lib.topotest import json_cmp
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -28,6 +30,7 @@ GRPCP_BFDD = 50053
GRPCP_ISISD = 50054
GRPCP_OSPFD = 50055
GRPCP_PIMD = 50056
+GRPCP_MGMTD = 50057
pytestmark = [
pytest.mark.mgmtd,
@@ -59,12 +62,15 @@ def tgen(request):
for rname, router in router_list.items():
router.load_config(TopoRouter.RD_ZEBRA, "zebra.conf", f"-M grpc:{GRPCP_ZEBRA}")
- router.load_config(TopoRouter.RD_STATIC, None, f"-M grpc:{GRPCP_STATICD}")
- # router.load_config(TopoRouter.RD_BFD, None, f"-M grpc:{GRPCP_BFDD}")
+ router.load_config(TopoRouter.RD_STATIC, "", f"-M grpc:{GRPCP_STATICD}")
+ # router.load_config(TopoRouter.RD_BFDD, "", f"-M grpc:{GRPCP_BFDD}")
# router.load_config(TopoRouter.RD_ISIS, None, f"-M grpc:{GRPCP_ISISD}")
# router.load_config(TopoRouter.RD_OSPF, None, f"-M grpc:{GRPCP_OSPFD}")
# router.load_config(TopoRouter.RD_PIM, None, f"-M grpc:{GRPCP_PIMD}")
+ # This doesn't work yet...
+ # router.load_config(TopoRouter.RD_MGMTD, "", f"-M grpc:{GRPCP_MGMTD}")
+
tgen.start_router()
yield tgen
@@ -94,40 +100,94 @@ def run_grpc_client(r, port, commands):
def test_connectivity(tgen):
- r1 = tgen.gears["r1"]
- output = r1.cmd_raises("ping -c1 192.168.1.2")
- logging.info("ping output: %s", output)
+ tgen.gears["r1"].cmd_raises("ping -c1 192.168.1.2")
def test_capabilities(tgen):
r1 = tgen.gears["r1"]
- output = run_grpc_client(r1, GRPCP_ZEBRA, "GETCAP")
- logging.info("grpc output: %s", output)
+ output = run_grpc_client(r1, GRPCP_STATICD, "GETCAP")
+ logging.debug("grpc output: %s", output)
+
+ modules = sorted(re.findall('name: "([^"]+)"', output))
+ expected = ["frr-interface", "frr-routing", "frr-staticd", "frr-vrf"]
+ assert modules == expected
+
+ encodings = sorted(re.findall("supported_encodings: (.*)", output))
+ expected = ["JSON", "XML"]
+ assert encodings == expected
def test_get_config(tgen):
nrepeat = 5
r1 = tgen.gears["r1"]
- step("'GET' interface config 10 times, once per invocation")
+ step("'GET' interface config and state 10 times, once per invocation")
for i in range(0, nrepeat):
- output = run_grpc_client(r1, GRPCP_ZEBRA, "GET,/frr-interface:lib")
- logging.info("[iteration %s]: grpc GET output: %s", i, output)
+ output = run_grpc_client(r1, GRPCP_ZEBRA, "GET-CONFIG,/frr-interface:lib")
+ logging.debug("[iteration %s]: grpc GET output: %s", i, output)
step(f"'GET' YANG {nrepeat} times in one invocation")
- commands = ["GET,/frr-interface:lib" for _ in range(0, 10)]
+ commands = ["GET-CONFIG,/frr-interface:lib" for _ in range(0, 10)]
output = run_grpc_client(r1, GRPCP_ZEBRA, commands)
- logging.info("grpc GET*{%d} output: %s", nrepeat, output)
+ logging.debug("grpc GET*{%d} output: %s", nrepeat, output)
+
+ output = run_grpc_client(r1, GRPCP_ZEBRA, commands[0])
+ out_json = json.loads(output)
+ expect = json.loads(
+ """{
+ "frr-interface:lib": {
+ "interface": [
+ {
+ "name": "r1-eth0",
+ "frr-zebra:zebra": {
+ "ipv4-addrs": [
+ {
+ "ip": "192.168.1.1",
+ "prefix-length": 24
+ }
+ ],
+ "evpn-mh": {},
+ "ipv6-router-advertisements": {}
+ }
+ }
+ ]
+ },
+ "frr-zebra:zebra": {
+ "import-kernel-table": {}
+ }
+} """
+ )
+ result = json_cmp(out_json, expect, exact=True)
+ assert result is None
def test_get_vrf_config(tgen):
r1 = tgen.gears["r1"]
- step("'GET' get VRF config")
-
- output = run_grpc_client(r1, GRPCP_ZEBRA, "GET,/frr-vrf:lib")
- logging.info("grpc GET /frr-vrf:lib output: %s", output)
+ step("'GET' VRF config and state")
+
+ output = run_grpc_client(r1, GRPCP_STATICD, "GET,/frr-vrf:lib")
+ logging.debug("grpc GET /frr-vrf:lib output: %s", output)
+ out_json = json.loads(output)
+ expect = json.loads(
+ """{
+ "frr-vrf:lib": {
+ "vrf": [
+ {
+ "name": "default",
+ "state": {
+ "id": 0,
+ "active": true
+ }
+ }
+ ]
+ }
+}
+ """
+ )
+ result = json_cmp(out_json, expect, exact=True)
+ assert result is None
def test_shutdown_checks(tgen):
diff --git a/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py b/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py
index 6a5f81d..6689cf4 100755
--- a/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py
+++ b/tests/topotests/isis_sr_flex_algo_topo2/test_isis_sr_flex_algo_topo2.py
@@ -118,11 +118,19 @@ def setup_module(mod):
# For all registered routers, load the zebra configuration file
for rname, router in router_list.items():
- router.load_config( TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)))
- router.load_config( TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
if rname in ["rt0", "rt9"]:
- router.load_config( TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname)))
- router.load_config( TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname)))
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_PATH, os.path.join(CWD, "{}/pathd.conf".format(rname))
+ )
router.run("ip link add dum0 type dummy")
router.run("ip link set dum0 up")
if rname == "rt0":
@@ -145,6 +153,7 @@ def setup_testcase(msg):
pytest.skip(tgen.errors)
return tgen
+
def open_json_file(filename):
try:
with open(filename, "r") as f:
@@ -162,7 +171,7 @@ def check_rib(name, cmd, expected_file):
expected = open_json_file("{}/{}".format(CWD, expected_file))
return topotest.json_cmp(output, expected)
- logger.info("[+] check {} \"{}\" {}".format(name, cmd, expected_file))
+ logger.info('[+] check {} "{}" {}'.format(name, cmd, expected_file))
tgen = get_topogen()
func = partial(_check, name, cmd, expected_file)
success, result = topotest.run_and_expect(func, None, count=120, wait=0.5)
diff --git a/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py b/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py
index 892f6e1..1a7505d 100644
--- a/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py
+++ b/tests/topotests/isis_srv6_topo1/test_isis_srv6_topo1.py
@@ -197,13 +197,16 @@ def setup_module(mod):
# For all registered routers, load the zebra and isis configuration files
for rname, router in tgen.routers().items():
- router.load_config(TopoRouter.RD_ZEBRA,
- os.path.join(CWD, '{}/zebra.conf'.format(rname)))
- router.load_config(TopoRouter.RD_ISIS,
- os.path.join(CWD, '{}/isisd.conf'.format(rname)))
- if (os.path.exists('{}/sharpd.conf'.format(rname))):
- router.load_config(TopoRouter.RD_SHARP,
- os.path.join(CWD, '{}/sharpd.conf'.format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
+ )
+ if os.path.exists("{}/sharpd.conf".format(rname)):
+ router.load_config(
+ TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
+ )
# Start routers
tgen.start_router()
@@ -227,7 +230,9 @@ def router_compare_json_output(rname, command, reference):
expected = json.loads(open(filename).read())
# Run test function until we get an result. Wait at most 60 seconds.
- test_func = functools.partial(topotest.router_json_cmp, tgen.gears[rname], command, expected)
+ test_func = functools.partial(
+ topotest.router_json_cmp, tgen.gears[rname], command, expected
+ )
_, diff = topotest.run_and_expect(test_func, None, count=120, wait=0.5)
assertmsg = '"{}" JSON output mismatches the expected result'.format(rname)
assert diff is None, assertmsg
@@ -308,8 +313,10 @@ def test_srv6_locator_step1():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step1/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step1/show_srv6_locator_table.ref",
+ )
def test_ping_step1():
@@ -326,10 +333,16 @@ def test_ping_step1():
pytest.skip(tgen.errors)
# Setup encap route on rt1, decap route on rt2
- tgen.gears["rt1"].vtysh_cmd("sharp install seg6-routes fc00:0:9::1 nexthop-seg6 2001:db8:1::2 encap fc00:0:1:2:6:f00d:: 1")
- tgen.gears["rt6"].vtysh_cmd("sharp install seg6local-routes fc00:0:f00d:: nexthop-seg6local eth-dst End_DT6 254 1")
- tgen.gears["dst"].vtysh_cmd("sharp install route 2001:db8:1::1 nexthop 2001:db8:10::1 1")
-
+ tgen.gears["rt1"].vtysh_cmd(
+ "sharp install seg6-routes fc00:0:9::1 nexthop-seg6 2001:db8:1::2 encap fc00:0:1:2:6:f00d:: 1"
+ )
+ tgen.gears["rt6"].vtysh_cmd(
+ "sharp install seg6local-routes fc00:0:f00d:: nexthop-seg6local eth-dst End_DT6 254 1"
+ )
+ tgen.gears["dst"].vtysh_cmd(
+ "sharp install route 2001:db8:1::1 nexthop 2001:db8:10::1 1"
+ )
+
# Try to ping dst from rt1
check_ping6("rt1", "fc00:0:9::1", True)
@@ -412,8 +425,10 @@ def test_srv6_locator_step2():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step2/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step2/show_srv6_locator_table.ref",
+ )
def test_ping_step2():
@@ -428,7 +443,7 @@ def test_ping_step2():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -512,8 +527,10 @@ def test_srv6_locator_step3():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step3/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step3/show_srv6_locator_table.ref",
+ )
def test_ping_step3():
@@ -528,7 +545,7 @@ def test_ping_step3():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
@@ -608,8 +625,10 @@ def test_srv6_locator_step4():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step4/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step4/show_srv6_locator_table.ref",
+ )
def test_ping_step4():
@@ -624,7 +643,7 @@ def test_ping_step4():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -704,8 +723,10 @@ def test_srv6_locator_step5():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step5/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step5/show_srv6_locator_table.ref",
+ )
def test_ping_step5():
@@ -720,7 +741,7 @@ def test_ping_step5():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
@@ -799,8 +820,10 @@ def test_srv6_locator_step6():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step6/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step6/show_srv6_locator_table.ref",
+ )
def test_ping_step6():
@@ -815,7 +838,7 @@ def test_ping_step6():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -895,8 +918,10 @@ def test_srv6_locator_step7():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step7/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step7/show_srv6_locator_table.ref",
+ )
def test_ping_step7():
@@ -911,7 +936,7 @@ def test_ping_step7():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
@@ -990,8 +1015,10 @@ def test_srv6_locator_step8():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step8/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step8/show_srv6_locator_table.ref",
+ )
def test_ping_step8():
@@ -1006,7 +1033,7 @@ def test_ping_step8():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", False)
@@ -1089,8 +1116,10 @@ def test_srv6_locator_step9():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show segment-routing srv6 locator json", "step9/show_srv6_locator_table.ref"
- )
+ rname,
+ "show segment-routing srv6 locator json",
+ "step9/show_srv6_locator_table.ref",
+ )
def test_ping_step9():
@@ -1105,7 +1134,7 @@ def test_ping_step9():
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
-
+
check_ping6("rt1", "fc00:0:9::1", True)
diff --git a/tests/topotests/isis_te_topo1/test_isis_te_topo1.py b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
index 9c70e05..eb4f310 100644
--- a/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
+++ b/tests/topotests/isis_te_topo1/test_isis_te_topo1.py
@@ -189,10 +189,18 @@ def test_step3():
tgen = setup_testcase("Step3: Add IPv6 on r1 and r2 interfaces")
- tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"')
- tgen.net["r1"].cmd('vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"')
- tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"')
- tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"')
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 address 2001:db8:0::1/64"'
+ )
+ tgen.net["r1"].cmd(
+ 'vtysh -c "conf t" -c "interface r1-eth0" -c "ipv6 router isis TE"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 address 2001:db8:0::2/64"'
+ )
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "interface r2-eth0" -c "ipv6 router isis TE"'
+ )
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step3.json")
@@ -202,8 +210,12 @@ def test_step4():
tgen = setup_testcase("Step4: Modify Prefix SID on router r4")
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"')
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"')
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 10.0.255.4/32 index 40"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "router isis TE" -c "segment-routing prefix 2001:db8:ffff::4/128 index 1040"'
+ )
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step4.json")
@@ -229,9 +241,15 @@ def test_step6():
tgen = setup_testcase("Step6: Modify link parameters on r2 & r4")
- tgen.net["r2"].cmd('vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"')
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"')
- tgen.net["r4"].cmd('vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"')
+ tgen.net["r2"].cmd(
+ 'vtysh -c "conf t" -c "interface r2-eth3" -c "link-params" -c "no use-bw"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay 20000"'
+ )
+ tgen.net["r4"].cmd(
+ 'vtysh -c "conf t" -c "interface r4-eth0" -c "link-params" -c "delay-variation 10000"'
+ )
for rname in ["r1", "r2", "r3", "r4"]:
compare_ted_json_output(tgen, rname, "ted_step6.json")
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step1/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step1/show_mpls_table.ref
index aa0357d..f73b22d 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step1/show_mpls_table.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step1/show_mpls_table.ref
@@ -7,7 +7,8 @@
"type":"SR (IS-IS)",
"outLabel":3,
"installed":true,
- "nexthop":"10.0.1.2"
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
}
]
},
@@ -31,7 +32,8 @@
"type":"SR (IS-IS)",
"outLabel":3,
"installed":true,
- "nexthop":"10.0.1.3"
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
}
]
},
@@ -55,7 +57,8 @@
"type":"SR (IS-IS)",
"outLabel":16040,
"installed":true,
- "nexthop":"10.0.1.2"
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
}
]
},
@@ -79,7 +82,8 @@
"type":"SR (IS-IS)",
"outLabel":16050,
"installed":true,
- "nexthop":"10.0.1.3"
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
}
]
},
@@ -103,13 +107,15 @@
"type":"SR (IS-IS)",
"outLabel":16060,
"installed":true,
- "nexthop":"10.0.1.3"
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
},
{
"type":"SR (IS-IS)",
"outLabel":16060,
"installed":true,
- "nexthop":"10.0.1.2"
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
}
]
},
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref
index 9c5901b..fcef68c 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step1/show_yang_interface_isis_adjacencies.ref
@@ -10,14 +10,14 @@
"adjacency": [
{
"neighbor-sys-type": "level-1",
- "neighbor-sysid": "0000.0000.0003",
+ "neighbor-sysid": "0000.0000.0002",
"hold-timer": 10,
"neighbor-priority": 64,
"state": "up"
},
{
"neighbor-sys-type": "level-1",
- "neighbor-sysid": "0000.0000.0002",
+ "neighbor-sysid": "0000.0000.0003",
"hold-timer": 10,
"neighbor-priority": 64,
"state": "up"
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step12/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step12/show_ip_route.ref.diff
deleted file mode 100644
index a8d6e6c..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step12/show_ip_route.ref.diff
+++ /dev/null
@@ -1,19 +0,0 @@
---- a/rt1/step11/show_ip_route.ref
-+++ b/rt1/step12/show_ip_route.ref
-@@ -110,16 +110,6 @@
- "labels":[
- 16060
- ]
-- },
-- {
-- "fib":true,
-- "ip":"10.0.1.3",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16060
-- ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step12/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step12/show_ipv6_route.ref.diff
deleted file mode 100644
index 637c59f..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step12/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,18 +0,0 @@
---- a/rt1/step11/show_ipv6_route.ref
-+++ b/rt1/step12/show_ipv6_route.ref
-@@ -105,15 +105,6 @@
- "labels":[
- 16061
- ]
-- },
-- {
-- "fib":true,
-- "afi":"ipv6",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16061
-- ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step12/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step12/show_mpls_table.ref.diff
deleted file mode 100644
index e110bf4..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step12/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,28 +0,0 @@
---- a/rt1/step11/show_mpls_table.ref
-+++ b/rt1/step12/show_mpls_table.ref
-@@ -79,12 +79,6 @@
- "type":"SR (IS-IS)",
- "outLabel":16060,
- "installed":true,
-- "nexthop":"10.0.1.3"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16060,
-- "installed":true,
- "nexthop":"10.0.1.2"
- }
- ]
-@@ -96,12 +90,6 @@
- {
- "type":"SR (IS-IS)",
- "outLabel":16061,
-- "installed":true,
-- "interface":"eth-sw1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16061,
- "installed":true,
- "interface":"eth-sw1"
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ip_route.ref
new file mode 100644
index 0000000..92b7437
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ip_route.ref
@@ -0,0 +1,294 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ipv6_route.ref
new file mode 100644
index 0000000..3232121
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step2/show_ipv6_route.ref
@@ -0,0 +1,121 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step2/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step2/show_mpls_table.ref
new file mode 100644
index 0000000..f73b22d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step2/show_mpls_table.ref
@@ -0,0 +1,140 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ip_route.ref
new file mode 100644
index 0000000..92b7437
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ip_route.ref
@@ -0,0 +1,294 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ipv6_route.ref
new file mode 100644
index 0000000..3232121
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step3/show_ipv6_route.ref
@@ -0,0 +1,121 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step3/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step3/show_mpls_table.ref
new file mode 100644
index 0000000..f73b22d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step3/show_mpls_table.ref
@@ -0,0 +1,140 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref
new file mode 100644
index 0000000..89e0b16
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref
@@ -0,0 +1,291 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref.diff
deleted file mode 100644
index 10b336f..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ip_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step3/show_ip_route.ref
-+++ b/rt1/step4/show_ip_route.ref
-@@ -60,10 +60,7 @@
- "ip":"10.0.1.2",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref
new file mode 100644
index 0000000..0358d5d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref
@@ -0,0 +1,118 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref.diff
deleted file mode 100644
index 904aaa1..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step3/show_ipv6_route.ref
-+++ b/rt1/step4/show_ipv6_route.ref
-@@ -57,10 +57,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16041
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref
new file mode 100644
index 0000000..d587d42
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref
@@ -0,0 +1,115 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref.diff
deleted file mode 100644
index d7d8753..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step4/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/rt1/step3/show_mpls_table.ref
-+++ b/rt1/step4/show_mpls_table.ref
-@@ -47,30 +47,6 @@
- }
- ]
- },
-- "16040":{
-- "inLabel":16040,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "installed":true,
-- "nexthop":"10.0.1.2"
-- }
-- ]
-- },
-- "16041":{
-- "inLabel":16041,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "installed":true,
-- "interface":"eth-sw1"
-- }
-- ]
-- },
- "16050":{
- "inLabel":16050,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref
new file mode 100644
index 0000000..92b7437
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref
@@ -0,0 +1,294 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref.diff
deleted file mode 100644
index b583fa9..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ip_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step4/show_ip_route.ref
-+++ b/rt1/step5/show_ip_route.ref
-@@ -60,7 +60,10 @@
- "ip":"10.0.1.2",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref
new file mode 100644
index 0000000..3232121
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref
@@ -0,0 +1,121 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref.diff
deleted file mode 100644
index d608abe..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step4/show_ipv6_route.ref
-+++ b/rt1/step5/show_ipv6_route.ref
-@@ -57,7 +57,10 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16041
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref
new file mode 100644
index 0000000..f73b22d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref
@@ -0,0 +1,140 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref.diff
deleted file mode 100644
index b5161fc..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step5/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/rt1/step4/show_mpls_table.ref
-+++ b/rt1/step5/show_mpls_table.ref
-@@ -47,6 +47,30 @@
- }
- ]
- },
-+ "16040":{
-+ "inLabel":16040,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "installed":true,
-+ "nexthop":"10.0.1.2"
-+ }
-+ ]
-+ },
-+ "16041":{
-+ "inLabel":16041,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "installed":true,
-+ "interface":"eth-sw1"
-+ }
-+ ]
-+ },
- "16050":{
- "inLabel":16050,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ip_route.ref
new file mode 100644
index 0000000..92b7437
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ip_route.ref
@@ -0,0 +1,294 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ipv6_route.ref
new file mode 100644
index 0000000..3232121
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step6/show_ipv6_route.ref
@@ -0,0 +1,121 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step6/show_mpls_table.ref
new file mode 100644
index 0000000..f73b22d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step6/show_mpls_table.ref
@@ -0,0 +1,140 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref
new file mode 100644
index 0000000..270fcef
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref
@@ -0,0 +1,291 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref.diff
deleted file mode 100644
index 726aed5..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ip_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step6/show_ip_route.ref
-+++ b/rt1/step7/show_ip_route.ref
-@@ -83,10 +83,7 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref
new file mode 100644
index 0000000..7ded014
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref
@@ -0,0 +1,118 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref.diff
deleted file mode 100644
index 2049f6f..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step6/show_ipv6_route.ref
-+++ b/rt1/step7/show_ipv6_route.ref
-@@ -79,10 +79,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref
new file mode 100644
index 0000000..b4ba438
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref
@@ -0,0 +1,115 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref.diff
deleted file mode 100644
index 22301ba..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step7/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/rt1/step6/show_mpls_table.ref
-+++ b/rt1/step7/show_mpls_table.ref
-@@ -71,30 +71,6 @@
- }
- ]
- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.1.3"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
-- "interface":"eth-sw1"
-- }
-- ]
-- },
- "16060":{
- "inLabel":16060,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref
new file mode 100644
index 0000000..92b7437
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref
@@ -0,0 +1,294 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref.diff
deleted file mode 100644
index 4a1d480..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ip_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step7/show_ip_route.ref
-+++ b/rt1/step8/show_ip_route.ref
-@@ -83,7 +83,10 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref
new file mode 100644
index 0000000..3232121
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref
@@ -0,0 +1,121 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref.diff
deleted file mode 100644
index eaece74..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,14 +0,0 @@
---- a/rt1/step7/show_ipv6_route.ref
-+++ b/rt1/step8/show_ipv6_route.ref
-@@ -79,7 +79,10 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref
new file mode 100644
index 0000000..f73b22d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref
@@ -0,0 +1,140 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref.diff
deleted file mode 100644
index 46c17de..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step8/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,33 +0,0 @@
---- a/rt1/step7/show_mpls_table.ref
-+++ b/rt1/step8/show_mpls_table.ref
-@@ -71,6 +71,30 @@
- }
- ]
- },
-+ "16050":{
-+ "inLabel":16050,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "installed":true,
-+ "nexthop":"10.0.1.3"
-+ }
-+ ]
-+ },
-+ "16051":{
-+ "inLabel":16051,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "installed":true,
-+ "interface":"eth-sw1"
-+ }
-+ ]
-+ },
- "16060":{
- "inLabel":16060,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref
new file mode 100644
index 0000000..841c902
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref
@@ -0,0 +1,294 @@
+{
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref.diff
deleted file mode 100644
index 06efdc9..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ip_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt1/step8/show_ip_route.ref
-+++ b/rt1/step9/show_ip_route.ref
-@@ -85,7 +85,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref
new file mode 100644
index 0000000..4d35cf1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref
@@ -0,0 +1,121 @@
+{
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16501
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref.diff
deleted file mode 100644
index a58f2d4..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt1/step8/show_ipv6_route.ref
-+++ b/rt1/step9/show_ipv6_route.ref
-@@ -81,7 +81,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16051
-+ 16501
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref
new file mode 100644
index 0000000..dc64494
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref
@@ -0,0 +1,140 @@
+{
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16500":{
+ "inLabel":16500,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16501":{
+ "inLabel":16501,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref.diff
deleted file mode 100644
index c0a1ac5..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt1/step9/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,64 +0,0 @@
---- a/rt1/step8/show_mpls_table.ref
-+++ b/rt1/step9/show_mpls_table.ref
-@@ -71,30 +71,6 @@
- }
- ]
- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.1.3"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
-- "interface":"eth-sw1"
-- }
-- ]
-- },
- "16060":{
- "inLabel":16060,
- "installed":true,
-@@ -129,6 +105,30 @@
- "installed":true,
- "interface":"eth-sw1"
- }
-+ ]
-+ },
-+ "16500":{
-+ "inLabel":16500,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16500,
-+ "installed":true,
-+ "nexthop":"10.0.1.3"
-+ }
-+ ]
-+ },
-+ "16501":{
-+ "inLabel":16501,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16501,
-+ "installed":true,
-+ "interface":"eth-sw1"
-+ }
- ]
- }
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step1/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step1/show_ipv6_route.ref
index 6d31f6f..9543231 100644
--- a/tests/topotests/isis_tilfa_topo1/rt2/step1/show_ipv6_route.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step1/show_ipv6_route.ref
@@ -152,7 +152,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt4-1",
+ "interfaceName":"eth-sw1",
"active":true,
"labels":[
16051
@@ -161,7 +161,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-sw1",
+ "interfaceName":"eth-rt4-1",
"active":true,
"labels":[
16051
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step1/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step1/show_mpls_table.ref
index b9b906a..8580cb0 100644
--- a/tests/topotests/isis_tilfa_topo1/rt2/step1/show_mpls_table.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step1/show_mpls_table.ref
@@ -8,6 +8,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
"backupIndex":[
0,
1
@@ -18,12 +19,14 @@
{
"type":"SR (IS-IS)",
"outLabel":16050,
- "nexthop":"10.0.2.4"
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
},
{
"type":"SR (IS-IS)",
"outLabel":16050,
- "nexthop":"10.0.3.4"
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
}
]
},
@@ -64,6 +67,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.1.3",
+ "interface":"eth-sw1",
"backupIndex":[
0,
1
@@ -74,12 +78,14 @@
{
"type":"SR (IS-IS)",
"outLabel":16050,
- "nexthop":"10.0.2.4"
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
},
{
"type":"SR (IS-IS)",
"outLabel":16050,
- "nexthop":"10.0.3.4"
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
}
]
},
@@ -120,6 +126,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
"backupIndex":[
0
]
@@ -129,6 +136,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
"backupIndex":[
0
]
@@ -138,7 +146,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16050,
- "nexthop":"10.0.1.3"
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
}
]
},
@@ -181,19 +190,22 @@
"type":"SR (IS-IS)",
"outLabel":16050,
"installed":true,
- "nexthop":"10.0.3.4"
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
},
{
"type":"SR (IS-IS)",
"outLabel":16050,
"installed":true,
- "nexthop":"10.0.2.4"
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
},
{
"type":"SR (IS-IS)",
"outLabel":16050,
"installed":true,
- "nexthop":"10.0.1.3"
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
}
]
},
@@ -205,19 +217,19 @@
"type":"SR (IS-IS)",
"outLabel":16051,
"installed":true,
- "interface":"eth-rt4-2"
+ "interface":"eth-sw1"
},
{
"type":"SR (IS-IS)",
"outLabel":16051,
"installed":true,
- "interface":"eth-rt4-1"
+ "interface":"eth-rt4-2"
},
{
"type":"SR (IS-IS)",
"outLabel":16051,
"installed":true,
- "interface":"eth-sw1"
+ "interface":"eth-rt4-1"
}
]
},
@@ -230,6 +242,7 @@
"outLabel":16060,
"installed":true,
"nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
"backupIndex":[
0
]
@@ -239,6 +252,7 @@
"outLabel":16060,
"installed":true,
"nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
"backupIndex":[
0
]
@@ -248,7 +262,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16060,
- "nexthop":"10.0.1.3"
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
}
]
},
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step10/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step10/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step10/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step10/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step10/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step10/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step10/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step10/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step10/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step11/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step11/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step11/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step11/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step11/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step11/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step11/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step11/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step11/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step12/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step12/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step12/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step12/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step12/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step12/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step12/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step12/show_mpls_table.ref.diff
deleted file mode 100644
index 84a3644..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step12/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,20 +0,0 @@
---- a/rt2/step11/show_mpls_table.ref
-+++ b/rt2/step12/show_mpls_table.ref
-@@ -199,7 +199,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16060,
-+ "outLabel":16500,
- "nexthop":"10.0.1.3"
- }
- ]
-@@ -230,7 +230,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16061,
-+ "outLabel":16501,
- "interface":"eth-sw1"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ip_route.ref
new file mode 100644
index 0000000..374eec7
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ip_route.ref
@@ -0,0 +1,447 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step2/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ip_route.ref.diff
deleted file mode 100644
index 90e0895..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ip_route.ref.diff
+++ /dev/null
@@ -1,169 +0,0 @@
---- a/rt2/step1/show_ip_route.ref
-+++ b/rt2/step2/show_ip_route.ref
-@@ -15,36 +15,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050,
-- 16010
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050,
-- 16010
-- ]
-- }
- ]
- }
- ],
-@@ -64,36 +38,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050,
-- 16030
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050,
-- 16030
-- ]
-- }
- ]
- }
- ],
-@@ -251,40 +199,12 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-+ "interfaceName":"eth-sw1"
- },
- {
- "ip":"10.0.1.3",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "interfaceName":"eth-sw1"
- }
- ]
- }
-@@ -380,24 +300,6 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
- "active":true
- }
- ]
-@@ -418,24 +320,6 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
- "active":true
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref
new file mode 100644
index 0000000..ca4f96f
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref
@@ -0,0 +1,181 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref.diff
deleted file mode 100644
index 2d19f20..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,72 +0,0 @@
---- a/rt2/step1/show_ipv6_route.ref
-+++ b/rt2/step2/show_ipv6_route.ref
-@@ -14,34 +14,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051,
-- 16011
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051,
-- 16011
-- ]
-- }
- ]
- }
- ],
-@@ -60,34 +36,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051,
-- 16031
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051,
-- 16031
-- ]
-- }
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref
new file mode 100644
index 0000000..7b48e86
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref
@@ -0,0 +1,233 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref.diff
deleted file mode 100644
index 01fc74a..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step2/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,102 +0,0 @@
---- a/rt2/step1/show_mpls_table.ref
-+++ b/rt2/step2/show_mpls_table.ref
-@@ -7,23 +7,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.3.4"
-+ "nexthop":"10.0.1.1"
- }
- ]
- },
-@@ -35,23 +19,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-2"
-+ "interface":"eth-sw1"
- }
- ]
- },
-@@ -63,23 +31,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.3",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.3.4"
-+ "nexthop":"10.0.1.3"
- }
- ]
- },
-@@ -91,23 +43,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-2"
-+ "interface":"eth-sw1"
- }
- ]
- },
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ip_route.ref
new file mode 100644
index 0000000..7e1ccd1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step3/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ip_route.ref.diff
deleted file mode 100644
index d93f036..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ip_route.ref.diff
+++ /dev/null
@@ -1,169 +0,0 @@
---- a/rt2/step2/show_ip_route.ref
-+++ b/rt2/step3/show_ip_route.ref
-@@ -15,10 +15,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16010
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16010
-+ ]
-+ }
- ]
- }
- ],
-@@ -38,10 +64,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16030
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16030
-+ ]
-+ }
- ]
- }
- ],
-@@ -199,12 +251,40 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
- },
- {
- "ip":"10.0.1.3",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
-@@ -300,6 +380,24 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-+ "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
- "active":true
- }
- ]
-@@ -320,6 +418,24 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-+ "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
- "active":true
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref
new file mode 100644
index 0000000..9543231
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref.diff
deleted file mode 100644
index 68b618e..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,72 +0,0 @@
---- a/rt2/step2/show_ipv6_route.ref
-+++ b/rt2/step3/show_ipv6_route.ref
-@@ -14,10 +14,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16011
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16011
-+ ]
-+ }
- ]
- }
- ],
-@@ -36,10 +60,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16031
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16031
-+ ]
-+ }
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref
new file mode 100644
index 0000000..8580cb0
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref.diff
deleted file mode 100644
index 966e153..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step3/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,102 +0,0 @@
---- a/rt2/step2/show_mpls_table.ref
-+++ b/rt2/step3/show_mpls_table.ref
-@@ -7,7 +7,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1"
-+ "nexthop":"10.0.1.1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.3.4"
- }
- ]
- },
-@@ -19,7 +35,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1"
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-2"
- }
- ]
- },
-@@ -31,7 +63,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.3"
-+ "nexthop":"10.0.1.3",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.3.4"
- }
- ]
- },
-@@ -43,7 +91,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1"
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-2"
- }
- ]
- },
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ip_route.ref
new file mode 100644
index 0000000..c5fc51b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ip_route.ref
@@ -0,0 +1,464 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "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
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step4/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ip_route.ref.diff
deleted file mode 100644
index dd75d76..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ip_route.ref.diff
+++ /dev/null
@@ -1,192 +0,0 @@
---- a/rt2/step3/show_ip_route.ref
-+++ b/rt2/step4/show_ip_route.ref
-@@ -15,36 +15,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050,
-- 16010
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050,
-- 16010
-- ]
-- }
- ]
- }
- ],
-@@ -64,36 +38,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050,
-- 16030
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050,
-- 16030
-- ]
-- }
- ]
- }
- ],
-@@ -115,9 +63,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- },
- {
-@@ -128,9 +73,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -141,8 +83,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050,
-- 16040
-+ 16050
- ]
- }
- ]
-@@ -173,20 +114,14 @@
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
-@@ -209,9 +144,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 16060
- ]
- },
- {
-@@ -222,9 +154,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 16060
- ]
- }
- ],
-@@ -251,40 +180,12 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-+ "interfaceName":"eth-sw1"
- },
- {
- "ip":"10.0.1.3",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "interfaceName":"eth-sw1"
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref
new file mode 100644
index 0000000..22bec0f
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref
@@ -0,0 +1,162 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref.diff
deleted file mode 100644
index 6373123..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,146 +0,0 @@
---- a/rt2/step3/show_ipv6_route.ref
-+++ b/rt2/step4/show_ipv6_route.ref
-@@ -14,34 +14,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051,
-- 16011
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051,
-- 16011
-- ]
-- }
- ]
- }
- ],
-@@ -60,34 +36,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051,
-- 16031
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051,
-- 16031
-- ]
-- }
- ]
- }
- ],
-@@ -108,9 +60,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- },
- {
-@@ -120,9 +69,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -132,8 +78,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16051,
-- 16041
-+ 16051
- ]
- }
- ]
-@@ -153,10 +98,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- },
- {
- "fib":true,
-@@ -171,10 +113,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- }
- ]
- }
-@@ -196,9 +135,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 16061
- ]
- },
- {
-@@ -208,9 +144,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 16061
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref
new file mode 100644
index 0000000..67f2b53
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref
@@ -0,0 +1,142 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref.diff
deleted file mode 100644
index 3872ce4..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step4/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,200 +0,0 @@
---- a/rt2/step3/show_mpls_table.ref
-+++ b/rt2/step4/show_mpls_table.ref
-@@ -7,23 +7,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.3.4"
-+ "nexthop":"10.0.1.1"
- }
- ]
- },
-@@ -35,23 +19,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-2"
-+ "interface":"eth-sw1"
- }
- ]
- },
-@@ -63,23 +31,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.3",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.3.4"
-+ "nexthop":"10.0.1.3"
- }
- ]
- },
-@@ -91,84 +43,6 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-2"
-- }
-- ]
-- },
-- "16040":{
-- "inLabel":16040,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.3.4",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.2.4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.1.3"
-- }
-- ]
-- },
-- "16041":{
-- "inLabel":16041,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt4-2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt4-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
- "interface":"eth-sw1"
- }
- ]
-@@ -181,18 +55,6 @@
- "type":"SR (IS-IS)",
- "outLabel":16050,
- "installed":true,
-- "nexthop":"10.0.3.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
- "nexthop":"10.0.1.3"
- }
- ]
-@@ -204,18 +66,6 @@
- {
- "type":"SR (IS-IS)",
- "outLabel":16051,
-- "installed":true,
-- "interface":"eth-rt4-2"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
- "installed":true,
- "interface":"eth-sw1"
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ip_route.ref
new file mode 100644
index 0000000..7e1ccd1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step5/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ip_route.ref.diff
deleted file mode 100644
index 4d56364..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ip_route.ref.diff
+++ /dev/null
@@ -1,192 +0,0 @@
---- a/rt2/step4/show_ip_route.ref
-+++ b/rt2/step5/show_ip_route.ref
-@@ -15,10 +15,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16010
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16010
-+ ]
-+ }
- ]
- }
- ],
-@@ -38,10 +64,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16030
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16030
-+ ]
-+ }
- ]
- }
- ],
-@@ -63,6 +115,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- },
- {
-@@ -73,6 +128,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -83,7 +141,8 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050
-+ 16050,
-+ 16040
- ]
- }
- ]
-@@ -114,14 +173,20 @@
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
-@@ -144,6 +209,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 16060
- ]
- },
- {
-@@ -154,6 +222,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 16060
- ]
- }
- ],
-@@ -180,12 +251,40 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
- },
- {
- "ip":"10.0.1.3",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref
new file mode 100644
index 0000000..9543231
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref.diff
deleted file mode 100644
index f9e0276..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,146 +0,0 @@
---- a/rt2/step4/show_ipv6_route.ref
-+++ b/rt2/step5/show_ipv6_route.ref
-@@ -14,10 +14,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16011
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16011
-+ ]
-+ }
- ]
- }
- ],
-@@ -36,10 +60,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16031
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16031
-+ ]
-+ }
- ]
- }
- ],
-@@ -60,6 +108,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- },
- {
-@@ -69,6 +120,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -78,7 +132,8 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16051
-+ 16051,
-+ 16041
- ]
- }
- ]
-@@ -98,7 +153,10 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- },
- {
- "fib":true,
-@@ -113,7 +171,10 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- }
- ]
- }
-@@ -135,6 +196,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 16061
- ]
- },
- {
-@@ -144,6 +208,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 16061
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref
new file mode 100644
index 0000000..ecaaae1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref.diff
deleted file mode 100644
index 6aebbd6..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step5/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,200 +0,0 @@
---- a/rt2/step4/show_mpls_table.ref
-+++ b/rt2/step5/show_mpls_table.ref
-@@ -7,7 +7,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1"
-+ "nexthop":"10.0.1.1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.3.4"
- }
- ]
- },
-@@ -19,7 +35,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1"
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-2"
- }
- ]
- },
-@@ -31,7 +63,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.3"
-+ "nexthop":"10.0.1.3",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.3.4"
- }
- ]
- },
-@@ -43,6 +91,84 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-2"
-+ }
-+ ]
-+ },
-+ "16040":{
-+ "inLabel":16040,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.3.4",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.2.4",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.1.3"
-+ }
-+ ]
-+ },
-+ "16041":{
-+ "inLabel":16041,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt4-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt4-1",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
- "interface":"eth-sw1"
- }
- ]
-@@ -55,6 +181,18 @@
- "type":"SR (IS-IS)",
- "outLabel":16050,
- "installed":true,
-+ "nexthop":"10.0.3.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "installed":true,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "installed":true,
- "nexthop":"10.0.1.3"
- }
- ]
-@@ -66,6 +204,18 @@
- {
- "type":"SR (IS-IS)",
- "outLabel":16051,
-+ "installed":true,
-+ "interface":"eth-rt4-2"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "installed":true,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
- "installed":true,
- "interface":"eth-sw1"
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ip_route.ref
new file mode 100644
index 0000000..7e1ccd1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step6/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref
new file mode 100644
index 0000000..9543231
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref
new file mode 100644
index 0000000..ecaaae1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step6/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ip_route.ref
new file mode 100644
index 0000000..9459f2e
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ip_route.ref
@@ -0,0 +1,405 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1"
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2"
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step7/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ip_route.ref.diff
deleted file mode 100644
index 5e73b97..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ip_route.ref.diff
+++ /dev/null
@@ -1,288 +0,0 @@
---- a/rt2/step6/show_ip_route.ref
-+++ b/rt2/step7/show_ip_route.ref
-@@ -15,36 +15,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050,
-- 16010
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050,
-- 16010
-- ]
-- }
- ]
- }
- ],
-@@ -64,36 +38,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050,
-- 16030
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050,
-- 16030
-- ]
-- }
- ]
- }
- ],
-@@ -113,9 +61,6 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
-@@ -126,25 +71,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.3",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16050,
-- 16040
-- ]
-- }
- ]
- }
- ],
-@@ -163,30 +93,21 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
-@@ -251,40 +172,12 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-+ "interfaceName":"eth-sw1"
- },
- {
- "ip":"10.0.1.3",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.2.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-- },
-- {
-- "ip":"10.0.3.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "interfaceName":"eth-sw1"
- }
- ]
- }
-@@ -299,30 +192,13 @@
- {
- "ip":"10.0.2.4",
- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1",
-- "backupIndex":[
-- 0
-- ]
-+ "interfaceName":"eth-rt4-1"
- },
- {
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.3",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
-@@ -338,29 +214,12 @@
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-+ "active":true
- },
- {
- "ip":"10.0.3.4",
- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.3",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "interfaceName":"eth-rt4-2"
- }
- ]
- }
-@@ -497,31 +356,14 @@
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.3",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref
new file mode 100644
index 0000000..a75e585
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref
@@ -0,0 +1,155 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref.diff
deleted file mode 100644
index 5dc4e59..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,139 +0,0 @@
---- a/rt2/step6/show_ipv6_route.ref
-+++ b/rt2/step7/show_ipv6_route.ref
-@@ -14,34 +14,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051,
-- 16011
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051,
-- 16011
-- ]
-- }
- ]
- }
- ],
-@@ -60,34 +36,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051,
-- 16031
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051,
-- 16031
-- ]
-- }
- ]
- }
- ],
-@@ -106,9 +58,6 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt4-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
-@@ -118,24 +67,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt4-2",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16051,
-- 16041
-- ]
-- }
- ]
- }
- ],
-@@ -153,28 +88,19 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-1",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-2",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref
new file mode 100644
index 0000000..2c0139f
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref
@@ -0,0 +1,155 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref.diff
deleted file mode 100644
index 6c0d739..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step7/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,207 +0,0 @@
---- a/rt2/step6/show_mpls_table.ref
-+++ b/rt2/step7/show_mpls_table.ref
-@@ -7,23 +7,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.3.4"
-+ "nexthop":"10.0.1.1"
- }
- ]
- },
-@@ -35,23 +19,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-2"
-+ "interface":"eth-sw1"
- }
- ]
- },
-@@ -63,23 +31,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.3",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.3.4"
-+ "nexthop":"10.0.1.3"
- }
- ]
- },
-@@ -91,23 +43,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4-2"
-+ "interface":"eth-sw1"
- }
- ]
- },
-@@ -119,26 +55,13 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.3.4",
-- "backupIndex":[
-- 0
-- ]
-+ "nexthop":"10.0.3.4"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.2.4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.1.3"
-+ "nexthop":"10.0.2.4"
- }
- ]
- },
-@@ -150,74 +73,13 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt4-2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt4-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-sw1"
-- }
-- ]
-- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.3.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.1.3"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
- "interface":"eth-rt4-2"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-+ "outLabel":3,
- "installed":true,
- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
-- "interface":"eth-sw1"
- }
- ]
- },
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ip_route.ref
new file mode 100644
index 0000000..7e1ccd1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050,
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step8/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ip_route.ref.diff
deleted file mode 100644
index f5df607..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ip_route.ref.diff
+++ /dev/null
@@ -1,288 +0,0 @@
---- a/rt2/step7/show_ip_route.ref
-+++ b/rt2/step8/show_ip_route.ref
-@@ -15,10 +15,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16010
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16010
-+ ]
-+ }
- ]
- }
- ],
-@@ -38,10 +64,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16030
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16030
-+ ]
-+ }
- ]
- }
- ],
-@@ -61,6 +113,9 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
-@@ -71,10 +126,25 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.3",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16050,
-+ 16040
-+ ]
-+ }
- ]
- }
- ],
-@@ -93,21 +163,30 @@
- "ip":"10.0.1.3",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
-@@ -172,12 +251,40 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
- },
- {
- "ip":"10.0.1.3",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.2.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
-+ },
-+ {
-+ "ip":"10.0.3.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
-@@ -192,13 +299,30 @@
- {
- "ip":"10.0.2.4",
- "afi":"ipv4",
-- "interfaceName":"eth-rt4-1"
-+ "interfaceName":"eth-rt4-1",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.3",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
-@@ -214,12 +338,29 @@
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.3.4",
- "afi":"ipv4",
-- "interfaceName":"eth-rt4-2"
-+ "interfaceName":"eth-rt4-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.3",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
-@@ -356,14 +497,31 @@
- "ip":"10.0.2.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.3.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.3",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref
new file mode 100644
index 0000000..9543231
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051,
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref.diff
deleted file mode 100644
index 125f36b..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,139 +0,0 @@
---- a/rt2/step7/show_ipv6_route.ref
-+++ b/rt2/step8/show_ipv6_route.ref
-@@ -14,10 +14,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16011
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16011
-+ ]
-+ }
- ]
- }
- ],
-@@ -36,10 +60,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-1",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16031
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4-2",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16031
-+ ]
-+ }
- ]
- }
- ],
-@@ -58,6 +106,9 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt4-1",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
-@@ -67,10 +118,24 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt4-2",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16051,
-+ 16041
-+ ]
-+ }
- ]
- }
- ],
-@@ -88,19 +153,28 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref
new file mode 100644
index 0000000..8580cb0
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "installed":true,
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref.diff
deleted file mode 100644
index a1d5d79..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step8/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,207 +0,0 @@
---- a/rt2/step7/show_mpls_table.ref
-+++ b/rt2/step8/show_mpls_table.ref
-@@ -7,7 +7,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1"
-+ "nexthop":"10.0.1.1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.3.4"
- }
- ]
- },
-@@ -19,7 +35,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1"
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-2"
- }
- ]
- },
-@@ -31,7 +63,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.3"
-+ "nexthop":"10.0.1.3",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.3.4"
- }
- ]
- },
-@@ -43,7 +91,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1"
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4-2"
- }
- ]
- },
-@@ -55,13 +119,26 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.3.4"
-+ "nexthop":"10.0.3.4",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.2.4"
-+ "nexthop":"10.0.2.4",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.1.3"
- }
- ]
- },
-@@ -73,13 +150,74 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt4-2"
-+ "interface":"eth-rt4-2",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-+ "interface":"eth-rt4-1",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-sw1"
-+ }
-+ ]
-+ },
-+ "16050":{
-+ "inLabel":16050,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "installed":true,
-+ "nexthop":"10.0.3.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "installed":true,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "installed":true,
-+ "nexthop":"10.0.1.3"
-+ }
-+ ]
-+ },
-+ "16051":{
-+ "inLabel":16051,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "installed":true,
-+ "interface":"eth-rt4-2"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "installed":true,
- "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "installed":true,
-+ "interface":"eth-sw1"
- }
- ]
- },
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ip_route.ref
new file mode 100644
index 0000000..5096155
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16500,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16500,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16500,
+ 16030
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16500,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16500,
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt2/step9/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ip_route.ref.diff
deleted file mode 100644
index 2475c63..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ip_route.ref.diff
+++ /dev/null
@@ -1,119 +0,0 @@
---- a/rt2/step8/show_ip_route.ref
-+++ b/rt2/step9/show_ip_route.ref
-@@ -31,7 +31,7 @@
- "interfaceName":"eth-rt4-1",
- "active":true,
- "labels":[
-- 16050,
-+ 16500,
- 16010
- ]
- },
-@@ -41,7 +41,7 @@
- "interfaceName":"eth-rt4-2",
- "active":true,
- "labels":[
-- 16050,
-+ 16500,
- 16010
- ]
- }
-@@ -80,7 +80,7 @@
- "interfaceName":"eth-rt4-1",
- "active":true,
- "labels":[
-- 16050,
-+ 16500,
- 16030
- ]
- },
-@@ -90,7 +90,7 @@
- "interfaceName":"eth-rt4-2",
- "active":true,
- "labels":[
-- 16050,
-+ 16500,
- 16030
- ]
- }
-@@ -141,7 +141,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050,
-+ 16500,
- 16040
- ]
- }
-@@ -165,7 +165,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- },
- {
-@@ -175,7 +175,7 @@
- "interfaceName":"eth-rt4-1",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- },
- {
-@@ -185,7 +185,7 @@
- "interfaceName":"eth-rt4-2",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
-@@ -274,7 +274,7 @@
- "interfaceName":"eth-rt4-1",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- },
- {
-@@ -283,7 +283,7 @@
- "interfaceName":"eth-rt4-2",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
-@@ -321,7 +321,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
-@@ -359,7 +359,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
-@@ -520,7 +520,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref
new file mode 100644
index 0000000..50e6a0a
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16501,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16501,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16501,
+ 16031
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16501,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16501,
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16501
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "labels":[
+ 16501
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "labels":[
+ 16501
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref.diff
deleted file mode 100644
index 2d21fbc..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,74 +0,0 @@
---- a/rt2/step8/show_ipv6_route.ref
-+++ b/rt2/step9/show_ipv6_route.ref
-@@ -29,7 +29,7 @@
- "interfaceName":"eth-rt4-1",
- "active":true,
- "labels":[
-- 16051,
-+ 16501,
- 16011
- ]
- },
-@@ -38,7 +38,7 @@
- "interfaceName":"eth-rt4-2",
- "active":true,
- "labels":[
-- 16051,
-+ 16501,
- 16011
- ]
- }
-@@ -75,7 +75,7 @@
- "interfaceName":"eth-rt4-1",
- "active":true,
- "labels":[
-- 16051,
-+ 16501,
- 16031
- ]
- },
-@@ -84,7 +84,7 @@
- "interfaceName":"eth-rt4-2",
- "active":true,
- "labels":[
-- 16051,
-+ 16501,
- 16031
- ]
- }
-@@ -132,7 +132,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16051,
-+ 16501,
- 16041
- ]
- }
-@@ -155,7 +155,7 @@
- "interfaceName":"eth-rt4-1",
- "active":true,
- "labels":[
-- 16051
-+ 16501
- ]
- },
- {
-@@ -164,7 +164,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16051
-+ 16501
- ]
- },
- {
-@@ -173,7 +173,7 @@
- "interfaceName":"eth-rt4-2",
- "active":true,
- "labels":[
-- 16051
-+ 16501
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref
new file mode 100644
index 0000000..0bba135
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "interface":"eth-rt4-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "interface":"eth-rt4-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16500":{
+ "inLabel":16500,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "installed":true,
+ "nexthop":"10.0.1.3",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "installed":true,
+ "nexthop":"10.0.3.4",
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "installed":true,
+ "nexthop":"10.0.2.4",
+ "interface":"eth-rt4-1"
+ }
+ ]
+ },
+ "16501":{
+ "inLabel":16501,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "installed":true,
+ "interface":"eth-rt4-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "installed":true,
+ "interface":"eth-rt4-1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref.diff
deleted file mode 100644
index bc0ec31..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt2/step9/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,182 +0,0 @@
---- a/rt2/step8/show_mpls_table.ref
-+++ b/rt2/step9/show_mpls_table.ref
-@@ -17,12 +17,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-+ "outLabel":16500,
- "nexthop":"10.0.2.4"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-+ "outLabel":16500,
- "nexthop":"10.0.3.4"
- }
- ]
-@@ -45,12 +45,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-+ "outLabel":16501,
- "interface":"eth-rt4-1"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-+ "outLabel":16501,
- "interface":"eth-rt4-2"
- }
- ]
-@@ -73,12 +73,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-+ "outLabel":16500,
- "nexthop":"10.0.2.4"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-+ "outLabel":16500,
- "nexthop":"10.0.3.4"
- }
- ]
-@@ -101,12 +101,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-+ "outLabel":16501,
- "interface":"eth-rt4-1"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-+ "outLabel":16501,
- "interface":"eth-rt4-2"
- }
- ]
-@@ -137,7 +137,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-+ "outLabel":16500,
- "nexthop":"10.0.1.3"
- }
- ]
-@@ -168,55 +168,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-sw1"
-- }
-- ]
-- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.3.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.2.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "installed":true,
-- "nexthop":"10.0.1.3"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
-- "interface":"eth-rt4-2"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
-- "interface":"eth-rt4-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "installed":true,
-+ "outLabel":16501,
- "interface":"eth-sw1"
- }
- ]
-@@ -282,5 +234,53 @@
- "interface":"eth-sw1"
- }
- ]
-+ },
-+ "16500":{
-+ "inLabel":16500,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16500,
-+ "installed":true,
-+ "nexthop":"10.0.3.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16500,
-+ "installed":true,
-+ "nexthop":"10.0.2.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16500,
-+ "installed":true,
-+ "nexthop":"10.0.1.3"
-+ }
-+ ]
-+ },
-+ "16501":{
-+ "inLabel":16501,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16501,
-+ "installed":true,
-+ "interface":"eth-rt4-2"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16501,
-+ "installed":true,
-+ "interface":"eth-rt4-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16501,
-+ "installed":true,
-+ "interface":"eth-sw1"
-+ }
-+ ]
- }
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_ipv6_route.ref
index 058d336..45af4e0 100644
--- a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_ipv6_route.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_ipv6_route.ref
@@ -104,7 +104,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt5-1",
+ "interfaceName":"eth-rt5-2",
"active":true,
"labels":[
16041
@@ -113,7 +113,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-sw1",
+ "interfaceName":"eth-rt5-1",
"active":true,
"labels":[
16041
@@ -122,7 +122,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt5-2",
+ "interfaceName":"eth-sw1",
"active":true,
"labels":[
16041
@@ -144,7 +144,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt5-1",
+ "interfaceName":"eth-rt5-2",
"active":true,
"backupIndex":[
0
@@ -156,7 +156,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt5-2",
+ "interfaceName":"eth-rt5-1",
"active":true,
"backupIndex":[
0
@@ -192,7 +192,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt5-1",
+ "interfaceName":"eth-rt5-2",
"active":true,
"backupIndex":[
0
@@ -204,7 +204,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt5-2",
+ "interfaceName":"eth-rt5-1",
"active":true,
"backupIndex":[
0
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_mpls_table.ref
index 1912df3..1b12d04 100644
--- a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_mpls_table.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_mpls_table.ref
@@ -8,6 +8,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
"backupIndex":[
0,
1
@@ -18,12 +19,14 @@
{
"type":"SR (IS-IS)",
"outLabel":16040,
- "nexthop":"10.0.4.5"
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
},
{
"type":"SR (IS-IS)",
"outLabel":16040,
- "nexthop":"10.0.5.5"
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
}
]
},
@@ -64,6 +67,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
"backupIndex":[
0,
1
@@ -74,12 +78,14 @@
{
"type":"SR (IS-IS)",
"outLabel":16040,
- "nexthop":"10.0.4.5"
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
},
{
"type":"SR (IS-IS)",
"outLabel":16040,
- "nexthop":"10.0.5.5"
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
}
]
},
@@ -119,19 +125,22 @@
"type":"SR (IS-IS)",
"outLabel":16040,
"installed":true,
- "nexthop":"10.0.5.5"
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
},
{
"type":"SR (IS-IS)",
"outLabel":16040,
"installed":true,
- "nexthop":"10.0.4.5"
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
},
{
"type":"SR (IS-IS)",
"outLabel":16040,
"installed":true,
- "nexthop":"10.0.1.2"
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
}
]
},
@@ -143,19 +152,19 @@
"type":"SR (IS-IS)",
"outLabel":16041,
"installed":true,
- "interface":"eth-rt5-2"
+ "interface":"eth-sw1"
},
{
"type":"SR (IS-IS)",
"outLabel":16041,
"installed":true,
- "interface":"eth-rt5-1"
+ "interface":"eth-rt5-2"
},
{
"type":"SR (IS-IS)",
"outLabel":16041,
"installed":true,
- "interface":"eth-sw1"
+ "interface":"eth-rt5-1"
}
]
},
@@ -168,6 +177,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
"backupIndex":[
0
]
@@ -177,6 +187,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
"backupIndex":[
0
]
@@ -186,7 +197,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16040,
- "nexthop":"10.0.1.2"
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
}
]
},
@@ -230,6 +242,7 @@
"outLabel":16060,
"installed":true,
"nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
"backupIndex":[
0
]
@@ -239,6 +252,7 @@
"outLabel":16060,
"installed":true,
"nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
"backupIndex":[
0
]
@@ -248,7 +262,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16060,
- "nexthop":"10.0.1.2"
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
}
]
},
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref
index 777c749..2645827 100644
--- a/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step1/show_yang_interface_isis_adjacencies.ref
@@ -48,16 +48,16 @@
"adjacency": [
{
"neighbor-sys-type": "level-1",
- "neighbor-sysid": "0000.0000.0001",
+ "neighbor-sysid": "0000.0000.0002",
"hold-timer": 10,
- "neighbor-priority": 100,
+ "neighbor-priority": 64,
"state": "up"
},
{
"neighbor-sys-type": "level-1",
- "neighbor-sysid": "0000.0000.0002",
+ "neighbor-sysid": "0000.0000.0001",
"hold-timer": 10,
- "neighbor-priority": 64,
+ "neighbor-priority": 100,
"state": "up"
}
]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step10/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step10/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step10/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step10/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step10/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step10/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step10/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step10/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step10/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step11/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step11/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step11/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step11/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step11/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step11/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step11/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step11/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step11/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step12/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step12/show_ip_route.ref.diff
deleted file mode 100644
index 8695cf8..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step12/show_ip_route.ref.diff
+++ /dev/null
@@ -1,58 +0,0 @@
---- a/rt3/step11/show_ip_route.ref
-+++ b/rt3/step12/show_ip_route.ref
-@@ -198,44 +198,37 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":30,
-+ "metric":40,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
-- "ip":"10.0.4.5",
-+ "ip":"10.0.1.2",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5-1",
-+ "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
-- 30060
-+ 16060
- ]
- },
- {
- "fib":true,
-- "ip":"10.0.5.5",
-+ "ip":"10.0.4.5",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5-2",
-+ "interfaceName":"eth-rt5-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 30060
- ]
-- }
-- ],
-- "backupNexthops":[
-+ },
- {
-- "ip":"10.0.1.2",
-+ "fib":true,
-+ "ip":"10.0.5.5",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-+ "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16060
-+ 30060
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step12/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step12/show_ipv6_route.ref.diff
deleted file mode 100644
index 661d0fe..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step12/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,45 +0,0 @@
---- a/rt3/step11/show_ipv6_route.ref
-+++ b/rt3/step12/show_ipv6_route.ref
-@@ -186,7 +186,7 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":30,
-+ "metric":40,
- "installed":true,
- "nexthops":[
- {
-@@ -194,9 +194,6 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt5-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 30061
- ]
-@@ -206,23 +203,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt5-2",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 30061
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16061
-- ]
-- }
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step12/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step12/show_mpls_table.ref.diff
deleted file mode 100644
index 30941b3..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step12/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,60 +0,0 @@
---- a/rt3/step11/show_mpls_table.ref
-+++ b/rt3/step12/show_mpls_table.ref
-@@ -165,27 +165,8 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30060,
-- "installed":true,
-- "nexthop":"10.0.5.5",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30060,
-- "installed":true,
-- "nexthop":"10.0.4.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16060,
-+ "installed":true,
- "nexthop":"10.0.1.2"
- }
- ]
-@@ -196,27 +177,8 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30061,
-- "installed":true,
-- "interface":"eth-rt5-2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30061,
-- "installed":true,
-- "interface":"eth-rt5-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16061,
-+ "installed":true,
- "interface":"eth-sw1"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref
new file mode 100644
index 0000000..d70e9fe
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16020
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref
new file mode 100644
index 0000000..45af4e0
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16021
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref
new file mode 100644
index 0000000..1b12d04
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step2/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref
new file mode 100644
index 0000000..d70e9fe
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16020
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref
new file mode 100644
index 0000000..45af4e0
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16021
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref
new file mode 100644
index 0000000..1b12d04
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step3/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ip_route.ref
new file mode 100644
index 0000000..5f87799
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ip_route.ref
@@ -0,0 +1,405 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1"
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1"
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2"
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt3/step4/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ip_route.ref.diff
deleted file mode 100644
index 9ba73b0..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ip_route.ref.diff
+++ /dev/null
@@ -1,288 +0,0 @@
---- a/rt3/step3/show_ip_route.ref
-+++ b/rt3/step4/show_ip_route.ref
-@@ -15,36 +15,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.4.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "labels":[
-- 16040,
-- 16010
-- ]
-- },
-- {
-- "ip":"10.0.5.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "labels":[
-- 16040,
-- 16010
-- ]
-- }
- ]
- }
- ],
-@@ -64,36 +38,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.4.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "labels":[
-- 16040,
-- 16020
-- ]
-- },
-- {
-- "ip":"10.0.5.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "labels":[
-- 16040,
-- 16020
-- ]
-- }
- ]
- }
- ],
-@@ -112,30 +60,21 @@
- "ip":"10.0.1.2",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.4.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.5.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- }
- ]
- }
-@@ -156,9 +95,6 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
-@@ -169,25 +105,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16040,
-- 16050
-- ]
-- }
- ]
- }
- ],
-@@ -251,40 +172,12 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-+ "interfaceName":"eth-sw1"
- },
- {
- "ip":"10.0.1.2",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.4.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-- },
-- {
-- "ip":"10.0.5.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "interfaceName":"eth-sw1"
- }
- ]
- }
-@@ -375,30 +268,13 @@
- {
- "ip":"10.0.4.5",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5-1",
-- "backupIndex":[
-- 0
-- ]
-+ "interfaceName":"eth-rt5-1"
- },
- {
- "ip":"10.0.5.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- }
- ]
- }
-@@ -414,29 +290,12 @@
- "ip":"10.0.4.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-+ "active":true
- },
- {
- "ip":"10.0.5.5",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5-2",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "interfaceName":"eth-rt5-2"
- }
- ]
- }
-@@ -531,31 +390,14 @@
- "ip":"10.0.4.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.5.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.1.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref
new file mode 100644
index 0000000..9142640
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref
@@ -0,0 +1,155 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref.diff
deleted file mode 100644
index 04f61c4..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,139 +0,0 @@
---- a/rt3/step3/show_ipv6_route.ref
-+++ b/rt3/step4/show_ipv6_route.ref
-@@ -14,34 +14,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "labels":[
-- 16041,
-- 16011
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "labels":[
-- 16041,
-- 16011
-- ]
-- }
- ]
- }
- ],
-@@ -60,34 +36,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-- "backupIndex":[
-- 0,
-- 1
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "labels":[
-- 16041,
-- 16021
-- ]
-- },
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "labels":[
-- 16041,
-- 16021
-- ]
-- }
- ]
- }
- ],
-@@ -105,28 +57,19 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5-1",
-- "active":true,
-- "labels":[
-- 16041
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16041
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5-2",
-- "active":true,
-- "labels":[
-- 16041
-- ]
-+ "active":true
- }
- ]
- }
-@@ -146,9 +89,6 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt5-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
-@@ -158,24 +98,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt5-2",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-sw1",
-- "active":true,
-- "labels":[
-- 16041,
-- 16051
-- ]
-- }
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref
new file mode 100644
index 0000000..0a6e316
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref
@@ -0,0 +1,155 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref.diff
deleted file mode 100644
index b3588ca..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step4/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,206 +0,0 @@
---- a/rt3/step3/show_mpls_table.ref
-+++ b/rt3/step4/show_mpls_table.ref
-@@ -7,23 +7,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.4.5"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.5.5"
-+ "nexthop":"10.0.1.1"
- }
- ]
- },
-@@ -35,23 +19,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-rt5-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-rt5-2"
-+ "interface":"eth-sw1"
- }
- ]
- },
-@@ -63,23 +31,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.2",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.4.5"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.5.5"
-+ "nexthop":"10.0.1.2"
- }
- ]
- },
-@@ -91,70 +43,6 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1",
-- "backupIndex":[
-- 0,
-- 1
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-rt5-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-rt5-2"
-- }
-- ]
-- },
-- "16040":{
-- "inLabel":16040,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "installed":true,
-- "nexthop":"10.0.5.5"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "installed":true,
-- "nexthop":"10.0.4.5"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "installed":true,
-- "nexthop":"10.0.1.2"
-- }
-- ]
-- },
-- "16041":{
-- "inLabel":16041,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "installed":true,
-- "interface":"eth-rt5-2"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "installed":true,
-- "interface":"eth-rt5-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "installed":true,
- "interface":"eth-sw1"
- }
- ]
-@@ -167,26 +55,13 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.5.5",
-- "backupIndex":[
-- 0
-- ]
-+ "nexthop":"10.0.5.5"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.4.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.1.2"
-+ "nexthop":"10.0.4.5"
- }
- ]
- },
-@@ -198,26 +73,13 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt5-2",
-- "backupIndex":[
-- 0
-- ]
-+ "interface":"eth-rt5-2"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt5-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-sw1"
-+ "interface":"eth-rt5-1"
- }
- ]
- },
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref
new file mode 100644
index 0000000..d70e9fe
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16020
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040,
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref.diff
deleted file mode 100644
index 1af024f..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ip_route.ref.diff
+++ /dev/null
@@ -1,288 +0,0 @@
---- a/rt3/step4/show_ip_route.ref
-+++ b/rt3/step5/show_ip_route.ref
-@@ -15,10 +15,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.4.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5-1",
-+ "active":true,
-+ "labels":[
-+ 16040,
-+ 16010
-+ ]
-+ },
-+ {
-+ "ip":"10.0.5.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5-2",
-+ "active":true,
-+ "labels":[
-+ 16040,
-+ 16010
-+ ]
-+ }
- ]
- }
- ],
-@@ -38,10 +64,36 @@
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.4.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5-1",
-+ "active":true,
-+ "labels":[
-+ 16040,
-+ 16020
-+ ]
-+ },
-+ {
-+ "ip":"10.0.5.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5-2",
-+ "active":true,
-+ "labels":[
-+ 16040,
-+ 16020
-+ ]
-+ }
- ]
- }
- ],
-@@ -60,21 +112,30 @@
- "ip":"10.0.1.2",
- "afi":"ipv4",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.4.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.5.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
-@@ -95,6 +156,9 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
-@@ -105,10 +169,25 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16040,
-+ 16050
-+ ]
-+ }
- ]
- }
- ],
-@@ -172,12 +251,40 @@
- {
- "ip":"10.0.1.1",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
- },
- {
- "ip":"10.0.1.2",
- "afi":"ipv4",
-- "interfaceName":"eth-sw1"
-+ "interfaceName":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.4.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5-1",
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
-+ },
-+ {
-+ "ip":"10.0.5.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5-2",
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
-@@ -268,13 +375,30 @@
- {
- "ip":"10.0.4.5",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5-1"
-+ "interfaceName":"eth-rt5-1",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.5.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
-@@ -290,12 +414,29 @@
- "ip":"10.0.4.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.5.5",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5-2"
-+ "interfaceName":"eth-rt5-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
-@@ -390,14 +531,31 @@
- "ip":"10.0.4.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.5.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.1.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref
new file mode 100644
index 0000000..45af4e0
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16021
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041,
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref.diff
deleted file mode 100644
index 7cc79d0..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,139 +0,0 @@
---- a/rt3/step4/show_ipv6_route.ref
-+++ b/rt3/step5/show_ipv6_route.ref
-@@ -14,10 +14,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt5-1",
-+ "active":true,
-+ "labels":[
-+ 16041,
-+ 16011
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt5-2",
-+ "active":true,
-+ "labels":[
-+ 16041,
-+ 16011
-+ ]
-+ }
- ]
- }
- ],
-@@ -36,10 +60,34 @@
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
- "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt5-1",
-+ "active":true,
-+ "labels":[
-+ 16041,
-+ 16021
-+ ]
-+ },
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt5-2",
-+ "active":true,
-+ "labels":[
-+ 16041,
-+ 16021
-+ ]
-+ }
- ]
- }
- ],
-@@ -57,19 +105,28 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16041
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-sw1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16041
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16041
-+ ]
- }
- ]
- }
-@@ -89,6 +146,9 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt5-1",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
-@@ -98,10 +158,24 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt5-2",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-sw1",
-+ "active":true,
-+ "labels":[
-+ 16041,
-+ 16051
-+ ]
-+ }
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref
new file mode 100644
index 0000000..1b12d04
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref.diff
deleted file mode 100644
index 75a0f01..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step5/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,206 +0,0 @@
---- a/rt3/step4/show_mpls_table.ref
-+++ b/rt3/step5/show_mpls_table.ref
-@@ -7,7 +7,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.1"
-+ "nexthop":"10.0.1.1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.4.5"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.5.5"
- }
- ]
- },
-@@ -19,7 +35,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-sw1"
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-rt5-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-rt5-2"
- }
- ]
- },
-@@ -31,7 +63,23 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.1.2"
-+ "nexthop":"10.0.1.2",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.4.5"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.5.5"
- }
- ]
- },
-@@ -43,6 +91,70 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-+ "interface":"eth-sw1",
-+ "backupIndex":[
-+ 0,
-+ 1
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-rt5-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-rt5-2"
-+ }
-+ ]
-+ },
-+ "16040":{
-+ "inLabel":16040,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "installed":true,
-+ "nexthop":"10.0.5.5"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "installed":true,
-+ "nexthop":"10.0.4.5"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "installed":true,
-+ "nexthop":"10.0.1.2"
-+ }
-+ ]
-+ },
-+ "16041":{
-+ "inLabel":16041,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "installed":true,
-+ "interface":"eth-rt5-2"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "installed":true,
-+ "interface":"eth-rt5-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "installed":true,
- "interface":"eth-sw1"
- }
- ]
-@@ -55,13 +167,26 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.5.5"
-+ "nexthop":"10.0.5.5",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.4.5"
-+ "nexthop":"10.0.4.5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.1.2"
- }
- ]
- },
-@@ -73,13 +198,26 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt5-2"
-+ "interface":"eth-rt5-2",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt5-1"
-+ "interface":"eth-rt5-1",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-sw1"
- }
- ]
- },
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref
new file mode 100644
index 0000000..e6d99e5
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040,
+ 30050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref.diff
deleted file mode 100644
index c814a28..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ip_route.ref.diff
+++ /dev/null
@@ -1,101 +0,0 @@
---- a/rt3/step5/show_ip_route.ref
-+++ b/rt3/step6/show_ip_route.ref
-@@ -31,7 +31,7 @@
- "interfaceName":"eth-rt5-1",
- "active":true,
- "labels":[
-- 16040,
-+ 30040,
- 16010
- ]
- },
-@@ -41,7 +41,7 @@
- "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16040,
-+ 30040,
- 16010
- ]
- }
-@@ -80,7 +80,7 @@
- "interfaceName":"eth-rt5-1",
- "active":true,
- "labels":[
-- 16040,
-+ 30040,
- 16020
- ]
- },
-@@ -90,7 +90,7 @@
- "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16040,
-+ 30040,
- 16020
- ]
- }
-@@ -124,7 +124,7 @@
- "interfaceName":"eth-rt5-1",
- "active":true,
- "labels":[
-- 16040
-+ 30040
- ]
- },
- {
-@@ -134,7 +134,7 @@
- "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16040
-+ 30040
- ]
- }
- ]
-@@ -185,7 +185,7 @@
- "active":true,
- "labels":[
- 16040,
-- 16050
-+ 30050
- ]
- }
- ]
-@@ -211,7 +211,7 @@
- 0
- ],
- "labels":[
-- 16060
-+ 30060
- ]
- },
- {
-@@ -224,7 +224,7 @@
- 0
- ],
- "labels":[
-- 16060
-+ 30060
- ]
- }
- ],
-@@ -274,7 +274,7 @@
- "interfaceName":"eth-rt5-1",
- "active":true,
- "labels":[
-- 16040
-+ 30040
- ]
- },
- {
-@@ -283,7 +283,7 @@
- "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16040
-+ 30040
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref
new file mode 100644
index 0000000..f844d5a
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041,
+ 30051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref.diff
deleted file mode 100644
index 6f9405f..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,83 +0,0 @@
---- a/rt3/step5/show_ipv6_route.ref
-+++ b/rt3/step6/show_ipv6_route.ref
-@@ -29,7 +29,7 @@
- "interfaceName":"eth-rt5-1",
- "active":true,
- "labels":[
-- 16041,
-+ 30041,
- 16011
- ]
- },
-@@ -38,7 +38,7 @@
- "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16041,
-+ 30041,
- 16011
- ]
- }
-@@ -75,7 +75,7 @@
- "interfaceName":"eth-rt5-1",
- "active":true,
- "labels":[
-- 16041,
-+ 30041,
- 16021
- ]
- },
-@@ -84,7 +84,7 @@
- "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16041,
-+ 30041,
- 16021
- ]
- }
-@@ -107,7 +107,7 @@
- "interfaceName":"eth-rt5-1",
- "active":true,
- "labels":[
-- 16041
-+ 30041
- ]
- },
- {
-@@ -125,7 +125,7 @@
- "interfaceName":"eth-rt5-2",
- "active":true,
- "labels":[
-- 16041
-+ 30041
- ]
- }
- ]
-@@ -173,7 +173,7 @@
- "active":true,
- "labels":[
- 16041,
-- 16051
-+ 30051
- ]
- }
- ]
-@@ -198,7 +198,7 @@
- 0
- ],
- "labels":[
-- 16061
-+ 30061
- ]
- },
- {
-@@ -210,7 +210,7 @@
- 0
- ],
- "labels":[
-- 16061
-+ 30061
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref
new file mode 100644
index 0000000..052a5a1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref.diff
deleted file mode 100644
index d8c3968..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step6/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,130 +0,0 @@
---- a/rt3/step5/show_mpls_table.ref
-+++ b/rt3/step6/show_mpls_table.ref
-@@ -17,12 +17,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":30040,
- "nexthop":"10.0.4.5"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":30040,
- "nexthop":"10.0.5.5"
- }
- ]
-@@ -45,12 +45,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":30041,
- "interface":"eth-rt5-1"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":30041,
- "interface":"eth-rt5-2"
- }
- ]
-@@ -73,12 +73,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":30040,
- "nexthop":"10.0.4.5"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":30040,
- "nexthop":"10.0.5.5"
- }
- ]
-@@ -101,12 +101,12 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":30041,
- "interface":"eth-rt5-1"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":30041,
- "interface":"eth-rt5-2"
- }
- ]
-@@ -117,13 +117,13 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":30040,
- "installed":true,
- "nexthop":"10.0.5.5"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":30040,
- "installed":true,
- "nexthop":"10.0.4.5"
- },
-@@ -141,13 +141,13 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":30041,
- "installed":true,
- "interface":"eth-rt5-2"
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":30041,
- "installed":true,
- "interface":"eth-rt5-1"
- },
-@@ -227,7 +227,7 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16060,
-+ "outLabel":30060,
- "installed":true,
- "nexthop":"10.0.5.5",
- "backupIndex":[
-@@ -236,7 +236,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16060,
-+ "outLabel":30060,
- "installed":true,
- "nexthop":"10.0.4.5",
- "backupIndex":[
-@@ -258,7 +258,7 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16061,
-+ "outLabel":30061,
- "installed":true,
- "interface":"eth-rt5-2",
- "backupIndex":[
-@@ -267,7 +267,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16061,
-+ "outLabel":30061,
- "installed":true,
- "interface":"eth-rt5-1",
- "backupIndex":[
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref
new file mode 100644
index 0000000..fd340ba
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref
@@ -0,0 +1,556 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref.diff
deleted file mode 100644
index c928fcd..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ip_route.ref.diff
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/rt3/step6/show_ip_route.ref
-+++ b/rt3/step7/show_ip_route.ref
-@@ -158,9 +158,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- },
- {
-@@ -171,9 +168,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -184,8 +178,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16040,
-- 30050
-+ 16040
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref
new file mode 100644
index 0000000..27be692
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref
@@ -0,0 +1,222 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref.diff
deleted file mode 100644
index 0170971..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/rt3/step6/show_ipv6_route.ref
-+++ b/rt3/step7/show_ipv6_route.ref
-@@ -148,9 +148,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- },
- {
-@@ -160,9 +157,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -172,8 +166,7 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16041,
-- 30051
-+ 16041
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref
new file mode 100644
index 0000000..1d8d1d0
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref
@@ -0,0 +1,236 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref.diff
deleted file mode 100644
index d7a3ed9..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step7/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,71 +0,0 @@
---- a/rt3/step6/show_mpls_table.ref
-+++ b/rt3/step7/show_mpls_table.ref
-@@ -159,68 +159,6 @@
- }
- ]
- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.5.5",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.4.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.1.2"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt5-2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt5-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-sw1"
-- }
-- ]
-- },
- "16060":{
- "inLabel":16060,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref
new file mode 100644
index 0000000..e6d99e5
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040,
+ 30050
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref.diff
deleted file mode 100644
index 41a7ff3..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ip_route.ref.diff
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/rt3/step7/show_ip_route.ref
-+++ b/rt3/step8/show_ip_route.ref
-@@ -158,6 +158,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- },
- {
-@@ -168,6 +171,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -178,7 +184,8 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16040
-+ 16040,
-+ 30050
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref
new file mode 100644
index 0000000..f844d5a
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041,
+ 30051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref.diff
deleted file mode 100644
index bd49f86..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,32 +0,0 @@
---- a/rt3/step7/show_ipv6_route.ref
-+++ b/rt3/step8/show_ipv6_route.ref
-@@ -148,6 +148,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- },
- {
-@@ -157,6 +160,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -166,7 +172,8 @@
- "interfaceName":"eth-sw1",
- "active":true,
- "labels":[
-- 16041
-+ 16041,
-+ 30051
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref
new file mode 100644
index 0000000..052a5a1
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref.diff
deleted file mode 100644
index 4cc69b6..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step8/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,71 +0,0 @@
---- a/rt3/step7/show_mpls_table.ref
-+++ b/rt3/step8/show_mpls_table.ref
-@@ -159,6 +159,68 @@
- }
- ]
- },
-+ "16050":{
-+ "inLabel":16050,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.5.5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.4.5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.1.2"
-+ }
-+ ]
-+ },
-+ "16051":{
-+ "inLabel":16051,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt5-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt5-1",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-sw1"
-+ }
-+ ]
-+ },
- "16060":{
- "inLabel":16060,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref
new file mode 100644
index 0000000..a9590ee
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref
@@ -0,0 +1,563 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30040
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040,
+ 30500
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30060
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.1.1",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ },
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.1.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref.diff
deleted file mode 100644
index cc0a482..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ip_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt3/step8/show_ip_route.ref
-+++ b/rt3/step9/show_ip_route.ref
-@@ -185,7 +185,7 @@
- "active":true,
- "labels":[
- 16040,
-- 30050
-+ 30500
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref
new file mode 100644
index 0000000..ce63540
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref
@@ -0,0 +1,229 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ },
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16041,
+ 30501
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30061
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-sw1",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref.diff
deleted file mode 100644
index 650b982..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt3/step8/show_ipv6_route.ref
-+++ b/rt3/step9/show_ipv6_route.ref
-@@ -173,7 +173,7 @@
- "active":true,
- "labels":[
- 16041,
-- 30051
-+ 30501
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref
new file mode 100644
index 0000000..a364c2e
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.1",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-sw1",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5-2"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "installed":true,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "installed":true,
+ "interface":"eth-sw1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "installed":true,
+ "interface":"eth-rt5-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16500":{
+ "inLabel":16500,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.5",
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.5",
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.1.2",
+ "interface":"eth-sw1"
+ }
+ ]
+ },
+ "16501":{
+ "inLabel":16501,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-sw1"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref.diff
deleted file mode 100644
index 8ce4f1d..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt3/step9/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,133 +0,0 @@
---- a/rt3/step8/show_mpls_table.ref
-+++ b/rt3/step9/show_mpls_table.ref
-@@ -159,13 +159,13 @@
- }
- ]
- },
-- "16050":{
-- "inLabel":16050,
-+ "16060":{
-+ "inLabel":16060,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":30060,
- "installed":true,
- "nexthop":"10.0.5.5",
- "backupIndex":[
-@@ -174,7 +174,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":30060,
- "installed":true,
- "nexthop":"10.0.4.5",
- "backupIndex":[
-@@ -185,18 +185,18 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":16060,
- "nexthop":"10.0.1.2"
- }
- ]
- },
-- "16051":{
-- "inLabel":16051,
-+ "16061":{
-+ "inLabel":16061,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":30061,
- "installed":true,
- "interface":"eth-rt5-2",
- "backupIndex":[
-@@ -205,7 +205,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":30061,
- "installed":true,
- "interface":"eth-rt5-1",
- "backupIndex":[
-@@ -216,18 +216,18 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":16061,
- "interface":"eth-sw1"
- }
- ]
- },
-- "16060":{
-- "inLabel":16060,
-+ "16500":{
-+ "inLabel":16500,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30060,
-+ "outLabel":3,
- "installed":true,
- "nexthop":"10.0.5.5",
- "backupIndex":[
-@@ -236,7 +236,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":30060,
-+ "outLabel":3,
- "installed":true,
- "nexthop":"10.0.4.5",
- "backupIndex":[
-@@ -247,18 +247,18 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16060,
-+ "outLabel":16040,
- "nexthop":"10.0.1.2"
- }
- ]
- },
-- "16061":{
-- "inLabel":16061,
-+ "16501":{
-+ "inLabel":16501,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30061,
-+ "outLabel":3,
- "installed":true,
- "interface":"eth-rt5-2",
- "backupIndex":[
-@@ -267,7 +267,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":30061,
-+ "outLabel":3,
- "installed":true,
- "interface":"eth-rt5-1",
- "backupIndex":[
-@@ -278,7 +278,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16061,
-+ "outLabel":16041,
- "interface":"eth-sw1"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step1/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step1/show_ipv6_route.ref
index b640df3..c757031 100644
--- a/tests/topotests/isis_tilfa_topo1/rt4/step1/show_ipv6_route.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step1/show_ipv6_route.ref
@@ -12,7 +12,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt2-2",
+ "interfaceName":"eth-rt2-1",
"active":true,
"backupIndex":[
0
@@ -24,7 +24,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt2-1",
+ "interfaceName":"eth-rt2-2",
"active":true,
"backupIndex":[
0
@@ -59,7 +59,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt2-2",
+ "interfaceName":"eth-rt2-1",
"active":true,
"backupIndex":[
0
@@ -71,7 +71,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt2-1",
+ "interfaceName":"eth-rt2-2",
"active":true,
"backupIndex":[
0
@@ -107,7 +107,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt2-2",
+ "interfaceName":"eth-rt2-1",
"active":true,
"labels":[
16031
@@ -116,7 +116,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt2-1",
+ "interfaceName":"eth-rt2-2",
"active":true,
"labels":[
16031
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step1/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step1/show_mpls_table.ref
index f60937c..2a70907 100644
--- a/tests/topotests/isis_tilfa_topo1/rt4/step1/show_mpls_table.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step1/show_mpls_table.ref
@@ -8,6 +8,7 @@
"outLabel":16010,
"installed":true,
"nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
"backupIndex":[
0
]
@@ -17,6 +18,7 @@
"outLabel":16010,
"installed":true,
"nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
"backupIndex":[
0
]
@@ -26,7 +28,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16010,
- "nexthop":"10.0.6.5"
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
}
]
},
@@ -70,6 +73,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
"backupIndex":[
0
]
@@ -79,6 +83,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
"backupIndex":[
0
]
@@ -88,7 +93,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16030,
- "nexthop":"10.0.6.5"
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
}
]
},
@@ -131,19 +137,22 @@
"type":"SR (IS-IS)",
"outLabel":16030,
"installed":true,
- "nexthop":"10.0.3.2"
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
},
{
"type":"SR (IS-IS)",
"outLabel":16030,
"installed":true,
- "nexthop":"10.0.2.2"
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
},
{
"type":"SR (IS-IS)",
"outLabel":16030,
"installed":true,
- "nexthop":"10.0.6.5"
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
}
]
},
@@ -180,6 +189,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.6.5",
+ "interface":"eth-rt5",
"backupIndex":[
0
]
@@ -189,7 +199,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16050,
- "nexthop":"10.0.7.6"
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6"
}
]
},
@@ -224,6 +235,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
"backupIndex":[
0
]
@@ -233,7 +245,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16060,
- "nexthop":"10.0.6.5"
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
}
]
},
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step10/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step10/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step10/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step10/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step10/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step10/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step10/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step10/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step10/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step11/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step11/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step11/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step11/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step11/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step11/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step11/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step11/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step11/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step12/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step12/show_ip_route.ref.diff
deleted file mode 100644
index 2645c59..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step12/show_ip_route.ref.diff
+++ /dev/null
@@ -1,144 +0,0 @@
---- a/rt4/step11/show_ip_route.ref
-+++ b/rt4/step12/show_ip_route.ref
-@@ -160,23 +160,13 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "backupIndex":[
-- 0
-+ 0,
-+ 1
- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16500
-- ]
-- }
- ]
- }
- ],
-@@ -196,24 +186,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt6",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30060
-- ]
-- }
- ]
- }
- ],
-@@ -352,19 +328,12 @@
- "active":true,
- "backupIndex":[
- 0,
-- 1,
-- 2
-+ 1
- ]
- }
- ],
- "backupNexthops":[
- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- },
-- {
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-@@ -397,19 +366,12 @@
- "active":true,
- "backupIndex":[
- 0,
-- 1,
-- 2
-+ 1
- ]
- }
- ],
- "backupNexthops":[
- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- },
-- {
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-@@ -439,14 +401,6 @@
- 0
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- }
- ]
- }
- ],
-@@ -460,18 +414,7 @@
- {
- "ip":"10.0.7.6",
- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true
-+ "interfaceName":"eth-rt6"
- }
- ]
- }
-@@ -492,13 +435,6 @@
- "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/isis_tilfa_topo1/rt4/step12/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step12/show_ipv6_route.ref.diff
deleted file mode 100644
index 37e3185..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step12/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,50 +0,0 @@
---- a/rt4/step11/show_ipv6_route.ref
-+++ b/rt4/step12/show_ipv6_route.ref
-@@ -149,23 +149,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt5",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16501
-- ]
-- }
- ]
- }
- ],
-@@ -184,23 +171,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt6",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30061
-- ]
-- }
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step12/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step12/show_mpls_table.ref.diff
deleted file mode 100644
index 186291a..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step12/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,78 +0,0 @@
---- a/rt4/step11/show_mpls_table.ref
-+++ b/rt4/step12/show_mpls_table.ref
-@@ -179,17 +179,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.7.6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30060,
-- "nexthop":"10.0.6.5"
-+ "nexthop":"10.0.7.6"
- }
- ]
- },
-@@ -201,17 +191,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30061,
-- "interface":"eth-rt5"
-+ "interface":"eth-rt6"
- }
- ]
- },
-@@ -223,17 +203,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.6.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16500,
-- "nexthop":"10.0.7.6"
-+ "nexthop":"10.0.6.5"
- }
- ]
- },
-@@ -245,17 +215,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16501,
-- "interface":"eth-rt6"
-+ "interface":"eth-rt5"
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ip_route.ref
new file mode 100644
index 0000000..0ef5d1b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step2/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref
new file mode 100644
index 0000000..c757031
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16031,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref
new file mode 100644
index 0000000..2a70907
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step2/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ip_route.ref
new file mode 100644
index 0000000..0ef5d1b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step3/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref
new file mode 100644
index 0000000..c757031
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16031,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref
new file mode 100644
index 0000000..2a70907
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step3/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ip_route.ref
new file mode 100644
index 0000000..0f26fa5
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ip_route.ref
@@ -0,0 +1,296 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1"
+ },
+ {
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2"
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5"
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6"
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step4/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ip_route.ref.diff
deleted file mode 100644
index a941847..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ip_route.ref.diff
+++ /dev/null
@@ -1,367 +0,0 @@
---- a/rt4/step3/show_ip_route.ref
-+++ b/rt4/step4/show_ip_route.ref
-@@ -14,37 +14,14 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 16010
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 16010
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16010
-- ]
-+ "active":true
- }
- ]
- }
-@@ -64,38 +41,14 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16030,
-- 16020
-- ]
-+ "active":true
- }
- ]
- }
-@@ -115,30 +68,21 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "labels":[
-- 16030
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "labels":[
-- 16030
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16030
-- ]
-+ "active":true
- }
- ]
- }
-@@ -158,24 +102,7 @@
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
-@@ -195,24 +122,7 @@
- "ip":"10.0.7.6",
- "afi":"ipv4",
- "interfaceName":"eth-rt6",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16060
-- ]
-+ "active":true
- }
- ]
- }
-@@ -232,27 +142,13 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
- "active":true
- }
- ]
-@@ -268,30 +164,13 @@
- {
- "ip":"10.0.2.2",
- "afi":"ipv4",
-- "interfaceName":"eth-rt2-1",
-- "backupIndex":[
-- 0
-- ]
-+ "interfaceName":"eth-rt2-1"
- },
- {
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16030
-- ]
-+ "active":true
- }
- ]
- }
-@@ -307,29 +186,12 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-+ "active":true
- },
- {
- "ip":"10.0.3.2",
- "afi":"ipv4",
-- "interfaceName":"eth-rt2-2",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16030
-- ]
-+ "interfaceName":"eth-rt2-2"
- }
- ]
- }
-@@ -349,31 +211,6 @@
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0,
-- 1,
-- 2
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- },
-- {
-- "ip":"10.0.2.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt2-1",
-- "active":true
-- },
-- {
-- "ip":"10.0.3.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt2-2",
- "active":true
- }
- ]
-@@ -394,31 +231,6 @@
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0,
-- 1,
-- 2
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- },
-- {
-- "ip":"10.0.2.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt2-1",
-- "active":true
-- },
-- {
-- "ip":"10.0.3.2",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt2-2",
- "active":true
- }
- ]
-@@ -434,18 +246,7 @@
- {
- "ip":"10.0.6.5",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.7.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-+ "interfaceName":"eth-rt5"
- }
- ]
- }
-@@ -460,18 +261,7 @@
- {
- "ip":"10.0.7.6",
- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true
-+ "interfaceName":"eth-rt6"
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref
new file mode 100644
index 0000000..329fa39
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref
@@ -0,0 +1,121 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref.diff
deleted file mode 100644
index 991562a..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,161 +0,0 @@
---- a/rt4/step3/show_ipv6_route.ref
-+++ b/rt4/step4/show_ipv6_route.ref
-@@ -13,35 +13,13 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 16011
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 16011
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16011
-- ]
-+ "active":true
- }
- ]
- }
-@@ -60,36 +38,13 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16031,
-- 16021
-- ]
-+ "active":true
- }
- ]
- }
-@@ -108,28 +63,19 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-2",
-- "active":true,
-- "labels":[
-- 16031
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-1",
-- "active":true,
-- "labels":[
-- 16031
-- ]
-+ "active":true
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16031
-- ]
-+ "active":true
- }
- ]
- }
-@@ -148,23 +94,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- }
- ]
- }
-@@ -183,23 +113,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt6",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16061
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref
new file mode 100644
index 0000000..0967ef4
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref
@@ -0,0 +1 @@
+{}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref.diff
deleted file mode 100644
index 660d2fb..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step4/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,265 +0,0 @@
---- a/rt4/step3/show_mpls_table.ref
-+++ b/rt4/step4/show_mpls_table.ref
-@@ -1,262 +1,2 @@
- {
-- "16010":{
-- "inLabel":16010,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16010,
-- "installed":true,
-- "nexthop":"10.0.3.2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16010,
-- "installed":true,
-- "nexthop":"10.0.2.2",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16010,
-- "nexthop":"10.0.6.5"
-- }
-- ]
-- },
-- "16011":{
-- "inLabel":16011,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16011,
-- "installed":true,
-- "interface":"eth-rt2-2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16011,
-- "installed":true,
-- "interface":"eth-rt2-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16011,
-- "interface":"eth-rt5"
-- }
-- ]
-- },
-- "16020":{
-- "inLabel":16020,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.3.2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.2.2",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16030,
-- "nexthop":"10.0.6.5"
-- }
-- ]
-- },
-- "16021":{
-- "inLabel":16021,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt2-2",
-- "backupIndex":[
-- 0
-- ]
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt2-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16031,
-- "interface":"eth-rt5"
-- }
-- ]
-- },
-- "16030":{
-- "inLabel":16030,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16030,
-- "installed":true,
-- "nexthop":"10.0.3.2"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16030,
-- "installed":true,
-- "nexthop":"10.0.2.2"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16030,
-- "installed":true,
-- "nexthop":"10.0.6.5"
-- }
-- ]
-- },
-- "16031":{
-- "inLabel":16031,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16031,
-- "installed":true,
-- "interface":"eth-rt2-2"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16031,
-- "installed":true,
-- "interface":"eth-rt2-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16031,
-- "installed":true,
-- "interface":"eth-rt5"
-- }
-- ]
-- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.6.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.7.6"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt6"
-- }
-- ]
-- },
-- "16060":{
-- "inLabel":16060,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.7.6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16060,
-- "nexthop":"10.0.6.5"
-- }
-- ]
-- },
-- "16061":{
-- "inLabel":16061,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16061,
-- "interface":"eth-rt5"
-- }
-- ]
-- }
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ip_route.ref
new file mode 100644
index 0000000..0ef5d1b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step5/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ip_route.ref.diff
deleted file mode 100644
index 4385df2..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ip_route.ref.diff
+++ /dev/null
@@ -1,367 +0,0 @@
---- a/rt4/step4/show_ip_route.ref
-+++ b/rt4/step5/show_ip_route.ref
-@@ -14,14 +14,37 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 16010
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 16010
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16010
-+ ]
- }
- ]
- }
-@@ -41,14 +64,38 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16030,
-+ 16020
-+ ]
- }
- ]
- }
-@@ -68,21 +115,30 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16030
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16030
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16030
-+ ]
- }
- ]
- }
-@@ -102,7 +158,24 @@
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.7.6",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt6",
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
-@@ -122,7 +195,24 @@
- "ip":"10.0.7.6",
- "afi":"ipv4",
- "interfaceName":"eth-rt6",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16060
-+ ]
- }
- ]
- }
-@@ -142,13 +232,27 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "fib":true,
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5",
- "active":true
- }
- ]
-@@ -164,13 +268,30 @@
- {
- "ip":"10.0.2.2",
- "afi":"ipv4",
-- "interfaceName":"eth-rt2-1"
-+ "interfaceName":"eth-rt2-1",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.3.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16030
-+ ]
- }
- ]
- }
-@@ -186,12 +307,29 @@
- "ip":"10.0.2.2",
- "afi":"ipv4",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.3.2",
- "afi":"ipv4",
-- "interfaceName":"eth-rt2-2"
-+ "interfaceName":"eth-rt2-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16030
-+ ]
- }
- ]
- }
-@@ -211,6 +349,31 @@
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-+ "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1,
-+ 2
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.7.6",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt6",
-+ "active":true
-+ },
-+ {
-+ "ip":"10.0.2.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt2-1",
-+ "active":true
-+ },
-+ {
-+ "ip":"10.0.3.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt2-2",
- "active":true
- }
- ]
-@@ -231,6 +394,31 @@
- "ip":"10.0.6.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-+ "active":true,
-+ "backupIndex":[
-+ 0,
-+ 1,
-+ 2
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.7.6",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt6",
-+ "active":true
-+ },
-+ {
-+ "ip":"10.0.2.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt2-1",
-+ "active":true
-+ },
-+ {
-+ "ip":"10.0.3.2",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt2-2",
- "active":true
- }
- ]
-@@ -246,7 +434,18 @@
- {
- "ip":"10.0.6.5",
- "afi":"ipv4",
-- "interfaceName":"eth-rt5"
-+ "interfaceName":"eth-rt5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.7.6",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt6",
-+ "active":true
- }
- ]
- }
-@@ -261,7 +460,18 @@
- {
- "ip":"10.0.7.6",
- "afi":"ipv4",
-- "interfaceName":"eth-rt6"
-+ "interfaceName":"eth-rt6",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.5",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt5",
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref
new file mode 100644
index 0000000..c757031
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16031,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref.diff
deleted file mode 100644
index 54a1dc2..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,161 +0,0 @@
---- a/rt4/step4/show_ipv6_route.ref
-+++ b/rt4/step5/show_ipv6_route.ref
-@@ -13,13 +13,35 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 16011
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 16011
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16011
-+ ]
- }
- ]
- }
-@@ -38,13 +60,36 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16031,
-+ 16021
-+ ]
- }
- ]
- }
-@@ -63,19 +108,28 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-2",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16031
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt2-1",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16031
-+ ]
- },
- {
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16031
-+ ]
- }
- ]
- }
-@@ -94,7 +148,23 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt5",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt6",
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- }
- ]
- }
-@@ -113,7 +183,23 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt6",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
-+ "labels":[
-+ 3
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt5",
-+ "active":true,
-+ "labels":[
-+ 16061
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref
new file mode 100644
index 0000000..2a70907
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref.diff
deleted file mode 100644
index fb6a119..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step5/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,265 +0,0 @@
---- a/rt4/step4/show_mpls_table.ref
-+++ b/rt4/step5/show_mpls_table.ref
-@@ -1,2 +1,262 @@
- {
-+ "16010":{
-+ "inLabel":16010,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16010,
-+ "installed":true,
-+ "nexthop":"10.0.3.2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16010,
-+ "installed":true,
-+ "nexthop":"10.0.2.2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16010,
-+ "nexthop":"10.0.6.5"
-+ }
-+ ]
-+ },
-+ "16011":{
-+ "inLabel":16011,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16011,
-+ "installed":true,
-+ "interface":"eth-rt2-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16011,
-+ "installed":true,
-+ "interface":"eth-rt2-1",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16011,
-+ "interface":"eth-rt5"
-+ }
-+ ]
-+ },
-+ "16020":{
-+ "inLabel":16020,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.3.2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.2.2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16030,
-+ "nexthop":"10.0.6.5"
-+ }
-+ ]
-+ },
-+ "16021":{
-+ "inLabel":16021,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt2-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt2-1",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16031,
-+ "interface":"eth-rt5"
-+ }
-+ ]
-+ },
-+ "16030":{
-+ "inLabel":16030,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16030,
-+ "installed":true,
-+ "nexthop":"10.0.3.2"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16030,
-+ "installed":true,
-+ "nexthop":"10.0.2.2"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16030,
-+ "installed":true,
-+ "nexthop":"10.0.6.5"
-+ }
-+ ]
-+ },
-+ "16031":{
-+ "inLabel":16031,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16031,
-+ "installed":true,
-+ "interface":"eth-rt2-2"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16031,
-+ "installed":true,
-+ "interface":"eth-rt2-1"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16031,
-+ "installed":true,
-+ "interface":"eth-rt5"
-+ }
-+ ]
-+ },
-+ "16050":{
-+ "inLabel":16050,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.6.5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.7.6"
-+ }
-+ ]
-+ },
-+ "16051":{
-+ "inLabel":16051,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt6"
-+ }
-+ ]
-+ },
-+ "16060":{
-+ "inLabel":16060,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.7.6",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16060,
-+ "nexthop":"10.0.6.5"
-+ }
-+ ]
-+ },
-+ "16061":{
-+ "inLabel":16061,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt6",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16061,
-+ "interface":"eth-rt5"
-+ }
-+ ]
-+ }
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ip_route.ref
new file mode 100644
index 0000000..89e556e
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step6/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ip_route.ref.diff
deleted file mode 100644
index 9070414..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ip_route.ref.diff
+++ /dev/null
@@ -1,56 +0,0 @@
---- a/rt4/step5/show_ip_route.ref
-+++ b/rt4/step6/show_ip_route.ref
-@@ -43,7 +43,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16010
-+ 30010
- ]
- }
- ]
-@@ -93,7 +93,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16030,
-+ 30030,
- 16020
- ]
- }
-@@ -137,7 +137,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16030
-+ 30030
- ]
- }
- ]
-@@ -211,7 +211,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16060
-+ 30060
- ]
- }
- ]
-@@ -290,7 +290,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16030
-+ 30030
- ]
- }
- ]
-@@ -328,7 +328,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16030
-+ 30030
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref
new file mode 100644
index 0000000..12479fa
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref.diff
deleted file mode 100644
index 57a5764..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,38 +0,0 @@
---- a/rt4/step5/show_ipv6_route.ref
-+++ b/rt4/step6/show_ipv6_route.ref
-@@ -40,7 +40,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16011
-+ 30011
- ]
- }
- ]
-@@ -87,7 +87,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16031,
-+ 30031,
- 16021
- ]
- }
-@@ -128,7 +128,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16031
-+ 30031
- ]
- }
- ]
-@@ -198,7 +198,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16061
-+ 30061
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref
new file mode 100644
index 0000000..6693de7
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "interface":"eth-rt5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref.diff
deleted file mode 100644
index 94f8785..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step6/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,74 +0,0 @@
---- a/rt4/step5/show_mpls_table.ref
-+++ b/rt4/step6/show_mpls_table.ref
-@@ -25,7 +25,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16010,
-+ "outLabel":30010,
- "nexthop":"10.0.6.5"
- }
- ]
-@@ -56,7 +56,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16011,
-+ "outLabel":30011,
- "interface":"eth-rt5"
- }
- ]
-@@ -87,7 +87,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16030,
-+ "outLabel":30030,
- "nexthop":"10.0.6.5"
- }
- ]
-@@ -118,7 +118,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16031,
-+ "outLabel":30031,
- "interface":"eth-rt5"
- }
- ]
-@@ -141,7 +141,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16030,
-+ "outLabel":30030,
- "installed":true,
- "nexthop":"10.0.6.5"
- }
-@@ -165,7 +165,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16031,
-+ "outLabel":30031,
- "installed":true,
- "interface":"eth-rt5"
- }
-@@ -232,7 +232,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16060,
-+ "outLabel":30060,
- "nexthop":"10.0.6.5"
- }
- ]
-@@ -254,7 +254,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16061,
-+ "outLabel":30061,
- "interface":"eth-rt5"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ip_route.ref
new file mode 100644
index 0000000..f90e7f4
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ip_route.ref
@@ -0,0 +1,500 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step7/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ip_route.ref.diff
deleted file mode 100644
index e54873d..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ip_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt4/step6/show_ip_route.ref
-+++ b/rt4/step7/show_ip_route.ref
-@@ -161,9 +161,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -172,10 +169,7 @@
- "ip":"10.0.7.6",
- "afi":"ipv4",
- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref
new file mode 100644
index 0000000..f55d6ba
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref
@@ -0,0 +1,201 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref.diff
deleted file mode 100644
index 92e08f9..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt4/step6/show_ipv6_route.ref
-+++ b/rt4/step7/show_ipv6_route.ref
-@@ -151,9 +151,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -161,10 +158,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref
new file mode 100644
index 0000000..e6a73be
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref
@@ -0,0 +1,229 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "interface":"eth-rt5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref.diff
deleted file mode 100644
index fb614eb..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step7/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,53 +0,0 @@
---- a/rt4/step6/show_mpls_table.ref
-+++ b/rt4/step7/show_mpls_table.ref
-@@ -171,50 +171,6 @@
- }
- ]
- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.6.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.7.6"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt6"
-- }
-- ]
-- },
- "16060":{
- "inLabel":16060,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ip_route.ref
new file mode 100644
index 0000000..89e556e
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step8/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ip_route.ref.diff
deleted file mode 100644
index 252da6e..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ip_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt4/step7/show_ip_route.ref
-+++ b/rt4/step8/show_ip_route.ref
-@@ -161,6 +161,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -169,7 +172,10 @@
- "ip":"10.0.7.6",
- "afi":"ipv4",
- "interfaceName":"eth-rt6",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref
new file mode 100644
index 0000000..12479fa
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref.diff
deleted file mode 100644
index 7057d21..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt4/step7/show_ipv6_route.ref
-+++ b/rt4/step8/show_ipv6_route.ref
-@@ -151,6 +151,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -158,7 +161,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt6",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref
new file mode 100644
index 0000000..6693de7
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "interface":"eth-rt5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref.diff
deleted file mode 100644
index 3dc4303..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step8/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,53 +0,0 @@
---- a/rt4/step7/show_mpls_table.ref
-+++ b/rt4/step8/show_mpls_table.ref
-@@ -171,6 +171,50 @@
- }
- ]
- },
-+ "16050":{
-+ "inLabel":16050,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.6.5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.7.6"
-+ }
-+ ]
-+ },
-+ "16051":{
-+ "inLabel":16051,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt6"
-+ }
-+ ]
-+ },
- "16060":{
- "inLabel":16060,
- "installed":true,
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ip_route.ref
new file mode 100644
index 0000000..1a084c7
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030,
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "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":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.3.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30030
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.2.2",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt2-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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/isis_tilfa_topo1/rt4/step9/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ip_route.ref.diff
deleted file mode 100644
index 56f9cc5..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ip_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt4/step8/show_ip_route.ref
-+++ b/rt4/step9/show_ip_route.ref
-@@ -174,7 +174,7 @@
- "interfaceName":"eth-rt6",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref
new file mode 100644
index 0000000..1b08fde
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031,
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-1",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt2-2",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16501
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref.diff
deleted file mode 100644
index 41e5521..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt4/step8/show_ipv6_route.ref
-+++ b/rt4/step9/show_ipv6_route.ref
-@@ -163,7 +163,7 @@
- "interfaceName":"eth-rt6",
- "active":true,
- "labels":[
-- 16051
-+ 16501
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref
new file mode 100644
index 0000000..2c8ea08
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt2-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.3.2",
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.2.2",
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt2-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30060,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30061,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16500":{
+ "inLabel":16500,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "nexthop":"10.0.7.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16501":{
+ "inLabel":16501,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "interface":"eth-rt6"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref.diff
deleted file mode 100644
index 627e292..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt4/step9/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,110 +0,0 @@
---- a/rt4/step8/show_mpls_table.ref
-+++ b/rt4/step9/show_mpls_table.ref
-@@ -171,15 +171,15 @@
- }
- ]
- },
-- "16050":{
-- "inLabel":16050,
-+ "16060":{
-+ "inLabel":16060,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.6.5",
-+ "nexthop":"10.0.7.6",
- "backupIndex":[
- 0
- ]
-@@ -188,20 +188,20 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.7.6"
-+ "outLabel":30060,
-+ "nexthop":"10.0.6.5"
- }
- ]
- },
-- "16051":{
-- "inLabel":16051,
-+ "16061":{
-+ "inLabel":16061,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt5",
-+ "interface":"eth-rt6",
- "backupIndex":[
- 0
- ]
-@@ -210,20 +210,20 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt6"
-+ "outLabel":30061,
-+ "interface":"eth-rt5"
- }
- ]
- },
-- "16060":{
-- "inLabel":16060,
-+ "16500":{
-+ "inLabel":16500,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.7.6",
-+ "nexthop":"10.0.6.5",
- "backupIndex":[
- 0
- ]
-@@ -232,20 +232,20 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30060,
-- "nexthop":"10.0.6.5"
-+ "outLabel":16500,
-+ "nexthop":"10.0.7.6"
- }
- ]
- },
-- "16061":{
-- "inLabel":16061,
-+ "16501":{
-+ "inLabel":16501,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt6",
-+ "interface":"eth-rt5",
- "backupIndex":[
- 0
- ]
-@@ -254,8 +254,8 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30061,
-- "interface":"eth-rt5"
-+ "outLabel":16501,
-+ "interface":"eth-rt6"
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step1/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step1/show_ipv6_route.ref
index 6dafa69..168828d 100644
--- a/tests/topotests/isis_tilfa_topo1/rt5/step1/show_ipv6_route.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step1/show_ipv6_route.ref
@@ -12,7 +12,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt3-2",
+ "interfaceName":"eth-rt3-1",
"active":true,
"backupIndex":[
0
@@ -24,7 +24,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt3-1",
+ "interfaceName":"eth-rt3-2",
"active":true,
"backupIndex":[
0
@@ -59,7 +59,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt4",
+ "interfaceName":"eth-rt3-1",
"active":true,
"labels":[
16021
@@ -77,7 +77,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt3-1",
+ "interfaceName":"eth-rt4",
"active":true,
"labels":[
16021
@@ -99,7 +99,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt3-2",
+ "interfaceName":"eth-rt3-1",
"active":true,
"backupIndex":[
0
@@ -111,7 +111,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt3-1",
+ "interfaceName":"eth-rt3-2",
"active":true,
"backupIndex":[
0
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step1/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step1/show_mpls_table.ref
index 0c5861b..14de03d 100644
--- a/tests/topotests/isis_tilfa_topo1/rt5/step1/show_mpls_table.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step1/show_mpls_table.ref
@@ -8,6 +8,7 @@
"outLabel":16010,
"installed":true,
"nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
"backupIndex":[
0
]
@@ -17,6 +18,7 @@
"outLabel":16010,
"installed":true,
"nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
"backupIndex":[
0
]
@@ -26,7 +28,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16010,
- "nexthop":"10.0.6.4"
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
}
]
},
@@ -69,19 +72,22 @@
"type":"SR (IS-IS)",
"outLabel":16020,
"installed":true,
- "nexthop":"10.0.5.3"
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
},
{
"type":"SR (IS-IS)",
"outLabel":16020,
"installed":true,
- "nexthop":"10.0.4.3"
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
},
{
"type":"SR (IS-IS)",
"outLabel":16020,
"installed":true,
- "nexthop":"10.0.6.4"
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
}
]
},
@@ -118,6 +124,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
"backupIndex":[
0
]
@@ -127,6 +134,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
"backupIndex":[
0
]
@@ -136,7 +144,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16020,
- "nexthop":"10.0.6.4"
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
}
]
},
@@ -180,6 +189,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
"backupIndex":[
0
]
@@ -189,7 +199,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16040,
- "nexthop":"10.0.8.6"
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
}
]
},
@@ -224,6 +235,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
"backupIndex":[
0
]
@@ -233,7 +245,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16060,
- "nexthop":"10.0.6.4"
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
}
]
},
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref
new file mode 100644
index 0000000..ff8ace2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref
@@ -0,0 +1,485 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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"
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref
new file mode 100644
index 0000000..bc39e11
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref
@@ -0,0 +1,194 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref
new file mode 100644
index 0000000..8a339e6
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref
@@ -0,0 +1,301 @@
+{
+ "30010":{
+ "inLabel":30010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30011":{
+ "inLabel":30011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30020":{
+ "inLabel":30020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30021":{
+ "inLabel":30021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30030":{
+ "inLabel":30030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30031":{
+ "inLabel":30031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30040":{
+ "inLabel":30040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ }
+ ]
+ },
+ "30041":{
+ "inLabel":30041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt3-2"
+ }
+ ]
+ },
+ "30060":{
+ "inLabel":30060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ }
+ ]
+ },
+ "30061":{
+ "inLabel":30061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0,
+ 1
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt3-2"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step10/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step11/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step11/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step11/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step11/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step11/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step11/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step11/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step11/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step11/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step12/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step12/show_ip_route.ref.diff
deleted file mode 100644
index 3d21c04..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step12/show_ip_route.ref.diff
+++ /dev/null
@@ -1,151 +0,0 @@
---- a/rt5/step11/show_ip_route.ref
-+++ b/rt5/step12/show_ip_route.ref
-@@ -159,24 +159,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.8.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-- }
- ]
- }
- ],
-@@ -187,25 +173,11 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":20,
-+ "metric":30,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
-- "ip":"10.0.8.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
- "ip":"10.0.6.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-@@ -276,19 +248,12 @@
- "active":true,
- "backupIndex":[
- 0,
-- 1,
-- 2
-+ 1
- ]
- }
- ],
- "backupNexthops":[
- {
-- "ip":"10.0.8.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- },
-- {
- "ip":"10.0.4.3",
- "afi":"ipv4",
- "interfaceName":"eth-rt3-1",
-@@ -321,19 +286,12 @@
- "active":true,
- "backupIndex":[
- 0,
-- 1,
-- 2
-+ 1
- ]
- }
- ],
- "backupNexthops":[
- {
-- "ip":"10.0.8.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- },
-- {
- "ip":"10.0.4.3",
- "afi":"ipv4",
- "interfaceName":"eth-rt3-1",
-@@ -439,14 +397,6 @@
- 0
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.8.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "active":true
-- }
- ]
- }
- ],
-@@ -465,39 +415,6 @@
- "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":"isis",
-- "distance":115,
-- "metric":20,
-- "nexthops":[
-- {
-- "ip":"10.0.8.6",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4",
- "active":true
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step12/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step12/show_ipv6_route.ref.diff
deleted file mode 100644
index 66a9dac..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step12/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,53 +0,0 @@
---- a/rt5/step11/show_ipv6_route.ref
-+++ b/rt5/step12/show_ipv6_route.ref
-@@ -149,23 +149,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16041
-- ]
-- }
- ]
- }
- ],
-@@ -176,25 +163,12 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":20,
-+ "metric":30,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
- "afi":"ipv6",
-- "interfaceName":"eth-rt6",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
- "interfaceName":"eth-rt4",
- "active":true,
- "labels":[
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step12/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step12/show_mpls_table.ref.diff
deleted file mode 100644
index cdfc407..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step12/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,80 +0,0 @@
---- a/rt5/step11/show_mpls_table.ref
-+++ b/rt5/step12/show_mpls_table.ref
-@@ -179,17 +179,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.6.4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.8.6"
-+ "nexthop":"10.0.6.4"
- }
- ]
- },
-@@ -201,17 +191,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-rt6"
-+ "interface":"eth-rt4"
- }
- ]
- },
-@@ -221,18 +201,8 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.8.6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16060,
-+ "installed":true,
- "nexthop":"10.0.6.4"
- }
- ]
-@@ -243,18 +213,8 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt6",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16061,
-+ "installed":true,
- "interface":"eth-rt4"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref
new file mode 100644
index 0000000..93740e2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref
new file mode 100644
index 0000000..168828d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref
new file mode 100644
index 0000000..14de03d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step2/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref
new file mode 100644
index 0000000..93740e2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref
new file mode 100644
index 0000000..168828d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref
new file mode 100644
index 0000000..14de03d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step3/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref
new file mode 100644
index 0000000..b5bd8c7
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref
@@ -0,0 +1,439 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "6.6.6.6\/32":[
+ {
+ "prefix":"6.6.6.6\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1"
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2"
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref.diff
deleted file mode 100644
index 7545a31..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ip_route.ref.diff
+++ /dev/null
@@ -1,161 +0,0 @@
---- a/rt5/step3/show_ip_route.ref
-+++ b/rt5/step4/show_ip_route.ref
-@@ -41,10 +41,7 @@
- "ip":"10.0.6.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16010
-- ]
-+ "active":true
- }
- ]
- }
-@@ -84,10 +81,7 @@
- "ip":"10.0.6.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16020
-- ]
-+ "active":true
- }
- ]
- }
-@@ -108,9 +102,6 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt3-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
-@@ -121,25 +112,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt3-2",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16020,
-- 16030
-- ]
-- }
- ]
- }
- ],
-@@ -161,9 +137,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -172,10 +145,7 @@
- "ip":"10.0.8.6",
- "afi":"ipv4",
- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- }
- ]
- }
-@@ -209,10 +179,7 @@
- "ip":"10.0.6.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16060
-- ]
-+ "active":true
- }
- ]
- }
-@@ -358,30 +325,13 @@
- {
- "ip":"10.0.4.3",
- "afi":"ipv4",
-- "interfaceName":"eth-rt3-1",
-- "backupIndex":[
-- 0
-- ]
-+ "interfaceName":"eth-rt3-1"
- },
- {
- "ip":"10.0.5.3",
- "afi":"ipv4",
- "interfaceName":"eth-rt3-2",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16020
-- ]
-+ "active":true
- }
- ]
- }
-@@ -397,29 +347,12 @@
- "ip":"10.0.4.3",
- "afi":"ipv4",
- "interfaceName":"eth-rt3-1",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-+ "active":true
- },
- {
- "ip":"10.0.5.3",
- "afi":"ipv4",
-- "interfaceName":"eth-rt3-2",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.6.4",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16020
-- ]
-+ "interfaceName":"eth-rt3-2"
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref
new file mode 100644
index 0000000..647add8
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref
@@ -0,0 +1,175 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 3
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref.diff
deleted file mode 100644
index 1de62bb..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,95 +0,0 @@
---- a/rt5/step3/show_ipv6_route.ref
-+++ b/rt5/step4/show_ipv6_route.ref
-@@ -38,10 +38,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16011
-- ]
-+ "active":true
- }
- ]
- }
-@@ -60,10 +57,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16021
-- ]
-+ "active":true
- },
- {
- "fib":true,
-@@ -101,9 +95,6 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt3-2",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
-@@ -113,24 +104,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt3-1",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16021,
-- 16031
-- ]
-- }
- ]
- }
- ],
-@@ -151,9 +128,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -161,10 +135,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt6",
-- "active":true,
-- "labels":[
-- 16041
-- ]
-+ "active":true
- }
- ]
- }
-@@ -196,10 +167,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16061
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref
new file mode 100644
index 0000000..cfb0bf2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref
@@ -0,0 +1,189 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref.diff
deleted file mode 100644
index b3d5252..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step4/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,166 +0,0 @@
---- a/rt5/step3/show_mpls_table.ref
-+++ b/rt5/step4/show_mpls_table.ref
-@@ -25,7 +25,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16010,
-+ "outLabel":3,
- "nexthop":"10.0.6.4"
- }
- ]
-@@ -56,7 +56,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16011,
-+ "outLabel":3,
- "interface":"eth-rt4"
- }
- ]
-@@ -76,12 +76,6 @@
- "outLabel":16020,
- "installed":true,
- "nexthop":"10.0.4.3"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16020,
-- "installed":true,
-- "nexthop":"10.0.6.4"
- }
- ]
- },
-@@ -100,12 +94,6 @@
- "outLabel":16021,
- "installed":true,
- "interface":"eth-rt3-1"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16021,
-- "installed":true,
-- "interface":"eth-rt4"
- }
- ]
- },
-@@ -117,26 +105,13 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.5.3",
-- "backupIndex":[
-- 0
-- ]
-+ "nexthop":"10.0.5.3"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.4.3",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16020,
-- "nexthop":"10.0.6.4"
-+ "nexthop":"10.0.4.3"
- }
- ]
- },
-@@ -148,70 +123,13 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt3-2",
-- "backupIndex":[
-- 0
-- ]
-+ "interface":"eth-rt3-2"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt3-1",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16021,
-- "interface":"eth-rt4"
-- }
-- ]
-- },
-- "16040":{
-- "inLabel":16040,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.6.4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.8.6"
-- }
-- ]
-- },
-- "16041":{
-- "inLabel":16041,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-rt6"
-+ "interface":"eth-rt3-1"
- }
- ]
- },
-@@ -232,7 +150,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16060,
-+ "outLabel":3,
- "nexthop":"10.0.6.4"
- }
- ]
-@@ -254,7 +172,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16061,
-+ "outLabel":3,
- "interface":"eth-rt4"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref
new file mode 100644
index 0000000..93740e2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref.diff
deleted file mode 100644
index be5d83f..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ip_route.ref.diff
+++ /dev/null
@@ -1,161 +0,0 @@
---- a/rt5/step4/show_ip_route.ref
-+++ b/rt5/step5/show_ip_route.ref
-@@ -41,7 +41,10 @@
- "ip":"10.0.6.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16010
-+ ]
- }
- ]
- }
-@@ -81,7 +84,10 @@
- "ip":"10.0.6.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16020
-+ ]
- }
- ]
- }
-@@ -102,6 +108,9 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt3-1",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
-@@ -112,10 +121,25 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt3-2",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4",
-+ "active":true,
-+ "labels":[
-+ 16020,
-+ 16030
-+ ]
-+ }
- ]
- }
- ],
-@@ -137,6 +161,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -145,7 +172,10 @@
- "ip":"10.0.8.6",
- "afi":"ipv4",
- "interfaceName":"eth-rt6",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
-@@ -179,7 +209,10 @@
- "ip":"10.0.6.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16060
-+ ]
- }
- ]
- }
-@@ -325,13 +358,30 @@
- {
- "ip":"10.0.4.3",
- "afi":"ipv4",
-- "interfaceName":"eth-rt3-1"
-+ "interfaceName":"eth-rt3-1",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.5.3",
- "afi":"ipv4",
- "interfaceName":"eth-rt3-2",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4",
-+ "active":true,
-+ "labels":[
-+ 16020
-+ ]
- }
- ]
- }
-@@ -347,12 +397,29 @@
- "ip":"10.0.4.3",
- "afi":"ipv4",
- "interfaceName":"eth-rt3-1",
-- "active":true
-+ "active":true,
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "ip":"10.0.5.3",
- "afi":"ipv4",
-- "interfaceName":"eth-rt3-2"
-+ "interfaceName":"eth-rt3-2",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "ip":"10.0.6.4",
-+ "afi":"ipv4",
-+ "interfaceName":"eth-rt4",
-+ "active":true,
-+ "labels":[
-+ 16020
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref
new file mode 100644
index 0000000..168828d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref.diff
deleted file mode 100644
index a856019..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,95 +0,0 @@
---- a/rt5/step4/show_ipv6_route.ref
-+++ b/rt5/step5/show_ipv6_route.ref
-@@ -38,7 +38,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16011
-+ ]
- }
- ]
- }
-@@ -57,7 +60,10 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16021
-+ ]
- },
- {
- "fib":true,
-@@ -95,6 +101,9 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt3-2",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
-@@ -104,10 +113,24 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt3-1",
- "active":true,
-+ "backupIndex":[
-+ 0
-+ ],
- "labels":[
- 3
- ]
- }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "afi":"ipv6",
-+ "interfaceName":"eth-rt4",
-+ "active":true,
-+ "labels":[
-+ 16021,
-+ 16031
-+ ]
-+ }
- ]
- }
- ],
-@@ -128,6 +151,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -135,7 +161,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt6",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16041
-+ ]
- }
- ]
- }
-@@ -167,7 +196,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16061
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref
new file mode 100644
index 0000000..d40be3d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "16060":{
+ "inLabel":16060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16061":{
+ "inLabel":16061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref.diff
deleted file mode 100644
index 74caa86..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step5/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,166 +0,0 @@
---- a/rt5/step4/show_mpls_table.ref
-+++ b/rt5/step5/show_mpls_table.ref
-@@ -25,7 +25,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16010,
- "nexthop":"10.0.6.4"
- }
- ]
-@@ -56,7 +56,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16011,
- "interface":"eth-rt4"
- }
- ]
-@@ -69,6 +69,12 @@
- "type":"SR (IS-IS)",
- "outLabel":16020,
- "installed":true,
-+ "nexthop":"10.0.6.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16020,
-+ "installed":true,
- "nexthop":"10.0.5.3"
- },
- {
-@@ -87,6 +93,12 @@
- "type":"SR (IS-IS)",
- "outLabel":16021,
- "installed":true,
-+ "interface":"eth-rt4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16021,
-+ "installed":true,
- "interface":"eth-rt3-2"
- },
- {
-@@ -105,13 +117,26 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.5.3"
-+ "nexthop":"10.0.5.3",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.4.3"
-+ "nexthop":"10.0.4.3",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16020,
-+ "nexthop":"10.0.6.4"
- }
- ]
- },
-@@ -123,13 +148,70 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt3-2"
-+ "interface":"eth-rt3-2",
-+ "backupIndex":[
-+ 0
-+ ]
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt3-1"
-+ "interface":"eth-rt3-1",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16021,
-+ "interface":"eth-rt4"
-+ }
-+ ]
-+ },
-+ "16040":{
-+ "inLabel":16040,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.6.4",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.8.6"
-+ }
-+ ]
-+ },
-+ "16041":{
-+ "inLabel":16041,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt4",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-rt6"
- }
- ]
- },
-@@ -150,7 +232,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16060,
- "nexthop":"10.0.6.4"
- }
- ]
-@@ -172,7 +254,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16061,
- "interface":"eth-rt4"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref
new file mode 100644
index 0000000..93740e2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref
new file mode 100644
index 0000000..168828d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref
new file mode 100644
index 0000000..a21038b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "30010":{
+ "inLabel":30010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30011":{
+ "inLabel":30011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30020":{
+ "inLabel":30020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30021":{
+ "inLabel":30021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30030":{
+ "inLabel":30030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30031":{
+ "inLabel":30031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30040":{
+ "inLabel":30040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30041":{
+ "inLabel":30041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30060":{
+ "inLabel":30060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30061":{
+ "inLabel":30061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref.diff
deleted file mode 100644
index 2883c04..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step6/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,146 +0,0 @@
---- a/rt5/step5/show_mpls_table.ref
-+++ b/rt5/step6/show_mpls_table.ref
-@@ -1,6 +1,6 @@
- {
-- "16010":{
-- "inLabel":16010,
-+ "30010":{
-+ "inLabel":30010,
- "installed":true,
- "nexthops":[
- {
-@@ -30,8 +30,8 @@
- }
- ]
- },
-- "16011":{
-- "inLabel":16011,
-+ "30011":{
-+ "inLabel":30011,
- "installed":true,
- "nexthops":[
- {
-@@ -61,56 +61,56 @@
- }
- ]
- },
-- "16020":{
-- "inLabel":16020,
-+ "30020":{
-+ "inLabel":30020,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
- "outLabel":16020,
- "installed":true,
-- "nexthop":"10.0.6.4"
-+ "nexthop":"10.0.5.3"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":16020,
- "installed":true,
-- "nexthop":"10.0.5.3"
-+ "nexthop":"10.0.4.3"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":16020,
- "installed":true,
-- "nexthop":"10.0.4.3"
-+ "nexthop":"10.0.6.4"
- }
- ]
- },
-- "16021":{
-- "inLabel":16021,
-+ "30021":{
-+ "inLabel":30021,
- "installed":true,
- "nexthops":[
- {
- "type":"SR (IS-IS)",
- "outLabel":16021,
- "installed":true,
-- "interface":"eth-rt4"
-+ "interface":"eth-rt3-2"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":16021,
- "installed":true,
-- "interface":"eth-rt3-2"
-+ "interface":"eth-rt3-1"
- },
- {
- "type":"SR (IS-IS)",
- "outLabel":16021,
- "installed":true,
-- "interface":"eth-rt3-1"
-+ "interface":"eth-rt4"
- }
- ]
- },
-- "16030":{
-- "inLabel":16030,
-+ "30030":{
-+ "inLabel":30030,
- "installed":true,
- "nexthops":[
- {
-@@ -140,8 +140,8 @@
- }
- ]
- },
-- "16031":{
-- "inLabel":16031,
-+ "30031":{
-+ "inLabel":30031,
- "installed":true,
- "nexthops":[
- {
-@@ -171,8 +171,8 @@
- }
- ]
- },
-- "16040":{
-- "inLabel":16040,
-+ "30040":{
-+ "inLabel":30040,
- "installed":true,
- "nexthops":[
- {
-@@ -193,8 +193,8 @@
- }
- ]
- },
-- "16041":{
-- "inLabel":16041,
-+ "30041":{
-+ "inLabel":30041,
- "installed":true,
- "nexthops":[
- {
-@@ -215,8 +215,8 @@
- }
- ]
- },
-- "16060":{
-- "inLabel":16060,
-+ "30060":{
-+ "inLabel":30060,
- "installed":true,
- "nexthops":[
- {
-@@ -237,8 +237,8 @@
- }
- ]
- },
-- "16061":{
-- "inLabel":16061,
-+ "30061":{
-+ "inLabel":30061,
- "installed":true,
- "nexthops":[
- {
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref
new file mode 100644
index 0000000..93740e2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref
new file mode 100644
index 0000000..168828d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref
new file mode 100644
index 0000000..a21038b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "30010":{
+ "inLabel":30010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30011":{
+ "inLabel":30011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30020":{
+ "inLabel":30020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30021":{
+ "inLabel":30021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30030":{
+ "inLabel":30030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30031":{
+ "inLabel":30031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30040":{
+ "inLabel":30040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30041":{
+ "inLabel":30041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30060":{
+ "inLabel":30060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30061":{
+ "inLabel":30061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step7/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref
new file mode 100644
index 0000000..93740e2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref
new file mode 100644
index 0000000..168828d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref
new file mode 100644
index 0000000..a21038b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "30010":{
+ "inLabel":30010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30011":{
+ "inLabel":30011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30020":{
+ "inLabel":30020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30021":{
+ "inLabel":30021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30030":{
+ "inLabel":30030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30031":{
+ "inLabel":30031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30040":{
+ "inLabel":30040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30041":{
+ "inLabel":30041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30060":{
+ "inLabel":30060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30061":{
+ "inLabel":30061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step8/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref
new file mode 100644
index 0000000..93740e2
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref
@@ -0,0 +1,506 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16010
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ },
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020,
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16060
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "fib":true,
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.2.0\/24":[
+ {
+ "prefix":"10.0.2.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0,
+ 1,
+ 2
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ },
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.4.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "ip":"10.0.5.3",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.7.0\/24":[
+ {
+ "prefix":"10.0.7.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.6",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.6.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref
new file mode 100644
index 0000000..168828d
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref
@@ -0,0 +1,207 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16011
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-1",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt3-2",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16021,
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::6\/128":[
+ {
+ "prefix":"2001:db8:1000::6\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt6",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16061
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref
new file mode 100644
index 0000000..a21038b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref
@@ -0,0 +1,275 @@
+{
+ "30010":{
+ "inLabel":30010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30011":{
+ "inLabel":30011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30020":{
+ "inLabel":30020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30021":{
+ "inLabel":30021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-2"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt3-1"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30030":{
+ "inLabel":30030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.5.3",
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.4.3",
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30031":{
+ "inLabel":30031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-2",
+ "backupIndex":[
+ 0
+ ]
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt3-1",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30040":{
+ "inLabel":30040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30041":{
+ "inLabel":30041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt6"
+ }
+ ]
+ },
+ "30060":{
+ "inLabel":30060,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.6",
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16060,
+ "nexthop":"10.0.6.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "30061":{
+ "inLabel":30061,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt6",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16061,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt5/step9/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step1/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step1/show_ipv6_route.ref
index 1b19429..de31816 100644
--- a/tests/topotests/isis_tilfa_topo1/rt6/step1/show_ipv6_route.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step1/show_ipv6_route.ref
@@ -12,7 +12,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt4",
+ "interfaceName":"eth-rt5",
"active":true,
"labels":[
16011
@@ -21,7 +21,7 @@
{
"fib":true,
"afi":"ipv6",
- "interfaceName":"eth-rt5",
+ "interfaceName":"eth-rt4",
"active":true,
"labels":[
16011
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step1/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step1/show_mpls_table.ref
index 5b52a16..4bd85c3 100644
--- a/tests/topotests/isis_tilfa_topo1/rt6/step1/show_mpls_table.ref
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step1/show_mpls_table.ref
@@ -7,13 +7,15 @@
"type":"SR (IS-IS)",
"outLabel":16010,
"installed":true,
- "nexthop":"10.0.8.5"
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
},
{
"type":"SR (IS-IS)",
"outLabel":16010,
"installed":true,
- "nexthop":"10.0.7.4"
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
}
]
},
@@ -44,6 +46,7 @@
"outLabel":16020,
"installed":true,
"nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
"backupIndex":[
0
]
@@ -53,7 +56,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16020,
- "nexthop":"10.0.8.5"
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
}
]
},
@@ -88,6 +92,7 @@
"outLabel":16030,
"installed":true,
"nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
"backupIndex":[
0
]
@@ -97,7 +102,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16030,
- "nexthop":"10.0.7.4"
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
}
]
},
@@ -132,6 +138,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
"backupIndex":[
0
]
@@ -141,7 +148,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16040,
- "nexthop":"10.0.8.5"
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
}
]
},
@@ -176,6 +184,7 @@
"outLabel":3,
"installed":true,
"nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
"backupIndex":[
0
]
@@ -185,7 +194,8 @@
{
"type":"SR (IS-IS)",
"outLabel":16050,
- "nexthop":"10.0.7.4"
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
}
]
},
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_down.ref b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_down.ref
new file mode 100644
index 0000000..2b573d0
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_down.ref
@@ -0,0 +1,6 @@
+{
+ "multihop":false,
+ "peer":"10.0.8.5",
+ "interface":"eth-rt5",
+ "status":"down"
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_up.ref b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_up.ref
new file mode 100644
index 0000000..f536b36
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_bfd_peer_up.ref
@@ -0,0 +1,6 @@
+{
+ "multihop":false,
+ "peer":"10.0.8.5",
+ "interface":"eth-rt5",
+ "status":"up"
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref
new file mode 100644
index 0000000..822e24b
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref
@@ -0,0 +1,354 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":30,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref
new file mode 100644
index 0000000..7a87f44
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref
@@ -0,0 +1,147 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16501
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref
new file mode 100644
index 0000000..6e4a783
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref
@@ -0,0 +1,127 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16500":{
+ "inLabel":16500,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16501":{
+ "inLabel":16501,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step10/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step11/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step11/show_ip_route.ref.diff
deleted file mode 100644
index e477e87..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step11/show_ip_route.ref.diff
+++ /dev/null
@@ -1,125 +0,0 @@
---- a/rt6/step10/show_ip_route.ref
-+++ b/rt6/step11/show_ip_route.ref
-@@ -76,25 +76,11 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":30,
-+ "metric":40,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 30030
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-@@ -150,25 +136,11 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":20,
-+ "metric":30,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-@@ -276,22 +248,11 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":20,
-+ "metric":30,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-@@ -307,22 +268,11 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":20,
-+ "metric":30,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-@@ -389,19 +339,9 @@
- "prefix":"10.0.8.0\/24",
- "protocol":"isis",
- "distance":115,
-- "metric":20,
-+ "metric":30,
- "nexthops":[
- {
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step11/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step11/show_ipv6_route.ref.diff
deleted file mode 100644
index 12e0b59..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step11/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,56 +0,0 @@
---- a/rt6/step10/show_ipv6_route.ref
-+++ b/rt6/step11/show_ipv6_route.ref
-@@ -72,25 +72,12 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":30,
-+ "metric":40,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 30031
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
- "interfaceName":"eth-rt4",
- "active":true,
- "labels":[
-@@ -142,25 +129,12 @@
- "selected":true,
- "destSelected":true,
- "distance":115,
-- "metric":20,
-+ "metric":30,
- "installed":true,
- "nexthops":[
- {
- "fib":true,
- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "backupIndex":[
-- 0
-- ],
-- "labels":[
-- 3
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
- "interfaceName":"eth-rt4",
- "active":true,
- "labels":[
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step11/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step11/show_mpls_table.ref.diff
deleted file mode 100644
index 387dcca..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step11/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,106 +0,0 @@
---- a/rt6/step10/show_mpls_table.ref
-+++ b/rt6/step11/show_mpls_table.ref
-@@ -8,12 +8,6 @@
- "outLabel":16010,
- "installed":true,
- "nexthop":"10.0.7.4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30010,
-- "installed":true,
-- "nexthop":"10.0.8.5"
- }
- ]
- },
-@@ -26,12 +20,6 @@
- "outLabel":16011,
- "installed":true,
- "interface":"eth-rt4"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30011,
-- "installed":true,
-- "interface":"eth-rt5"
- }
- ]
- },
-@@ -85,18 +73,8 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30030,
-- "installed":true,
-- "nexthop":"10.0.8.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16030,
-+ "installed":true,
- "nexthop":"10.0.7.4"
- }
- ]
-@@ -107,17 +85,6 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":30031,
-- "installed":true,
-- "interface":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16031,
- "interface":"eth-rt4"
- }
-@@ -173,18 +140,8 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.8.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16500,
-+ "installed":true,
- "nexthop":"10.0.7.4"
- }
- ]
-@@ -195,18 +152,8 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":16501,
-+ "installed":true,
- "interface":"eth-rt4"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step12/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step12/show_ip_route.ref.diff
deleted file mode 100644
index 1086b6e..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step12/show_ip_route.ref.diff
+++ /dev/null
@@ -1,153 +0,0 @@
---- a/rt6/step12/show_ip_route.ref
-+++ b/rt6/step12/show_ip_route.ref
-@@ -18,16 +18,6 @@
- "labels":[
- 16010
- ]
-- },
-- {
-- "fib":true,
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30010
-- ]
- }
- ]
- }
-@@ -48,24 +38,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 16020
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30020
-- ]
-- }
- ]
- }
- ],
-@@ -108,24 +84,10 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30040
-- ]
-- }
- ]
- }
- ],
-@@ -168,13 +130,6 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
- "active":true
-- },
-- {
-- "fib":true,
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true
- }
- ]
- }
-@@ -194,17 +149,6 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
- "active":true
- }
- ]
-@@ -225,17 +169,6 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
- "active":true
- }
- ]
-@@ -297,13 +230,6 @@
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
- "active":true
-- },
-- {
-- "fib":true,
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true
- }
- ]
- }
-@@ -318,18 +244,7 @@
- {
- "ip":"10.0.7.4",
- "afi":"ipv4",
-- "interfaceName":"eth-rt4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "ip":"10.0.8.5",
-- "afi":"ipv4",
-- "interfaceName":"eth-rt5",
-- "active":true
-+ "interfaceName":"eth-rt4"
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step12/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step12/show_ipv6_route.ref.diff
deleted file mode 100644
index 571c66f..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step12/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,66 +0,0 @@
---- a/rt6/step12/show_ipv6_route.ref
-+++ b/rt6/step12/show_ipv6_route.ref
-@@ -17,15 +17,6 @@
- "labels":[
- 16011
- ]
-- },
-- {
-- "fib":true,
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30011
-- ]
- }
- ]
- }
-@@ -45,23 +36,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 16021
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30021
-- ]
-- }
- ]
- }
- ],
-@@ -102,23 +80,10 @@
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
- "active":true,
-- "backupIndex":[
-- 0
-- ],
- "labels":[
- 3
- ]
- }
-- ],
-- "backupNexthops":[
-- {
-- "afi":"ipv6",
-- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 30041
-- ]
-- }
- ]
- }
- ],
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step12/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step12/show_mpls_table.ref.diff
deleted file mode 100644
index 18322f1..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step12/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,78 +0,0 @@
---- a/rt6/step12/show_mpls_table.ref
-+++ b/rt6/step12/show_mpls_table.ref
-@@ -31,17 +31,7 @@
- "type":"SR (IS-IS)",
- "outLabel":16020,
- "installed":true,
-- "nexthop":"10.0.7.4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30020,
-- "nexthop":"10.0.8.5"
-+ "nexthop":"10.0.7.4"
- }
- ]
- },
-@@ -53,17 +43,7 @@
- "type":"SR (IS-IS)",
- "outLabel":16021,
- "installed":true,
-- "interface":"eth-rt4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30021,
-- "interface":"eth-rt5"
-+ "interface":"eth-rt4"
- }
- ]
- },
-@@ -98,17 +78,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "nexthop":"10.0.7.4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30040,
-- "nexthop":"10.0.8.5"
-+ "nexthop":"10.0.7.4"
- }
- ]
- },
-@@ -120,17 +90,7 @@
- "type":"SR (IS-IS)",
- "outLabel":3,
- "installed":true,
-- "interface":"eth-rt4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":30041,
-- "interface":"eth-rt5"
-+ "interface":"eth-rt4"
- }
- ]
- }, \ No newline at end of file
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref
new file mode 100644
index 0000000..b9b43c4
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref
@@ -0,0 +1,413 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref
new file mode 100644
index 0000000..de31816
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref
@@ -0,0 +1,173 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref
new file mode 100644
index 0000000..4bd85c3
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref
@@ -0,0 +1,224 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt5"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step2/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref
new file mode 100644
index 0000000..b9b43c4
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref
@@ -0,0 +1,413 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ip_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref
new file mode 100644
index 0000000..de31816
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref
@@ -0,0 +1,173 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_ipv6_route.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref
new file mode 100644
index 0000000..4bd85c3
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref
@@ -0,0 +1,224 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt5"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref.diff
deleted file mode 100644
index e69de29..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step3/show_mpls_table.ref.diff
+++ /dev/null
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref
new file mode 100644
index 0000000..d34a28e
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref
@@ -0,0 +1,395 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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,
+ "labels":[
+ 16010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref.diff
deleted file mode 100644
index 7c2f004..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ip_route.ref.diff
+++ /dev/null
@@ -1,70 +0,0 @@
---- a/rt6/step3/show_ip_route.ref
-+++ b/rt6/step4/show_ip_route.ref
-@@ -14,10 +14,7 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16010
-- ]
-+ "active":true
- },
- {
- "fib":true,
-@@ -50,9 +47,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 16020
- ]
- }
- ],
-@@ -98,10 +92,7 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16030
-- ]
-+ "active":true
- }
- ]
- }
-@@ -124,9 +115,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -135,10 +123,7 @@
- "ip":"10.0.8.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16040
-- ]
-+ "active":true
- }
- ]
- }
-@@ -172,10 +157,7 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref
new file mode 100644
index 0000000..2527c85
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref
@@ -0,0 +1,155 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref.diff
deleted file mode 100644
index 70f872e..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,70 +0,0 @@
---- a/rt6/step3/show_ipv6_route.ref
-+++ b/rt6/step4/show_ipv6_route.ref
-@@ -13,10 +13,7 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16011
-- ]
-+ "active":true
- },
- {
- "fib":true,
-@@ -47,9 +44,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 16021
- ]
- }
- ],
-@@ -92,10 +86,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16031
-- ]
-+ "active":true
- }
- ]
- }
-@@ -117,9 +108,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -127,10 +115,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt5",
-- "active":true,
-- "labels":[
-- 16041
-- ]
-+ "active":true
- }
- ]
- }
-@@ -162,10 +147,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref
new file mode 100644
index 0000000..5cac925
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref
@@ -0,0 +1,165 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref.diff
deleted file mode 100644
index c191763..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step4/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,109 +0,0 @@
---- a/rt6/step3/show_mpls_table.ref
-+++ b/rt6/step4/show_mpls_table.ref
-@@ -8,12 +8,6 @@
- "outLabel":16010,
- "installed":true,
- "nexthop":"10.0.8.5"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16010,
-- "installed":true,
-- "nexthop":"10.0.7.4"
- }
- ]
- },
-@@ -26,12 +20,6 @@
- "outLabel":16011,
- "installed":true,
- "interface":"eth-rt5"
-- },
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16011,
-- "installed":true,
-- "interface":"eth-rt4"
- }
- ]
- },
-@@ -96,7 +84,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16030,
-+ "outLabel":3,
- "nexthop":"10.0.7.4"
- }
- ]
-@@ -118,52 +106,8 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16031,
-- "interface":"eth-rt4"
-- }
-- ]
-- },
-- "16040":{
-- "inLabel":16040,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.7.4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16040,
-- "nexthop":"10.0.8.5"
-- }
-- ]
-- },
-- "16041":{
-- "inLabel":16041,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt4",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16041,
-- "interface":"eth-rt5"
-+ "interface":"eth-rt4"
- }
- ]
- },
-@@ -184,7 +128,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-+ "outLabel":3,
- "nexthop":"10.0.7.4"
- }
- ]
-@@ -206,7 +150,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-+ "outLabel":3,
- "interface":"eth-rt4"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref
new file mode 100644
index 0000000..b9b43c4
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref
@@ -0,0 +1,413 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref.diff
deleted file mode 100644
index 9f017d2..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ip_route.ref.diff
+++ /dev/null
@@ -1,70 +0,0 @@
---- a/rt6/step4/show_ip_route.ref
-+++ b/rt6/step5/show_ip_route.ref
-@@ -14,7 +14,10 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16010
-+ ]
- },
- {
- "fib":true,
-@@ -47,6 +50,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 16020
- ]
- }
- ],
-@@ -92,7 +98,10 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16030
-+ ]
- }
- ]
- }
-@@ -115,6 +124,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -123,7 +135,10 @@
- "ip":"10.0.8.5",
- "afi":"ipv4",
- "interfaceName":"eth-rt5",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16040
-+ ]
- }
- ]
- }
-@@ -157,7 +172,10 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref
new file mode 100644
index 0000000..de31816
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref
@@ -0,0 +1,173 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 16041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref.diff
deleted file mode 100644
index 1209504..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,70 +0,0 @@
---- a/rt6/step4/show_ipv6_route.ref
-+++ b/rt6/step5/show_ipv6_route.ref
-@@ -13,7 +13,10 @@
- "fib":true,
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16011
-+ ]
- },
- {
- "fib":true,
-@@ -44,6 +47,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 16021
- ]
- }
- ],
-@@ -86,7 +92,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16031
-+ ]
- }
- ]
- }
-@@ -108,6 +117,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -115,7 +127,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt5",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16041
-+ ]
- }
- ]
- }
-@@ -147,7 +162,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref
new file mode 100644
index 0000000..ef2310f
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref
@@ -0,0 +1,224 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16040,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16041,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref.diff
deleted file mode 100644
index abf7c2a..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step5/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,112 +0,0 @@
---- a/rt6/step4/show_mpls_table.ref
-+++ b/rt6/step5/show_mpls_table.ref
-@@ -7,6 +7,12 @@
- "type":"SR (IS-IS)",
- "outLabel":16010,
- "installed":true,
-+ "nexthop":"10.0.7.4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16010,
-+ "installed":true,
- "nexthop":"10.0.8.5"
- }
- ]
-@@ -19,6 +25,12 @@
- "type":"SR (IS-IS)",
- "outLabel":16011,
- "installed":true,
-+ "interface":"eth-rt4"
-+ },
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16011,
-+ "installed":true,
- "interface":"eth-rt5"
- }
- ]
-@@ -84,7 +96,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16030,
- "nexthop":"10.0.7.4"
- }
- ]
-@@ -106,11 +118,55 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16031,
- "interface":"eth-rt4"
- }
- ]
- },
-+ "16040":{
-+ "inLabel":16040,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.7.4",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16040,
-+ "nexthop":"10.0.8.5"
-+ }
-+ ]
-+ },
-+ "16041":{
-+ "inLabel":16041,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt4",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16041,
-+ "interface":"eth-rt5"
-+ }
-+ ]
-+ },
- "16050":{
- "inLabel":16050,
- "installed":true,
-@@ -128,7 +184,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16050,
- "nexthop":"10.0.7.4"
- }
- ]
-@@ -150,7 +206,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":3,
-+ "outLabel":16051,
- "interface":"eth-rt4"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref
new file mode 100644
index 0000000..ca39251
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref
@@ -0,0 +1,413 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref.diff
deleted file mode 100644
index f318f95..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ip_route.ref.diff
+++ /dev/null
@@ -1,38 +0,0 @@
---- a/rt6/step5/show_ip_route.ref
-+++ b/rt6/step6/show_ip_route.ref
-@@ -26,7 +26,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16010
-+ 30010
- ]
- }
- ]
-@@ -63,7 +63,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16020
-+ 30020
- ]
- }
- ]
-@@ -89,7 +89,7 @@
- 0
- ],
- "labels":[
-- 16030
-+ 30030
- ]
- }
- ],
-@@ -137,7 +137,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16040
-+ 30040
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref
new file mode 100644
index 0000000..4a42ec9
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref
@@ -0,0 +1,173 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref.diff
deleted file mode 100644
index 9208491..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,38 +0,0 @@
---- a/rt6/step5/show_ipv6_route.ref
-+++ b/rt6/step6/show_ipv6_route.ref
-@@ -24,7 +24,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16011
-+ 30011
- ]
- }
- ]
-@@ -59,7 +59,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16021
-+ 30021
- ]
- }
- ]
-@@ -84,7 +84,7 @@
- 0
- ],
- "labels":[
-- 16031
-+ 30031
- ]
- }
- ],
-@@ -129,7 +129,7 @@
- "interfaceName":"eth-rt5",
- "active":true,
- "labels":[
-- 16041
-+ 30041
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref
new file mode 100644
index 0000000..edbe78a
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref
@@ -0,0 +1,224 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref.diff
deleted file mode 100644
index aee8969..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step6/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,74 +0,0 @@
---- a/rt6/step5/show_mpls_table.ref
-+++ b/rt6/step6/show_mpls_table.ref
-@@ -11,7 +11,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16010,
-+ "outLabel":30010,
- "installed":true,
- "nexthop":"10.0.8.5"
- }
-@@ -29,7 +29,7 @@
- },
- {
- "type":"SR (IS-IS)",
-- "outLabel":16011,
-+ "outLabel":30011,
- "installed":true,
- "interface":"eth-rt5"
- }
-@@ -52,7 +52,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16020,
-+ "outLabel":30020,
- "nexthop":"10.0.8.5"
- }
- ]
-@@ -74,7 +74,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16021,
-+ "outLabel":30021,
- "interface":"eth-rt5"
- }
- ]
-@@ -85,7 +85,7 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16030,
-+ "outLabel":30030,
- "installed":true,
- "nexthop":"10.0.8.5",
- "backupIndex":[
-@@ -107,7 +107,7 @@
- "nexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16031,
-+ "outLabel":30031,
- "installed":true,
- "interface":"eth-rt5",
- "backupIndex":[
-@@ -140,7 +140,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16040,
-+ "outLabel":30040,
- "nexthop":"10.0.8.5"
- }
- ]
-@@ -162,7 +162,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16041,
-+ "outLabel":30041,
- "interface":"eth-rt5"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref
new file mode 100644
index 0000000..ee47c1a
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref
@@ -0,0 +1,407 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref.diff
deleted file mode 100644
index 0e6c3ff..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ip_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt6/step6/show_ip_route.ref
-+++ b/rt6/step7/show_ip_route.ref
-@@ -161,9 +161,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -172,10 +169,7 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16050
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref
new file mode 100644
index 0000000..c5ef607
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref
@@ -0,0 +1,167 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref.diff
deleted file mode 100644
index 2fe46c8..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt6/step6/show_ipv6_route.ref
-+++ b/rt6/step7/show_ipv6_route.ref
-@@ -152,9 +152,6 @@
- "active":true,
- "backupIndex":[
- 0
-- ],
-- "labels":[
-- 3
- ]
- }
- ],
-@@ -162,10 +159,7 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true,
-- "labels":[
-- 16051
-- ]
-+ "active":true
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref
new file mode 100644
index 0000000..ad965ce
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref
@@ -0,0 +1,178 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref.diff
deleted file mode 100644
index 179a4f4..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step7/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,52 +0,0 @@
---- a/rt6/step6/show_mpls_table.ref
-+++ b/rt6/step7/show_mpls_table.ref
-@@ -166,49 +166,5 @@
- "interface":"eth-rt5"
- }
- ]
-- },
-- "16050":{
-- "inLabel":16050,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "nexthop":"10.0.8.5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16050,
-- "nexthop":"10.0.7.4"
-- }
-- ]
-- },
-- "16051":{
-- "inLabel":16051,
-- "installed":true,
-- "nexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":3,
-- "installed":true,
-- "interface":"eth-rt5",
-- "backupIndex":[
-- 0
-- ]
-- }
-- ],
-- "backupNexthops":[
-- {
-- "type":"SR (IS-IS)",
-- "outLabel":16051,
-- "interface":"eth-rt4"
-- }
-- ]
- }
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref
new file mode 100644
index 0000000..ca39251
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref
@@ -0,0 +1,413 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16050
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref.diff
deleted file mode 100644
index 9d5c440..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ip_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt6/step7/show_ip_route.ref
-+++ b/rt6/step8/show_ip_route.ref
-@@ -161,6 +161,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -169,7 +172,10 @@
- "ip":"10.0.7.4",
- "afi":"ipv4",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16050
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref
new file mode 100644
index 0000000..4a42ec9
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref
@@ -0,0 +1,173 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16051
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref.diff
deleted file mode 100644
index 21cab20..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,24 +0,0 @@
---- a/rt6/step7/show_ipv6_route.ref
-+++ b/rt6/step8/show_ipv6_route.ref
-@@ -152,6 +152,9 @@
- "active":true,
- "backupIndex":[
- 0
-+ ],
-+ "labels":[
-+ 3
- ]
- }
- ],
-@@ -159,7 +162,10 @@
- {
- "afi":"ipv6",
- "interfaceName":"eth-rt4",
-- "active":true
-+ "active":true,
-+ "labels":[
-+ 16051
-+ ]
- }
- ]
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref
new file mode 100644
index 0000000..edbe78a
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref
@@ -0,0 +1,224 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16050":{
+ "inLabel":16050,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16050,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16051":{
+ "inLabel":16051,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16051,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref.diff
deleted file mode 100644
index 760c554..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step8/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,52 +0,0 @@
---- a/rt6/step7/show_mpls_table.ref
-+++ b/rt6/step8/show_mpls_table.ref
-@@ -166,5 +166,49 @@
- "interface":"eth-rt5"
- }
- ]
-+ },
-+ "16050":{
-+ "inLabel":16050,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "nexthop":"10.0.8.5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16050,
-+ "nexthop":"10.0.7.4"
-+ }
-+ ]
-+ },
-+ "16051":{
-+ "inLabel":16051,
-+ "installed":true,
-+ "nexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":3,
-+ "installed":true,
-+ "interface":"eth-rt5",
-+ "backupIndex":[
-+ 0
-+ ]
-+ }
-+ ],
-+ "backupNexthops":[
-+ {
-+ "type":"SR (IS-IS)",
-+ "outLabel":16051,
-+ "interface":"eth-rt4"
-+ }
-+ ]
- }
- }
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref
new file mode 100644
index 0000000..879d595
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref
@@ -0,0 +1,413 @@
+{
+ "1.1.1.1\/32":[
+ {
+ "prefix":"1.1.1.1\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "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":[
+ 30010
+ ]
+ }
+ ]
+ }
+ ],
+ "2.2.2.2\/32":[
+ {
+ "prefix":"2.2.2.2\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16020
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30020
+ ]
+ }
+ ]
+ }
+ ],
+ "3.3.3.3\/32":[
+ {
+ "prefix":"3.3.3.3\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30030
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16030
+ ]
+ }
+ ]
+ }
+ ],
+ "4.4.4.4\/32":[
+ {
+ "prefix":"4.4.4.4\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30040
+ ]
+ }
+ ]
+ }
+ ],
+ "5.5.5.5\/32":[
+ {
+ "prefix":"5.5.5.5\/32",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16500
+ ]
+ }
+ ]
+ }
+ ],
+ "10.0.1.0\/24":[
+ {
+ "prefix":"10.0.1.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.3.0\/24":[
+ {
+ "prefix":"10.0.3.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.4.0\/24":[
+ {
+ "prefix":"10.0.4.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.5.0\/24":[
+ {
+ "prefix":"10.0.5.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.6.0\/24":[
+ {
+ "prefix":"10.0.6.0\/24",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "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":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "active":true
+ }
+ ]
+ }
+ ],
+ "10.0.8.0\/24":[
+ {
+ "prefix":"10.0.8.0\/24",
+ "protocol":"isis",
+ "distance":115,
+ "metric":20,
+ "nexthops":[
+ {
+ "ip":"10.0.8.5",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "ip":"10.0.7.4",
+ "afi":"ipv4",
+ "interfaceName":"eth-rt4",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref.diff
deleted file mode 100644
index ee29647..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ip_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt6/step8/show_ip_route.ref
-+++ b/rt6/step9/show_ip_route.ref
-@@ -174,7 +174,7 @@
- "interfaceName":"eth-rt4",
- "active":true,
- "labels":[
-- 16050
-+ 16500
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref
new file mode 100644
index 0000000..e8a7200
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref
@@ -0,0 +1,173 @@
+{
+ "2001:db8:1000::1\/128":[
+ {
+ "prefix":"2001:db8:1000::1\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":40,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30011
+ ]
+ },
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16011
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::2\/128":[
+ {
+ "prefix":"2001:db8:1000::2\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 16021
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30021
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::3\/128":[
+ {
+ "prefix":"2001:db8:1000::3\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":30,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 30031
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16031
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::4\/128":[
+ {
+ "prefix":"2001:db8:1000::4\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "labels":[
+ 30041
+ ]
+ }
+ ]
+ }
+ ],
+ "2001:db8:1000::5\/128":[
+ {
+ "prefix":"2001:db8:1000::5\/128",
+ "protocol":"isis",
+ "selected":true,
+ "destSelected":true,
+ "distance":115,
+ "metric":20,
+ "installed":true,
+ "nexthops":[
+ {
+ "fib":true,
+ "afi":"ipv6",
+ "interfaceName":"eth-rt5",
+ "active":true,
+ "backupIndex":[
+ 0
+ ],
+ "labels":[
+ 3
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "afi":"ipv6",
+ "interfaceName":"eth-rt4",
+ "active":true,
+ "labels":[
+ 16501
+ ]
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref.diff
deleted file mode 100644
index bebca4d..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_ipv6_route.ref.diff
+++ /dev/null
@@ -1,11 +0,0 @@
---- a/rt6/step8/show_ipv6_route.ref
-+++ b/rt6/step9/show_ipv6_route.ref
-@@ -164,7 +164,7 @@
- "interfaceName":"eth-rt4",
- "active":true,
- "labels":[
-- 16051
-+ 16501
- ]
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref
new file mode 100644
index 0000000..4b6c4ee
--- /dev/null
+++ b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref
@@ -0,0 +1,224 @@
+{
+ "16010":{
+ "inLabel":16010,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16010,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30010,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16011":{
+ "inLabel":16011,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16011,
+ "installed":true,
+ "interface":"eth-rt4"
+ },
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30011,
+ "installed":true,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16020":{
+ "inLabel":16020,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16020,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30020,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16021":{
+ "inLabel":16021,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16021,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30021,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16030":{
+ "inLabel":16030,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30030,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16030,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16031":{
+ "inLabel":16031,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30031,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16031,
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16040":{
+ "inLabel":16040,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30040,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16041":{
+ "inLabel":16041,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt4",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":30041,
+ "interface":"eth-rt5"
+ }
+ ]
+ },
+ "16500":{
+ "inLabel":16500,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "nexthop":"10.0.8.5",
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16500,
+ "nexthop":"10.0.7.4",
+ "interface":"eth-rt4"
+ }
+ ]
+ },
+ "16501":{
+ "inLabel":16501,
+ "installed":true,
+ "nexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":3,
+ "installed":true,
+ "interface":"eth-rt5",
+ "backupIndex":[
+ 0
+ ]
+ }
+ ],
+ "backupNexthops":[
+ {
+ "type":"SR (IS-IS)",
+ "outLabel":16501,
+ "interface":"eth-rt4"
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref.diff b/tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref.diff
deleted file mode 100644
index 57347d1..0000000
--- a/tests/topotests/isis_tilfa_topo1/rt6/step9/show_mpls_table.ref.diff
+++ /dev/null
@@ -1,39 +0,0 @@
---- a/rt6/step8/show_mpls_table.ref
-+++ b/rt6/step9/show_mpls_table.ref
-@@ -167,8 +167,8 @@
- }
- ]
- },
-- "16050":{
-- "inLabel":16050,
-+ "16500":{
-+ "inLabel":16500,
- "installed":true,
- "nexthops":[
- {
-@@ -184,13 +184,13 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16050,
-+ "outLabel":16500,
- "nexthop":"10.0.7.4"
- }
- ]
- },
-- "16051":{
-- "inLabel":16051,
-+ "16501":{
-+ "inLabel":16501,
- "installed":true,
- "nexthops":[
- {
-@@ -206,7 +206,7 @@
- "backupNexthops":[
- {
- "type":"SR (IS-IS)",
-- "outLabel":16051,
-+ "outLabel":16501,
- "interface":"eth-rt4"
- }
- ]
diff --git a/tests/topotests/isis_tilfa_topo1/rt6/zebra.conf b/tests/topotests/isis_tilfa_topo1/rt6/zebra.conf
index 94fed46..c765996 100644
--- a/tests/topotests/isis_tilfa_topo1/rt6/zebra.conf
+++ b/tests/topotests/isis_tilfa_topo1/rt6/zebra.conf
@@ -16,6 +16,7 @@ interface eth-rt4
!
interface eth-rt5
ip address 10.0.8.6/24
+ no link-detect
!
ip forwarding
!
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 e2bbf45..aaf6af0 100755
--- a/tests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py
+++ b/tests/topotests/isis_tilfa_topo1/test_isis_tilfa_topo1.py
@@ -56,6 +56,7 @@ import pytest
import json
import tempfile
from functools import partial
+from time import sleep
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -120,45 +121,6 @@ def build_topo(tgen):
switch.add_link(tgen.gears["rt5"], nodeif="eth-rt6")
switch.add_link(tgen.gears["rt6"], nodeif="eth-rt5")
- #
- # Populate multi-dimensional dictionary containing all expected outputs
- #
- files = [
- "show_ip_route.ref",
- "show_ipv6_route.ref",
- "show_mpls_table.ref",
- "show_yang_interface_isis_adjacencies.ref",
- ]
- for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
- outputs[rname] = {}
- for step in range(1, 12 + 1):
- outputs[rname][step] = {}
- for file in files:
- if step == 1:
- # Get snapshots relative to the expected initial network convergence
- filename = "{}/{}/step{}/{}".format(CWD, rname, step, file)
- outputs[rname][step][file] = open(filename).read()
- else:
- if file == "show_yang_interface_isis_adjacencies.ref":
- continue
-
- # Get diff relative to the previous step
- filename = "{}/{}/step{}/{}.diff".format(CWD, rname, step, file)
-
- # Create temporary files in order to apply the diff
- f_in = tempfile.NamedTemporaryFile(mode="w")
- f_in.write(outputs[rname][step - 1][file])
- f_in.flush()
- f_out = tempfile.NamedTemporaryFile(mode="r")
- os.system(
- "patch -s -o %s %s %s" % (f_out.name, f_in.name, filename)
- )
-
- # Store the updated snapshot and remove the temporary files
- outputs[rname][step][file] = open(f_out.name).read()
- f_in.close()
- f_out.close()
-
def setup_module(mod):
"Sets up the pytest environment"
@@ -176,7 +138,7 @@ def setup_module(mod):
TopoRouter.RD_ISIS, os.path.join(CWD, "{}/isisd.conf".format(rname))
)
router.load_config(
- TopoRouter.RD_BFD, os.path.join(CWD, "/dev/null".format(rname))
+ TopoRouter.RD_BFD, os.path.join(CWD, "{}/bfdd.conf".format(rname))
)
tgen.start_router()
@@ -190,12 +152,174 @@ def teardown_module(mod):
tgen.stop_topology()
-def router_compare_json_output(rname, command, reference, count=120, wait=0.5):
+def filter_json(data, keys_to_keep):
+ """
+ Filters a dictionary, keeping only the specified keys.
+ """
+ return {k: v for k, v in data.items() if k in keys_to_keep}
+
+
+def regen_data(rname, command, step, file, wait):
+ """
+ Regenerates reference data.
+ """
+ # Sleep enough time to ensure the protocol has converged
+ if rname == "rt1":
+ sleep(wait)
+ if step == 10:
+ sleep(10)
+
+ # Get and parse JSON output
+ tgen = get_topogen()
+ output = json.loads(tgen.gears[rname].vtysh_cmd(command))
+
+ # Default JSON separators
+ separators = (",", ":")
+
+ # Process JSON output based on the specified file
+ if file == "show_yang_interface_isis_adjacencies.ref":
+ # Filter out the loopback interface
+ output["frr-interface:lib"]["interface"] = [
+ interface
+ for interface in output["frr-interface:lib"]["interface"]
+ if interface["name"] != "lo"
+ ]
+
+ # Filter out unwanted fields
+ for interface in output["frr-interface:lib"]["interface"]:
+ keys_to_keep = {"name", "vrf", "state"}
+ filtered_interface = filter_json(interface, keys_to_keep)
+ interface.clear()
+ interface.update(filtered_interface)
+
+ keys_to_keep = {"frr-isisd:isis"}
+ filtered_state = filter_json(interface["state"], keys_to_keep)
+ interface["state"].clear()
+ interface["state"].update(filtered_state)
+
+ keys_to_keep = {"adjacencies"}
+ filtered_isis = filter_json(
+ interface["state"]["frr-isisd:isis"], keys_to_keep
+ )
+ interface["state"]["frr-isisd:isis"].clear()
+ interface["state"]["frr-isisd:isis"].update(filtered_isis)
+ if "adjacencies" in interface["state"]["frr-isisd:isis"]:
+ for adjacency in interface["state"]["frr-isisd:isis"]["adjacencies"][
+ "adjacency"
+ ]:
+ keys_to_keep = {
+ "neighbor-sys-type",
+ "neighbor-sysid",
+ "hold-timer",
+ "neighbor-priority",
+ "state",
+ }
+ filtered_adjacency = filter_json(adjacency, keys_to_keep)
+ adjacency.clear()
+ adjacency.update(filtered_adjacency)
+ # Adjust separators to match libyang's output.
+ separators = (",", ": ")
+
+ elif file == "show_ip_route.ref" or file == "show_ipv6_route.ref":
+ # Filter out unwanted fields
+ keys_to_keep_route = {
+ "prefix",
+ "protocol",
+ "selected",
+ "destSelected",
+ "distance",
+ "metric",
+ "installed",
+ "nexthops",
+ "backupNexthops",
+ }
+ keys_to_keep_nh = {
+ "fib",
+ "ip",
+ "afi",
+ "interfaceName",
+ "active",
+ "backupIndex",
+ "labels",
+ }
+ for prefix_key, prefix_value in output.items():
+ filtered_routes = []
+ for route in prefix_value:
+ if "nexthops" in route:
+ filtered_nhs = []
+ for nh in route["nexthops"]:
+ if nh["ip"].startswith("fe80"):
+ del nh["ip"]
+ filtered_nhs.append(filter_json(nh, keys_to_keep_nh))
+ route["nexthops"] = filtered_nhs
+ if "backupNexthops" in route:
+ filtered_nhs = []
+ for nh in route["backupNexthops"]:
+ if nh["ip"].startswith("fe80"):
+ del nh["ip"]
+ filtered_nhs.append(filter_json(nh, keys_to_keep_nh))
+ route["backupNexthops"] = filtered_nhs
+ filtered_routes.append(filter_json(route, keys_to_keep_route))
+ output[prefix_key] = filtered_routes
+
+ elif file == "show_mpls_table.ref":
+ # Filter out Adj-SID labels
+ output = {int(key): value for key, value in output.items() if int(key) >= 16000}
+
+ # Filter out unwanted fields
+ keys_to_keep_label = {
+ "inLabel",
+ "installed",
+ "nexthops",
+ "backupNexthops",
+ }
+ keys_to_keep_nh = {
+ "type",
+ "outLabel",
+ "installed",
+ "interface",
+ "nexthop",
+ "backupIndex",
+ }
+ for label_key, label_value in output.items():
+ if "nexthops" in label_value:
+ filtered_nhs = []
+ for nh in label_value["nexthops"]:
+ if nh["nexthop"].startswith("fe80"):
+ del nh["nexthop"]
+ filtered_nhs.append(filter_json(nh, keys_to_keep_nh))
+ label_value["nexthops"] = filtered_nhs
+ if "backupNexthops" in label_value:
+ filtered_nhs = []
+ for nh in label_value["backupNexthops"]:
+ if nh["nexthop"].startswith("fe80"):
+ del nh["nexthop"]
+ filtered_nhs.append(filter_json(nh, keys_to_keep_nh))
+ label_value["backupNexthops"] = filtered_nhs
+ output[label_key] = filter_json(label_value, keys_to_keep_label)
+
+ elif file.startswith("show_bfd_peer"):
+ keys_to_keep = ["multihop", "peer", "interface", "status"]
+ output = filter_json(output, keys_to_keep)
+
+ # Save the processed output to a file
+ filename = "{}/{}/step{}/{}".format(CWD, rname, step, file)
+ output = json.dumps(output, separators=separators, indent=2).replace("/", "\\/")
+ with open(filename, "w", encoding="ascii") as file:
+ file.write(output + "\n")
+
+
+def router_compare_json_output(rname, command, step, file, count=120, wait=0.5):
"Compare router JSON output"
- logger.info('Comparing router "%s" "%s" output', rname, command)
+ # Regenerate reference data when the REGEN_DATA environment variable is set
+ if os.environ.get("REGEN_DATA") is not None:
+ regen_data(rname, command, step, file, count * wait)
+ return
tgen = get_topogen()
+ logger.info('Comparing router "%s" "%s" output', rname, command)
+ reference = open("{}/{}/step{}/{}".format(CWD, rname, step, file)).read()
expected = json.loads(reference)
# Run test function until we get an result. Wait at most 60 seconds.
@@ -222,7 +346,8 @@ def test_isis_adjacencies_step1():
router_compare_json_output(
rname,
"show yang operational-data /frr-interface:lib isisd",
- outputs[rname][1]["show_yang_interface_isis_adjacencies.ref"],
+ 1,
+ "show_yang_interface_isis_adjacencies.ref",
)
@@ -236,7 +361,7 @@ def test_rib_ipv4_step1():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][1]["show_ip_route.ref"]
+ rname, "show ip route isis json", 1, "show_ip_route.ref"
)
@@ -250,7 +375,7 @@ def test_rib_ipv6_step1():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][1]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 1, "show_ipv6_route.ref"
)
@@ -264,7 +389,7 @@ def test_mpls_lib_step1():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][1]["show_mpls_table.ref"]
+ rname, "show mpls table json", 1, "show_mpls_table.ref"
)
@@ -292,7 +417,7 @@ def test_rib_ipv4_step2():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][2]["show_ip_route.ref"]
+ rname, "show ip route isis json", 2, "show_ip_route.ref"
)
@@ -306,7 +431,7 @@ def test_rib_ipv6_step2():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][2]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 2, "show_ipv6_route.ref"
)
@@ -320,7 +445,7 @@ def test_mpls_lib_step2():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][2]["show_mpls_table.ref"]
+ rname, "show mpls table json", 2, "show_mpls_table.ref"
)
@@ -348,7 +473,7 @@ def test_rib_ipv4_step3():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][3]["show_ip_route.ref"]
+ rname, "show ip route isis json", 3, "show_ip_route.ref"
)
@@ -362,7 +487,7 @@ def test_rib_ipv6_step3():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][3]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 3, "show_ipv6_route.ref"
)
@@ -376,7 +501,7 @@ def test_mpls_lib_step3():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][3]["show_mpls_table.ref"]
+ rname, "show mpls table json", 3, "show_mpls_table.ref"
)
@@ -409,7 +534,7 @@ def test_rib_ipv4_step4():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][4]["show_ip_route.ref"]
+ rname, "show ip route isis json", 4, "show_ip_route.ref"
)
@@ -423,7 +548,7 @@ def test_rib_ipv6_step4():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][4]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 4, "show_ipv6_route.ref"
)
@@ -437,7 +562,7 @@ def test_mpls_lib_step4():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][4]["show_mpls_table.ref"]
+ rname, "show mpls table json", 4, "show_mpls_table.ref"
)
@@ -463,7 +588,7 @@ def test_rib_ipv4_step5():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][5]["show_ip_route.ref"]
+ rname, "show ip route isis json", 5, "show_ip_route.ref"
)
@@ -477,7 +602,7 @@ def test_rib_ipv6_step5():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][5]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 5, "show_ipv6_route.ref"
)
@@ -491,7 +616,7 @@ def test_mpls_lib_step5():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][5]["show_mpls_table.ref"]
+ rname, "show mpls table json", 5, "show_mpls_table.ref"
)
@@ -519,7 +644,7 @@ def test_rib_ipv4_step6():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][6]["show_ip_route.ref"]
+ rname, "show ip route isis json", 6, "show_ip_route.ref"
)
@@ -533,7 +658,7 @@ def test_rib_ipv6_step6():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][6]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 6, "show_ipv6_route.ref"
)
@@ -547,7 +672,7 @@ def test_mpls_lib_step6():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][6]["show_mpls_table.ref"]
+ rname, "show mpls table json", 6, "show_mpls_table.ref"
)
@@ -579,7 +704,7 @@ def test_rib_ipv4_step7():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][7]["show_ip_route.ref"]
+ rname, "show ip route isis json", 7, "show_ip_route.ref"
)
@@ -593,7 +718,7 @@ def test_rib_ipv6_step7():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][7]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 7, "show_ipv6_route.ref"
)
@@ -607,7 +732,7 @@ def test_mpls_lib_step7():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][7]["show_mpls_table.ref"]
+ rname, "show mpls table json", 7, "show_mpls_table.ref"
)
@@ -638,7 +763,7 @@ def test_rib_ipv4_step8():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][8]["show_ip_route.ref"]
+ rname, "show ip route isis json", 8, "show_ip_route.ref"
)
@@ -652,7 +777,7 @@ def test_rib_ipv6_step8():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][8]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 8, "show_ipv6_route.ref"
)
@@ -666,7 +791,7 @@ def test_mpls_lib_step8():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][8]["show_mpls_table.ref"]
+ rname, "show mpls table json", 8, "show_mpls_table.ref"
)
@@ -698,7 +823,7 @@ def test_rib_ipv4_step9():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][9]["show_ip_route.ref"]
+ rname, "show ip route isis json", 9, "show_ip_route.ref"
)
@@ -712,7 +837,7 @@ def test_rib_ipv6_step9():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show ipv6 route isis json", outputs[rname][9]["show_ipv6_route.ref"]
+ rname, "show ipv6 route isis json", 9, "show_ipv6_route.ref"
)
@@ -726,7 +851,7 @@ def test_mpls_lib_step9():
for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
router_compare_json_output(
- rname, "show mpls table json", outputs[rname][9]["show_mpls_table.ref"]
+ rname, "show mpls table json", 9, "show_mpls_table.ref"
)
@@ -734,11 +859,17 @@ def test_mpls_lib_step9():
# Step 10
#
# Action(s):
-# - Setting spf-delay-ietf init-delay of 15s
+# - Enable ISIS BFD between rt5 and rt6
+# - Verify that the BFD session is up
+# - Configure an SPF delay-ietf initial delay of 60 seconds on both rt5 and rt6
+# - Shut down the eth-rt5 interface on rt6 from the switch side to test fast-reroute
#
# Expected changes:
-# - No routing table change
-# - At the end of test, SPF reacts to a failure in 15s
+# - Verify that the BFD session is down
+# - Routes should switch over to use alternate paths
+# - On rt5, the switchover should be triggered by the link down event
+# - On rt6, the switchover should be triggered by the BFD down event, since it has
+# link-detect disabled on the eth-rt5 interface
#
def test_rib_ipv4_step10():
logger.info("Test (step 10): verify IPv4 RIB")
@@ -748,353 +879,69 @@ def test_rib_ipv4_step10():
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
- logger.info("Setting spf-delay-ietf init-delay of 15s")
- tgen.net["rt6"].cmd(
- 'vtysh -c "conf t" -c "router isis 1" -c "spf-delay-ietf init-delay 15000 short-delay 0 long-delay 0 holddown 0 time-to-learn 0"'
- )
-
- for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
- router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][10]["show_ip_route.ref"]
- )
-
-
-def test_rib_ipv6_step10():
- logger.info("Test (step 10): verify IPv6 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 ipv6 route isis json",
- outputs[rname][10]["show_ipv6_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", outputs[rname][10]["show_mpls_table.ref"]
- )
-
-
-#
-# Step 11
-#
-# Action(s):
-# - shut the eth-rt5 interface on rt6
-#
-# Expected changes:
-# - Route switchover of routes via eth-rt5
-#
-def test_rt6_step11():
- logger.info(
- "Test (step 11): Check IPv4/6 RIB and MPLS table after a LFA switchover"
- )
- tgen = get_topogen()
-
- # Skip if previous fatal error condition is raised
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- logger.info(
- "Shut a rt6 interface to rt5 from the switch side and check fast-reroute"
- )
- tgen.net.cmd_raises("ip link set %s down" % tgen.net["s8"].intfs[1])
-
- rname = "rt6"
- router_compare_json_output(
- rname,
- "show ip route isis json",
- outputs[rname][11]["show_ip_route.ref"],
- count=20,
- )
- router_compare_json_output(
- rname,
- "show ipv6 route isis json",
- outputs[rname][11]["show_ipv6_route.ref"],
- count=20,
- )
- router_compare_json_output(
- rname,
- "show mpls table json",
- outputs[rname][11]["show_mpls_table.ref"],
- count=20,
- )
-
-
-#
-# Step 12
-#
-# Action(s): wait for the convergence and SPF computation on rt6
-#
-# Expected changes:
-# - convergence of IPv4/6 RIB and MPLS table
-#
-def test_rib_ipv4_step12():
- logger.info("Test (step 12): 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("Check SPF convergence")
- for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
- router_compare_json_output(
- rname,
- "show ip route isis json",
- outputs[rname][12]["show_ip_route.ref"],
- )
-
-
-def test_rib_ipv6_step12():
- logger.info("Test (step 12): verify IPv6 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 ipv6 route isis json",
- outputs[rname][12]["show_ipv6_route.ref"],
- )
-
-
-def test_mpls_lib_step12():
- logger.info("Test (step 12): 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",
- outputs[rname][12]["show_mpls_table.ref"],
- )
-
-
-#
-# Step 13
-#
-# Action(s):
-# - unshut the rt6 to rt5 interface
-# - Setup BFD
-#
-# Expected changes:
-# - All route tables go back to previous state situation
-# - At the end of test, next SPF is scheduled in approximatively 15s
-#
-def test_rib_ipv4_step13():
- logger.info("Test (step 13): 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("Unsetting spf-delay-ietf init-delay of 15s")
- tgen.net["rt6"].cmd('vtysh -c "conf t" -c "router isis 1" -c "no spf-delay-ietf"')
-
- logger.info(
- "Unshut the rt6 interface to rt5 from the switch side and check fast-reroute"
- )
- tgen.net.cmd_raises("ip link set %s up" % tgen.net["s8"].intfs[1])
-
- logger.info("Setup BFD on rt5 and rt6")
- for rname in ["rt5", "rt6"]:
- conf_file = os.path.join(CWD, "{}/bfdd.conf".format(rname))
- tgen.net[rname].cmd("vtysh -f {}".format(conf_file))
-
- expect = (
- '[{"multihop":false,"peer":"10.0.8.5","interface":"eth-rt5","status":"up"}]'
- )
- router_compare_json_output("rt6", "show bfd peers json", expect)
-
- # Unset link detection. We want zebra to consider linkdow as operationaly up
- # in order that BFD triggers LFA instead of the interface down
-
- # reset spf-interval
- logger.info("Set spf-interval to 15s")
- tgen.net["rt6"].cmd(
- 'vtysh -c "conf t" -c "router isis 1" -c "spf-delay-ietf init-delay 15000 short-delay 0 long-delay 0 holddown 0 time-to-learn 0"'
- )
-
- for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
- router_compare_json_output(
- rname, "show ip route isis json", outputs[rname][10]["show_ip_route.ref"]
- )
-
- logger.info("Set ISIS BFD")
+ logger.info("Enabling ISIS BFD between rt5 and rt6")
tgen.net["rt5"].cmd('vtysh -c "conf t" -c "int eth-rt6" -c "isis bfd"')
tgen.net["rt6"].cmd('vtysh -c "conf t" -c "int eth-rt5" -c "isis bfd"')
- expect = (
- '[{"multihop":false,"peer":"10.0.8.5","interface":"eth-rt5","status":"up"}]'
- )
+ logger.info("Checking if the BFD session is up")
+ expect = '{"multihop":false,"peer":"10.0.8.5","interface":"eth-rt5","status":"up"}'
router_compare_json_output(
- rname,
- "show bfd peers json",
- expect,
+ "rt6", "show bfd peer 10.0.8.5 json", 10, "show_bfd_peer_up.ref"
)
-
-def test_rib_ipv6_step13():
- logger.info("Test (step 13): verify IPv6 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 ipv6 route isis json",
- outputs[rname][10]["show_ipv6_route.ref"],
- )
-
-
-def test_mpls_lib_step13():
- logger.info("Test (step 13): 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", outputs[rname][10]["show_mpls_table.ref"]
+ logger.info("Setting SPF delay-ietf initial delay to 60 seconds")
+ for rname in ["rt5", "rt6"]:
+ tgen.net[rname].cmd(
+ 'vtysh -c "conf t" -c "router isis 1" -c "spf-delay-ietf init-delay 60000 short-delay 0 long-delay 0 holddown 0 time-to-learn 0"'
)
-
-#
-# Step 14
-#
-# Action(s):
-# - drop traffic between rt5 and rt6 by shutting down the bridge between
-# the routers. Interfaces on rt5 and rt6 stay up.
-#
-# Expected changes:
-# - Route switchover of routes via eth-rt5
-#
-def test_rt6_step14():
- logger.info("Test (step 14): verify IPv4/6 RIB and MPLS table")
- tgen = get_topogen()
-
- # Skip if previous fatal error condition is raised
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- logger.info("Drop traffic between rt5 and rt6")
- tgen.net.cmd_raises("ip link set s8 down")
-
- rname = "rt6"
-
- expect = (
- '[{"multihop":false,"peer":"10.0.8.5","interface":"eth-rt5","status":"down"}]'
- )
- router_compare_json_output(
- rname,
- "show bfd peers json",
- expect,
- count=40,
- wait=0.5,
+ logger.info(
+ "Shutting down rt5 interface to rt6 from the switch side to test fast-reroute"
)
+ tgen.net.cmd_raises("ip link set %s down" % tgen.net["s8"].intfs[0])
- router_compare_json_output(
- rname,
- "show ip route isis json",
- outputs[rname][11]["show_ip_route.ref"],
- count=20,
- )
- router_compare_json_output(
- rname,
- "show ipv6 route isis json",
- outputs[rname][11]["show_ipv6_route.ref"],
- count=20,
- wait=2,
+ logger.info("Verifying if the BFD session is down")
+ expect = (
+ '{"multihop":false,"peer":"10.0.8.5","interface":"eth-rt5","status":"down"}'
)
router_compare_json_output(
- rname,
- "show mpls table json",
- outputs[rname][11]["show_mpls_table.ref"],
- count=20,
+ "rt6", "show bfd peer 10.0.8.5 json", 10, "show_bfd_peer_down.ref"
)
-
-#
-# Step 15
-#
-# Action(s): wait for the convergence and SPF computation on rt6
-#
-# Expected changes:
-# - convergence of IPv4/6 RIB and MPLS table
-#
-def test_rib_ipv4_step15():
- logger.info("Test (step 15): 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("Check SPF convergence")
- for rname in ["rt1", "rt2", "rt3", "rt4", "rt5", "rt6"]:
+ for rname in ["rt5", "rt6"]:
router_compare_json_output(
- rname,
- "show ip route isis json",
- outputs[rname][12]["show_ip_route.ref"],
+ rname, "show ip route isis json", 10, "show_ip_route.ref"
)
-def test_rib_ipv6_step15():
- logger.info("Test (step 15): verify IPv6 RIB")
+def test_rib_ipv6_step10():
+ logger.info("Test (step 10): verify IPv6 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"]:
+ for rname in ["rt5", "rt6"]:
router_compare_json_output(
rname,
"show ipv6 route isis json",
- outputs[rname][12]["show_ipv6_route.ref"],
+ 10,
+ "show_ipv6_route.ref",
)
-def test_mpls_lib_step15():
- logger.info("Test (step 15): verify MPLS LIB")
+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"]:
+ for rname in ["rt5", "rt6"]:
router_compare_json_output(
- rname,
- "show mpls table json",
- outputs[rname][12]["show_mpls_table.ref"],
+ rname, "show mpls table json", 10, "show_mpls_table.ref"
)
diff --git a/tests/topotests/isis_topo1/test_isis_topo1.py b/tests/topotests/isis_topo1/test_isis_topo1.py
index 532e708..b388f52 100644
--- a/tests/topotests/isis_topo1/test_isis_topo1.py
+++ b/tests/topotests/isis_topo1/test_isis_topo1.py
@@ -685,7 +685,7 @@ def _check_lsp_overload_bit(router, overloaded_router_lsp, att_p_ol_expected):
)
database_json = json.loads(isis_database_output)
- att_p_ol = database_json["areas"][0]["levels"][1]["att-p-ol"]
+ att_p_ol = database_json["areas"][0]["levels"][1]["lsps"][0]["attPOl"]
if att_p_ol == att_p_ol_expected:
return True
return "{} peer with expected att_p_ol {} got {} ".format(
diff --git a/tests/topotests/key_sendaccept/r1/frr.conf b/tests/topotests/key_sendaccept/r1/frr.conf
new file mode 100644
index 0000000..d231634
--- /dev/null
+++ b/tests/topotests/key_sendaccept/r1/frr.conf
@@ -0,0 +1,31 @@
+log timestamp precision 6
+log file frr.log debug
+
+! debug northbound libyang
+
+debug northbound notifications
+debug northbound events
+debug northbound callbacks
+
+debug mgmt backend datastore frontend transaction
+debug mgmt client frontend
+debug mgmt client backend
+
+interface r1-eth0
+ ip address 1.1.1.1/24
+
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+exit
+
+router ospf
+ ospf router-id 1.1.1.1
+ network 1.1.1.0/24 area 0
+exit
+
+router rip
+ network 1.1.1.0/24
+ network r1-eth0
+exit
+
+!ip route 250.0.0.1/32 Null0 \ No newline at end of file
diff --git a/tests/topotests/key_sendaccept/r2/frr.conf b/tests/topotests/key_sendaccept/r2/frr.conf
new file mode 100644
index 0000000..95bb6e2
--- /dev/null
+++ b/tests/topotests/key_sendaccept/r2/frr.conf
@@ -0,0 +1,20 @@
+log timestamp precision 6
+log file frr.log debug
+
+interface r2-eth0
+ ip address 1.1.1.2/24
+
+ ip ospf hello-interval 2
+ ip ospf dead-interval 10
+exit
+
+router ospf
+ ospf router-id 2.2.2.2
+ network 1.1.1.0/24 area 0
+exit
+
+router rip
+ network 1.1.1.0/24
+exit
+
+ip route 250.0.0.2/32 Null0 \ No newline at end of file
diff --git a/tests/topotests/key_sendaccept/test_keychain.py b/tests/topotests/key_sendaccept/test_keychain.py
new file mode 100644
index 0000000..b11d31b
--- /dev/null
+++ b/tests/topotests/key_sendaccept/test_keychain.py
@@ -0,0 +1,150 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# March 4 2024, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2024, LabN Consulting, L.L.C.
+#
+"""
+Test static route functionality
+"""
+import json
+
+import pytest
+from lib.topogen import Topogen
+
+pytestmark = [pytest.mark.ripd, pytest.mark.mgmtd]
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ topodef = {"s1": ("r1", "r2")}
+
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.load_frr_config("frr.conf")
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+DIR_SEND = 0
+DIR_ACCEPT = 1
+
+
+def is_key_active(router, keychain, keyid, direction):
+ dstr = "send" if direction == DIR_SEND else "accept"
+ node = f"{dstr}-lifetime-active"
+ output = router.net.cmd_raises(
+ "vtysh -c 'show mgmt get-data "
+ f'/ietf-key-chain:key-chains/key-chain[name="{keychain}"]'
+ f'/key[key-id="{keyid}"]/{node} json'
+ "'"
+ )
+ jd = json.loads(output)
+ return jd["ietf-key-chain:key-chains"]["key-chain"][0]["key"][0][node]
+
+
+def test_send_accept(tgen):
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ conf = """conf t
+key chain kc
+ key 1
+ key-string theSecret
+ cryptographic-algorithm hmac-sha-256
+ exit
+exit
+"""
+ r1.vtysh_multicmd(conf.split("\n"), pretty_output=True)
+ assert is_key_active(r1, "kc", 1, DIR_SEND)
+ assert is_key_active(r1, "kc", 1, DIR_ACCEPT)
+
+ conf = """conf t
+key chain kc
+ key 1
+ key-string theSecret
+ cryptographic-algorithm hmac-sha-256
+ send-lifetime 00:00:00 Jan 1 2024 infinite
+ accept-lifetime 00:00:00 Jan 1 2024 infinite
+ exit
+exit
+"""
+ r1.vtysh_multicmd(conf.split("\n"), pretty_output=True)
+ assert is_key_active(r1, "kc", 1, DIR_SEND)
+ assert is_key_active(r1, "kc", 1, DIR_ACCEPT)
+
+ conf = """conf t
+key chain kc
+ key 1
+ send-lifetime 00:00:00 Jan 1 2035 infinite
+ accept-lifetime 00:00:00 Jan 1 2035 infinite
+ exit
+exit
+"""
+ r1.vtysh_multicmd(conf.split("\n"), pretty_output=True)
+ assert not is_key_active(r1, "kc", 1, DIR_SEND)
+ assert not is_key_active(r1, "kc", 1, DIR_ACCEPT)
+
+ secs_in_10_years = 60 * 60 * 24 * 365 * 10
+ conf = f"""conf t
+key chain kc
+ key 2
+ key-string theSecret
+ cryptographic-algorithm hmac-sha-256
+ send-lifetime 00:00:00 Jan 1 2024 duration {secs_in_10_years}
+ accept-lifetime 00:00:00 Jan 1 2024 duration {secs_in_10_years}
+ exit
+exit
+"""
+ r1.vtysh_multicmd(conf.split("\n"), pretty_output=True)
+ assert is_key_active(r1, "kc", 2, DIR_SEND)
+ assert is_key_active(r1, "kc", 2, DIR_ACCEPT)
+
+ conf = f"""conf t
+key chain kc
+ key 2
+ send-lifetime 00:00:00 Jan 1 2000 duration 10
+ accept-lifetime 00:00:00 Jan 1 2000 duration 10
+ exit
+exit
+"""
+ r1.vtysh_multicmd(conf.split("\n"), pretty_output=True)
+ assert not is_key_active(r1, "kc", 2, DIR_SEND)
+ assert not is_key_active(r1, "kc", 2, DIR_ACCEPT)
+
+ conf = """conf t
+key chain kc
+ key 3
+ key-string theSecret
+ cryptographic-algorithm hmac-sha-256
+ send-lifetime 00:00:00 Jan 1 2024 23:59:59 Dec 31 2034
+ accept-lifetime 00:00:00 Jan 1 2024 23:59:59 Dec 31 2034
+ exit
+exit
+"""
+ r1.vtysh_multicmd(conf.split("\n"), pretty_output=True)
+ assert is_key_active(r1, "kc", 3, DIR_SEND)
+ assert is_key_active(r1, "kc", 3, DIR_ACCEPT)
+
+ conf = """conf t
+key chain kc
+ key 3
+ send-lifetime 00:00:00 Dec 1 2035 23:59:59 Dec 31 2034
+ accept-lifetime 00:00:00 Dec 1 2035 23:59:59 Dec 31 2034
+ exit
+exit
+"""
+ r1.vtysh_multicmd(conf.split("\n"), pretty_output=True)
+ assert not is_key_active(r1, "kc", 3, DIR_SEND)
+ assert not is_key_active(r1, "kc", 3, DIR_ACCEPT)
diff --git a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync.ref b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync.ref
index 6c27a10..846be5b 100644
--- a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync.ref
+++ b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync.ref
@@ -5,8 +5,8 @@
"ldpIgpSyncState":"Sync achieved"
},
"r2-eth2":{
- "ldpIgpSyncEnabled":false,
+ "ldpIgpSyncEnabled":true,
"holdDownTimeInSec":50,
- "ldpIgpSyncState":"Sync not required"
+ "ldpIgpSyncState":"Sync achieved"
}
}
diff --git a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r1_eth1_shutdown.ref
index 889f69e..ad3b8b5 100644
--- a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r1_eth1_shutdown.ref
+++ b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r1_eth1_shutdown.ref
@@ -5,8 +5,8 @@
"ldpIgpSyncState":"Holding down until Sync"
},
"r2-eth2":{
- "ldpIgpSyncEnabled":false,
+ "ldpIgpSyncEnabled":true,
"holdDownTimeInSec":50,
- "ldpIgpSyncState":"Sync not required"
+ "ldpIgpSyncState":"Sync achieved"
}
}
diff --git a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r2_eth1_shutdown.ref b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r2_eth1_shutdown.ref
index d9036e1..d5e4b88 100644
--- a/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r2_eth1_shutdown.ref
+++ b/tests/topotests/ldp_sync_ospf_topo1/r2/show_ospf_ldp_sync_r2_eth1_shutdown.ref
@@ -1,7 +1,7 @@
{
"r2-eth2":{
- "ldpIgpSyncEnabled":false,
+ "ldpIgpSyncEnabled":true,
"holdDownTimeInSec":50,
- "ldpIgpSyncState":"Sync not required"
+ "ldpIgpSyncState":"Sync achieved"
}
}
diff --git a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync.ref b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync.ref
index b417ab0..5b9542d 100644
--- a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync.ref
+++ b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync.ref
@@ -1,8 +1,8 @@
{
"r3-eth1":{
- "ldpIgpSyncEnabled":false,
+ "ldpIgpSyncEnabled":true,
"holdDownTimeInSec":50,
- "ldpIgpSyncState":"Sync not required"
+ "ldpIgpSyncState":"Sync achieved"
},
"r3-eth2":{
"ldpIgpSyncEnabled":true,
diff --git a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r1_eth1_shutdown.ref b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r1_eth1_shutdown.ref
index b417ab0..5b9542d 100644
--- a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r1_eth1_shutdown.ref
+++ b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r1_eth1_shutdown.ref
@@ -1,8 +1,8 @@
{
"r3-eth1":{
- "ldpIgpSyncEnabled":false,
+ "ldpIgpSyncEnabled":true,
"holdDownTimeInSec":50,
- "ldpIgpSyncState":"Sync not required"
+ "ldpIgpSyncState":"Sync achieved"
},
"r3-eth2":{
"ldpIgpSyncEnabled":true,
diff --git a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r2_eth1_shutdown.ref b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r2_eth1_shutdown.ref
index b417ab0..5b9542d 100644
--- a/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r2_eth1_shutdown.ref
+++ b/tests/topotests/ldp_sync_ospf_topo1/r3/show_ospf_ldp_sync_r2_eth1_shutdown.ref
@@ -1,8 +1,8 @@
{
"r3-eth1":{
- "ldpIgpSyncEnabled":false,
+ "ldpIgpSyncEnabled":true,
"holdDownTimeInSec":50,
- "ldpIgpSyncState":"Sync not required"
+ "ldpIgpSyncState":"Sync achieved"
},
"r3-eth2":{
"ldpIgpSyncEnabled":true,
diff --git a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py
index 6c814ee..e1e6b51 100644
--- a/tests/topotests/lib/bmp_collector/bgp/open/__init__.py
+++ b/tests/topotests/lib/bmp_collector/bgp/open/__init__.py
@@ -8,27 +8,29 @@ import struct
class BGPOpen:
- UNPACK_STR = '!16sHBBHH4sB'
+ UNPACK_STR = "!16sHBBHH4sB"
@classmethod
def dissect(cls, data):
- (marker,
- length,
- open_type,
- version,
- my_as,
- hold_time,
- bgp_id,
- optional_params_len) = struct.unpack_from(cls.UNPACK_STR, data)
+ (
+ marker,
+ length,
+ open_type,
+ version,
+ my_as,
+ hold_time,
+ bgp_id,
+ optional_params_len,
+ ) = struct.unpack_from(cls.UNPACK_STR, data)
- data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len:]
+ data = data[struct.calcsize(cls.UNPACK_STR) + optional_params_len :]
# XXX: parse optional parameters
return data, {
- 'version': version,
- 'my_as': my_as,
- 'hold_time': hold_time,
- 'bgp_id': ipaddress.ip_address(bgp_id),
- 'optional_params_len': optional_params_len,
+ "version": version,
+ "my_as": my_as,
+ "hold_time": hold_time,
+ "bgp_id": ipaddress.ip_address(bgp_id),
+ "optional_params_len": optional_params_len,
}
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py
index d079b35..629e175 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/__init__.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/__init__.py
@@ -10,45 +10,47 @@ from .nlri import NlriIPv4Unicast
from .path_attributes import PathAttribute
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BGPUpdate:
- UNPACK_STR = '!16sHBH'
+ UNPACK_STR = "!16sHBH"
STATIC_SIZE = 23
@classmethod
def dissect(cls, data):
- msg = {'bmp_log_type': 'update'}
+ msg = {"bmp_log_type": "update"}
common_size = struct.calcsize(cls.UNPACK_STR)
- (marker,
- length,
- update_type,
- withdrawn_routes_len) = struct.unpack_from(cls.UNPACK_STR, data)
+ (marker, length, update_type, withdrawn_routes_len) = struct.unpack_from(
+ cls.UNPACK_STR, data
+ )
# get withdrawn routes
- withdrawn_routes = ''
+ withdrawn_routes = ""
if withdrawn_routes_len:
withdrawn_routes = NlriIPv4Unicast.parse(
- data[common_size:common_size + withdrawn_routes_len]
+ data[common_size : common_size + withdrawn_routes_len]
)
- msg['bmp_log_type'] = 'withdraw'
+ msg["bmp_log_type"] = "withdraw"
msg.update(withdrawn_routes)
# get path attributes
(total_path_attrs_len,) = struct.unpack_from(
- '!H', data[common_size+withdrawn_routes_len:])
+ "!H", data[common_size + withdrawn_routes_len :]
+ )
if total_path_attrs_len:
offset = cls.STATIC_SIZE + withdrawn_routes_len
- path_attrs_data = data[offset:offset + total_path_attrs_len]
+ path_attrs_data = data[offset : offset + total_path_attrs_len]
while path_attrs_data:
path_attrs_data, pattr = PathAttribute.dissect(path_attrs_data)
if pattr:
msg = {**msg, **pattr}
# get nlri
- nlri_len = length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len
+ nlri_len = (
+ length - cls.STATIC_SIZE - withdrawn_routes_len - total_path_attrs_len
+ )
if nlri_len > 0:
- nlri = NlriIPv4Unicast.parse(data[length - nlri_len:length])
+ nlri = NlriIPv4Unicast.parse(data[length - nlri_len : length])
msg.update(nlri)
return data[length:], msg
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/af.py b/tests/topotests/lib/bmp_collector/bgp/update/af.py
index 01af1ae..200b15a 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/af.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/af.py
@@ -19,7 +19,7 @@ SAFI_IP_FLOWSPEC = 133
SAFI_VPN_FLOWSPEC = 134
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class AddressFamily:
def __init__(self, afi, safi):
self.afi = afi
@@ -31,13 +31,13 @@ class AddressFamily:
return (self.afi, self.safi) == (other.afi, other.safi)
def __str__(self):
- return f'afi: {self.afi}, safi: {self.safi}'
+ return f"afi: {self.afi}, safi: {self.safi}"
def __hash__(self):
return hash((self.afi, self.safi))
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class AF:
IPv4_UNICAST = AddressFamily(AFI_IP, SAFI_UNICAST)
IPv6_UNICAST = AddressFamily(AFI_IP6, SAFI_UNICAST)
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py
index c1720f1..b362520 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/nlri.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/nlri.py
@@ -13,7 +13,8 @@ from .rd import RouteDistinguisher
def decode_label(label):
# from frr
# frr encode just one label
- return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xf0) >> 4
+ return (label[0] << 12) | (label[1] << 4) | (label[2] & 0xF0) >> 4
+
def padding(databin, len_):
"""
@@ -23,7 +24,8 @@ def padding(databin, len_):
"""
if len(databin) >= len_:
return databin
- return databin + b'\0' * (len_ - len(databin))
+ return databin + b"\0" * (len_ - len(databin))
+
def dissect_nlri(nlri_data, afi, safi):
"""
@@ -37,35 +39,34 @@ def dissect_nlri(nlri_data, afi, safi):
elif addr_family == AF.IPv6_UNICAST:
return NlriIPv6Unicast.parse(nlri_data)
- return {'ip_prefix': 'Unknown'}
+ return {"ip_prefix": "Unknown"}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4Unicast:
-
@staticmethod
def parse(data):
"""parses prefixes from withdrawn_routes or nrli data"""
- (prefix_len,) = struct.unpack_from('!B', data)
+ (prefix_len,) = struct.unpack_from("!B", data)
prefix = padding(data[1:], 4)
- return {'ip_prefix': f'{ipaddress.IPv4Address(prefix)}/{prefix_len}'}
+ return {"ip_prefix": f"{ipaddress.IPv4Address(prefix)}/{prefix_len}"}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6Unicast:
@staticmethod
def parse(data):
"""parses prefixes from withdrawn_routes or nrli data"""
- (prefix_len,) = struct.unpack_from('!B', data)
+ (prefix_len,) = struct.unpack_from("!B", data)
prefix = padding(data[1:], 16)
- return {'ip_prefix': f'{ipaddress.IPv6Address(prefix)}/{prefix_len}'}
+ return {"ip_prefix": f"{ipaddress.IPv6Address(prefix)}/{prefix_len}"}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4Vpn:
- UNPACK_STR = '!B3s8s'
+ UNPACK_STR = "!B3s8s"
@classmethod
def parse(cls, data):
@@ -74,17 +75,17 @@ class NlriIPv4Vpn:
ipv4 = padding(data[offset:], 4)
# prefix_len = total_bits_len - label_bits_len - rd_bits_len
- prefix_len = bit_len - 3*8 - 8*8
+ prefix_len = bit_len - 3 * 8 - 8 * 8
return {
- 'label': decode_label(label),
- 'rd': str(RouteDistinguisher(rd)),
- 'ip_prefix': f'{ipaddress.IPv4Address(ipv4)}/{prefix_len}',
+ "label": decode_label(label),
+ "rd": str(RouteDistinguisher(rd)),
+ "ip_prefix": f"{ipaddress.IPv4Address(ipv4)}/{prefix_len}",
}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6Vpn:
- UNPACK_STR = '!B3s8s'
+ UNPACK_STR = "!B3s8s"
@classmethod
def parse(cls, data):
@@ -93,48 +94,49 @@ class NlriIPv6Vpn:
offset = struct.calcsize(cls.UNPACK_STR)
ipv6 = padding(data[offset:], 16)
- prefix_len = bit_len - 3*8 - 8*8
+ prefix_len = bit_len - 3 * 8 - 8 * 8
return {
- 'label': decode_label(label),
- 'rd': str(RouteDistinguisher(rd)),
- 'ip_prefix': f'{ipaddress.IPv6Address(ipv6)}/{prefix_len}',
+ "label": decode_label(label),
+ "rd": str(RouteDistinguisher(rd)),
+ "ip_prefix": f"{ipaddress.IPv6Address(ipv6)}/{prefix_len}",
}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4Mpls:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6Mpls:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv4FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriIPv6FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriVpn4FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriVpn6FlowSpec:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class NlriL2EVPN:
pass
-#------------------------------------------------------------------------------
+
+# ------------------------------------------------------------------------------
class NlriL2VPNFlowSpec:
pass
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
index 6e82e9c..3694cb4 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/path_attributes.py
@@ -38,17 +38,18 @@ ORIGIN_EGP = 0x01
ORIGIN_INCOMPLETE = 0x02
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttribute:
PATH_ATTRS = {}
UNKNOWN_ATTR = None
- UNPACK_STR = '!BB'
+ UNPACK_STR = "!BB"
@classmethod
def register_path_attr(cls, path_attr):
def _register_path_attr(subcls):
cls.PATH_ATTRS[path_attr] = subcls
return subcls
+
return _register_path_attr
@classmethod
@@ -61,7 +62,7 @@ class PathAttribute:
offset = struct.calcsize(cls.UNPACK_STR)
# get attribute length
- attr_len_str = '!H' if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else '!B'
+ attr_len_str = "!H" if (flags & PATH_ATTR_FLAG_EXTENDED_LENGTH) else "!B"
(attr_len,) = struct.unpack_from(attr_len_str, data[offset:])
@@ -69,32 +70,34 @@ class PathAttribute:
path_attr_cls = cls.lookup_path_attr(type_code)
if path_attr_cls == cls.UNKNOWN_ATTR:
- return data[offset + attr_len:], None
+ return data[offset + attr_len :], None
- return data[offset+attr_len:], path_attr_cls.dissect(data[offset:offset+attr_len])
+ return data[offset + attr_len :], path_attr_cls.dissect(
+ data[offset : offset + attr_len]
+ )
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_ORIGIN)
class PathAttrOrigin:
ORIGIN_STR = {
- ORIGIN_IGP: 'IGP',
- ORIGIN_EGP: 'EGP',
- ORIGIN_INCOMPLETE: 'INCOMPLETE',
+ ORIGIN_IGP: "IGP",
+ ORIGIN_EGP: "EGP",
+ ORIGIN_INCOMPLETE: "INCOMPLETE",
}
@classmethod
def dissect(cls, data):
- (origin,) = struct.unpack_from('!B', data)
+ (origin,) = struct.unpack_from("!B", data)
- return {'origin': cls.ORIGIN_STR.get(origin, 'UNKNOWN')}
+ return {"origin": cls.ORIGIN_STR.get(origin, "UNKNOWN")}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_AS_PATH)
class PathAttrAsPath:
AS_PATH_TYPE_SET = 0x01
- AS_PATH_TYPE_SEQUENCE= 0x02
+ AS_PATH_TYPE_SEQUENCE = 0x02
@staticmethod
def get_asn_len(asns):
@@ -103,34 +106,34 @@ class PathAttrAsPath:
@classmethod
def dissect(cls, data):
- (_type, _len) = struct.unpack_from('!BB', data)
+ (_type, _len) = struct.unpack_from("!BB", data)
data = data[2:]
- _type_str = 'Ordred' if _type == cls.AS_PATH_TYPE_SEQUENCE else 'Raw'
+ _type_str = "Ordred" if _type == cls.AS_PATH_TYPE_SEQUENCE else "Raw"
segment = []
while data:
- (asn,) = struct.unpack_from('!I', data)
+ (asn,) = struct.unpack_from("!I", data)
segment.append(asn)
data = data[4:]
- return {'as_path': ' '.join(str(a) for a in segment)}
+ return {"as_path": " ".join(str(a) for a in segment)}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_NEXT_HOP)
class PathAttrNextHop:
@classmethod
def dissect(cls, data):
- (nexthop,) = struct.unpack_from('!4s', data)
- return {'bgp_nexthop': str(ipaddress.IPv4Address(nexthop))}
+ (nexthop,) = struct.unpack_from("!4s", data)
+ return {"bgp_nexthop": str(ipaddress.IPv4Address(nexthop))}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrMultiExitDisc:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_REACH_NLRI)
class PathAttrMpReachNLRI:
"""
@@ -162,7 +165,8 @@ class PathAttrMpReachNLRI:
| Network Layer Reachability Information (variable) |
+---------------------------------------------------------+
"""
- UNPACK_STR = '!HBB'
+
+ UNPACK_STR = "!HBB"
NLRI_RESERVED_LEN = 1
@staticmethod
@@ -170,35 +174,35 @@ class PathAttrMpReachNLRI:
msg = {}
if nexthop_len == 4:
# IPv4
- (ipv4,) = struct.unpack_from('!4s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4))
+ (ipv4,) = struct.unpack_from("!4s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4))
elif nexthop_len == 12:
# RD + IPv4
- (rd, ipv4) = struct.unpack_from('!8s4s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv4Address(ipv4))
- msg['nxhp_rd'] = str(RouteDistinguisher(rd))
+ (rd, ipv4) = struct.unpack_from("!8s4s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv4Address(ipv4))
+ msg["nxhp_rd"] = str(RouteDistinguisher(rd))
elif nexthop_len == 16:
# IPv6
- (ipv6,) = struct.unpack_from('!16s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
+ (ipv6,) = struct.unpack_from("!16s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
elif nexthop_len == 24:
# RD + IPv6
- (rd, ipv6) = struct.unpack_from('!8s16s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
- msg['nxhp_rd'] = str(RouteDistinguisher(rd))
+ (rd, ipv6) = struct.unpack_from("!8s16s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
+ msg["nxhp_rd"] = str(RouteDistinguisher(rd))
elif nexthop_len == 32:
# IPv6 + IPv6 link-local
- (ipv6, link_local)= struct.unpack_from('!16s16s', nexthop_data)
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
- msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local))
+ (ipv6, link_local) = struct.unpack_from("!16s16s", nexthop_data)
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
+ msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local))
elif nexthop_len == 48:
# RD + IPv6 + RD + IPv6 link-local
- u_str = '!8s16s8s16s'
- (rd1, ipv6, rd2, link_local)= struct.unpack_from(u_str, nexthop_data)
- msg['nxhp_rd1'] = str(RouteDistinguisher(rd1))
- msg['nxhp_ip'] = str(ipaddress.IPv6Address(ipv6))
- msg['nxhp_rd2'] = str(RouteDistinguisher(rd2))
- msg['nxhp_link-local'] = str(ipaddress.IPv6Address(link_local))
+ u_str = "!8s16s8s16s"
+ (rd1, ipv6, rd2, link_local) = struct.unpack_from(u_str, nexthop_data)
+ msg["nxhp_rd1"] = str(RouteDistinguisher(rd1))
+ msg["nxhp_ip"] = str(ipaddress.IPv6Address(ipv6))
+ msg["nxhp_rd2"] = str(RouteDistinguisher(rd2))
+ msg["nxhp_link-local"] = str(ipaddress.IPv6Address(link_local))
return msg
@@ -210,10 +214,10 @@ class PathAttrMpReachNLRI:
def dissect(cls, data):
(afi, safi, nexthop_len) = struct.unpack_from(cls.UNPACK_STR, data)
offset = struct.calcsize(cls.UNPACK_STR)
- msg = {'afi': afi, 'safi': safi}
+ msg = {"afi": afi, "safi": safi}
# dissect nexthop
- nexthop_data = data[offset: offset + nexthop_len]
+ nexthop_data = data[offset : offset + nexthop_len]
nexthop = cls.dissect_nexthop(nexthop_data, nexthop_len)
msg.update(nexthop)
@@ -227,7 +231,7 @@ class PathAttrMpReachNLRI:
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@PathAttribute.register_path_attr(PATH_ATTR_TYPE_MP_UNREACH_NLRI)
class PathAttrMpUnReachNLRI:
"""
@@ -239,13 +243,14 @@ class PathAttrMpUnReachNLRI:
| Withdrawn Routes (variable) |
+---------------------------------------------------------+
"""
- UNPACK_STR = '!HB'
+
+ UNPACK_STR = "!HB"
@classmethod
def dissect(cls, data):
(afi, safi) = struct.unpack_from(cls.UNPACK_STR, data)
offset = struct.calcsize(cls.UNPACK_STR)
- msg = {'bmp_log_type': 'withdraw','afi': afi, 'safi': safi}
+ msg = {"bmp_log_type": "withdraw", "afi": afi, "safi": safi}
if data[offset:]:
# dissect withdrawn_routes
@@ -254,51 +259,51 @@ class PathAttrMpUnReachNLRI:
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrLocalPref:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrAtomicAgregate:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrAggregator:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrCommunities:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrOriginatorID:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrClusterList:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrExtendedCommunities:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrPMSITunnel:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrLinkState:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class PathAttrLargeCommunities:
pass
diff --git a/tests/topotests/lib/bmp_collector/bgp/update/rd.py b/tests/topotests/lib/bmp_collector/bgp/update/rd.py
index c382fa8..3f08de5 100644
--- a/tests/topotests/lib/bmp_collector/bgp/update/rd.py
+++ b/tests/topotests/lib/bmp_collector/bgp/update/rd.py
@@ -7,7 +7,7 @@ import ipaddress
import struct
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class RouteDistinguisher:
"""
type 0:
@@ -28,32 +28,32 @@ class RouteDistinguisher:
+ | 4-bytes AS number (4 bytes)| Service Provider 2 bytes)|
+-------------------------------------------------------------------------+
"""
+
def __init__(self, rd):
self.rd = rd
self.as_number = None
self.admin_ipv4 = None
self.four_bytes_as = None
self.assigned_sp = None
- self.repr_str = ''
+ self.repr_str = ""
self.dissect()
def dissect(self):
- (rd_type,) = struct.unpack_from('!H', self.rd)
+ (rd_type,) = struct.unpack_from("!H", self.rd)
if rd_type == 0:
- (self.as_number,
- self.assigned_sp) = struct.unpack_from('!HI', self.rd[2:])
- self.repr_str = f'{self.as_number}:{self.assigned_sp}'
+ (self.as_number, self.assigned_sp) = struct.unpack_from("!HI", self.rd[2:])
+ self.repr_str = f"{self.as_number}:{self.assigned_sp}"
elif rd_type == 1:
- (self.admin_ipv4,
- self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:])
+ (self.admin_ipv4, self.assigned_sp) = struct.unpack_from("!IH", self.rd[2:])
ipv4 = str(ipaddress.IPv4Address(self.admin_ipv4))
- self.repr_str = f'{self.as_number}:{self.assigned_sp}'
+ self.repr_str = f"{self.as_number}:{self.assigned_sp}"
elif rd_type == 2:
- (self.four_bytes_as,
- self.assigned_sp) = struct.unpack_from('!IH', self.rd[2:])
- self.repr_str = f'{self.four_bytes_as}:{self.assigned_sp}'
+ (self.four_bytes_as, self.assigned_sp) = struct.unpack_from(
+ "!IH", self.rd[2:]
+ )
+ self.repr_str = f"{self.four_bytes_as}:{self.assigned_sp}"
def __str__(self):
return self.repr_str
diff --git a/tests/topotests/lib/bmp_collector/bmp.py b/tests/topotests/lib/bmp_collector/bmp.py
index 57f642a..237decd 100644
--- a/tests/topotests/lib/bmp_collector/bmp.py
+++ b/tests/topotests/lib/bmp_collector/bmp.py
@@ -33,30 +33,33 @@ IS_FILTERED = 1 << 7
if not os.path.exists(LOG_DIR):
os.makedirs(LOG_DIR)
+
def bin2str_ipaddress(ip_bytes, is_ipv6=False):
if is_ipv6:
return str(ipaddress.IPv6Address(ip_bytes))
return str(ipaddress.IPv4Address(ip_bytes[-4:]))
-def log2file(logs):
+
+def log2file(logs, log_file):
"""
XXX: extract the useful information and save it in a flat dictionnary
"""
- with open(LOG_FILE, 'a') as f:
+ with open(log_file, "a") as f:
f.write(json.dumps(logs) + "\n")
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPCodes:
"""
XXX: complete the list, provide RFCs.
"""
+
VERSION = 0x3
BMP_MSG_TYPE_ROUTE_MONITORING = 0x00
BMP_MSG_TYPE_STATISTICS_REPORT = 0x01
- BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION = 0x02
- BMP_MSG_TYPE_PEER_UP_NOTIFICATION = 0x03
+ BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION = 0x02
+ BMP_MSG_TYPE_PEER_UP_NOTIFICATION = 0x03
BMP_MSG_TYPE_INITIATION = 0x04
BMP_MSG_TYPE_TERMINATION = 0x05
BMP_MSG_TYPE_ROUTE_MIRRORING = 0x06
@@ -107,15 +110,15 @@ class BMPCodes:
# peer down reason code
BMP_PEER_DOWN_LOCAL_NOTIFY = 0x01
- BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0X02
- BMP_PEER_DOWN_REMOTE_NOTIFY = 0X03
- BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0X04
+ BMP_PEER_DOWN_LOCAL_NO_NOTIFY = 0x02
+ BMP_PEER_DOWN_REMOTE_NOTIFY = 0x03
+ BMP_PEER_DOWN_REMOTE_NO_NOTIFY = 0x04
BMP_PEER_DOWN_INFO_NO_LONGER = 0x05
- BMP_PEER_DOWN_SYSTEM_CLOSED = 0X06
+ BMP_PEER_DOWN_SYSTEM_CLOSED = 0x06
# termincation message types
BMP_TERM_TYPE_STRING = 0x00
- BMP_TERM_TYPE_REASON = 0X01
+ BMP_TERM_TYPE_REASON = 0x01
# termination reason code
BMP_TERM_REASON_ADMIN_CLOSE = 0x00
@@ -126,31 +129,32 @@ class BMPCodes:
# policy route tlv
BMP_ROUTE_POLICY_TLV_VRF = 0x00
- BMP_ROUTE_POLICY_TLV_POLICY= 0x01
+ BMP_ROUTE_POLICY_TLV_POLICY = 0x01
BMP_ROUTE_POLICY_TLV_PRE_POLICY = 0x02
BMP_ROUTE_POLICY_TLV_POST_POLICY = 0x03
BMP_ROUTE_POLICY_TLV_STRING = 0x04
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPMsg:
"""
XXX: should we move register_msg_type and look_msg_type
to generic Type class.
"""
+
TYPES = {}
UNKNOWN_TYPE = None
- HDR_STR = '!BIB'
+ HDR_STR = "!BIB"
MIN_LEN = struct.calcsize(HDR_STR)
TYPES_STR = {
- BMPCodes.BMP_MSG_TYPE_INITIATION: 'initiation',
- BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: 'peer down notification',
- BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: 'peer up notification',
- BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: 'route monitoring',
- BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: 'statistics report',
- BMPCodes.BMP_MSG_TYPE_TERMINATION: 'termination',
- BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: 'route mirroring',
- BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: 'route policy',
+ BMPCodes.BMP_MSG_TYPE_INITIATION: "initiation",
+ BMPCodes.BMP_MSG_TYPE_PEER_DOWN_NOTIFICATION: "peer down notification",
+ BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION: "peer up notification",
+ BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING: "route monitoring",
+ BMPCodes.BMP_MSG_TYPE_STATISTICS_REPORT: "statistics report",
+ BMPCodes.BMP_MSG_TYPE_TERMINATION: "termination",
+ BMPCodes.BMP_MSG_TYPE_ROUTE_MIRRORING: "route mirroring",
+ BMPCodes.BMP_MSG_TYPE_ROUTE_POLICY: "route policy",
}
@classmethod
@@ -158,6 +162,7 @@ class BMPMsg:
def _register_type(subcls):
cls.TYPES[msgtype] = subcls
return subcls
+
return _register_type
@classmethod
@@ -179,15 +184,15 @@ class BMPMsg:
if len(data) < cls.MIN_LEN:
pass
else:
- _version, _len, _type = struct.unpack(cls.HDR_STR, data[0:cls.MIN_LEN])
+ _version, _len, _type = struct.unpack(cls.HDR_STR, data[0 : cls.MIN_LEN])
return _version, _len, _type
@classmethod
- def dissect(cls, data):
+ def dissect(cls, data, log_file=None):
global SEQ
version, msglen, msgtype = cls.dissect_header(data)
- msg_data = data[cls.MIN_LEN:msglen]
+ msg_data = data[cls.MIN_LEN : msglen]
data = data[msglen:]
if version != BMPCodes.VERSION:
@@ -202,13 +207,13 @@ class BMPMsg:
msg_cls.MSG_LEN = msglen - cls.MIN_LEN
logs = msg_cls.dissect(msg_data)
logs["seq"] = SEQ
- log2file(logs)
+ log2file(logs, log_file if log_file else LOG_FILE)
SEQ += 1
return data
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPPerPeerMessage:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -229,30 +234,33 @@ class BMPPerPeerMessage:
| Timestamp (microseconds) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
- PEER_UNPACK_STR = '!BB8s16sI4sII'
+
+ PEER_UNPACK_STR = "!BB8s16sI4sII"
PEER_TYPE_STR = {
- BMPCodes.BMP_PEER_GLOBAL_INSTANCE: 'global instance',
- BMPCodes.BMP_PEER_RD_INSTANCE: 'route distinguisher instance',
- BMPCodes.BMP_PEER_LOCAL_INSTANCE: 'local instance',
- BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: 'loc-rib instance',
+ BMPCodes.BMP_PEER_GLOBAL_INSTANCE: "global instance",
+ BMPCodes.BMP_PEER_RD_INSTANCE: "route distinguisher instance",
+ BMPCodes.BMP_PEER_LOCAL_INSTANCE: "local instance",
+ BMPCodes.BMP_PEER_LOC_RIB_INSTANCE: "loc-rib instance",
}
@classmethod
def dissect(cls, data):
- (peer_type,
- peer_flags,
- peer_distinguisher,
- peer_address,
- peer_asn,
- peer_bgp_id,
- timestamp_secs,
- timestamp_microsecs) = struct.unpack_from(cls.PEER_UNPACK_STR, data)
-
- msg = {'peer_type': cls.PEER_TYPE_STR[peer_type]}
+ (
+ peer_type,
+ peer_flags,
+ peer_distinguisher,
+ peer_address,
+ peer_asn,
+ peer_bgp_id,
+ timestamp_secs,
+ timestamp_microsecs,
+ ) = struct.unpack_from(cls.PEER_UNPACK_STR, data)
+
+ msg = {"peer_type": cls.PEER_TYPE_STR[peer_type]}
if peer_type == 0x03:
- msg['is_filtered'] = bool(peer_flags & IS_FILTERED)
- msg['policy'] = 'loc-rib'
+ msg["is_filtered"] = bool(peer_flags & IS_FILTERED)
+ msg["policy"] = "loc-rib"
else:
# peer_flags = 0x0000 0000
# ipv6, post-policy, as-path, adj-rib-out, reserverdx4
@@ -260,29 +268,29 @@ class BMPPerPeerMessage:
is_as_path = bool(peer_flags & IS_AS_PATH)
is_post_policy = bool(peer_flags & IS_POST_POLICY)
is_ipv6 = bool(peer_flags & IS_IPV6)
- msg['policy'] = 'post-policy' if is_post_policy else 'pre-policy'
- msg['ipv6'] = is_ipv6
- msg['peer_ip'] = bin2str_ipaddress(peer_address, is_ipv6)
-
+ msg["policy"] = "post-policy" if is_post_policy else "pre-policy"
+ msg["ipv6"] = is_ipv6
+ msg["peer_ip"] = bin2str_ipaddress(peer_address, is_ipv6)
peer_bgp_id = bin2str_ipaddress(peer_bgp_id)
- timestamp = float(timestamp_secs) + timestamp_microsecs * (10 ** -6)
-
- data = data[struct.calcsize(cls.PEER_UNPACK_STR):]
- msg.update({
- 'peer_distinguisher': str(RouteDistinguisher(peer_distinguisher)),
- 'peer_asn': peer_asn,
- 'peer_bgp_id': peer_bgp_id,
- 'timestamp': str(datetime.datetime.fromtimestamp(timestamp)),
- })
+ timestamp = float(timestamp_secs) + timestamp_microsecs * (10**-6)
+
+ data = data[struct.calcsize(cls.PEER_UNPACK_STR) :]
+ msg.update(
+ {
+ "peer_distinguisher": str(RouteDistinguisher(peer_distinguisher)),
+ "peer_asn": peer_asn,
+ "peer_bgp_id": peer_bgp_id,
+ "timestamp": str(datetime.datetime.fromtimestamp(timestamp)),
+ }
+ )
return data, msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_ROUTE_MONITORING)
class BMPRouteMonitoring(BMPPerPeerMessage):
-
@classmethod
def dissect(cls, data):
data, peer_msg = super().dissect(data)
@@ -290,7 +298,7 @@ class BMPRouteMonitoring(BMPPerPeerMessage):
return {**peer_msg, **update_msg}
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPStatisticsReport:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -303,10 +311,11 @@ class BMPStatisticsReport:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
+
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPPeerDownNotification:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -316,10 +325,11 @@ class BMPPeerDownNotification:
| Data (present if Reason = 1, 2 or 3) |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
+
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_PEER_UP_NOTIFICATION)
class BMPPeerUpNotification(BMPPerPeerMessage):
"""
@@ -336,7 +346,8 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
- UNPACK_STR = '!16sHH'
+
+ UNPACK_STR = "!16sHH"
MIN_LEN = struct.calcsize(UNPACK_STR)
MSG_LEN = None
@@ -344,16 +355,14 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
def dissect(cls, data):
data, peer_msg = super().dissect(data)
- (local_addr,
- local_port,
- remote_port) = struct.unpack_from(cls.UNPACK_STR, data)
+ (local_addr, local_port, remote_port) = struct.unpack_from(cls.UNPACK_STR, data)
msg = {
**peer_msg,
**{
- 'local_ip': bin2str_ipaddress(local_addr, peer_msg.get('ipv6')),
- 'local_port': int(local_port),
- 'remote_port': int(remote_port),
+ "local_ip": bin2str_ipaddress(local_addr, peer_msg.get("ipv6")),
+ "local_port": int(local_port),
+ "remote_port": int(remote_port),
},
}
@@ -362,7 +371,7 @@ class BMPPeerUpNotification(BMPPerPeerMessage):
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
@BMPMsg.register_msg_type(BMPCodes.BMP_MSG_TYPE_INITIATION)
class BMPInitiation:
"""
@@ -374,30 +383,31 @@ class BMPInitiation:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
- TLV_STR = '!HH'
+
+ TLV_STR = "!HH"
MIN_LEN = struct.calcsize(TLV_STR)
FIELD_TO_STR = {
- BMPCodes.BMP_INIT_INFO_STRING: 'information',
- BMPCodes.BMP_INIT_ADMIN_LABEL: 'admin_label',
- BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: 'system_description',
- BMPCodes.BMP_INIT_SYSTEM_NAME: 'system_name',
- BMPCodes.BMP_INIT_VRF_TABLE_NAME: 'vrf_table_name',
+ BMPCodes.BMP_INIT_INFO_STRING: "information",
+ BMPCodes.BMP_INIT_ADMIN_LABEL: "admin_label",
+ BMPCodes.BMP_INIT_SYSTEM_DESCRIPTION: "system_description",
+ BMPCodes.BMP_INIT_SYSTEM_NAME: "system_name",
+ BMPCodes.BMP_INIT_VRF_TABLE_NAME: "vrf_table_name",
}
@classmethod
def dissect(cls, data):
msg = {}
while len(data) > cls.MIN_LEN:
- _type, _len = struct.unpack_from(cls.TLV_STR, data[0:cls.MIN_LEN])
- _value = data[cls.MIN_LEN: cls.MIN_LEN + _len].decode()
+ _type, _len = struct.unpack_from(cls.TLV_STR, data[0 : cls.MIN_LEN])
+ _value = data[cls.MIN_LEN : cls.MIN_LEN + _len].decode()
msg[cls.FIELD_TO_STR[_type]] = _value
- data = data[cls.MIN_LEN + _len:]
+ data = data[cls.MIN_LEN + _len :]
return msg
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPTermination:
"""
0 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8 1 2 3 4 5 6 7 8
@@ -408,14 +418,15 @@ class BMPTermination:
~ ~
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
"""
+
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPRouteMirroring:
pass
-#------------------------------------------------------------------------------
+# ------------------------------------------------------------------------------
class BMPRoutePolicy:
pass
diff --git a/tests/topotests/lib/bmp_collector/bmpserver b/tests/topotests/lib/bmp_collector/bmpserver
index 25b4a52..5257df7 100755
--- a/tests/topotests/lib/bmp_collector/bmpserver
+++ b/tests/topotests/lib/bmp_collector/bmpserver
@@ -16,10 +16,12 @@ BGP_MAX_SIZE = 4096
parser = argparse.ArgumentParser()
parser.add_argument("-a", "--address", type=str, default="0.0.0.0")
parser.add_argument("-p", "--port", type=int, default=1789)
+parser.add_argument("-l", "--logfile", type=str, default="/var/log/bmp.log")
def main():
args = parser.parse_args()
ADDRESS, PORT = args.address, args.port
+ LOG_FILE = args.logfile
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
@@ -31,7 +33,7 @@ def main():
while True:
data = connection.recv(BGP_MAX_SIZE)
while len(data) > BMPMsg.MIN_LEN:
- data = BMPMsg.dissect(data)
+ data = BMPMsg.dissect(data, log_file=LOG_FILE)
except Exception as e:
# XXX: do something
pass
diff --git a/tests/topotests/lib/checkping.py b/tests/topotests/lib/checkping.py
index aaa6164..5500807 100644
--- a/tests/topotests/lib/checkping.py
+++ b/tests/topotests/lib/checkping.py
@@ -8,7 +8,7 @@ from lib.topolog import logger
from lib import topotest
-def check_ping(name, dest_addr, expect_connected, count, wait):
+def check_ping(name, dest_addr, expect_connected, count, wait, source_addr=None):
"""
Assert that ping to dest_addr is expected
* 'name': the router to set the ping from
@@ -18,9 +18,13 @@ def check_ping(name, dest_addr, expect_connected, count, wait):
* 'wait': how long ping should wait to receive all replies
"""
- def _check(name, dest_addr, match):
+ def _check(name, dest_addr, source_addr, match):
tgen = get_topogen()
- output = tgen.gears[name].run("ping {} -c 1 -w 1".format(dest_addr))
+ cmd = "ping {}".format(dest_addr)
+ if source_addr:
+ cmd += " -I {}".format(source_addr)
+ cmd += " -c 1 -w 1"
+ output = tgen.gears[name].run(cmd)
logger.info(output)
if match not in output:
return "ping fail"
@@ -28,6 +32,6 @@ def check_ping(name, dest_addr, expect_connected, count, wait):
match = ", {} packet loss".format("0%" if expect_connected else "100%")
logger.info("[+] check {} {} {}".format(name, dest_addr, match))
tgen = get_topogen()
- func = functools.partial(_check, name, dest_addr, match)
+ func = functools.partial(_check, name, dest_addr, source_addr, match)
success, result = topotest.run_and_expect(func, None, count=count, wait=wait)
assert result is None, "Failed"
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index 598db84..7787b6f 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -936,14 +936,26 @@ def generate_support_bundle():
"""
tgen = get_topogen()
+ if tgen is None:
+ logger.warn(
+ "Support bundle attempted to be generated, but topogen is not being used"
+ )
+ return True
+
router_list = tgen.routers()
test_name = os.environ.get("PYTEST_CURRENT_TEST").split(":")[-1].split(" ")[0]
bundle_procs = {}
for rname, rnode in router_list.items():
logger.info("Spawn collection of support bundle for %s", rname)
- dst_bundle = "{}/{}/support_bundles/{}".format(tgen.logdir, rname, test_name)
- rnode.run("mkdir -p " + dst_bundle)
+ try:
+ dst_bundle = "{}/{}/support_bundles/{}".format(
+ tgen.logdir, rname, test_name
+ )
+ rnode.run("mkdir -p " + dst_bundle)
+ except Exception as err:
+ logger.error("Generation of Support bundle failed {}".format(err))
+ return True
gen_sup_cmd = [
"/usr/lib/frr/generate_support_bundle.py",
diff --git a/tests/topotests/lib/fe_client.py b/tests/topotests/lib/fe_client.py
index 07059cc..a475446 100755
--- a/tests/topotests/lib/fe_client.py
+++ b/tests/topotests/lib/fe_client.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
# -*- coding: utf-8 eval: (blacken-mode 1) -*-
# SPDX-License-Identifier: GPL-2.0-or-later
#
diff --git a/tests/topotests/lib/grpc-query.py b/tests/topotests/lib/grpc-query.py
index 8c4701c..13b6361 100755
--- a/tests/topotests/lib/grpc-query.py
+++ b/tests/topotests/lib/grpc-query.py
@@ -10,35 +10,46 @@ import argparse
import logging
import os
import sys
+import tempfile
import pytest
CWD = os.path.dirname(os.path.realpath(__file__))
-# This is painful but works if you have installed grpc and grpc_tools would be *way*
-# better if we actually built and installed these but ... python packaging.
try:
- import grpc
- import grpc_tools
-
- sys.path.append(os.path.dirname(CWD))
- from munet.base import commander
-
- commander.cmd_raises(f"cp {CWD}/../../../grpc/frr-northbound.proto .")
- commander.cmd_raises(
- f"python3 -m grpc_tools.protoc --python_out=. --grpc_python_out=. -I . frr-northbound.proto"
- )
-except Exception as error:
- logging.error("can't create proto definition modules %s", error)
- raise
-
-try:
- sys.path[0:0] = "."
- import frr_northbound_pb2
- import frr_northbound_pb2_grpc
-except Exception as error:
- logging.error("can't import proto definition modules %s", error)
- raise
+ # Make sure we don't run-into ourselves in parallel operating environment
+ tmpdir = tempfile.mkdtemp(prefix="grpc-client-")
+
+ # This is painful but works if you have installed grpc and grpc_tools would be *way*
+ # better if we actually built and installed these but ... python packaging.
+ try:
+ import grpc_tools
+ from munet.base import commander
+
+ import grpc
+
+ commander.cmd_raises(f"cp {CWD}/../../../grpc/frr-northbound.proto .")
+ commander.cmd_raises(
+ "python3 -m grpc_tools.protoc"
+ f" --python_out={tmpdir} --grpc_python_out={tmpdir}"
+ f" -I {CWD}/../../../grpc frr-northbound.proto"
+ )
+ except Exception as error:
+ logging.error("can't create proto definition modules %s", error)
+ raise
+
+ try:
+ sys.path[0:0] = [tmpdir]
+ print(sys.path)
+ import frr_northbound_pb2
+ import frr_northbound_pb2_grpc
+
+ sys.path = sys.path[1:]
+ except Exception as error:
+ logging.error("can't import proto definition modules %s", error)
+ raise
+finally:
+ commander.cmd_nostatus(f"rm -rf {tmpdir}")
class GRPCClient:
@@ -57,16 +68,16 @@ class GRPCClient:
logging.debug("GRPC Capabilities: %s", response)
return response
- def get(self, xpath):
+ def get(self, xpath, encoding, gtype):
request = frr_northbound_pb2.GetRequest()
request.path.append(xpath)
- request.type = frr_northbound_pb2.GetRequest.ALL
- request.encoding = frr_northbound_pb2.XML
- xml = ""
+ request.type = gtype
+ request.encoding = encoding
+ result = ""
for r in self.stub.Get(request):
- logging.info('GRPC Get path: "%s" value: %s', request.path, r)
- xml += str(r.data.data)
- return xml
+ logging.debug('GRPC Get path: "%s" value: %s', request.path, r)
+ result += str(r.data.data)
+ return result
def next_action(action_list=None):
@@ -95,6 +106,7 @@ def main(*args):
)
parser.add_argument("-v", "--verbose", action="store_true", help="be verbose")
parser.add_argument("--check", action="store_true", help="check runable")
+ parser.add_argument("--xml", action="store_true", help="encode XML instead of JSON")
parser.add_argument("actions", nargs="*", help="GETCAP|GET,xpath")
args = parser.parse_args(*args)
@@ -107,20 +119,32 @@ def main(*args):
if args.check:
sys.exit(0)
+ encoding = frr_northbound_pb2.XML if args.xml else frr_northbound_pb2.JSON
+
c = GRPCClient(args.server, args.port)
for action in next_action(args.actions):
action = action.casefold()
- logging.info("GOT ACTION: %s", action)
+ logging.debug("GOT ACTION: %s", action)
if action == "getcap":
caps = c.get_capabilities()
- print("Capabilities:", caps)
+ print(caps)
elif action.startswith("get,"):
- # Print Interface State and Config
+ # Get and print config and state
+ _, xpath = action.split(",", 1)
+ logging.debug("Get XPath: %s", xpath)
+ print(c.get(xpath, encoding, gtype=frr_northbound_pb2.GetRequest.ALL))
+ elif action.startswith("get-config,"):
+ # Get and print config
+ _, xpath = action.split(",", 1)
+ logging.debug("Get Config XPath: %s", xpath)
+ print(c.get(xpath, encoding, gtype=frr_northbound_pb2.GetRequest.CONFIG))
+ # for _ in range(0, 1):
+ elif action.startswith("get-state,"):
+ # Get and print state
_, xpath = action.split(",", 1)
- print("Get XPath: ", xpath)
- xml = c.get(xpath)
- print("{}: {}".format(xpath, xml))
+ logging.debug("Get State XPath: %s", xpath)
+ print(c.get(xpath, encoding, gtype=frr_northbound_pb2.GetRequest.STATE))
# for _ in range(0, 1):
diff --git a/tests/topotests/lib/snmptest.py b/tests/topotests/lib/snmptest.py
index 814813f..8e2e76d 100644
--- a/tests/topotests/lib/snmptest.py
+++ b/tests/topotests/lib/snmptest.py
@@ -85,15 +85,18 @@ class SnmpTester(object):
return out_dict, out_list
def get(self, oid):
- cmd = "snmpget {0} {1}".format(self._snmp_config(), oid)
-
+ cmd = "snmpget {0} {1} 2>&1 | grep -v SNMPv2-PDU".format(
+ self._snmp_config(), oid
+ )
result = self.router.cmd(cmd)
if "not found" in result:
return None
return self._get_snmp_value(result)
def get_next(self, oid):
- cmd = "snmpgetnext {0} {1}".format(self._snmp_config(), oid)
+ cmd = "snmpgetnext {0} {1} 2>&1 | grep -v SNMPv2-PDU".format(
+ self._snmp_config(), oid
+ )
result = self.router.cmd(cmd)
print("get_next: {}".format(result))
@@ -102,7 +105,9 @@ class SnmpTester(object):
return self._get_snmp_value(result)
def walk(self, oid):
- cmd = "snmpwalk {0} {1}".format(self._snmp_config(), oid)
+ cmd = "snmpwalk {0} {1} 2>&1 | grep -v SNMPv2-PDU".format(
+ self._snmp_config(), oid
+ )
result = self.router.cmd(cmd)
return self._parse_multiline(result)
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index 155d2d0..f49e30e 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -94,7 +94,9 @@ def get_exabgp_cmd(commander=None):
return False
version = m.group(1)
if topotest.version_cmp(version, "4.2.11") < 0:
- logging.debug("found exabgp version < 4.2.11 in %s will keep looking", exacmd)
+ logging.debug(
+ "found exabgp version < 4.2.11 in %s will keep looking", exacmd
+ )
return False
logger.info("Using ExaBGP version %s in %s", version, exacmd)
return True
@@ -746,6 +748,7 @@ class TopoRouter(TopoGear):
RD_PIM6 = 19
RD_MGMTD = 20
RD_TRAP = 21
+ RD_FPM_LISTENER = 22
RD = {
RD_FRR: "frr",
RD_ZEBRA: "zebra",
@@ -769,6 +772,7 @@ class TopoRouter(TopoGear):
RD_SNMP: "snmpd",
RD_MGMTD: "mgmtd",
RD_TRAP: "snmptrapd",
+ RD_FPM_LISTENER: "fpm_listener",
}
def __init__(self, tgen, cls, name, **params):
@@ -845,7 +849,8 @@ class TopoRouter(TopoGear):
TopoRouter.RD_RIPNG, TopoRouter.RD_OSPF, TopoRouter.RD_OSPF6,
TopoRouter.RD_ISIS, TopoRouter.RD_BGP, TopoRouter.RD_LDP,
TopoRouter.RD_PIM, TopoRouter.RD_PIM6, TopoRouter.RD_PBR,
- TopoRouter.RD_SNMP, TopoRouter.RD_MGMTD, TopoRouter.RD_TRAP.
+ TopoRouter.RD_SNMP, TopoRouter.RD_MGMTD, TopoRouter.RD_TRAP,
+ TopoRouter.RD_FPM_LISTENER.
Possible `source` values are `None` for an empty config file, a path name which is
used directly, or a file name with no path components which is first looked for
@@ -883,7 +888,12 @@ class TopoRouter(TopoGear):
# Enable all daemon command logging, logging files
# and set them to the start dir.
for daemon, enabled in nrouter.daemons.items():
- if enabled and daemon != "snmpd" and daemon != "snmptrapd":
+ if (
+ enabled
+ and daemon != "snmpd"
+ and daemon != "snmptrapd"
+ and daemon != "fpm_listener"
+ ):
self.vtysh_cmd(
"\n".join(
[
@@ -933,7 +943,7 @@ class TopoRouter(TopoGear):
# and set them to the start dir.
for daemon in daemons:
enabled = nrouter.daemons[daemon]
- if enabled and daemon != "snmpd":
+ if enabled and daemon != "snmpd" and daemon != "fpm_listener":
self.vtysh_cmd(
"\n".join(
[
@@ -1253,9 +1263,12 @@ class TopoBMPCollector(TopoHost):
gear += " TopoBMPCollector<>".format()
return gear
- def start(self):
+ def start(self, log_file=None):
+ log_arg = "-l {}".format(log_file) if log_file else ""
self.run(
- "{}/bmp_collector/bmpserver -a {} -p {}&".format(CWD, self.ip, self.port),
+ "{}/bmp_collector/bmpserver -a {} -p {} {}&".format(
+ CWD, self.ip, self.port, log_arg
+ ),
stdout=None,
)
diff --git a/tests/topotests/lib/topojson.py b/tests/topotests/lib/topojson.py
index 901e4f6..148fb04 100644
--- a/tests/topotests/lib/topojson.py
+++ b/tests/topotests/lib/topojson.py
@@ -227,13 +227,17 @@ def build_topo_from_json(tgen, topo=None):
topo["routers"][destRouter]["links"][curSwitch][
"interface"
] = "{}-{}-eth{}".format(
- destRouter, curSwitch, topo["routers"][destRouter]["nextIfname"]
+ destRouter,
+ curSwitch,
+ topo["routers"][destRouter]["nextIfname"],
)
topo["switches"][curSwitch]["links"][destRouter][
"interface"
] = "{}-{}-eth{}".format(
- curSwitch, destRouter, topo["routers"][destRouter]["nextIfname"]
+ curSwitch,
+ destRouter,
+ topo["routers"][destRouter]["nextIfname"],
)
topo["routers"][destRouter]["nextIfname"] += 1
diff --git a/tests/topotests/lib/topotest.py b/tests/topotests/lib/topotest.py
index 2bb8923..087d845 100644
--- a/tests/topotests/lib/topotest.py
+++ b/tests/topotests/lib/topotest.py
@@ -27,6 +27,7 @@ import time
import logging
from collections.abc import Mapping
from copy import deepcopy
+from pathlib import Path
import lib.topolog as topolog
from lib.micronet_compat import Node
@@ -1295,6 +1296,8 @@ def fix_netns_limits(ns):
sysctl_assure(ns, "net.ipv4.conf.all.ignore_routes_with_linkdown", 1)
sysctl_assure(ns, "net.ipv6.conf.all.ignore_routes_with_linkdown", 1)
+ sysctl_assure(ns, "net.ipv4.conf.default.ignore_routes_with_linkdown", 1)
+ sysctl_assure(ns, "net.ipv6.conf.default.ignore_routes_with_linkdown", 1)
# igmp
sysctl_atleast(ns, "net.ipv4.igmp_max_memberships", 1000)
@@ -1426,6 +1429,7 @@ class Router(Node):
"snmpd": 0,
"mgmtd": 0,
"snmptrapd": 0,
+ "fpm_listener": 0,
}
self.daemons_options = {"zebra": ""}
self.reportCores = True
@@ -1522,7 +1526,7 @@ class Router(Node):
pass
return ret
- def stopRouter(self, assertOnError=True, minErrorVersion="5.1"):
+ def stopRouter(self, assertOnError=True):
# Stop Running FRR Daemons
running = self.listDaemons()
if not running:
@@ -1569,9 +1573,6 @@ class Router(Node):
)
errors = self.checkRouterCores(reportOnce=True)
- if self.checkRouterVersion("<", minErrorVersion):
- # ignore errors in old versions
- errors = ""
if assertOnError and (errors is not None) and len(errors) > 0:
assert "Errors found - details follow:" == 0, errors
return errors
@@ -1802,6 +1803,8 @@ class Router(Node):
"Starts FRR daemons for this router."
asan_abort = bool(g_pytest_config.option.asan_abort)
+ cov_option = bool(g_pytest_config.option.cov_topotest)
+ cov_dir = Path(g_pytest_config.option.rundir) / "gcda"
gdb_breakpoints = g_pytest_config.get_option_list("--gdb-breakpoints")
gdb_daemons = g_pytest_config.get_option_list("--gdb-daemons")
gdb_routers = g_pytest_config.get_option_list("--gdb-routers")
@@ -1835,13 +1838,6 @@ class Router(Node):
# Re-enable to allow for report per run
self.reportCores = True
- # XXX: glue code forward ported from removed function.
- if self.version is None:
- self.version = self.cmd(
- os.path.join(self.daemondir, "bgpd") + " -v"
- ).split()[2]
- logger.info("{}: running version: {}".format(self.name, self.version))
-
perfds = {}
perf_options = g_pytest_config.get_option("--perf-options", "-g")
for perf in g_pytest_config.get_option("--perf", []):
@@ -1896,7 +1892,11 @@ class Router(Node):
)
rediropt = " > {0}.out 2> {0}.err".format(daemon)
- if daemon == "snmpd":
+ if daemon == "fpm_listener":
+ binary = "/usr/lib/frr/fpm_listener"
+ cmdenv = ""
+ cmdopt = "-d {}".format(daemon_opts)
+ elif daemon == "snmpd":
binary = "/usr/sbin/snmpd"
cmdenv = ""
cmdopt = "{} -C -c /etc/frr/snmpd.conf -p ".format(
@@ -1923,6 +1923,10 @@ class Router(Node):
self.logdir, self.name, daemon
)
+ if cov_option:
+ scount = os.environ["GCOV_PREFIX_STRIP"]
+ cmdenv += f"GCOV_PREFIX_STRIP={scount} GCOV_PREFIX={cov_dir}"
+
if valgrind_memleaks:
this_dir = os.path.dirname(
os.path.abspath(os.path.realpath(__file__))
@@ -2162,7 +2166,11 @@ class Router(Node):
"%s: %s %s started with rr", self, self.routertype, daemon
)
else:
- if daemon != "snmpd" and daemon != "snmptrapd":
+ if (
+ daemon != "snmpd"
+ and daemon != "snmptrapd"
+ and daemon != "fpm_listener"
+ ):
cmdopt += " -d "
cmdopt += rediropt
@@ -2175,12 +2183,16 @@ class Router(Node):
daemon,
error.returncode,
error.cmd,
- '\n:stdout: "{}"'.format(error.stdout.strip())
- if error.stdout
- else "",
- '\n:stderr: "{}"'.format(error.stderr.strip())
- if error.stderr
- else "",
+ (
+ '\n:stdout: "{}"'.format(error.stdout.strip())
+ if error.stdout
+ else ""
+ ),
+ (
+ '\n:stderr: "{}"'.format(error.stderr.strip())
+ if error.stderr
+ else ""
+ ),
)
else:
logger.debug("%s: %s %s started", self, self.routertype, daemon)
@@ -2212,6 +2224,11 @@ class Router(Node):
while "snmpd" in daemons_list:
daemons_list.remove("snmpd")
+ if "fpm_listener" in daemons_list:
+ start_daemon("fpm_listener")
+ while "fpm_listener" in daemons_list:
+ daemons_list.remove("fpm_listener")
+
# Now start all the other daemons
for daemon in daemons_list:
if self.daemons[daemon] == 0:
@@ -2263,9 +2280,7 @@ class Router(Node):
rc, o, e = self.cmd_status("kill -0 " + str(pid), warn=False)
return rc == 0 or "No such process" not in e
- def killRouterDaemons(
- self, daemons, wait=True, assertOnError=True, minErrorVersion="5.1"
- ):
+ def killRouterDaemons(self, daemons, wait=True, assertOnError=True):
# Kill Running FRR
# Daemons(user specified daemon only) using SIGKILL
rundaemons = self.cmd("ls -1 /var/run/%s/*.pid" % self.routertype)
@@ -2325,9 +2340,6 @@ class Router(Node):
self.cmd("rm -- {}".format(daemonpidfile))
if wait:
errors = self.checkRouterCores(reportOnce=True)
- if self.checkRouterVersion("<", minErrorVersion):
- # ignore errors in old versions
- errors = ""
if assertOnError and len(errors) > 0:
assert "Errors found - details follow:" == 0, errors
else:
@@ -2407,6 +2419,8 @@ class Router(Node):
continue
if daemon == "snmptrapd":
continue
+ if daemon == "fpm_listener":
+ continue
if (self.daemons[daemon] == 1) and not (daemon in daemonsRunning):
sys.stderr.write("%s: Daemon %s not running\n" % (self.name, daemon))
if daemon == "staticd":
diff --git a/tests/topotests/mgmt_fe_client/mgmt_pb2.py b/tests/topotests/mgmt_fe_client/mgmt_pb2.py
index 0aa8803..44dd2f6 100644
--- a/tests/topotests/mgmt_fe_client/mgmt_pb2.py
+++ b/tests/topotests/mgmt_fe_client/mgmt_pb2.py
@@ -7,90 +7,113 @@ from google.protobuf import descriptor as _descriptor
from google.protobuf import message as _message
from google.protobuf import reflection as _reflection
from google.protobuf import symbol_database as _symbol_database
+
# @@protoc_insertion_point(imports)
_sym_db = _symbol_database.Default()
-
-
DESCRIPTOR = _descriptor.FileDescriptor(
- name='mgmt.proto',
- package='mgmtd',
- syntax='proto2',
- serialized_options=None,
- create_key=_descriptor._internal_create_key,
- serialized_pb=b'\n\nmgmt.proto\x12\x05mgmtd\"\x1e\n\rYangDataXPath\x12\r\n\x05xpath\x18\x01 \x02(\t\"3\n\rYangDataValue\x12\x19\n\x0f\x65ncoded_str_val\x18\x64 \x01(\tH\x00\x42\x07\n\x05value\">\n\x08YangData\x12\r\n\x05xpath\x18\x01 \x02(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.mgmtd.YangDataValue\"X\n\x0eYangCfgDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\'\n\x08req_type\x18\x02 \x02(\x0e\x32\x15.mgmtd.CfgDataReqType\"B\n\x0eYangGetDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03\"R\n\x0e\x42\x65SubscribeReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\x12\x18\n\x10subscribe_xpaths\x18\x02 \x02(\x08\x12\x11\n\txpath_reg\x18\x03 \x03(\t\"#\n\x10\x42\x65SubscribeReply\x12\x0f\n\x07success\x18\x01 \x02(\x08\"*\n\x08\x42\x65TxnReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\"=\n\nBeTxnReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\x12\x0f\n\x07success\x18\x03 \x02(\x08\"b\n\x12\x42\x65\x43\x66gDataCreateReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\'\n\x08\x64\x61ta_req\x18\x02 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x13\n\x0b\x65nd_of_data\x18\x03 \x02(\x08\"M\n\x14\x42\x65\x43\x66gDataCreateReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t\"#\n\x11\x42\x65\x43\x66gDataApplyReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\"L\n\x13\x42\x65\x43\x66gDataApplyReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t\"A\n\rYangDataReply\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03\"\x94\x03\n\tBeMessage\x12+\n\nsubscr_req\x18\x02 \x01(\x0b\x32\x15.mgmtd.BeSubscribeReqH\x00\x12/\n\x0csubscr_reply\x18\x03 \x01(\x0b\x32\x17.mgmtd.BeSubscribeReplyH\x00\x12\"\n\x07txn_req\x18\x04 \x01(\x0b\x32\x0f.mgmtd.BeTxnReqH\x00\x12&\n\ttxn_reply\x18\x05 \x01(\x0b\x32\x11.mgmtd.BeTxnReplyH\x00\x12\x31\n\x0c\x63\x66g_data_req\x18\x06 \x01(\x0b\x32\x19.mgmtd.BeCfgDataCreateReqH\x00\x12\x35\n\x0e\x63\x66g_data_reply\x18\x07 \x01(\x0b\x32\x1b.mgmtd.BeCfgDataCreateReplyH\x00\x12\x31\n\rcfg_apply_req\x18\x08 \x01(\x0b\x32\x18.mgmtd.BeCfgDataApplyReqH\x00\x12\x35\n\x0f\x63\x66g_apply_reply\x18\t \x01(\x0b\x32\x1a.mgmtd.BeCfgDataApplyReplyH\x00\x42\t\n\x07message\"$\n\rFeRegisterReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\"T\n\x0c\x46\x65SessionReq\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x18\n\x0e\x63lient_conn_id\x18\x02 \x01(\x04H\x00\x12\x14\n\nsession_id\x18\x03 \x01(\x04H\x00\x42\x04\n\x02id\"]\n\x0e\x46\x65SessionReply\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x16\n\x0e\x63lient_conn_id\x18\x03 \x01(\x04\x12\x12\n\nsession_id\x18\x04 \x02(\x04\"b\n\x0b\x46\x65LockDsReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\"\x8b\x01\n\rFeLockDsReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\"\xbf\x01\n\x0e\x46\x65SetConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12(\n\x0c\x63ommit_ds_id\x18\x06 \x02(\x0e\x32\x12.mgmtd.DatastoreId\"\x99\x01\n\x10\x46\x65SetConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12\x0f\n\x07success\x18\x04 \x02(\x08\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\"\xab\x01\n\x11\x46\x65\x43ommitConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x06 \x02(\x08\"\xd4\x01\n\x13\x46\x65\x43ommitConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\x0f\n\x07success\x18\x06 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x07 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x08 \x01(\t\"\x86\x01\n\x08\x46\x65GetReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x15.mgmtd.YangGetDataReq\"\xae\x01\n\nFeGetReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\x12\"\n\x04\x64\x61ta\x18\x07 \x01(\x0b\x32\x14.mgmtd.YangDataReply\"0\n\x0f\x46\x65NotifyDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\"\x9c\x01\n\x13\x46\x65RegisterNotifyReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x14\n\x0cregister_req\x18\x03 \x02(\x08\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12(\n\ndata_xpath\x18\x05 \x03(\x0b\x32\x14.mgmtd.YangDataXPath\"\xf0\x04\n\tFeMessage\x12,\n\x0cregister_req\x18\x02 \x01(\x0b\x32\x14.mgmtd.FeRegisterReqH\x00\x12*\n\x0bsession_req\x18\x03 \x01(\x0b\x32\x13.mgmtd.FeSessionReqH\x00\x12.\n\rsession_reply\x18\x04 \x01(\x0b\x32\x15.mgmtd.FeSessionReplyH\x00\x12(\n\nlockds_req\x18\x05 \x01(\x0b\x32\x12.mgmtd.FeLockDsReqH\x00\x12,\n\x0clockds_reply\x18\x06 \x01(\x0b\x32\x14.mgmtd.FeLockDsReplyH\x00\x12+\n\nsetcfg_req\x18\x07 \x01(\x0b\x32\x15.mgmtd.FeSetConfigReqH\x00\x12/\n\x0csetcfg_reply\x18\x08 \x01(\x0b\x32\x17.mgmtd.FeSetConfigReplyH\x00\x12/\n\x0b\x63ommcfg_req\x18\t \x01(\x0b\x32\x18.mgmtd.FeCommitConfigReqH\x00\x12\x33\n\rcommcfg_reply\x18\n \x01(\x0b\x32\x1a.mgmtd.FeCommitConfigReplyH\x00\x12\"\n\x07get_req\x18\x0b \x01(\x0b\x32\x0f.mgmtd.FeGetReqH\x00\x12&\n\tget_reply\x18\x0c \x01(\x0b\x32\x11.mgmtd.FeGetReplyH\x00\x12\x31\n\x0fnotify_data_req\x18\x0f \x01(\x0b\x32\x16.mgmtd.FeNotifyDataReqH\x00\x12\x33\n\rregnotify_req\x18\x10 \x01(\x0b\x32\x1a.mgmtd.FeRegisterNotifyReqH\x00\x42\t\n\x07message*B\n\x0e\x43\x66gDataReqType\x12\x11\n\rREQ_TYPE_NONE\x10\x00\x12\x0c\n\x08SET_DATA\x10\x01\x12\x0f\n\x0b\x44\x45LETE_DATA\x10\x02*`\n\x0b\x44\x61tastoreId\x12\x0b\n\x07\x44S_NONE\x10\x00\x12\x0e\n\nRUNNING_DS\x10\x01\x12\x10\n\x0c\x43\x41NDIDATE_DS\x10\x02\x12\x12\n\x0eOPERATIONAL_DS\x10\x03\x12\x0e\n\nSTARTUP_DS\x10\x04'
+ name="mgmt.proto",
+ package="mgmtd",
+ syntax="proto2",
+ serialized_options=None,
+ create_key=_descriptor._internal_create_key,
+ serialized_pb=b'\n\nmgmt.proto\x12\x05mgmtd"\x1e\n\rYangDataXPath\x12\r\n\x05xpath\x18\x01 \x02(\t"3\n\rYangDataValue\x12\x19\n\x0f\x65ncoded_str_val\x18\x64 \x01(\tH\x00\x42\x07\n\x05value">\n\x08YangData\x12\r\n\x05xpath\x18\x01 \x02(\t\x12#\n\x05value\x18\x02 \x01(\x0b\x32\x14.mgmtd.YangDataValue"X\n\x0eYangCfgDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\'\n\x08req_type\x18\x02 \x02(\x0e\x32\x15.mgmtd.CfgDataReqType"B\n\x0eYangGetDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x02(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03"R\n\x0e\x42\x65SubscribeReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t\x12\x18\n\x10subscribe_xpaths\x18\x02 \x02(\x08\x12\x11\n\txpath_reg\x18\x03 \x03(\t"#\n\x10\x42\x65SubscribeReply\x12\x0f\n\x07success\x18\x01 \x02(\x08"*\n\x08\x42\x65TxnReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08"=\n\nBeTxnReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63reate\x18\x02 \x02(\x08\x12\x0f\n\x07success\x18\x03 \x02(\x08"b\n\x12\x42\x65\x43\x66gDataCreateReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\'\n\x08\x64\x61ta_req\x18\x02 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x13\n\x0b\x65nd_of_data\x18\x03 \x02(\x08"M\n\x14\x42\x65\x43\x66gDataCreateReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t"#\n\x11\x42\x65\x43\x66gDataApplyReq\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04"L\n\x13\x42\x65\x43\x66gDataApplyReply\x12\x0e\n\x06txn_id\x18\x01 \x02(\x04\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x03 \x01(\t"A\n\rYangDataReply\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData\x12\x11\n\tnext_indx\x18\x02 \x02(\x03"\x94\x03\n\tBeMessage\x12+\n\nsubscr_req\x18\x02 \x01(\x0b\x32\x15.mgmtd.BeSubscribeReqH\x00\x12/\n\x0csubscr_reply\x18\x03 \x01(\x0b\x32\x17.mgmtd.BeSubscribeReplyH\x00\x12"\n\x07txn_req\x18\x04 \x01(\x0b\x32\x0f.mgmtd.BeTxnReqH\x00\x12&\n\ttxn_reply\x18\x05 \x01(\x0b\x32\x11.mgmtd.BeTxnReplyH\x00\x12\x31\n\x0c\x63\x66g_data_req\x18\x06 \x01(\x0b\x32\x19.mgmtd.BeCfgDataCreateReqH\x00\x12\x35\n\x0e\x63\x66g_data_reply\x18\x07 \x01(\x0b\x32\x1b.mgmtd.BeCfgDataCreateReplyH\x00\x12\x31\n\rcfg_apply_req\x18\x08 \x01(\x0b\x32\x18.mgmtd.BeCfgDataApplyReqH\x00\x12\x35\n\x0f\x63\x66g_apply_reply\x18\t \x01(\x0b\x32\x1a.mgmtd.BeCfgDataApplyReplyH\x00\x42\t\n\x07message"$\n\rFeRegisterReq\x12\x13\n\x0b\x63lient_name\x18\x01 \x02(\t"T\n\x0c\x46\x65SessionReq\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x18\n\x0e\x63lient_conn_id\x18\x02 \x01(\x04H\x00\x12\x14\n\nsession_id\x18\x03 \x01(\x04H\x00\x42\x04\n\x02id"]\n\x0e\x46\x65SessionReply\x12\x0e\n\x06\x63reate\x18\x01 \x02(\x08\x12\x0f\n\x07success\x18\x02 \x02(\x08\x12\x16\n\x0e\x63lient_conn_id\x18\x03 \x01(\x04\x12\x12\n\nsession_id\x18\x04 \x02(\x04"b\n\x0b\x46\x65LockDsReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08"\x8b\x01\n\rFeLockDsReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06req_id\x18\x02 \x02(\x04\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0c\n\x04lock\x18\x04 \x02(\x08\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t"\xbf\x01\n\x0e\x46\x65SetConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x04 \x03(\x0b\x32\x15.mgmtd.YangCfgDataReq\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12(\n\x0c\x63ommit_ds_id\x18\x06 \x02(\x0e\x32\x12.mgmtd.DatastoreId"\x99\x01\n\x10\x46\x65SetConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x03 \x02(\x04\x12\x0f\n\x07success\x18\x04 \x02(\x08\x12\x17\n\x0fimplicit_commit\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t"\xab\x01\n\x11\x46\x65\x43ommitConfigReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x06 \x02(\x08"\xd4\x01\n\x13\x46\x65\x43ommitConfigReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12%\n\tsrc_ds_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12%\n\tdst_ds_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x15\n\rvalidate_only\x18\x05 \x02(\x08\x12\x0f\n\x07success\x18\x06 \x02(\x08\x12\r\n\x05\x61\x62ort\x18\x07 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x08 \x01(\t"\x86\x01\n\x08\x46\x65GetReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12#\n\x04\x64\x61ta\x18\x05 \x03(\x0b\x32\x15.mgmtd.YangGetDataReq"\xae\x01\n\nFeGetReply\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12\x0e\n\x06\x63onfig\x18\x02 \x02(\x08\x12!\n\x05\x64s_id\x18\x03 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12\x0f\n\x07success\x18\x05 \x02(\x08\x12\x14\n\x0c\x65rror_if_any\x18\x06 \x01(\t\x12"\n\x04\x64\x61ta\x18\x07 \x01(\x0b\x32\x14.mgmtd.YangDataReply"0\n\x0f\x46\x65NotifyDataReq\x12\x1d\n\x04\x64\x61ta\x18\x01 \x03(\x0b\x32\x0f.mgmtd.YangData"\x9c\x01\n\x13\x46\x65RegisterNotifyReq\x12\x12\n\nsession_id\x18\x01 \x02(\x04\x12!\n\x05\x64s_id\x18\x02 \x02(\x0e\x32\x12.mgmtd.DatastoreId\x12\x14\n\x0cregister_req\x18\x03 \x02(\x08\x12\x0e\n\x06req_id\x18\x04 \x02(\x04\x12(\n\ndata_xpath\x18\x05 \x03(\x0b\x32\x14.mgmtd.YangDataXPath"\xf0\x04\n\tFeMessage\x12,\n\x0cregister_req\x18\x02 \x01(\x0b\x32\x14.mgmtd.FeRegisterReqH\x00\x12*\n\x0bsession_req\x18\x03 \x01(\x0b\x32\x13.mgmtd.FeSessionReqH\x00\x12.\n\rsession_reply\x18\x04 \x01(\x0b\x32\x15.mgmtd.FeSessionReplyH\x00\x12(\n\nlockds_req\x18\x05 \x01(\x0b\x32\x12.mgmtd.FeLockDsReqH\x00\x12,\n\x0clockds_reply\x18\x06 \x01(\x0b\x32\x14.mgmtd.FeLockDsReplyH\x00\x12+\n\nsetcfg_req\x18\x07 \x01(\x0b\x32\x15.mgmtd.FeSetConfigReqH\x00\x12/\n\x0csetcfg_reply\x18\x08 \x01(\x0b\x32\x17.mgmtd.FeSetConfigReplyH\x00\x12/\n\x0b\x63ommcfg_req\x18\t \x01(\x0b\x32\x18.mgmtd.FeCommitConfigReqH\x00\x12\x33\n\rcommcfg_reply\x18\n \x01(\x0b\x32\x1a.mgmtd.FeCommitConfigReplyH\x00\x12"\n\x07get_req\x18\x0b \x01(\x0b\x32\x0f.mgmtd.FeGetReqH\x00\x12&\n\tget_reply\x18\x0c \x01(\x0b\x32\x11.mgmtd.FeGetReplyH\x00\x12\x31\n\x0fnotify_data_req\x18\x0f \x01(\x0b\x32\x16.mgmtd.FeNotifyDataReqH\x00\x12\x33\n\rregnotify_req\x18\x10 \x01(\x0b\x32\x1a.mgmtd.FeRegisterNotifyReqH\x00\x42\t\n\x07message*B\n\x0e\x43\x66gDataReqType\x12\x11\n\rREQ_TYPE_NONE\x10\x00\x12\x0c\n\x08SET_DATA\x10\x01\x12\x0f\n\x0b\x44\x45LETE_DATA\x10\x02*`\n\x0b\x44\x61tastoreId\x12\x0b\n\x07\x44S_NONE\x10\x00\x12\x0e\n\nRUNNING_DS\x10\x01\x12\x10\n\x0c\x43\x41NDIDATE_DS\x10\x02\x12\x12\n\x0eOPERATIONAL_DS\x10\x03\x12\x0e\n\nSTARTUP_DS\x10\x04',
)
_CFGDATAREQTYPE = _descriptor.EnumDescriptor(
- name='CfgDataReqType',
- full_name='mgmtd.CfgDataReqType',
- filename=None,
- file=DESCRIPTOR,
- create_key=_descriptor._internal_create_key,
- values=[
- _descriptor.EnumValueDescriptor(
- name='REQ_TYPE_NONE', index=0, number=0,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='SET_DATA', index=1, number=1,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='DELETE_DATA', index=2, number=2,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=3674,
- serialized_end=3740,
+ name="CfgDataReqType",
+ full_name="mgmtd.CfgDataReqType",
+ filename=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name="REQ_TYPE_NONE",
+ index=0,
+ number=0,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="SET_DATA",
+ index=1,
+ number=1,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="DELETE_DATA",
+ index=2,
+ number=2,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ containing_type=None,
+ serialized_options=None,
+ serialized_start=3674,
+ serialized_end=3740,
)
_sym_db.RegisterEnumDescriptor(_CFGDATAREQTYPE)
CfgDataReqType = enum_type_wrapper.EnumTypeWrapper(_CFGDATAREQTYPE)
_DATASTOREID = _descriptor.EnumDescriptor(
- name='DatastoreId',
- full_name='mgmtd.DatastoreId',
- filename=None,
- file=DESCRIPTOR,
- create_key=_descriptor._internal_create_key,
- values=[
- _descriptor.EnumValueDescriptor(
- name='DS_NONE', index=0, number=0,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='RUNNING_DS', index=1, number=1,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='CANDIDATE_DS', index=2, number=2,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='OPERATIONAL_DS', index=3, number=3,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- _descriptor.EnumValueDescriptor(
- name='STARTUP_DS', index=4, number=4,
- serialized_options=None,
- type=None,
- create_key=_descriptor._internal_create_key),
- ],
- containing_type=None,
- serialized_options=None,
- serialized_start=3742,
- serialized_end=3838,
+ name="DatastoreId",
+ full_name="mgmtd.DatastoreId",
+ filename=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ values=[
+ _descriptor.EnumValueDescriptor(
+ name="DS_NONE",
+ index=0,
+ number=0,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="RUNNING_DS",
+ index=1,
+ number=1,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="CANDIDATE_DS",
+ index=2,
+ number=2,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="OPERATIONAL_DS",
+ index=3,
+ number=3,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.EnumValueDescriptor(
+ name="STARTUP_DS",
+ index=4,
+ number=4,
+ serialized_options=None,
+ type=None,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ containing_type=None,
+ serialized_options=None,
+ serialized_start=3742,
+ serialized_end=3838,
)
_sym_db.RegisterEnumDescriptor(_DATASTOREID)
@@ -105,1885 +128,3341 @@ OPERATIONAL_DS = 3
STARTUP_DS = 4
-
_YANGDATAXPATH = _descriptor.Descriptor(
- name='YangDataXPath',
- full_name='mgmtd.YangDataXPath',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='xpath', full_name='mgmtd.YangDataXPath.xpath', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=21,
- serialized_end=51,
+ name="YangDataXPath",
+ full_name="mgmtd.YangDataXPath",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="xpath",
+ full_name="mgmtd.YangDataXPath.xpath",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=21,
+ serialized_end=51,
)
_YANGDATAVALUE = _descriptor.Descriptor(
- name='YangDataValue',
- full_name='mgmtd.YangDataValue',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='encoded_str_val', full_name='mgmtd.YangDataValue.encoded_str_val', index=0,
- number=100, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='value', full_name='mgmtd.YangDataValue.value',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=53,
- serialized_end=104,
+ name="YangDataValue",
+ full_name="mgmtd.YangDataValue",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="encoded_str_val",
+ full_name="mgmtd.YangDataValue.encoded_str_val",
+ index=0,
+ number=100,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="value",
+ full_name="mgmtd.YangDataValue.value",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=53,
+ serialized_end=104,
)
_YANGDATA = _descriptor.Descriptor(
- name='YangData',
- full_name='mgmtd.YangData',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='xpath', full_name='mgmtd.YangData.xpath', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='value', full_name='mgmtd.YangData.value', index=1,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=106,
- serialized_end=168,
+ name="YangData",
+ full_name="mgmtd.YangData",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="xpath",
+ full_name="mgmtd.YangData.xpath",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="value",
+ full_name="mgmtd.YangData.value",
+ index=1,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=106,
+ serialized_end=168,
)
_YANGCFGDATAREQ = _descriptor.Descriptor(
- name='YangCfgDataReq',
- full_name='mgmtd.YangCfgDataReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.YangCfgDataReq.data', index=0,
- number=1, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_type', full_name='mgmtd.YangCfgDataReq.req_type', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=170,
- serialized_end=258,
+ name="YangCfgDataReq",
+ full_name="mgmtd.YangCfgDataReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.YangCfgDataReq.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=2,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_type",
+ full_name="mgmtd.YangCfgDataReq.req_type",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=170,
+ serialized_end=258,
)
_YANGGETDATAREQ = _descriptor.Descriptor(
- name='YangGetDataReq',
- full_name='mgmtd.YangGetDataReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.YangGetDataReq.data', index=0,
- number=1, type=11, cpp_type=10, label=2,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='next_indx', full_name='mgmtd.YangGetDataReq.next_indx', index=1,
- number=2, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=260,
- serialized_end=326,
+ name="YangGetDataReq",
+ full_name="mgmtd.YangGetDataReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.YangGetDataReq.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=2,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="next_indx",
+ full_name="mgmtd.YangGetDataReq.next_indx",
+ index=1,
+ number=2,
+ type=3,
+ cpp_type=2,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=260,
+ serialized_end=326,
)
_BESUBSCRIBEREQ = _descriptor.Descriptor(
- name='BeSubscribeReq',
- full_name='mgmtd.BeSubscribeReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='client_name', full_name='mgmtd.BeSubscribeReq.client_name', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='subscribe_xpaths', full_name='mgmtd.BeSubscribeReq.subscribe_xpaths', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='xpath_reg', full_name='mgmtd.BeSubscribeReq.xpath_reg', index=2,
- number=3, type=9, cpp_type=9, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=328,
- serialized_end=410,
+ name="BeSubscribeReq",
+ full_name="mgmtd.BeSubscribeReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="client_name",
+ full_name="mgmtd.BeSubscribeReq.client_name",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="subscribe_xpaths",
+ full_name="mgmtd.BeSubscribeReq.subscribe_xpaths",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="xpath_reg",
+ full_name="mgmtd.BeSubscribeReq.xpath_reg",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=328,
+ serialized_end=410,
)
_BESUBSCRIBEREPLY = _descriptor.Descriptor(
- name='BeSubscribeReply',
- full_name='mgmtd.BeSubscribeReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeSubscribeReply.success', index=0,
- number=1, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=412,
- serialized_end=447,
+ name="BeSubscribeReply",
+ full_name="mgmtd.BeSubscribeReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeSubscribeReply.success",
+ index=0,
+ number=1,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=412,
+ serialized_end=447,
)
_BETXNREQ = _descriptor.Descriptor(
- name='BeTxnReq',
- full_name='mgmtd.BeTxnReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeTxnReq.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.BeTxnReq.create', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=449,
- serialized_end=491,
+ name="BeTxnReq",
+ full_name="mgmtd.BeTxnReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeTxnReq.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.BeTxnReq.create",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=449,
+ serialized_end=491,
)
_BETXNREPLY = _descriptor.Descriptor(
- name='BeTxnReply',
- full_name='mgmtd.BeTxnReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeTxnReply.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.BeTxnReply.create', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeTxnReply.success', index=2,
- number=3, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=493,
- serialized_end=554,
+ name="BeTxnReply",
+ full_name="mgmtd.BeTxnReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeTxnReply.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.BeTxnReply.create",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeTxnReply.success",
+ index=2,
+ number=3,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=493,
+ serialized_end=554,
)
_BECFGDATACREATEREQ = _descriptor.Descriptor(
- name='BeCfgDataCreateReq',
- full_name='mgmtd.BeCfgDataCreateReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataCreateReq.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data_req', full_name='mgmtd.BeCfgDataCreateReq.data_req', index=1,
- number=2, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='end_of_data', full_name='mgmtd.BeCfgDataCreateReq.end_of_data', index=2,
- number=3, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=556,
- serialized_end=654,
+ name="BeCfgDataCreateReq",
+ full_name="mgmtd.BeCfgDataCreateReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataCreateReq.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data_req",
+ full_name="mgmtd.BeCfgDataCreateReq.data_req",
+ index=1,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="end_of_data",
+ full_name="mgmtd.BeCfgDataCreateReq.end_of_data",
+ index=2,
+ number=3,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=556,
+ serialized_end=654,
)
_BECFGDATACREATEREPLY = _descriptor.Descriptor(
- name='BeCfgDataCreateReply',
- full_name='mgmtd.BeCfgDataCreateReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataCreateReply.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeCfgDataCreateReply.success', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.BeCfgDataCreateReply.error_if_any', index=2,
- number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=656,
- serialized_end=733,
+ name="BeCfgDataCreateReply",
+ full_name="mgmtd.BeCfgDataCreateReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataCreateReply.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeCfgDataCreateReply.success",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.BeCfgDataCreateReply.error_if_any",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=656,
+ serialized_end=733,
)
_BECFGDATAAPPLYREQ = _descriptor.Descriptor(
- name='BeCfgDataApplyReq',
- full_name='mgmtd.BeCfgDataApplyReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataApplyReq.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=735,
- serialized_end=770,
+ name="BeCfgDataApplyReq",
+ full_name="mgmtd.BeCfgDataApplyReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataApplyReq.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=735,
+ serialized_end=770,
)
_BECFGDATAAPPLYREPLY = _descriptor.Descriptor(
- name='BeCfgDataApplyReply',
- full_name='mgmtd.BeCfgDataApplyReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='txn_id', full_name='mgmtd.BeCfgDataApplyReply.txn_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.BeCfgDataApplyReply.success', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.BeCfgDataApplyReply.error_if_any', index=2,
- number=3, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=772,
- serialized_end=848,
+ name="BeCfgDataApplyReply",
+ full_name="mgmtd.BeCfgDataApplyReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="txn_id",
+ full_name="mgmtd.BeCfgDataApplyReply.txn_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.BeCfgDataApplyReply.success",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.BeCfgDataApplyReply.error_if_any",
+ index=2,
+ number=3,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=772,
+ serialized_end=848,
)
_YANGDATAREPLY = _descriptor.Descriptor(
- name='YangDataReply',
- full_name='mgmtd.YangDataReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.YangDataReply.data', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='next_indx', full_name='mgmtd.YangDataReply.next_indx', index=1,
- number=2, type=3, cpp_type=2, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=850,
- serialized_end=915,
+ name="YangDataReply",
+ full_name="mgmtd.YangDataReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.YangDataReply.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="next_indx",
+ full_name="mgmtd.YangDataReply.next_indx",
+ index=1,
+ number=2,
+ type=3,
+ cpp_type=2,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=850,
+ serialized_end=915,
)
_BEMESSAGE = _descriptor.Descriptor(
- name='BeMessage',
- full_name='mgmtd.BeMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='subscr_req', full_name='mgmtd.BeMessage.subscr_req', index=0,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='subscr_reply', full_name='mgmtd.BeMessage.subscr_reply', index=1,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='txn_req', full_name='mgmtd.BeMessage.txn_req', index=2,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='txn_reply', full_name='mgmtd.BeMessage.txn_reply', index=3,
- number=5, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_data_req', full_name='mgmtd.BeMessage.cfg_data_req', index=4,
- number=6, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_data_reply', full_name='mgmtd.BeMessage.cfg_data_reply', index=5,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_apply_req', full_name='mgmtd.BeMessage.cfg_apply_req', index=6,
- number=8, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='cfg_apply_reply', full_name='mgmtd.BeMessage.cfg_apply_reply', index=7,
- number=9, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='message', full_name='mgmtd.BeMessage.message',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=918,
- serialized_end=1322,
+ name="BeMessage",
+ full_name="mgmtd.BeMessage",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="subscr_req",
+ full_name="mgmtd.BeMessage.subscr_req",
+ index=0,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="subscr_reply",
+ full_name="mgmtd.BeMessage.subscr_reply",
+ index=1,
+ number=3,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="txn_req",
+ full_name="mgmtd.BeMessage.txn_req",
+ index=2,
+ number=4,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="txn_reply",
+ full_name="mgmtd.BeMessage.txn_reply",
+ index=3,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_data_req",
+ full_name="mgmtd.BeMessage.cfg_data_req",
+ index=4,
+ number=6,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_data_reply",
+ full_name="mgmtd.BeMessage.cfg_data_reply",
+ index=5,
+ number=7,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_apply_req",
+ full_name="mgmtd.BeMessage.cfg_apply_req",
+ index=6,
+ number=8,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="cfg_apply_reply",
+ full_name="mgmtd.BeMessage.cfg_apply_reply",
+ index=7,
+ number=9,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="message",
+ full_name="mgmtd.BeMessage.message",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=918,
+ serialized_end=1322,
)
_FEREGISTERREQ = _descriptor.Descriptor(
- name='FeRegisterReq',
- full_name='mgmtd.FeRegisterReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='client_name', full_name='mgmtd.FeRegisterReq.client_name', index=0,
- number=1, type=9, cpp_type=9, label=2,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1324,
- serialized_end=1360,
+ name="FeRegisterReq",
+ full_name="mgmtd.FeRegisterReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="client_name",
+ full_name="mgmtd.FeRegisterReq.client_name",
+ index=0,
+ number=1,
+ type=9,
+ cpp_type=9,
+ label=2,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1324,
+ serialized_end=1360,
)
_FESESSIONREQ = _descriptor.Descriptor(
- name='FeSessionReq',
- full_name='mgmtd.FeSessionReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.FeSessionReq.create', index=0,
- number=1, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='client_conn_id', full_name='mgmtd.FeSessionReq.client_conn_id', index=1,
- number=2, type=4, cpp_type=4, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSessionReq.session_id', index=2,
- number=3, type=4, cpp_type=4, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='id', full_name='mgmtd.FeSessionReq.id',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=1362,
- serialized_end=1446,
+ name="FeSessionReq",
+ full_name="mgmtd.FeSessionReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.FeSessionReq.create",
+ index=0,
+ number=1,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="client_conn_id",
+ full_name="mgmtd.FeSessionReq.client_conn_id",
+ index=1,
+ number=2,
+ type=4,
+ cpp_type=4,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSessionReq.session_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="id",
+ full_name="mgmtd.FeSessionReq.id",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=1362,
+ serialized_end=1446,
)
_FESESSIONREPLY = _descriptor.Descriptor(
- name='FeSessionReply',
- full_name='mgmtd.FeSessionReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='create', full_name='mgmtd.FeSessionReply.create', index=0,
- number=1, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeSessionReply.success', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='client_conn_id', full_name='mgmtd.FeSessionReply.client_conn_id', index=2,
- number=3, type=4, cpp_type=4, label=1,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSessionReply.session_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1448,
- serialized_end=1541,
+ name="FeSessionReply",
+ full_name="mgmtd.FeSessionReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="create",
+ full_name="mgmtd.FeSessionReply.create",
+ index=0,
+ number=1,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeSessionReply.success",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="client_conn_id",
+ full_name="mgmtd.FeSessionReply.client_conn_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=1,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSessionReply.session_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1448,
+ serialized_end=1541,
)
_FELOCKDSREQ = _descriptor.Descriptor(
- name='FeLockDsReq',
- full_name='mgmtd.FeLockDsReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeLockDsReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeLockDsReq.req_id', index=1,
- number=2, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeLockDsReq.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lock', full_name='mgmtd.FeLockDsReq.lock', index=3,
- number=4, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1543,
- serialized_end=1641,
+ name="FeLockDsReq",
+ full_name="mgmtd.FeLockDsReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeLockDsReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeLockDsReq.req_id",
+ index=1,
+ number=2,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeLockDsReq.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lock",
+ full_name="mgmtd.FeLockDsReq.lock",
+ index=3,
+ number=4,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1543,
+ serialized_end=1641,
)
_FELOCKDSREPLY = _descriptor.Descriptor(
- name='FeLockDsReply',
- full_name='mgmtd.FeLockDsReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeLockDsReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeLockDsReply.req_id', index=1,
- number=2, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeLockDsReply.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lock', full_name='mgmtd.FeLockDsReply.lock', index=3,
- number=4, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeLockDsReply.success', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeLockDsReply.error_if_any', index=5,
- number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1644,
- serialized_end=1783,
+ name="FeLockDsReply",
+ full_name="mgmtd.FeLockDsReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeLockDsReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeLockDsReply.req_id",
+ index=1,
+ number=2,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeLockDsReply.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lock",
+ full_name="mgmtd.FeLockDsReply.lock",
+ index=3,
+ number=4,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeLockDsReply.success",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeLockDsReply.error_if_any",
+ index=5,
+ number=6,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1644,
+ serialized_end=1783,
)
_FESETCONFIGREQ = _descriptor.Descriptor(
- name='FeSetConfigReq',
- full_name='mgmtd.FeSetConfigReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSetConfigReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeSetConfigReq.ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeSetConfigReq.req_id', index=2,
- number=3, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeSetConfigReq.data', index=3,
- number=4, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='implicit_commit', full_name='mgmtd.FeSetConfigReq.implicit_commit', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='commit_ds_id', full_name='mgmtd.FeSetConfigReq.commit_ds_id', index=5,
- number=6, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1786,
- serialized_end=1977,
+ name="FeSetConfigReq",
+ full_name="mgmtd.FeSetConfigReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSetConfigReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeSetConfigReq.ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeSetConfigReq.req_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeSetConfigReq.data",
+ index=3,
+ number=4,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="implicit_commit",
+ full_name="mgmtd.FeSetConfigReq.implicit_commit",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="commit_ds_id",
+ full_name="mgmtd.FeSetConfigReq.commit_ds_id",
+ index=5,
+ number=6,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1786,
+ serialized_end=1977,
)
_FESETCONFIGREPLY = _descriptor.Descriptor(
- name='FeSetConfigReply',
- full_name='mgmtd.FeSetConfigReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeSetConfigReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeSetConfigReply.ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeSetConfigReply.req_id', index=2,
- number=3, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeSetConfigReply.success', index=3,
- number=4, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='implicit_commit', full_name='mgmtd.FeSetConfigReply.implicit_commit', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeSetConfigReply.error_if_any', index=5,
- number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=1980,
- serialized_end=2133,
+ name="FeSetConfigReply",
+ full_name="mgmtd.FeSetConfigReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeSetConfigReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeSetConfigReply.ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeSetConfigReply.req_id",
+ index=2,
+ number=3,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeSetConfigReply.success",
+ index=3,
+ number=4,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="implicit_commit",
+ full_name="mgmtd.FeSetConfigReply.implicit_commit",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeSetConfigReply.error_if_any",
+ index=5,
+ number=6,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=1980,
+ serialized_end=2133,
)
_FECOMMITCONFIGREQ = _descriptor.Descriptor(
- name='FeCommitConfigReq',
- full_name='mgmtd.FeCommitConfigReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeCommitConfigReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='src_ds_id', full_name='mgmtd.FeCommitConfigReq.src_ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='dst_ds_id', full_name='mgmtd.FeCommitConfigReq.dst_ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeCommitConfigReq.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='validate_only', full_name='mgmtd.FeCommitConfigReq.validate_only', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='abort', full_name='mgmtd.FeCommitConfigReq.abort', index=5,
- number=6, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2136,
- serialized_end=2307,
+ name="FeCommitConfigReq",
+ full_name="mgmtd.FeCommitConfigReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeCommitConfigReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="src_ds_id",
+ full_name="mgmtd.FeCommitConfigReq.src_ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="dst_ds_id",
+ full_name="mgmtd.FeCommitConfigReq.dst_ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeCommitConfigReq.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="validate_only",
+ full_name="mgmtd.FeCommitConfigReq.validate_only",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="abort",
+ full_name="mgmtd.FeCommitConfigReq.abort",
+ index=5,
+ number=6,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2136,
+ serialized_end=2307,
)
_FECOMMITCONFIGREPLY = _descriptor.Descriptor(
- name='FeCommitConfigReply',
- full_name='mgmtd.FeCommitConfigReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeCommitConfigReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='src_ds_id', full_name='mgmtd.FeCommitConfigReply.src_ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='dst_ds_id', full_name='mgmtd.FeCommitConfigReply.dst_ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeCommitConfigReply.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='validate_only', full_name='mgmtd.FeCommitConfigReply.validate_only', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeCommitConfigReply.success', index=5,
- number=6, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='abort', full_name='mgmtd.FeCommitConfigReply.abort', index=6,
- number=7, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeCommitConfigReply.error_if_any', index=7,
- number=8, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2310,
- serialized_end=2522,
+ name="FeCommitConfigReply",
+ full_name="mgmtd.FeCommitConfigReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeCommitConfigReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="src_ds_id",
+ full_name="mgmtd.FeCommitConfigReply.src_ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="dst_ds_id",
+ full_name="mgmtd.FeCommitConfigReply.dst_ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeCommitConfigReply.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="validate_only",
+ full_name="mgmtd.FeCommitConfigReply.validate_only",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeCommitConfigReply.success",
+ index=5,
+ number=6,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="abort",
+ full_name="mgmtd.FeCommitConfigReply.abort",
+ index=6,
+ number=7,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeCommitConfigReply.error_if_any",
+ index=7,
+ number=8,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2310,
+ serialized_end=2522,
)
_FEGETREQ = _descriptor.Descriptor(
- name='FeGetReq',
- full_name='mgmtd.FeGetReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeGetReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='config', full_name='mgmtd.FeGetReq.config', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeGetReq.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeGetReq.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeGetReq.data', index=4,
- number=5, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2525,
- serialized_end=2659,
+ name="FeGetReq",
+ full_name="mgmtd.FeGetReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeGetReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="config",
+ full_name="mgmtd.FeGetReq.config",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeGetReq.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeGetReq.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeGetReq.data",
+ index=4,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2525,
+ serialized_end=2659,
)
_FEGETREPLY = _descriptor.Descriptor(
- name='FeGetReply',
- full_name='mgmtd.FeGetReply',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeGetReply.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='config', full_name='mgmtd.FeGetReply.config', index=1,
- number=2, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeGetReply.ds_id', index=2,
- number=3, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeGetReply.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='success', full_name='mgmtd.FeGetReply.success', index=4,
- number=5, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='error_if_any', full_name='mgmtd.FeGetReply.error_if_any', index=5,
- number=6, type=9, cpp_type=9, label=1,
- has_default_value=False, default_value=b"".decode('utf-8'),
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeGetReply.data', index=6,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2662,
- serialized_end=2836,
+ name="FeGetReply",
+ full_name="mgmtd.FeGetReply",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeGetReply.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="config",
+ full_name="mgmtd.FeGetReply.config",
+ index=1,
+ number=2,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeGetReply.ds_id",
+ index=2,
+ number=3,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeGetReply.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="success",
+ full_name="mgmtd.FeGetReply.success",
+ index=4,
+ number=5,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="error_if_any",
+ full_name="mgmtd.FeGetReply.error_if_any",
+ index=5,
+ number=6,
+ type=9,
+ cpp_type=9,
+ label=1,
+ has_default_value=False,
+ default_value=b"".decode("utf-8"),
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeGetReply.data",
+ index=6,
+ number=7,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2662,
+ serialized_end=2836,
)
_FENOTIFYDATAREQ = _descriptor.Descriptor(
- name='FeNotifyDataReq',
- full_name='mgmtd.FeNotifyDataReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='data', full_name='mgmtd.FeNotifyDataReq.data', index=0,
- number=1, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2838,
- serialized_end=2886,
+ name="FeNotifyDataReq",
+ full_name="mgmtd.FeNotifyDataReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="data",
+ full_name="mgmtd.FeNotifyDataReq.data",
+ index=0,
+ number=1,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2838,
+ serialized_end=2886,
)
_FEREGISTERNOTIFYREQ = _descriptor.Descriptor(
- name='FeRegisterNotifyReq',
- full_name='mgmtd.FeRegisterNotifyReq',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='session_id', full_name='mgmtd.FeRegisterNotifyReq.session_id', index=0,
- number=1, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='ds_id', full_name='mgmtd.FeRegisterNotifyReq.ds_id', index=1,
- number=2, type=14, cpp_type=8, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='register_req', full_name='mgmtd.FeRegisterNotifyReq.register_req', index=2,
- number=3, type=8, cpp_type=7, label=2,
- has_default_value=False, default_value=False,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='req_id', full_name='mgmtd.FeRegisterNotifyReq.req_id', index=3,
- number=4, type=4, cpp_type=4, label=2,
- has_default_value=False, default_value=0,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='data_xpath', full_name='mgmtd.FeRegisterNotifyReq.data_xpath', index=4,
- number=5, type=11, cpp_type=10, label=3,
- has_default_value=False, default_value=[],
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- ],
- serialized_start=2889,
- serialized_end=3045,
+ name="FeRegisterNotifyReq",
+ full_name="mgmtd.FeRegisterNotifyReq",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="session_id",
+ full_name="mgmtd.FeRegisterNotifyReq.session_id",
+ index=0,
+ number=1,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="ds_id",
+ full_name="mgmtd.FeRegisterNotifyReq.ds_id",
+ index=1,
+ number=2,
+ type=14,
+ cpp_type=8,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="register_req",
+ full_name="mgmtd.FeRegisterNotifyReq.register_req",
+ index=2,
+ number=3,
+ type=8,
+ cpp_type=7,
+ label=2,
+ has_default_value=False,
+ default_value=False,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="req_id",
+ full_name="mgmtd.FeRegisterNotifyReq.req_id",
+ index=3,
+ number=4,
+ type=4,
+ cpp_type=4,
+ label=2,
+ has_default_value=False,
+ default_value=0,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="data_xpath",
+ full_name="mgmtd.FeRegisterNotifyReq.data_xpath",
+ index=4,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=3,
+ has_default_value=False,
+ default_value=[],
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[],
+ serialized_start=2889,
+ serialized_end=3045,
)
_FEMESSAGE = _descriptor.Descriptor(
- name='FeMessage',
- full_name='mgmtd.FeMessage',
- filename=None,
- file=DESCRIPTOR,
- containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[
- _descriptor.FieldDescriptor(
- name='register_req', full_name='mgmtd.FeMessage.register_req', index=0,
- number=2, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_req', full_name='mgmtd.FeMessage.session_req', index=1,
- number=3, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='session_reply', full_name='mgmtd.FeMessage.session_reply', index=2,
- number=4, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lockds_req', full_name='mgmtd.FeMessage.lockds_req', index=3,
- number=5, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='lockds_reply', full_name='mgmtd.FeMessage.lockds_reply', index=4,
- number=6, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='setcfg_req', full_name='mgmtd.FeMessage.setcfg_req', index=5,
- number=7, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='setcfg_reply', full_name='mgmtd.FeMessage.setcfg_reply', index=6,
- number=8, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='commcfg_req', full_name='mgmtd.FeMessage.commcfg_req', index=7,
- number=9, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='commcfg_reply', full_name='mgmtd.FeMessage.commcfg_reply', index=8,
- number=10, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='get_req', full_name='mgmtd.FeMessage.get_req', index=9,
- number=11, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='get_reply', full_name='mgmtd.FeMessage.get_reply', index=10,
- number=12, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='notify_data_req', full_name='mgmtd.FeMessage.notify_data_req', index=11,
- number=15, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- _descriptor.FieldDescriptor(
- name='regnotify_req', full_name='mgmtd.FeMessage.regnotify_req', index=12,
- number=16, type=11, cpp_type=10, label=1,
- has_default_value=False, default_value=None,
- message_type=None, enum_type=None, containing_type=None,
- is_extension=False, extension_scope=None,
- serialized_options=None, file=DESCRIPTOR, create_key=_descriptor._internal_create_key),
- ],
- extensions=[
- ],
- nested_types=[],
- enum_types=[
- ],
- serialized_options=None,
- is_extendable=False,
- syntax='proto2',
- extension_ranges=[],
- oneofs=[
- _descriptor.OneofDescriptor(
- name='message', full_name='mgmtd.FeMessage.message',
- index=0, containing_type=None,
- create_key=_descriptor._internal_create_key,
- fields=[]),
- ],
- serialized_start=3048,
- serialized_end=3672,
-)
-
-_YANGDATAVALUE.oneofs_by_name['value'].fields.append(
- _YANGDATAVALUE.fields_by_name['encoded_str_val'])
-_YANGDATAVALUE.fields_by_name['encoded_str_val'].containing_oneof = _YANGDATAVALUE.oneofs_by_name['value']
-_YANGDATA.fields_by_name['value'].message_type = _YANGDATAVALUE
-_YANGCFGDATAREQ.fields_by_name['data'].message_type = _YANGDATA
-_YANGCFGDATAREQ.fields_by_name['req_type'].enum_type = _CFGDATAREQTYPE
-_YANGGETDATAREQ.fields_by_name['data'].message_type = _YANGDATA
-_BECFGDATACREATEREQ.fields_by_name['data_req'].message_type = _YANGCFGDATAREQ
-_YANGDATAREPLY.fields_by_name['data'].message_type = _YANGDATA
-_BEMESSAGE.fields_by_name['subscr_req'].message_type = _BESUBSCRIBEREQ
-_BEMESSAGE.fields_by_name['subscr_reply'].message_type = _BESUBSCRIBEREPLY
-_BEMESSAGE.fields_by_name['txn_req'].message_type = _BETXNREQ
-_BEMESSAGE.fields_by_name['txn_reply'].message_type = _BETXNREPLY
-_BEMESSAGE.fields_by_name['cfg_data_req'].message_type = _BECFGDATACREATEREQ
-_BEMESSAGE.fields_by_name['cfg_data_reply'].message_type = _BECFGDATACREATEREPLY
-_BEMESSAGE.fields_by_name['cfg_apply_req'].message_type = _BECFGDATAAPPLYREQ
-_BEMESSAGE.fields_by_name['cfg_apply_reply'].message_type = _BECFGDATAAPPLYREPLY
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['subscr_req'])
-_BEMESSAGE.fields_by_name['subscr_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['subscr_reply'])
-_BEMESSAGE.fields_by_name['subscr_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['txn_req'])
-_BEMESSAGE.fields_by_name['txn_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['txn_reply'])
-_BEMESSAGE.fields_by_name['txn_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_data_req'])
-_BEMESSAGE.fields_by_name['cfg_data_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_data_reply'])
-_BEMESSAGE.fields_by_name['cfg_data_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_apply_req'])
-_BEMESSAGE.fields_by_name['cfg_apply_req'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_BEMESSAGE.oneofs_by_name['message'].fields.append(
- _BEMESSAGE.fields_by_name['cfg_apply_reply'])
-_BEMESSAGE.fields_by_name['cfg_apply_reply'].containing_oneof = _BEMESSAGE.oneofs_by_name['message']
-_FESESSIONREQ.oneofs_by_name['id'].fields.append(
- _FESESSIONREQ.fields_by_name['client_conn_id'])
-_FESESSIONREQ.fields_by_name['client_conn_id'].containing_oneof = _FESESSIONREQ.oneofs_by_name['id']
-_FESESSIONREQ.oneofs_by_name['id'].fields.append(
- _FESESSIONREQ.fields_by_name['session_id'])
-_FESESSIONREQ.fields_by_name['session_id'].containing_oneof = _FESESSIONREQ.oneofs_by_name['id']
-_FELOCKDSREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FELOCKDSREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FESETCONFIGREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FESETCONFIGREQ.fields_by_name['data'].message_type = _YANGCFGDATAREQ
-_FESETCONFIGREQ.fields_by_name['commit_ds_id'].enum_type = _DATASTOREID
-_FESETCONFIGREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREQ.fields_by_name['src_ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREQ.fields_by_name['dst_ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREPLY.fields_by_name['src_ds_id'].enum_type = _DATASTOREID
-_FECOMMITCONFIGREPLY.fields_by_name['dst_ds_id'].enum_type = _DATASTOREID
-_FEGETREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FEGETREQ.fields_by_name['data'].message_type = _YANGGETDATAREQ
-_FEGETREPLY.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FEGETREPLY.fields_by_name['data'].message_type = _YANGDATAREPLY
-_FENOTIFYDATAREQ.fields_by_name['data'].message_type = _YANGDATA
-_FEREGISTERNOTIFYREQ.fields_by_name['ds_id'].enum_type = _DATASTOREID
-_FEREGISTERNOTIFYREQ.fields_by_name['data_xpath'].message_type = _YANGDATAXPATH
-_FEMESSAGE.fields_by_name['register_req'].message_type = _FEREGISTERREQ
-_FEMESSAGE.fields_by_name['session_req'].message_type = _FESESSIONREQ
-_FEMESSAGE.fields_by_name['session_reply'].message_type = _FESESSIONREPLY
-_FEMESSAGE.fields_by_name['lockds_req'].message_type = _FELOCKDSREQ
-_FEMESSAGE.fields_by_name['lockds_reply'].message_type = _FELOCKDSREPLY
-_FEMESSAGE.fields_by_name['setcfg_req'].message_type = _FESETCONFIGREQ
-_FEMESSAGE.fields_by_name['setcfg_reply'].message_type = _FESETCONFIGREPLY
-_FEMESSAGE.fields_by_name['commcfg_req'].message_type = _FECOMMITCONFIGREQ
-_FEMESSAGE.fields_by_name['commcfg_reply'].message_type = _FECOMMITCONFIGREPLY
-_FEMESSAGE.fields_by_name['get_req'].message_type = _FEGETREQ
-_FEMESSAGE.fields_by_name['get_reply'].message_type = _FEGETREPLY
-_FEMESSAGE.fields_by_name['notify_data_req'].message_type = _FENOTIFYDATAREQ
-_FEMESSAGE.fields_by_name['regnotify_req'].message_type = _FEREGISTERNOTIFYREQ
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['register_req'])
-_FEMESSAGE.fields_by_name['register_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['session_req'])
-_FEMESSAGE.fields_by_name['session_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['session_reply'])
-_FEMESSAGE.fields_by_name['session_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['lockds_req'])
-_FEMESSAGE.fields_by_name['lockds_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['lockds_reply'])
-_FEMESSAGE.fields_by_name['lockds_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['setcfg_req'])
-_FEMESSAGE.fields_by_name['setcfg_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['setcfg_reply'])
-_FEMESSAGE.fields_by_name['setcfg_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['commcfg_req'])
-_FEMESSAGE.fields_by_name['commcfg_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['commcfg_reply'])
-_FEMESSAGE.fields_by_name['commcfg_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['get_req'])
-_FEMESSAGE.fields_by_name['get_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['get_reply'])
-_FEMESSAGE.fields_by_name['get_reply'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['notify_data_req'])
-_FEMESSAGE.fields_by_name['notify_data_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-_FEMESSAGE.oneofs_by_name['message'].fields.append(
- _FEMESSAGE.fields_by_name['regnotify_req'])
-_FEMESSAGE.fields_by_name['regnotify_req'].containing_oneof = _FEMESSAGE.oneofs_by_name['message']
-DESCRIPTOR.message_types_by_name['YangDataXPath'] = _YANGDATAXPATH
-DESCRIPTOR.message_types_by_name['YangDataValue'] = _YANGDATAVALUE
-DESCRIPTOR.message_types_by_name['YangData'] = _YANGDATA
-DESCRIPTOR.message_types_by_name['YangCfgDataReq'] = _YANGCFGDATAREQ
-DESCRIPTOR.message_types_by_name['YangGetDataReq'] = _YANGGETDATAREQ
-DESCRIPTOR.message_types_by_name['BeSubscribeReq'] = _BESUBSCRIBEREQ
-DESCRIPTOR.message_types_by_name['BeSubscribeReply'] = _BESUBSCRIBEREPLY
-DESCRIPTOR.message_types_by_name['BeTxnReq'] = _BETXNREQ
-DESCRIPTOR.message_types_by_name['BeTxnReply'] = _BETXNREPLY
-DESCRIPTOR.message_types_by_name['BeCfgDataCreateReq'] = _BECFGDATACREATEREQ
-DESCRIPTOR.message_types_by_name['BeCfgDataCreateReply'] = _BECFGDATACREATEREPLY
-DESCRIPTOR.message_types_by_name['BeCfgDataApplyReq'] = _BECFGDATAAPPLYREQ
-DESCRIPTOR.message_types_by_name['BeCfgDataApplyReply'] = _BECFGDATAAPPLYREPLY
-DESCRIPTOR.message_types_by_name['YangDataReply'] = _YANGDATAREPLY
-DESCRIPTOR.message_types_by_name['BeMessage'] = _BEMESSAGE
-DESCRIPTOR.message_types_by_name['FeRegisterReq'] = _FEREGISTERREQ
-DESCRIPTOR.message_types_by_name['FeSessionReq'] = _FESESSIONREQ
-DESCRIPTOR.message_types_by_name['FeSessionReply'] = _FESESSIONREPLY
-DESCRIPTOR.message_types_by_name['FeLockDsReq'] = _FELOCKDSREQ
-DESCRIPTOR.message_types_by_name['FeLockDsReply'] = _FELOCKDSREPLY
-DESCRIPTOR.message_types_by_name['FeSetConfigReq'] = _FESETCONFIGREQ
-DESCRIPTOR.message_types_by_name['FeSetConfigReply'] = _FESETCONFIGREPLY
-DESCRIPTOR.message_types_by_name['FeCommitConfigReq'] = _FECOMMITCONFIGREQ
-DESCRIPTOR.message_types_by_name['FeCommitConfigReply'] = _FECOMMITCONFIGREPLY
-DESCRIPTOR.message_types_by_name['FeGetReq'] = _FEGETREQ
-DESCRIPTOR.message_types_by_name['FeGetReply'] = _FEGETREPLY
-DESCRIPTOR.message_types_by_name['FeNotifyDataReq'] = _FENOTIFYDATAREQ
-DESCRIPTOR.message_types_by_name['FeRegisterNotifyReq'] = _FEREGISTERNOTIFYREQ
-DESCRIPTOR.message_types_by_name['FeMessage'] = _FEMESSAGE
-DESCRIPTOR.enum_types_by_name['CfgDataReqType'] = _CFGDATAREQTYPE
-DESCRIPTOR.enum_types_by_name['DatastoreId'] = _DATASTOREID
+ name="FeMessage",
+ full_name="mgmtd.FeMessage",
+ filename=None,
+ file=DESCRIPTOR,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[
+ _descriptor.FieldDescriptor(
+ name="register_req",
+ full_name="mgmtd.FeMessage.register_req",
+ index=0,
+ number=2,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_req",
+ full_name="mgmtd.FeMessage.session_req",
+ index=1,
+ number=3,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="session_reply",
+ full_name="mgmtd.FeMessage.session_reply",
+ index=2,
+ number=4,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lockds_req",
+ full_name="mgmtd.FeMessage.lockds_req",
+ index=3,
+ number=5,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="lockds_reply",
+ full_name="mgmtd.FeMessage.lockds_reply",
+ index=4,
+ number=6,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="setcfg_req",
+ full_name="mgmtd.FeMessage.setcfg_req",
+ index=5,
+ number=7,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="setcfg_reply",
+ full_name="mgmtd.FeMessage.setcfg_reply",
+ index=6,
+ number=8,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="commcfg_req",
+ full_name="mgmtd.FeMessage.commcfg_req",
+ index=7,
+ number=9,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="commcfg_reply",
+ full_name="mgmtd.FeMessage.commcfg_reply",
+ index=8,
+ number=10,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="get_req",
+ full_name="mgmtd.FeMessage.get_req",
+ index=9,
+ number=11,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="get_reply",
+ full_name="mgmtd.FeMessage.get_reply",
+ index=10,
+ number=12,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="notify_data_req",
+ full_name="mgmtd.FeMessage.notify_data_req",
+ index=11,
+ number=15,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ _descriptor.FieldDescriptor(
+ name="regnotify_req",
+ full_name="mgmtd.FeMessage.regnotify_req",
+ index=12,
+ number=16,
+ type=11,
+ cpp_type=10,
+ label=1,
+ has_default_value=False,
+ default_value=None,
+ message_type=None,
+ enum_type=None,
+ containing_type=None,
+ is_extension=False,
+ extension_scope=None,
+ serialized_options=None,
+ file=DESCRIPTOR,
+ create_key=_descriptor._internal_create_key,
+ ),
+ ],
+ extensions=[],
+ nested_types=[],
+ enum_types=[],
+ serialized_options=None,
+ is_extendable=False,
+ syntax="proto2",
+ extension_ranges=[],
+ oneofs=[
+ _descriptor.OneofDescriptor(
+ name="message",
+ full_name="mgmtd.FeMessage.message",
+ index=0,
+ containing_type=None,
+ create_key=_descriptor._internal_create_key,
+ fields=[],
+ ),
+ ],
+ serialized_start=3048,
+ serialized_end=3672,
+)
+
+_YANGDATAVALUE.oneofs_by_name["value"].fields.append(
+ _YANGDATAVALUE.fields_by_name["encoded_str_val"]
+)
+_YANGDATAVALUE.fields_by_name[
+ "encoded_str_val"
+].containing_oneof = _YANGDATAVALUE.oneofs_by_name["value"]
+_YANGDATA.fields_by_name["value"].message_type = _YANGDATAVALUE
+_YANGCFGDATAREQ.fields_by_name["data"].message_type = _YANGDATA
+_YANGCFGDATAREQ.fields_by_name["req_type"].enum_type = _CFGDATAREQTYPE
+_YANGGETDATAREQ.fields_by_name["data"].message_type = _YANGDATA
+_BECFGDATACREATEREQ.fields_by_name["data_req"].message_type = _YANGCFGDATAREQ
+_YANGDATAREPLY.fields_by_name["data"].message_type = _YANGDATA
+_BEMESSAGE.fields_by_name["subscr_req"].message_type = _BESUBSCRIBEREQ
+_BEMESSAGE.fields_by_name["subscr_reply"].message_type = _BESUBSCRIBEREPLY
+_BEMESSAGE.fields_by_name["txn_req"].message_type = _BETXNREQ
+_BEMESSAGE.fields_by_name["txn_reply"].message_type = _BETXNREPLY
+_BEMESSAGE.fields_by_name["cfg_data_req"].message_type = _BECFGDATACREATEREQ
+_BEMESSAGE.fields_by_name["cfg_data_reply"].message_type = _BECFGDATACREATEREPLY
+_BEMESSAGE.fields_by_name["cfg_apply_req"].message_type = _BECFGDATAAPPLYREQ
+_BEMESSAGE.fields_by_name["cfg_apply_reply"].message_type = _BECFGDATAAPPLYREPLY
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["subscr_req"]
+)
+_BEMESSAGE.fields_by_name["subscr_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["subscr_reply"]
+)
+_BEMESSAGE.fields_by_name["subscr_reply"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(_BEMESSAGE.fields_by_name["txn_req"])
+_BEMESSAGE.fields_by_name["txn_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["txn_reply"]
+)
+_BEMESSAGE.fields_by_name["txn_reply"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_data_req"]
+)
+_BEMESSAGE.fields_by_name["cfg_data_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_data_reply"]
+)
+_BEMESSAGE.fields_by_name[
+ "cfg_data_reply"
+].containing_oneof = _BEMESSAGE.oneofs_by_name["message"]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_apply_req"]
+)
+_BEMESSAGE.fields_by_name["cfg_apply_req"].containing_oneof = _BEMESSAGE.oneofs_by_name[
+ "message"
+]
+_BEMESSAGE.oneofs_by_name["message"].fields.append(
+ _BEMESSAGE.fields_by_name["cfg_apply_reply"]
+)
+_BEMESSAGE.fields_by_name[
+ "cfg_apply_reply"
+].containing_oneof = _BEMESSAGE.oneofs_by_name["message"]
+_FESESSIONREQ.oneofs_by_name["id"].fields.append(
+ _FESESSIONREQ.fields_by_name["client_conn_id"]
+)
+_FESESSIONREQ.fields_by_name[
+ "client_conn_id"
+].containing_oneof = _FESESSIONREQ.oneofs_by_name["id"]
+_FESESSIONREQ.oneofs_by_name["id"].fields.append(
+ _FESESSIONREQ.fields_by_name["session_id"]
+)
+_FESESSIONREQ.fields_by_name[
+ "session_id"
+].containing_oneof = _FESESSIONREQ.oneofs_by_name["id"]
+_FELOCKDSREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FELOCKDSREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FESETCONFIGREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FESETCONFIGREQ.fields_by_name["data"].message_type = _YANGCFGDATAREQ
+_FESETCONFIGREQ.fields_by_name["commit_ds_id"].enum_type = _DATASTOREID
+_FESETCONFIGREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREQ.fields_by_name["src_ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREQ.fields_by_name["dst_ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREPLY.fields_by_name["src_ds_id"].enum_type = _DATASTOREID
+_FECOMMITCONFIGREPLY.fields_by_name["dst_ds_id"].enum_type = _DATASTOREID
+_FEGETREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FEGETREQ.fields_by_name["data"].message_type = _YANGGETDATAREQ
+_FEGETREPLY.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FEGETREPLY.fields_by_name["data"].message_type = _YANGDATAREPLY
+_FENOTIFYDATAREQ.fields_by_name["data"].message_type = _YANGDATA
+_FEREGISTERNOTIFYREQ.fields_by_name["ds_id"].enum_type = _DATASTOREID
+_FEREGISTERNOTIFYREQ.fields_by_name["data_xpath"].message_type = _YANGDATAXPATH
+_FEMESSAGE.fields_by_name["register_req"].message_type = _FEREGISTERREQ
+_FEMESSAGE.fields_by_name["session_req"].message_type = _FESESSIONREQ
+_FEMESSAGE.fields_by_name["session_reply"].message_type = _FESESSIONREPLY
+_FEMESSAGE.fields_by_name["lockds_req"].message_type = _FELOCKDSREQ
+_FEMESSAGE.fields_by_name["lockds_reply"].message_type = _FELOCKDSREPLY
+_FEMESSAGE.fields_by_name["setcfg_req"].message_type = _FESETCONFIGREQ
+_FEMESSAGE.fields_by_name["setcfg_reply"].message_type = _FESETCONFIGREPLY
+_FEMESSAGE.fields_by_name["commcfg_req"].message_type = _FECOMMITCONFIGREQ
+_FEMESSAGE.fields_by_name["commcfg_reply"].message_type = _FECOMMITCONFIGREPLY
+_FEMESSAGE.fields_by_name["get_req"].message_type = _FEGETREQ
+_FEMESSAGE.fields_by_name["get_reply"].message_type = _FEGETREPLY
+_FEMESSAGE.fields_by_name["notify_data_req"].message_type = _FENOTIFYDATAREQ
+_FEMESSAGE.fields_by_name["regnotify_req"].message_type = _FEREGISTERNOTIFYREQ
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["register_req"]
+)
+_FEMESSAGE.fields_by_name["register_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["session_req"]
+)
+_FEMESSAGE.fields_by_name["session_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["session_reply"]
+)
+_FEMESSAGE.fields_by_name["session_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["lockds_req"]
+)
+_FEMESSAGE.fields_by_name["lockds_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["lockds_reply"]
+)
+_FEMESSAGE.fields_by_name["lockds_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["setcfg_req"]
+)
+_FEMESSAGE.fields_by_name["setcfg_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["setcfg_reply"]
+)
+_FEMESSAGE.fields_by_name["setcfg_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["commcfg_req"]
+)
+_FEMESSAGE.fields_by_name["commcfg_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["commcfg_reply"]
+)
+_FEMESSAGE.fields_by_name["commcfg_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(_FEMESSAGE.fields_by_name["get_req"])
+_FEMESSAGE.fields_by_name["get_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["get_reply"]
+)
+_FEMESSAGE.fields_by_name["get_reply"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["notify_data_req"]
+)
+_FEMESSAGE.fields_by_name[
+ "notify_data_req"
+].containing_oneof = _FEMESSAGE.oneofs_by_name["message"]
+_FEMESSAGE.oneofs_by_name["message"].fields.append(
+ _FEMESSAGE.fields_by_name["regnotify_req"]
+)
+_FEMESSAGE.fields_by_name["regnotify_req"].containing_oneof = _FEMESSAGE.oneofs_by_name[
+ "message"
+]
+DESCRIPTOR.message_types_by_name["YangDataXPath"] = _YANGDATAXPATH
+DESCRIPTOR.message_types_by_name["YangDataValue"] = _YANGDATAVALUE
+DESCRIPTOR.message_types_by_name["YangData"] = _YANGDATA
+DESCRIPTOR.message_types_by_name["YangCfgDataReq"] = _YANGCFGDATAREQ
+DESCRIPTOR.message_types_by_name["YangGetDataReq"] = _YANGGETDATAREQ
+DESCRIPTOR.message_types_by_name["BeSubscribeReq"] = _BESUBSCRIBEREQ
+DESCRIPTOR.message_types_by_name["BeSubscribeReply"] = _BESUBSCRIBEREPLY
+DESCRIPTOR.message_types_by_name["BeTxnReq"] = _BETXNREQ
+DESCRIPTOR.message_types_by_name["BeTxnReply"] = _BETXNREPLY
+DESCRIPTOR.message_types_by_name["BeCfgDataCreateReq"] = _BECFGDATACREATEREQ
+DESCRIPTOR.message_types_by_name["BeCfgDataCreateReply"] = _BECFGDATACREATEREPLY
+DESCRIPTOR.message_types_by_name["BeCfgDataApplyReq"] = _BECFGDATAAPPLYREQ
+DESCRIPTOR.message_types_by_name["BeCfgDataApplyReply"] = _BECFGDATAAPPLYREPLY
+DESCRIPTOR.message_types_by_name["YangDataReply"] = _YANGDATAREPLY
+DESCRIPTOR.message_types_by_name["BeMessage"] = _BEMESSAGE
+DESCRIPTOR.message_types_by_name["FeRegisterReq"] = _FEREGISTERREQ
+DESCRIPTOR.message_types_by_name["FeSessionReq"] = _FESESSIONREQ
+DESCRIPTOR.message_types_by_name["FeSessionReply"] = _FESESSIONREPLY
+DESCRIPTOR.message_types_by_name["FeLockDsReq"] = _FELOCKDSREQ
+DESCRIPTOR.message_types_by_name["FeLockDsReply"] = _FELOCKDSREPLY
+DESCRIPTOR.message_types_by_name["FeSetConfigReq"] = _FESETCONFIGREQ
+DESCRIPTOR.message_types_by_name["FeSetConfigReply"] = _FESETCONFIGREPLY
+DESCRIPTOR.message_types_by_name["FeCommitConfigReq"] = _FECOMMITCONFIGREQ
+DESCRIPTOR.message_types_by_name["FeCommitConfigReply"] = _FECOMMITCONFIGREPLY
+DESCRIPTOR.message_types_by_name["FeGetReq"] = _FEGETREQ
+DESCRIPTOR.message_types_by_name["FeGetReply"] = _FEGETREPLY
+DESCRIPTOR.message_types_by_name["FeNotifyDataReq"] = _FENOTIFYDATAREQ
+DESCRIPTOR.message_types_by_name["FeRegisterNotifyReq"] = _FEREGISTERNOTIFYREQ
+DESCRIPTOR.message_types_by_name["FeMessage"] = _FEMESSAGE
+DESCRIPTOR.enum_types_by_name["CfgDataReqType"] = _CFGDATAREQTYPE
+DESCRIPTOR.enum_types_by_name["DatastoreId"] = _DATASTOREID
_sym_db.RegisterFileDescriptor(DESCRIPTOR)
-YangDataXPath = _reflection.GeneratedProtocolMessageType('YangDataXPath', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATAXPATH,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangDataXPath)
- })
+YangDataXPath = _reflection.GeneratedProtocolMessageType(
+ "YangDataXPath",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATAXPATH,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangDataXPath)
+ },
+)
_sym_db.RegisterMessage(YangDataXPath)
-YangDataValue = _reflection.GeneratedProtocolMessageType('YangDataValue', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATAVALUE,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangDataValue)
- })
+YangDataValue = _reflection.GeneratedProtocolMessageType(
+ "YangDataValue",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATAVALUE,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangDataValue)
+ },
+)
_sym_db.RegisterMessage(YangDataValue)
-YangData = _reflection.GeneratedProtocolMessageType('YangData', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATA,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangData)
- })
+YangData = _reflection.GeneratedProtocolMessageType(
+ "YangData",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATA,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangData)
+ },
+)
_sym_db.RegisterMessage(YangData)
-YangCfgDataReq = _reflection.GeneratedProtocolMessageType('YangCfgDataReq', (_message.Message,), {
- 'DESCRIPTOR' : _YANGCFGDATAREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangCfgDataReq)
- })
+YangCfgDataReq = _reflection.GeneratedProtocolMessageType(
+ "YangCfgDataReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGCFGDATAREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangCfgDataReq)
+ },
+)
_sym_db.RegisterMessage(YangCfgDataReq)
-YangGetDataReq = _reflection.GeneratedProtocolMessageType('YangGetDataReq', (_message.Message,), {
- 'DESCRIPTOR' : _YANGGETDATAREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangGetDataReq)
- })
+YangGetDataReq = _reflection.GeneratedProtocolMessageType(
+ "YangGetDataReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGGETDATAREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangGetDataReq)
+ },
+)
_sym_db.RegisterMessage(YangGetDataReq)
-BeSubscribeReq = _reflection.GeneratedProtocolMessageType('BeSubscribeReq', (_message.Message,), {
- 'DESCRIPTOR' : _BESUBSCRIBEREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReq)
- })
+BeSubscribeReq = _reflection.GeneratedProtocolMessageType(
+ "BeSubscribeReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BESUBSCRIBEREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReq)
+ },
+)
_sym_db.RegisterMessage(BeSubscribeReq)
-BeSubscribeReply = _reflection.GeneratedProtocolMessageType('BeSubscribeReply', (_message.Message,), {
- 'DESCRIPTOR' : _BESUBSCRIBEREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReply)
- })
+BeSubscribeReply = _reflection.GeneratedProtocolMessageType(
+ "BeSubscribeReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BESUBSCRIBEREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeSubscribeReply)
+ },
+)
_sym_db.RegisterMessage(BeSubscribeReply)
-BeTxnReq = _reflection.GeneratedProtocolMessageType('BeTxnReq', (_message.Message,), {
- 'DESCRIPTOR' : _BETXNREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReq)
- })
+BeTxnReq = _reflection.GeneratedProtocolMessageType(
+ "BeTxnReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BETXNREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReq)
+ },
+)
_sym_db.RegisterMessage(BeTxnReq)
-BeTxnReply = _reflection.GeneratedProtocolMessageType('BeTxnReply', (_message.Message,), {
- 'DESCRIPTOR' : _BETXNREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReply)
- })
+BeTxnReply = _reflection.GeneratedProtocolMessageType(
+ "BeTxnReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BETXNREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeTxnReply)
+ },
+)
_sym_db.RegisterMessage(BeTxnReply)
-BeCfgDataCreateReq = _reflection.GeneratedProtocolMessageType('BeCfgDataCreateReq', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATACREATEREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReq)
- })
+BeCfgDataCreateReq = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataCreateReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATACREATEREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReq)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataCreateReq)
-BeCfgDataCreateReply = _reflection.GeneratedProtocolMessageType('BeCfgDataCreateReply', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATACREATEREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReply)
- })
+BeCfgDataCreateReply = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataCreateReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATACREATEREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataCreateReply)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataCreateReply)
-BeCfgDataApplyReq = _reflection.GeneratedProtocolMessageType('BeCfgDataApplyReq', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATAAPPLYREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReq)
- })
+BeCfgDataApplyReq = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataApplyReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATAAPPLYREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReq)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataApplyReq)
-BeCfgDataApplyReply = _reflection.GeneratedProtocolMessageType('BeCfgDataApplyReply', (_message.Message,), {
- 'DESCRIPTOR' : _BECFGDATAAPPLYREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReply)
- })
+BeCfgDataApplyReply = _reflection.GeneratedProtocolMessageType(
+ "BeCfgDataApplyReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BECFGDATAAPPLYREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeCfgDataApplyReply)
+ },
+)
_sym_db.RegisterMessage(BeCfgDataApplyReply)
-YangDataReply = _reflection.GeneratedProtocolMessageType('YangDataReply', (_message.Message,), {
- 'DESCRIPTOR' : _YANGDATAREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.YangDataReply)
- })
+YangDataReply = _reflection.GeneratedProtocolMessageType(
+ "YangDataReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _YANGDATAREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.YangDataReply)
+ },
+)
_sym_db.RegisterMessage(YangDataReply)
-BeMessage = _reflection.GeneratedProtocolMessageType('BeMessage', (_message.Message,), {
- 'DESCRIPTOR' : _BEMESSAGE,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.BeMessage)
- })
+BeMessage = _reflection.GeneratedProtocolMessageType(
+ "BeMessage",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _BEMESSAGE,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.BeMessage)
+ },
+)
_sym_db.RegisterMessage(BeMessage)
-FeRegisterReq = _reflection.GeneratedProtocolMessageType('FeRegisterReq', (_message.Message,), {
- 'DESCRIPTOR' : _FEREGISTERREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterReq)
- })
+FeRegisterReq = _reflection.GeneratedProtocolMessageType(
+ "FeRegisterReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEREGISTERREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterReq)
+ },
+)
_sym_db.RegisterMessage(FeRegisterReq)
-FeSessionReq = _reflection.GeneratedProtocolMessageType('FeSessionReq', (_message.Message,), {
- 'DESCRIPTOR' : _FESESSIONREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReq)
- })
+FeSessionReq = _reflection.GeneratedProtocolMessageType(
+ "FeSessionReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESESSIONREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReq)
+ },
+)
_sym_db.RegisterMessage(FeSessionReq)
-FeSessionReply = _reflection.GeneratedProtocolMessageType('FeSessionReply', (_message.Message,), {
- 'DESCRIPTOR' : _FESESSIONREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReply)
- })
+FeSessionReply = _reflection.GeneratedProtocolMessageType(
+ "FeSessionReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESESSIONREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSessionReply)
+ },
+)
_sym_db.RegisterMessage(FeSessionReply)
-FeLockDsReq = _reflection.GeneratedProtocolMessageType('FeLockDsReq', (_message.Message,), {
- 'DESCRIPTOR' : _FELOCKDSREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReq)
- })
+FeLockDsReq = _reflection.GeneratedProtocolMessageType(
+ "FeLockDsReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FELOCKDSREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReq)
+ },
+)
_sym_db.RegisterMessage(FeLockDsReq)
-FeLockDsReply = _reflection.GeneratedProtocolMessageType('FeLockDsReply', (_message.Message,), {
- 'DESCRIPTOR' : _FELOCKDSREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReply)
- })
+FeLockDsReply = _reflection.GeneratedProtocolMessageType(
+ "FeLockDsReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FELOCKDSREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeLockDsReply)
+ },
+)
_sym_db.RegisterMessage(FeLockDsReply)
-FeSetConfigReq = _reflection.GeneratedProtocolMessageType('FeSetConfigReq', (_message.Message,), {
- 'DESCRIPTOR' : _FESETCONFIGREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReq)
- })
+FeSetConfigReq = _reflection.GeneratedProtocolMessageType(
+ "FeSetConfigReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESETCONFIGREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReq)
+ },
+)
_sym_db.RegisterMessage(FeSetConfigReq)
-FeSetConfigReply = _reflection.GeneratedProtocolMessageType('FeSetConfigReply', (_message.Message,), {
- 'DESCRIPTOR' : _FESETCONFIGREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReply)
- })
+FeSetConfigReply = _reflection.GeneratedProtocolMessageType(
+ "FeSetConfigReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FESETCONFIGREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeSetConfigReply)
+ },
+)
_sym_db.RegisterMessage(FeSetConfigReply)
-FeCommitConfigReq = _reflection.GeneratedProtocolMessageType('FeCommitConfigReq', (_message.Message,), {
- 'DESCRIPTOR' : _FECOMMITCONFIGREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReq)
- })
+FeCommitConfigReq = _reflection.GeneratedProtocolMessageType(
+ "FeCommitConfigReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FECOMMITCONFIGREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReq)
+ },
+)
_sym_db.RegisterMessage(FeCommitConfigReq)
-FeCommitConfigReply = _reflection.GeneratedProtocolMessageType('FeCommitConfigReply', (_message.Message,), {
- 'DESCRIPTOR' : _FECOMMITCONFIGREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReply)
- })
+FeCommitConfigReply = _reflection.GeneratedProtocolMessageType(
+ "FeCommitConfigReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FECOMMITCONFIGREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeCommitConfigReply)
+ },
+)
_sym_db.RegisterMessage(FeCommitConfigReply)
-FeGetReq = _reflection.GeneratedProtocolMessageType('FeGetReq', (_message.Message,), {
- 'DESCRIPTOR' : _FEGETREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeGetReq)
- })
+FeGetReq = _reflection.GeneratedProtocolMessageType(
+ "FeGetReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEGETREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeGetReq)
+ },
+)
_sym_db.RegisterMessage(FeGetReq)
-FeGetReply = _reflection.GeneratedProtocolMessageType('FeGetReply', (_message.Message,), {
- 'DESCRIPTOR' : _FEGETREPLY,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeGetReply)
- })
+FeGetReply = _reflection.GeneratedProtocolMessageType(
+ "FeGetReply",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEGETREPLY,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeGetReply)
+ },
+)
_sym_db.RegisterMessage(FeGetReply)
-FeNotifyDataReq = _reflection.GeneratedProtocolMessageType('FeNotifyDataReq', (_message.Message,), {
- 'DESCRIPTOR' : _FENOTIFYDATAREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeNotifyDataReq)
- })
+FeNotifyDataReq = _reflection.GeneratedProtocolMessageType(
+ "FeNotifyDataReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FENOTIFYDATAREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeNotifyDataReq)
+ },
+)
_sym_db.RegisterMessage(FeNotifyDataReq)
-FeRegisterNotifyReq = _reflection.GeneratedProtocolMessageType('FeRegisterNotifyReq', (_message.Message,), {
- 'DESCRIPTOR' : _FEREGISTERNOTIFYREQ,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterNotifyReq)
- })
+FeRegisterNotifyReq = _reflection.GeneratedProtocolMessageType(
+ "FeRegisterNotifyReq",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEREGISTERNOTIFYREQ,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeRegisterNotifyReq)
+ },
+)
_sym_db.RegisterMessage(FeRegisterNotifyReq)
-FeMessage = _reflection.GeneratedProtocolMessageType('FeMessage', (_message.Message,), {
- 'DESCRIPTOR' : _FEMESSAGE,
- '__module__' : 'mgmt_pb2'
- # @@protoc_insertion_point(class_scope:mgmtd.FeMessage)
- })
+FeMessage = _reflection.GeneratedProtocolMessageType(
+ "FeMessage",
+ (_message.Message,),
+ {
+ "DESCRIPTOR": _FEMESSAGE,
+ "__module__": "mgmt_pb2",
+ # @@protoc_insertion_point(class_scope:mgmtd.FeMessage)
+ },
+)
_sym_db.RegisterMessage(FeMessage)
diff --git a/tests/topotests/mgmt_oper/oper.py b/tests/topotests/mgmt_oper/oper.py
index 0f6c3cd..162c1eb 100644
--- a/tests/topotests/mgmt_oper/oper.py
+++ b/tests/topotests/mgmt_oper/oper.py
@@ -62,7 +62,8 @@ def disable_debug(router):
router.vtysh_cmd("no debug northbound callbacks configuration")
-def do_oper_test(tgen, query_results):
+@retry(retry_timeout=30, initial_wait=1)
+def _do_oper_test(tgen, qr):
r1 = tgen.gears["r1"].net
qcmd = (
@@ -73,50 +74,55 @@ def do_oper_test(tgen, query_results):
r"""| sed -e 's/"if-index": [0-9][0-9]*/"if-index": "rubout"/'"""
r"""| sed -e 's/"id": [0-9][0-9]*/"id": "rubout"/'"""
)
-
- doreset = True
+ # Don't use this for now.
dd_json_cmp = None
- for qr in query_results:
- step(f"Perform query '{qr[0]}'", reset=doreset)
- if doreset:
- doreset = False
- expected = open(qr[1], encoding="ascii").read()
- output = r1.cmd_nostatus(qcmd.format(qr[0], qr[2] if len(qr) > 2 else ""))
-
- try:
- ojson = json.loads(output)
- except json.decoder.JSONDecodeError as error:
- logging.error("Error decoding json: %s\noutput:\n%s", error, output)
- raise
-
- try:
- ejson = json.loads(expected)
- except json.decoder.JSONDecodeError as error:
- logging.error(
- "Error decoding json exp result: %s\noutput:\n%s", error, expected
+
+ expected = open(qr[1], encoding="ascii").read()
+ output = r1.cmd_nostatus(qcmd.format(qr[0], qr[2] if len(qr) > 2 else ""))
+
+ try:
+ ojson = json.loads(output)
+ except json.decoder.JSONDecodeError as error:
+ logging.error("Error decoding json: %s\noutput:\n%s", error, output)
+ raise
+
+ try:
+ ejson = json.loads(expected)
+ except json.decoder.JSONDecodeError as error:
+ logging.error(
+ "Error decoding json exp result: %s\noutput:\n%s", error, expected
+ )
+ raise
+
+ if dd_json_cmp:
+ cmpout = json_cmp(ojson, ejson, exact_match=True)
+ if cmpout:
+ logging.warning(
+ "-------DIFF---------\n%s\n---------DIFF----------",
+ pprint.pformat(cmpout),
)
- raise
-
- if dd_json_cmp:
- cmpout = json_cmp(ojson, ejson, exact_match=True)
- if cmpout:
- logging.warning(
- "-------DIFF---------\n%s\n---------DIFF----------",
- pprint.pformat(cmpout),
- )
- else:
- cmpout = tt_json_cmp(ojson, ejson, exact=True)
- if cmpout:
- logging.warning(
- "-------EXPECT--------\n%s\n------END-EXPECT------",
- json.dumps(ejson, indent=4),
- )
- logging.warning(
- "--------GOT----------\n%s\n-------END-GOT--------",
- json.dumps(ojson, indent=4),
- )
-
- assert cmpout is None
+ else:
+ cmpout = tt_json_cmp(ojson, ejson, exact=True)
+ if cmpout:
+ logging.warning(
+ "-------EXPECT--------\n%s\n------END-EXPECT------",
+ json.dumps(ejson, indent=4),
+ )
+ logging.warning(
+ "--------GOT----------\n%s\n-------END-GOT--------",
+ json.dumps(ojson, indent=4),
+ )
+
+ assert cmpout is None
+
+
+def do_oper_test(tgen, query_results):
+ reset = True
+ for qr in query_results:
+ step(f"Perform query '{qr[0]}'", reset=reset)
+ if reset:
+ reset = False
+ _do_oper_test(tgen, qr)
def get_ip_networks(super_prefix, count):
diff --git a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json
index f04e3a5..04591b6 100644
--- a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json
+++ b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-exact.json
@@ -14,7 +14,8 @@
"frr-zebra:zebra": {
"state": {
"up-count": 0,
- "down-count": 0
+ "down-count": 0,
+ "zif-type": "zif-veth"
}
}
}
diff --git a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json
index 84ad82c..c770db4 100644
--- a/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json
+++ b/tests/topotests/mgmt_oper/simple-results/result-intf-eth0-with-config.json
@@ -25,7 +25,8 @@
},
"state": {
"up-count": 0,
- "down-count": 0
+ "down-count": 0,
+ "zif-type": "zif-veth"
}
}
}
diff --git a/tests/topotests/mgmt_oper/test_oper.py b/tests/topotests/mgmt_oper/test_oper.py
index 6971eaf..8b8a51c 100644
--- a/tests/topotests/mgmt_oper/test_oper.py
+++ b/tests/topotests/mgmt_oper/test_oper.py
@@ -95,7 +95,6 @@ def test_oper(tgen):
check_kernel_32(r1, "12.12.12.12", 1, "")
check_kernel_32(r1, "13.13.13.13", 1, "red")
check_kernel_32(r1, "14.14.14.14", 1, "red")
- time.sleep(2)
do_oper_test(tgen, query_results)
diff --git a/tests/topotests/mgmt_oper/test_scale.py b/tests/topotests/mgmt_oper/test_scale.py
index 41c2b8c..87794d7 100644
--- a/tests/topotests/mgmt_oper/test_scale.py
+++ b/tests/topotests/mgmt_oper/test_scale.py
@@ -52,7 +52,6 @@ def test_oper_simple(tgen):
r1 = tgen.gears["r1"].net
- time.sleep(2)
count = 20 * 1000
vrf = None # "red"
diff --git a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_mpls_table.ref.diff b/tests/topotests/mgmt_rpc/r1/frr.conf
index e69de29..e69de29 100644
--- a/tests/topotests/isis_tilfa_topo1/rt1/step6/show_mpls_table.ref.diff
+++ b/tests/topotests/mgmt_rpc/r1/frr.conf
diff --git a/tests/topotests/mgmt_rpc/test_rpc.py b/tests/topotests/mgmt_rpc/test_rpc.py
new file mode 100644
index 0000000..618d902
--- /dev/null
+++ b/tests/topotests/mgmt_rpc/test_rpc.py
@@ -0,0 +1,74 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+# SPDX-License-Identifier: ISC
+#
+# March 21 2024, Igor Ryzhov <iryzhov@nfware.com>
+#
+# Copyright (c) 2024, NFWare Inc.
+#
+
+"""
+Test YANG Notifications
+"""
+import json
+import os
+import threading
+
+import pytest
+from lib.topogen import Topogen
+from lib.topotest import json_cmp
+
+pytestmark = [pytest.mark.ripd, pytest.mark.mgmtd]
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+
+
+@pytest.fixture(scope="module")
+def tgen(request):
+ "Setup/Teardown the environment and provide tgen argument to tests"
+
+ topodef = {"s1": ("r1",)}
+
+ tgen = Topogen(topodef, request.module.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ for rname, router in router_list.items():
+ router.load_frr_config("frr.conf")
+
+ tgen.start_router()
+ yield tgen
+ tgen.stop_topology()
+
+
+def test_backend_rpc(tgen):
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+
+ be_client_path = "/usr/lib/frr/mgmtd_testc"
+ rc, _, _ = r1.net.cmd_status(be_client_path + " --help")
+
+ if rc:
+ pytest.skip("No mgmtd_testc")
+
+ out = []
+
+ def run_testc():
+ output = r1.net.cmd_raises(
+ be_client_path + " --timeout 10 --log file:mgmt_testc.log"
+ )
+ out.append(json.loads(output))
+
+ t = threading.Thread(target=run_testc)
+ t.start()
+
+ r1.vtysh_cmd("clear ip rip vrf testname")
+
+ t.join()
+
+ jsout = out[0]
+
+ expected = {"frr-ripd:clear-rip-route": {"vrf": "testname"}}
+ result = json_cmp(jsout, expected)
+ assert result is None
diff --git a/tests/topotests/mgmt_tests/test_yang_mgmt.py b/tests/topotests/mgmt_tests/test_yang_mgmt.py
index bf4e95b..605c142 100644
--- a/tests/topotests/mgmt_tests/test_yang_mgmt.py
+++ b/tests/topotests/mgmt_tests/test_yang_mgmt.py
@@ -36,6 +36,7 @@ import time
import os
import pytest
import platform
+import json
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -45,7 +46,7 @@ sys.path.append(os.path.join(CWD, "../lib/"))
# pylint: disable=C0413
# Import topogen and topotest helpers
from lib.topogen import Topogen, get_topogen
-from lib.topotest import version_cmp
+from lib.topotest import version_cmp, router_json_cmp
# Import topoJson from lib, to create topology and initial configuration
from lib.common_config import (
@@ -401,6 +402,242 @@ def test_mgmt_delete_config(request):
write_test_footer(tc_name)
+def test_mgmt_edit_config(request):
+ """
+ Verify mgmt edit config.
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ reset_config_on_routers(tgen)
+
+ r1 = tgen.gears["r1"]
+
+ # check "create" operation
+ data = {"frr-interface:interface": [{"name": "eth0", "description": "eth0-desc"}]}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit create /frr-interface:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check error on "create" for an existing object
+ data = {"frr-interface:interface": [{"name": "eth0", "description": "eth0-desc"}]}
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit create /frr-interface:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ assert "Data already exists" in ret
+
+ # check adding a leaf to an existing object using "merge"
+ data = {
+ "frr-interface:interface": [
+ {"name": "eth0", "frr-zebra:zebra": {"bandwidth": 100}}
+ ]
+ }
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit merge /frr-interface:lib/interface[name='eth0'] lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = {
+ "frr-interface:interface": [
+ {
+ "name": "eth0",
+ "description": "eth0-desc",
+ "frr-zebra:zebra": {"bandwidth": 100},
+ }
+ ]
+ }
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check replacing an existing object using "replace"
+ data = {
+ "frr-interface:interface": [{"name": "eth0", "description": "eth0-desc-new"}]
+ }
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit replace /frr-interface:lib/interface[name='eth0'] lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check error on "replace" when keys in xpath and data are different
+ data = {
+ "frr-interface:interface": [{"name": "eth1", "description": "eth0-desc-new"}]
+ }
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit replace /frr-interface:lib/interface[name='eth0'] lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ assert "List keys in xpath and data tree are different" in ret
+
+ # check deleting an existing object using "delete"
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit delete /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ {},
+ exact=True,
+ )
+ == None
+ )
+
+ # check error on "delete" for a non-existing object
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit delete /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert "Data missing" in ret
+
+ # check no error on "remove" for a non-existing object
+ ret = r1.vtysh_cmd(
+ f"conf\nmgmt edit remove /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert "Data missing" not in ret
+
+ # check "remove" for an existing object
+ data = {"frr-interface:interface": [{"name": "eth0", "description": "eth0-desc"}]}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit create /frr-interface:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit remove /frr-interface:lib/interface[name='eth0'] lock commit"
+ )
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib/interface[name='eth0'] only-config exact",
+ {},
+ exact=True,
+ )
+ == None
+ )
+
+ # check "create" of a top-level node
+ data = {"frr-vrf:lib": {"vrf": [{"name": "vrf1"}]}}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit create / lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-vrf:lib only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check "replace" of a top-level node
+ data = {"frr-vrf:lib": {"vrf": [{"name": "vrf2"}]}}
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit replace /frr-vrf:lib lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-vrf:lib only-config exact",
+ data_out,
+ exact=True,
+ )
+ == None
+ )
+
+ # check "delete" of a top-level node
+ r1.vtysh_cmd(f"conf\nmgmt edit delete /frr-vrf:lib lock commit")
+ assert (
+ router_json_cmp(
+ r1, "show mgmt get-data /frr-vrf:lib only-config exact", {}, exact=True
+ )
+ == None
+ )
+
+ # check replace of the whole config
+ # this test won't work at the moment, because we don't allow to delete
+ # interfaces from the config if they are present in the system
+ # another problem is that we don't allow "/" as an xpath in get-data command
+ # therefore, commenting it out for now
+ # data = {
+ # "frr-interface:lib": {
+ # "interface": [{"name": "eth1", "description": "eth1-desc"}]
+ # },
+ # "frr-vrf:lib": {"vrf": [{"name": "vrf3"}]},
+ # }
+ # r1.vtysh_cmd(
+ # f"conf\nmgmt edit replace / lock commit {json.dumps(data, separators=(',', ':'))}"
+ # )
+ # data_out = data
+ # assert (
+ # router_json_cmp(
+ # r1,
+ # "show mgmt get-data / only-config exact",
+ # data_out,
+ # exact=True,
+ # )
+ # == None
+ # )
+
+ # check "merge" of the whole config
+ data = {
+ "frr-interface:lib": {
+ "interface": [{"name": "eth2", "description": "eth2-desc"}]
+ },
+ "frr-vrf:lib": {"vrf": [{"name": "vrf4"}]},
+ }
+ r1.vtysh_cmd(
+ f"conf\nmgmt edit merge / lock commit {json.dumps(data, separators=(',', ':'))}"
+ )
+ data_out = data
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-interface:lib only-config exact",
+ {
+ "frr-interface:lib": {
+ "interface": [{"name": "eth2", "description": "eth2-desc"}]
+ }
+ },
+ )
+ == None
+ )
+ assert (
+ router_json_cmp(
+ r1,
+ "show mgmt get-data /frr-vrf:lib only-config exact",
+ {"frr-vrf:lib": {"vrf": [{"name": "vrf4"}]}},
+ )
+ == None
+ )
+
+
def test_mgmt_chaos_stop_start_frr(request):
"""
Kill mgmtd - verify that watch frr restarts.
diff --git a/tests/topotests/msdp_topo1/test_msdp_topo1.py b/tests/topotests/msdp_topo1/test_msdp_topo1.py
index 1af58b0..2fbff44 100755
--- a/tests/topotests/msdp_topo1/test_msdp_topo1.py
+++ b/tests/topotests/msdp_topo1/test_msdp_topo1.py
@@ -359,7 +359,7 @@ def test_msdp():
"192.168.10.100": {
"source": "192.168.10.100",
"group": "229.1.2.3",
- "rp": "192.168.1.1",
+ "rp": "10.254.254.1",
"local": "no",
"sptSetup": "no",
}
@@ -394,7 +394,7 @@ def test_msdp():
"192.168.10.100": {
"source": "192.168.10.100",
"group": "229.1.2.3",
- "rp": "192.168.1.1",
+ "rp": "10.254.254.1",
"local": "no",
"sptSetup": "yes",
}
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 9ee4112..1775c9b 100644
--- a/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
+++ b/tests/topotests/multicast_pim_bsm_topo1/test_mcast_pim_bsmp_01.py
@@ -202,7 +202,6 @@ def teardown_module():
def clear_bsrp_data(tgen, topo):
-
"""
clear bsm databas after test"
Parameters
@@ -218,7 +217,6 @@ def clear_bsrp_data(tgen, topo):
"""
for dut in tgen.routers():
-
rnode = tgen.routers()[dut]
logger.info("[DUT: %s]: clear_bsrp_data")
diff --git a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
index 302a778..e4df508 100644
--- a/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
+++ b/tests/topotests/multicast_pim_bsm_topo2/test_mcast_pim_bsmp_02.py
@@ -182,7 +182,6 @@ def teardown_module():
def clear_bsrp_data(tgen, topo):
-
"""
clear bsm databas after test"
Parameters
@@ -198,7 +197,6 @@ def clear_bsrp_data(tgen, topo):
"""
for dut in tgen.routers():
-
rnode = tgen.routers()[dut]
logger.info("[DUT: %s]: clear_bsrp_data")
diff --git a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
index 1de6eac..f87a90d 100755
--- a/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
+++ b/tests/topotests/multicast_pim_sm_topo1/test_multicast_pim_sm_topo1.py
@@ -42,7 +42,7 @@ import time
from time import sleep
import pytest
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -83,8 +83,6 @@ from lib.topolog import logger
from lib.topojson import build_config_from_json
-pytestmark = [pytest.mark.pimd]
-
TOPOLOGY = """
diff --git a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
index 17f52cb..b62f7bb 100755
--- a/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
+++ b/tests/topotests/multicast_pim_sm_topo2/test_multicast_pim_sm_topo2.py
@@ -37,7 +37,7 @@ import sys
import time
import pytest
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -81,8 +81,6 @@ from lib.topolog import logger
from lib.topojson import build_config_from_json
-pytestmark = [pytest.mark.pimd]
-
TOPOLOGY = """
diff --git a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
index 2c1241c..ae27546 100755
--- a/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
+++ b/tests/topotests/multicast_pim_sm_topo3/test_multicast_pim_sm_topo3.py
@@ -45,7 +45,7 @@ from time import sleep
import json
import functools
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -91,7 +91,6 @@ from lib.topolog import logger
from lib.topojson import build_config_from_json
CWD = os.path.dirname(os.path.realpath(__file__))
-pytestmark = pytest.mark.pimd
TOPOLOGY = """
@@ -265,11 +264,14 @@ def verify_state_incremented(state_before, state_after):
for intf, v2 in v1.items():
for state, value in v2.items():
if value >= state_after[ttype][intf][state]:
- errormsg = "[DUT: %s]: state %s value has not incremented, Initial value: %s, Current value: %s [FAILED!!]" % (
- intf,
- state,
- value,
- state_after[ttype][intf][state],
+ errormsg = (
+ "[DUT: %s]: state %s value has not incremented, Initial value: %s, Current value: %s [FAILED!!]"
+ % (
+ intf,
+ state,
+ value,
+ state_after[ttype][intf][state],
+ )
)
return errormsg
@@ -328,7 +330,6 @@ def find_tos_in_tcpdump(tgen, router, message, cap_file):
filepath = os.path.join(tgen.logdir, router, cap_file)
with open(filepath) as f:
-
if len(re.findall(message, f.read())) < 1:
errormsg = "[DUT: %s]: Verify Message: %s in tcpdump" " [FAILED!!]" % (
router,
diff --git a/tests/topotests/munet/__main__.py b/tests/topotests/munet/__main__.py
index 4419ab9..145eb26 100644
--- a/tests/topotests/munet/__main__.py
+++ b/tests/topotests/munet/__main__.py
@@ -16,8 +16,10 @@ import sys
from . import cli
from . import parser
+from .args import add_launch_args
from .base import get_event_loop
from .cleanup import cleanup_previous
+from .cleanup import is_running_in_rundir
from .compat import PytestConfig
@@ -106,66 +108,43 @@ def main(*args):
cap.add_argument(
"--project-root", help="directory to stop searching for kinds config at"
)
+
rap = ap.add_argument_group(title="Runtime", description="runtime related options")
+ add_launch_args(rap.add_argument)
+
+ # Move to munet.args?
rap.add_argument(
"-C",
"--cleanup",
action="store_true",
help="Remove the entire rundir (not just node subdirs) prior to running.",
)
- rap.add_argument(
- "--gdb", metavar="NODE-LIST", help="comma-sep list of hosts to run gdb on"
- )
- rap.add_argument(
- "--gdb-breakpoints",
- metavar="BREAKPOINT-LIST",
- help="comma-sep list of breakpoints to set",
- )
- rap.add_argument(
- "--host",
- action="store_true",
- help="no isolation for top namespace, bridges exposed to default namespace",
- )
- rap.add_argument(
- "--pcap",
- metavar="TARGET-LIST",
- help="comma-sep list of capture targets (NETWORK or NODE:IFNAME)",
- )
- rap.add_argument(
- "--shell", metavar="NODE-LIST", help="comma-sep list of nodes to open shells on"
- )
- rap.add_argument(
- "--stderr",
- metavar="NODE-LIST",
- help="comma-sep list of nodes to open windows viewing stderr",
- )
- rap.add_argument(
- "--stdout",
- metavar="NODE-LIST",
- help="comma-sep list of nodes to open windows viewing stdout",
- )
+ # Move to munet.args?
rap.add_argument(
"--topology-only",
action="store_true",
help="Do not run any node commands",
)
- rap.add_argument("--unshare-inline", action="store_true", help=argparse.SUPPRESS)
rap.add_argument(
"--validate-only",
action="store_true",
help="Validate the config against the schema definition",
)
+ rap.add_argument("--unshare-inline", action="store_true", help=argparse.SUPPRESS)
+
rap.add_argument("-v", "--verbose", action="store_true", help="be verbose")
rap.add_argument(
"-V", "--version", action="store_true", help="print the verison number and exit"
)
+
eap = ap.add_argument_group(title="Uncommon", description="uncommonly used options")
eap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)")
eap.add_argument(
- "--no-kill",
+ "--kill",
action="store_true",
- help="Do not kill previous running processes",
+ help="Kill previous running processes using same rundir and exit",
)
+ eap.add_argument("--no-kill", action="store_true", help=argparse.SUPPRESS)
eap.add_argument(
"--no-cli", action="store_true", help="Do not run the interactive CLI"
)
@@ -180,8 +159,18 @@ def main(*args):
sys.exit(0)
rundir = args.rundir if args.rundir else "/tmp/munet"
+ rundir = os.path.abspath(rundir)
args.rundir = rundir
+ if args.kill:
+ logging.info("Killing any previous run using rundir: {rundir}")
+ cleanup_previous(args.rundir)
+ elif is_running_in_rundir(args.rundir):
+ logging.fatal(
+ "Munet processes using rundir: %s, use `--kill` to cleanup first", rundir
+ )
+ return 1
+
if args.cleanup:
if os.path.exists(rundir):
if not os.path.exists(f"{rundir}/config.json"):
@@ -194,6 +183,9 @@ def main(*args):
else:
subprocess.run(["/usr/bin/rm", "-rf", rundir], check=True)
+ if args.kill:
+ return 0
+
subprocess.run(f"mkdir -p {rundir} && chmod 755 {rundir}", check=True, shell=True)
os.environ["MUNET_RUNDIR"] = rundir
@@ -208,9 +200,6 @@ def main(*args):
logger.critical("No nodes defined in config file")
return 1
- if not args.no_kill:
- cleanup_previous()
-
loop = None
status = 4
try:
diff --git a/tests/topotests/munet/args.py b/tests/topotests/munet/args.py
new file mode 100644
index 0000000..49ad891
--- /dev/null
+++ b/tests/topotests/munet/args.py
@@ -0,0 +1,89 @@
+# -*- coding: utf-8 eval: (blacken-mode 1) -*-
+#
+# April 14 2024, Christian Hopps <chopps@labn.net>
+#
+# Copyright (c) 2024, LabN Consulting, L.L.C.
+#
+"""Common CLI execute argument."""
+
+
+def add_launch_args(add_func):
+
+ add_func("--gdb", metavar="NODE-LIST", help="comma-sep list of hosts to run gdb on")
+ add_func(
+ "--gdb-breakpoints",
+ metavar="BREAKPOINT-LIST",
+ help="comma-sep list of breakpoints to set",
+ )
+ add_func(
+ "--gdb-use-emacs",
+ action="store_true",
+ help="Use emacsclient to run gdb instead of a shell",
+ )
+
+ add_func(
+ "--host",
+ action="store_true",
+ help="no isolation for top namespace, bridges exposed to default namespace",
+ )
+ add_func(
+ "--pcap",
+ metavar="TARGET-LIST",
+ help="comma-sep list of capture targets (NETWORK or NODE:IFNAME) or 'all'",
+ )
+ add_func(
+ "--shell", metavar="NODE-LIST", help="comma-sep list of nodes to open shells on"
+ )
+ add_func(
+ "--stderr",
+ metavar="NODE-LIST",
+ help="comma-sep list of nodes to open windows viewing stderr",
+ )
+ add_func(
+ "--stdout",
+ metavar="NODE-LIST",
+ help="comma-sep list of nodes to open windows viewing stdout",
+ )
+
+
+def add_testing_args(add_func):
+ add_func(
+ "--cli-on-error",
+ action="store_true",
+ help="CLI on test failure",
+ )
+
+ add_func(
+ "--coverage",
+ action="store_true",
+ help="Enable coverage gathering if supported",
+ )
+
+ add_func(
+ "--cov-build-dir",
+ help="Specify the build dir for locating coverage data files",
+ )
+
+ add_launch_args(add_func)
+
+ add_func(
+ "--pause",
+ action="store_true",
+ help="Pause after each test",
+ )
+ add_func(
+ "--pause-at-end",
+ action="store_true",
+ help="Pause before taking munet down",
+ )
+ add_func(
+ "--pause-on-error",
+ action="store_true",
+ help="Pause after (disables default when --shell or -vtysh given)",
+ )
+ add_func(
+ "--no-pause-on-error",
+ dest="pause_on_error",
+ action="store_false",
+ help="Do not pause after (disables default when --shell or -vtysh given)",
+ )
diff --git a/tests/topotests/munet/base.py b/tests/topotests/munet/base.py
index 72b5df5..e77eb15 100644
--- a/tests/topotests/munet/base.py
+++ b/tests/topotests/munet/base.py
@@ -21,6 +21,7 @@ import subprocess
import sys
import tempfile
import time as time_mod
+
from collections import defaultdict
from pathlib import Path
from typing import Union
@@ -28,8 +29,10 @@ from typing import Union
from . import config as munet_config
from . import linux
+
try:
import pexpect
+
from pexpect.fdpexpect import fdspawn
from pexpect.popen_spawn import PopenSpawn
@@ -273,6 +276,9 @@ def get_event_loop():
"""
policy = asyncio.get_event_loop_policy()
loop = policy.get_event_loop()
+ if not hasattr(os, "pidfd_open"):
+ return loop
+
owatcher = policy.get_child_watcher()
logging.debug(
"event_loop_fixture: global policy %s, current loop %s, current watcher %s",
@@ -463,6 +469,8 @@ class Commander: # pylint: disable=R0904
env = {**(kwargs["env"] if "env" in kwargs else os.environ)}
if "MUNET_NODENAME" not in env:
env["MUNET_NODENAME"] = self.name
+ if "MUNET_PID" not in env and "MUNET_PID" in os.environ:
+ env["MUNET_PID"] = os.environ["MUNET_PID"]
kwargs["env"] = env
defaults.update(kwargs)
@@ -774,8 +782,14 @@ class Commander: # pylint: disable=R0904
ps1 = re.escape(ps1)
ps2 = re.escape(ps2)
-
- extra = "PAGER=cat; export PAGER; TERM=dumb; unset HISTFILE; set +o emacs +o vi"
+ extra = [
+ "TERM=dumb",
+ "set +o emacs",
+ "set +o vi",
+ "unset HISTFILE",
+ "PAGER=cat",
+ "export PAGER",
+ ]
pchg = "PS1='{0}' PS2='{1}' PROMPT_COMMAND=''\n".format(ps1p, ps2p)
p.send(pchg)
return ShellWrapper(p, ps1, ps2, extra_init_cmd=extra, will_echo=will_echo)
@@ -928,15 +942,25 @@ class Commander: # pylint: disable=R0904
def _cmd_status(self, cmds, raises=False, warn=True, stdin=None, **kwargs):
"""Execute a command."""
+ timeout = None
+ if "timeout" in kwargs:
+ timeout = kwargs["timeout"]
+ del kwargs["timeout"]
+
pinput, stdin = Commander._cmd_status_input(stdin)
p, actual_cmd = self._popen("cmd_status", cmds, stdin=stdin, **kwargs)
- o, e = p.communicate(pinput)
+ o, e = p.communicate(pinput, timeout=timeout)
return self._cmd_status_finish(p, cmds, actual_cmd, o, e, raises, warn)
async def _async_cmd_status(
self, cmds, raises=False, warn=True, stdin=None, text=None, **kwargs
):
"""Execute a command."""
+ timeout = None
+ if "timeout" in kwargs:
+ timeout = kwargs["timeout"]
+ del kwargs["timeout"]
+
pinput, stdin = Commander._cmd_status_input(stdin)
p, actual_cmd = await self._async_popen(
"async_cmd_status", cmds, stdin=stdin, **kwargs
@@ -949,7 +973,12 @@ class Commander: # pylint: disable=R0904
if encoding is not None and isinstance(pinput, str):
pinput = pinput.encode(encoding)
- o, e = await p.communicate(pinput)
+ try:
+ o, e = await asyncio.wait_for(p.communicate(), timeout=timeout)
+ except (TimeoutError, asyncio.TimeoutError) as error:
+ raise subprocess.TimeoutExpired(
+ cmd=actual_cmd, timeout=timeout, output=None, stderr=None
+ ) from error
if encoding is not None:
o = o.decode(encoding) if o is not None else o
e = e.decode(encoding) if e is not None else e
@@ -1214,7 +1243,13 @@ class Commander: # pylint: disable=R0904
if self.is_vm and self.use_ssh and not ns_only: # pylint: disable=E1101
if isinstance(cmd, str):
cmd = shlex.split(cmd)
- cmd = ["/usr/bin/env", f"MUNET_NODENAME={self.name}"] + cmd
+ cmd = [
+ "/usr/bin/env",
+ f"MUNET_NODENAME={self.name}",
+ ]
+ if "MUNET_PID" in os.environ:
+ cmd.append(f"MUNET_PID={os.environ.get('MUNET_PID')}")
+ cmd += cmd
# get the ssh cmd
cmd = self._get_pre_cmd(False, True, ns_only=ns_only) + [shlex.join(cmd)]
@@ -1234,6 +1269,8 @@ class Commander: # pylint: disable=R0904
envvars = f"MUNET_NODENAME={self.name} NODENAME={self.name}"
if hasattr(self, "rundir"):
envvars += f" RUNDIR={self.rundir}"
+ if "MUNET_PID" in os.environ:
+ envvars += f" MUNET_PID={os.environ.get('MUNET_PID')}"
if hasattr(self.unet, "config_dirname") and self.unet.config_dirname:
envvars += f" CONFIGDIR={self.unet.config_dirname}"
elif "CONFIGDIR" in os.environ:
@@ -2514,7 +2551,7 @@ class Bridge(SharedNamespace, InterfaceMixin):
self.logger.debug("Bridge: Creating")
- assert len(self.name) <= 16 # Make sure fits in IFNAMSIZE
+ # assert len(self.name) <= 16 # Make sure fits in IFNAMSIZE
self.cmd_raises(f"ip link delete {name} || true")
self.cmd_raises(f"ip link add {name} type bridge")
if self.mtu:
@@ -2638,10 +2675,6 @@ class BaseMunet(LinuxNamespace):
self.cfgopt = munet_config.ConfigOptionsProxy(pytestconfig)
- super().__init__(
- name, mount=True, net=isolated, uts=isolated, pid=pid, unet=None, **kwargs
- )
-
# This allows us to cleanup any leftover running munet's
if "MUNET_PID" in os.environ:
if os.environ["MUNET_PID"] != str(our_pid):
@@ -2652,6 +2685,10 @@ class BaseMunet(LinuxNamespace):
)
os.environ["MUNET_PID"] = str(our_pid)
+ super().__init__(
+ name, mount=True, net=isolated, uts=isolated, pid=pid, unet=None, **kwargs
+ )
+
# this is for testing purposes do not use
if not BaseMunet.g_unet:
BaseMunet.g_unet = self
@@ -2759,7 +2796,7 @@ class BaseMunet(LinuxNamespace):
self.logger.error('"%s" len %s > 16', nsif1, len(nsif1))
elif len(nsif2) > 16:
self.logger.error('"%s" len %s > 16', nsif2, len(nsif2))
- assert len(nsif1) <= 16 and len(nsif2) <= 16 # Make sure fits in IFNAMSIZE
+ assert len(nsif1) < 16 and len(nsif2) < 16 # Make sure fits in IFNAMSIZE
self.logger.debug("%s: Creating veth pair for link %s", self, lname)
@@ -2987,8 +3024,11 @@ if True: # pylint: disable=using-constant-test
self._expectf = self.child.expect
if extra_init_cmd:
- self.expect_prompt()
- self.child.sendline(extra_init_cmd)
+ if isinstance(extra_init_cmd, str):
+ extra_init_cmd = [extra_init_cmd]
+ for ecmd in extra_init_cmd:
+ self.expect_prompt()
+ self.child.sendline(ecmd)
self.expect_prompt()
def expect_prompt(self, timeout=-1):
diff --git a/tests/topotests/munet/cleanup.py b/tests/topotests/munet/cleanup.py
index c641cda..12ea6e2 100644
--- a/tests/topotests/munet/cleanup.py
+++ b/tests/topotests/munet/cleanup.py
@@ -59,25 +59,33 @@ def _get_our_pids():
return {}
-def _get_other_pids():
- piddict = get_pids_with_env("MUNET_PID")
- unet_pids = {d["MUNET_PID"] for d in piddict.values()}
+def _get_other_pids(rundir):
+ if rundir:
+ # get only munet pids using the given rundir
+ piddict = get_pids_with_env("MUNET_RUNDIR", str(rundir))
+ else:
+ # Get all munet pids
+ piddict = get_pids_with_env("MUNET_PID")
+ unet_pids = {d["MUNET_PID"] for d in piddict.values() if "MUNET_PID" in d}
pids_by_upid = {p: set() for p in unet_pids}
for pid, envdict in piddict.items():
+ if "MUNET_PID" not in envdict:
+ continue
unet_pid = envdict["MUNET_PID"]
pids_by_upid[unet_pid].add(pid)
# Filter out any child pid sets whos munet pid is still running
return {x: y for x, y in pids_by_upid.items() if x not in y}
-def _get_pids_by_upid(ours):
+def _get_pids_by_upid(ours, rundir):
if ours:
+ assert rundir is None
return _get_our_pids()
- return _get_other_pids()
+ return _get_other_pids(rundir)
-def _cleanup_pids(ours):
- pids_by_upid = _get_pids_by_upid(ours).items()
+def _cleanup_pids(ours, rundir):
+ pids_by_upid = _get_pids_by_upid(ours, rundir).items()
if not pids_by_upid:
return
@@ -94,7 +102,7 @@ def _cleanup_pids(ours):
# return
# time.sleep(1)
- pids_by_upid = _get_pids_by_upid(ours).items()
+ pids_by_upid = _get_pids_by_upid(ours, rundir).items()
_kill_piddict(pids_by_upid, signal.SIGKILL)
@@ -103,12 +111,16 @@ def cleanup_current():
Currently this only scans for old processes.
"""
- _cleanup_pids(True)
+ _cleanup_pids(True, None)
-def cleanup_previous():
+def cleanup_previous(rundir=None):
"""Attempt to cleanup preview runs.
Currently this only scans for old processes.
"""
- _cleanup_pids(False)
+ _cleanup_pids(False, rundir)
+
+
+def is_running_in_rundir(rundir):
+ return bool(get_pids_with_env("MUNET_RUNDIR", str(rundir)))
diff --git a/tests/topotests/munet/cli.py b/tests/topotests/munet/cli.py
index 133644e..01a7091 100644
--- a/tests/topotests/munet/cli.py
+++ b/tests/topotests/munet/cli.py
@@ -106,9 +106,13 @@ def is_host_regex(restr):
def get_host_regex(restr):
- if len(restr) < 3 or restr[0] != "/" or restr[-1] != "/":
+ try:
+ if len(restr) < 3 or restr[0] != "/" or restr[-1] != "/":
+ return None
+ return re.compile(restr[1:-1])
+ except re.error:
+ logging.error("Invalid regex")
return None
- return re.compile(restr[1:-1])
def host_in(restr, names):
@@ -126,8 +130,8 @@ def expand_host(restr, names):
hosts = []
regexp = get_host_regex(restr)
if not regexp:
- assert restr in names
- hosts.append(restr)
+ if restr in names:
+ hosts.append(restr)
else:
for name in names:
if regexp.fullmatch(name):
diff --git a/tests/topotests/munet/logconf-mutest.yaml b/tests/topotests/munet/logconf-mutest.yaml
index b450fb9..c0b636c 100644
--- a/tests/topotests/munet/logconf-mutest.yaml
+++ b/tests/topotests/munet/logconf-mutest.yaml
@@ -1,5 +1,8 @@
version: 1
formatters:
+ result_color:
+ class: munet.mulog.ResultColorFormatter
+ format: '%(levelname)5s: %(message)s'
brief:
format: '%(levelname)5s: %(message)s'
operfmt:
@@ -22,7 +25,7 @@ handlers:
info_console:
level: INFO
class: logging.StreamHandler
- formatter: brief
+ formatter: result_color
stream: ext://sys.stderr
oper_console:
level: DEBUG
diff --git a/tests/topotests/munet/mucmd.py b/tests/topotests/munet/mucmd.py
index 5518c6d..cd356f3 100644
--- a/tests/topotests/munet/mucmd.py
+++ b/tests/topotests/munet/mucmd.py
@@ -9,7 +9,6 @@
import argparse
import json
import os
-import subprocess
import sys
from pathlib import Path
@@ -90,19 +89,14 @@ def main(*args):
ecmd = "/usr/bin/nsenter"
eargs = [ecmd]
- output = subprocess.check_output(["/usr/bin/nsenter", "--help"], encoding="utf-8")
- if " -a," in output:
- eargs.append("-a")
- else:
- # -U doesn't work
- for flag in ["-u", "-i", "-m", "-n", "-C", "-T"]:
- if f" {flag}," in output:
- eargs.append(flag)
+ #start mucmd same way base process is started
+ eargs.append(f"--mount=/proc/{pid}/ns/mnt")
+ eargs.append(f"--net=/proc/{pid}/ns/net")
eargs.append(f"--pid=/proc/{pid}/ns/pid_for_children")
+ eargs.append(f"--uts=/proc/{pid}/ns/uts")
eargs.append(f"--wd={rundir}")
- eargs.extend(["-t", pid])
eargs += args.shellcmd
- # print("Using ", eargs)
+ #print("Using ", eargs)
return os.execvpe(ecmd, eargs, {**env, **envcfg})
diff --git a/tests/topotests/munet/mulog.py b/tests/topotests/munet/mulog.py
index f840eae..968acd9 100644
--- a/tests/topotests/munet/mulog.py
+++ b/tests/topotests/munet/mulog.py
@@ -12,6 +12,9 @@ import logging
from pathlib import Path
+do_color = True
+
+
class MultiFileHandler(logging.FileHandler):
"""A logging handler that logs to new files based on the logger name.
@@ -118,5 +121,28 @@ class ColorFormatter(logging.Formatter):
super().__init__(fmt, datefmt, style, **kwargs)
def format(self, record):
+ if not do_color:
+ return super().format(record)
formatter = self.formatters.get(record.levelno)
return formatter.format(record)
+
+
+class ResultColorFormatter(logging.Formatter):
+ """A formatter that colorizes PASS/FAIL strings based on level."""
+
+ green = "\x1b[32m"
+ red = "\x1b[31m"
+ reset = "\x1b[0m"
+
+ def format(self, record):
+ s = super().format(record)
+ if not do_color:
+ return s
+ idx = s.find("FAIL")
+ if idx >= 0 and record.levelno > logging.INFO:
+ s = s[:idx] + self.red + "FAIL" + self.reset + s[idx + 4 :]
+ elif record.levelno == logging.INFO:
+ idx = s.find("PASS")
+ if idx >= 0:
+ s = s[:idx] + self.green + "PASS" + self.reset + s[idx + 4 :]
+ return s
diff --git a/tests/topotests/munet/munet-schema.json b/tests/topotests/munet/munet-schema.json
index a1dcd87..6ebc368 100644
--- a/tests/topotests/munet/munet-schema.json
+++ b/tests/topotests/munet/munet-schema.json
@@ -93,12 +93,24 @@
"image": {
"type": "string"
},
+ "hostnet": {
+ "type": "boolean"
+ },
"server": {
"type": "string"
},
"server-port": {
"type": "number"
},
+ "ssh-identity-file": {
+ "type": "string"
+ },
+ "ssh-user": {
+ "type": "string"
+ },
+ "ssh-password": {
+ "type": "string"
+ },
"qemu": {
"type": "object",
"properties": {
@@ -108,6 +120,15 @@
"disk": {
"type": "string"
},
+ "disk-driver": {
+ "type": "string"
+ },
+ "disk-template": {
+ "type": "string"
+ },
+ "initial-cmd": {
+ "type": "string"
+ },
"kerenel": {
"type": "string"
},
@@ -141,6 +162,9 @@
"password": {
"type": "string"
},
+ "initial-password": {
+ "type": "string"
+ },
"expects": {
"type": "array",
"items": {
@@ -362,6 +386,9 @@
},
"ipv6": {
"type": "string"
+ },
+ "external": {
+ "type": "boolean"
}
}
}
@@ -401,12 +428,24 @@
"image": {
"type": "string"
},
+ "hostnet": {
+ "type": "boolean"
+ },
"server": {
"type": "string"
},
"server-port": {
"type": "number"
},
+ "ssh-identity-file": {
+ "type": "string"
+ },
+ "ssh-user": {
+ "type": "string"
+ },
+ "ssh-password": {
+ "type": "string"
+ },
"qemu": {
"type": "object",
"properties": {
@@ -416,6 +455,15 @@
"disk": {
"type": "string"
},
+ "disk-driver": {
+ "type": "string"
+ },
+ "disk-template": {
+ "type": "string"
+ },
+ "initial-cmd": {
+ "type": "string"
+ },
"kerenel": {
"type": "string"
},
@@ -449,6 +497,9 @@
"password": {
"type": "string"
},
+ "initial-password": {
+ "type": "string"
+ },
"expects": {
"type": "array",
"items": {
diff --git a/tests/topotests/munet/mutest/__main__.py b/tests/topotests/munet/mutest/__main__.py
index c870311..a78c69e 100644
--- a/tests/topotests/munet/mutest/__main__.py
+++ b/tests/topotests/munet/mutest/__main__.py
@@ -20,9 +20,13 @@ from copy import deepcopy
from pathlib import Path
from typing import Union
+from munet import mulog
from munet import parser
+from munet.args import add_testing_args
from munet.base import Bridge
from munet.base import get_event_loop
+from munet.cli import async_cli
+from munet.compat import PytestConfig
from munet.mutest import userapi as uapi
from munet.native import L3NodeMixin
from munet.native import Munet
@@ -36,7 +40,9 @@ root_logger = logging.getLogger("")
exec_formatter = logging.Formatter("%(asctime)s %(levelname)5s: %(name)s: %(message)s")
-async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = False):
+async def get_unet(
+ config: dict, croot: Path, rundir: Path, args: Namespace, unshare: bool = False
+):
"""Create and run a new Munet topology.
The topology is built from the given ``config`` to run inside the path indicated
@@ -48,6 +54,7 @@ async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = Fals
value will be modified and stored in the built ``Munet`` object.
croot: common root of all tests, used to search for ``kinds.yaml`` files.
rundir: the path to the run directory for this topology.
+ args: argparse args
unshare: True to unshare the process into it's own private namespace.
Yields:
@@ -58,7 +65,11 @@ async def get_unet(config: dict, croot: Path, rundir: Path, unshare: bool = Fals
try:
try:
unet = await async_build_topology(
- config, rundir=str(rundir), unshare_inline=unshare
+ config,
+ rundir=str(rundir),
+ args=args,
+ pytestconfig=PytestConfig(args),
+ unshare_inline=unshare,
)
except Exception as error:
logging.debug("unet build failed: %s", error, exc_info=True)
@@ -221,9 +232,13 @@ async def execute_test(
targets["."] = unet
tc = uapi.TestCase(
- str(test_num), test_name, test, targets, logger, reslog, args.full_summary
+ str(test_num), test_name, test, targets, args, logger, reslog, args.full_summary
)
- passed, failed, e = tc.execute()
+ try:
+ passed, failed, e = tc.execute()
+ except uapi.CLIOnErrorError as error:
+ await async_cli(unet)
+ passed, failed, e = 0, 0, error
run_time = time.time() - tc.info.start_time
@@ -278,6 +293,10 @@ async def run_tests(args):
start_time = time.time()
try:
for dirpath in tests:
+ if args.validate_only:
+ parser.validate_config(configs[dirpath], reslog, args)
+ continue
+
test_files = tests[dirpath]
for test in test_files:
tnum += 1
@@ -294,10 +313,12 @@ async def run_tests(args):
root_logger.addHandler(exec_handler)
try:
- async for unet in get_unet(config, common, rundir):
+ async for unet in get_unet(config, common, rundir, args):
+
if not printed_header:
print_header(reslog, unet)
printed_header = True
+
passed, failed, e = await execute_test(
unet, test, args, tnum, exec_handler
)
@@ -321,6 +342,9 @@ async def run_tests(args):
except KeyboardInterrupt:
pass
+ if args.validate_only:
+ return False
+
run_time = time.time() - start_time
tnum = 0
tpassed = 0
@@ -357,8 +381,10 @@ async def run_tests(args):
for result in results:
test_name, passed, failed, e = result
tnum += 1
- s = "FAIL" if failed or e else "PASS"
- reslog.info(" %s %s:%s", s, tnum, test_name)
+ if failed or e:
+ reslog.warning(" FAIL %s:%s", tnum, test_name)
+ else:
+ reslog.info(" PASS %s:%s", tnum, test_name)
reslog.info("-" * 70)
reslog.info(
@@ -386,35 +412,47 @@ async def async_main(args):
def main():
ap = ArgumentParser()
ap.add_argument(
- "--dist",
- type=int,
- nargs="?",
- const=-1,
- default=0,
- action="store",
- metavar="NUM-THREADS",
- help="Run in parallel, value is num. of threads or no value for auto",
+ "-v", dest="verbose", action="count", default=0, help="More -v's, more verbose"
)
- ap.add_argument("-d", "--rundir", help="runtime directory for tempfiles, logs, etc")
ap.add_argument(
+ "-V", "--version", action="store_true", help="print the verison number and exit"
+ )
+ ap.add_argument("paths", nargs="*", help="Paths to collect tests from")
+
+ rap = ap.add_argument_group(title="Runtime", description="runtime related options")
+ rap.add_argument(
+ "-d", "--rundir", help="runtime directory for tempfiles, logs, etc"
+ )
+ add_testing_args(rap.add_argument)
+
+ eap = ap.add_argument_group(title="Uncommon", description="uncommonly used options")
+ eap.add_argument(
"--file-select", default="mutest_*.py", help="shell glob for finding tests"
)
- ap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)")
- ap.add_argument(
- "-V",
+ eap.add_argument(
"--full-summary",
action="store_true",
help="print full summary headers from docstrings",
)
- ap.add_argument(
- "-v", dest="verbose", action="count", default=0, help="More -v's, more verbose"
+ eap.add_argument("--log-config", help="logging config file (yaml, toml, json, ...)")
+ eap.add_argument(
+ "--validate-only",
+ action="store_true",
+ help="Validate the munet configs against the schema definition",
)
- ap.add_argument("paths", nargs="*", help="Paths to collect tests from")
+
args = ap.parse_args()
+ if args.version:
+ from importlib import metadata # pylint: disable=C0415
+
+ print(metadata.version("munet"))
+ sys.exit(0)
+
rundir = args.rundir if args.rundir else "/tmp/mutest"
- args.rundir = Path(rundir)
- os.environ["MUNET_RUNDIR"] = rundir
+ rundir = Path(rundir).absolute()
+ args.rundir = rundir
+ os.environ["MUNET_RUNDIR"] = str(rundir)
subprocess.run(f"mkdir -p {rundir} && chmod 755 {rundir}", check=True, shell=True)
config = parser.setup_logging(args, config_base="logconf-mutest")
@@ -425,6 +463,9 @@ def main():
fconfig.get("format"), fconfig.get("datefmt")
)
+ if not hasattr(sys.stderr, "isatty") or not sys.stderr.isatty():
+ mulog.do_color = False
+
loop = None
status = 4
try:
diff --git a/tests/topotests/munet/mutest/userapi.py b/tests/topotests/munet/mutest/userapi.py
index 7967dd0..abc63af 100644
--- a/tests/topotests/munet/mutest/userapi.py
+++ b/tests/topotests/munet/mutest/userapi.py
@@ -65,8 +65,11 @@ import json
import logging
import pprint
import re
+import subprocess
+import sys
import time
+from argparse import Namespace
from pathlib import Path
from typing import Any
from typing import Union
@@ -76,6 +79,51 @@ from deepdiff import DeepDiff as json_cmp
from munet.base import Commander
+class ScriptError(Exception):
+ """An unrecoverable script failure."""
+
+
+class CLIOnErrorError(Exception):
+ """Enter CLI after error."""
+
+
+def pause_test(desc=""):
+ isatty = sys.stdout.isatty()
+ if not isatty:
+ desc = f" for {desc}" if desc else ""
+ logging.info("NO PAUSE on non-tty terminal%s", desc)
+ return
+
+ while True:
+ if desc:
+ print(f"\n== PAUSING: {desc} ==")
+ try:
+ user = input('PAUSED, "cli" for CLI, "pdb" to debug, "Enter" to continue: ')
+ except EOFError:
+ print("^D...continuing")
+ break
+ user = user.strip()
+ if user == "cli":
+ raise CLIOnErrorError()
+ if user == "pdb":
+ breakpoint() # pylint: disable=W1515
+ elif user:
+ print(f'Unrecognized input: "{user}"')
+ else:
+ break
+
+
+def act_on_result(success, args, desc=""):
+ if args.pause:
+ pause_test(desc)
+ elif success:
+ return
+ if args.cli_on_error:
+ raise CLIOnErrorError()
+ if args.pause_on_error:
+ pause_test(desc)
+
+
class TestCaseInfo:
"""Object to hold nestable TestCase Results."""
@@ -140,6 +188,7 @@ class TestCase:
name: str,
path: Path,
targets: dict,
+ args: Namespace,
output_logger: logging.Logger = None,
result_logger: logging.Logger = None,
full_summary: bool = False,
@@ -157,6 +206,7 @@ class TestCase:
self.__in_section = False
self.targets = targets
+ self.args = args
self.last = ""
self.last_m = None
@@ -285,7 +335,10 @@ class TestCase:
# Extract any docstring as a title.
if print_header:
- title = locals()[f"_{name}"].__doc__.lstrip()
+ title = locals()[f"_{name}"].__doc__
+ if title is None:
+ title = ""
+ title = title.lstrip()
if self.__short_doc_header and (title := title.lstrip()):
if (idx := title.find("\n")) != -1:
title = title[:idx].strip()
@@ -299,6 +352,10 @@ class TestCase:
# Here's where we can do async in the future if we want.
# result = await locals()[f"_{name}"](_ok_result)
+ except ScriptError as error:
+ return error
+ except CLIOnErrorError:
+ raise
except Exception as error:
logging.error(
"Unexpected exception executing %s: %s", name, error, exc_info=True
@@ -381,7 +438,9 @@ class TestCase:
target: the target to execute the command on.
cmd: string to execut on the target.
"""
- out = self.targets[target].cmd_nostatus(cmd, warn=False)
+ out = self.targets[target].cmd_nostatus(
+ cmd, stdin=subprocess.DEVNULL, warn=False
+ )
self.last = out = out.rstrip()
report = out if out else "<no output>"
self.logf("COMMAND OUTPUT:\n%s", report)
@@ -398,12 +457,14 @@ class TestCase:
target: the target to execute the command on.
cmd: string to execute on the target.
"""
- out = self.targets[target].cmd_nostatus(cmd, warn=False)
+ out = self.targets[target].cmd_nostatus(
+ cmd, stdin=subprocess.DEVNULL, warn=False
+ )
self.last = out = out.rstrip()
try:
js = json.loads(out)
except Exception as error:
- js = {}
+ js = None
self.olog.warning(
"JSON load failed. Check command output is in JSON format: %s",
error,
@@ -482,20 +543,33 @@ class TestCase:
exact_match: if True then the json must exactly match.
"""
js = self._command_json(target, cmd)
+ if js is None:
+ # Always fail on bad json, even if user expected failure
+ # return expect_fail, {}
+ return False, {}
+
try:
+ # Convert to string to validate the input is valid JSON
+ if not isinstance(match, str):
+ match = json.dumps(match)
expect = json.loads(match)
except Exception as error:
expect = {}
self.olog.warning(
"JSON load failed. Check match value is in JSON format: %s", error
)
+ # Always fail on bad json, even if user expected failure
+ # return expect_fail, {}
+ return False, {}
if exact_match:
deep_diff = json_cmp(expect, js)
# Convert DeepDiff completely into dicts or lists at all levels
json_diff = json.loads(deep_diff.to_json())
else:
- deep_diff = json_cmp(expect, js, ignore_order=True)
+ deep_diff = json_cmp(
+ expect, js, ignore_order=True, cutoff_intersection_for_pairs=1
+ )
# Convert DeepDiff completely into dicts or lists at all levels
json_diff = json.loads(deep_diff.to_json())
# Remove new fields in json object from diff
@@ -570,6 +644,7 @@ class TestCase:
"""
path = Path(pathname)
path = self.info.path.parent.joinpath(path)
+ do_cli = False
self.oplogf(
"include: new path: %s create section: %s currently __in_section: %s",
@@ -589,7 +664,12 @@ class TestCase:
self.info.path = path
self.oplogf("include: swapped info path: new %s old %s", path, old_path)
- self.__exec_script(path, print_header=new_section, add_newline=new_section)
+ try:
+ e = self.__exec_script(
+ path, print_header=new_section, add_newline=new_section
+ )
+ except CLIOnErrorError:
+ do_cli = True
if new_section:
# Something within the section creating include has also created a section
@@ -616,6 +696,11 @@ class TestCase:
self.info.path = old_path
self.oplogf("include: restored info path: %s", old_path)
+ if do_cli:
+ raise CLIOnErrorError()
+ if e:
+ raise ScriptError(e)
+
def __end_section(self):
self.oplogf("__end_section: __in_section: %s", self.__in_section)
info = self.__pop_execinfo()
@@ -719,6 +804,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
def test_step(self, expr_or_value: Any, desc: str, target: str = "") -> bool:
@@ -728,6 +814,7 @@ class TestCase:
"""
success = bool(expr_or_value)
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success
def match_step_json(
@@ -760,6 +847,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
def wait_step(
@@ -808,6 +896,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
def wait_step_json(
@@ -846,6 +935,7 @@ class TestCase:
)
if desc:
self.__post_result(target, success, desc)
+ act_on_result(success, self.args, desc)
return success, ret
diff --git a/tests/topotests/munet/native.py b/tests/topotests/munet/native.py
index 4fbbb85..5747d5e 100644
--- a/tests/topotests/munet/native.py
+++ b/tests/topotests/munet/native.py
@@ -8,8 +8,10 @@
# pylint: disable=protected-access
"""A module that defines objects for standalone use."""
import asyncio
+import base64
import errno
import getpass
+import glob
import ipaddress
import logging
import os
@@ -26,8 +28,10 @@ from . import cli
from .base import BaseMunet
from .base import Bridge
from .base import Commander
+from .base import InterfaceMixin
from .base import LinuxNamespace
from .base import MunetError
+from .base import SharedNamespace
from .base import Timeout
from .base import _async_get_exec_path
from .base import _get_exec_path
@@ -130,6 +134,22 @@ def convert_ranges_to_bitmask(ranges):
return bitmask
+class ExternalNetwork(SharedNamespace, InterfaceMixin):
+ """A network external to munet."""
+
+ def __init__(self, name=None, unet=None, logger=None, mtu=None, config=None):
+ """Create an external network."""
+ del logger # avoid linter
+ del mtu # avoid linter
+ # Do we want to use os.getpid() rather than unet.pid?
+ super().__init__(name, pid=unet.pid, nsflags=unet.nsflags, unet=unet)
+ self.config = config if config else {}
+
+ async def _async_delete(self):
+ self.logger.debug("%s: deleting", self)
+ await super()._async_delete()
+
+
class L2Bridge(Bridge):
"""A linux bridge with no IP network address."""
@@ -394,6 +414,10 @@ class NodeMixin:
async def async_cleanup_cmd(self):
"""Run the configured cleanup commands for this node."""
+ if self.cleanup_called:
+ return
+ self.cleanup_called = True
+
return await self._async_cleanup_cmd()
def has_ready_cmd(self) -> bool:
@@ -433,14 +457,14 @@ class NodeMixin:
outopt = outopt if outopt is not None else ""
if outopt == "all" or self.name in outopt.split(","):
outname = stdout.name if hasattr(stdout, "name") else stdout
- self.run_in_window(f"tail -F {outname}", title=f"O:{self.name}")
+ self.run_in_window(f"tail -n+1 -F {outname}", title=f"O:{self.name}")
if stderr:
erropt = self.unet.cfgopt.getoption("--stderr")
erropt = erropt if erropt is not None else ""
if erropt == "all" or self.name in erropt.split(","):
errname = stderr.name if hasattr(stderr, "name") else stderr
- self.run_in_window(f"tail -F {errname}", title=f"E:{self.name}")
+ self.run_in_window(f"tail -n+1 -F {errname}", title=f"E:{self.name}")
def pytest_hook_open_shell(self):
if not self.unet:
@@ -549,17 +573,38 @@ class NodeMixin:
await super()._async_delete()
+class HostnetNode(NodeMixin, LinuxNamespace):
+ """A node for running commands in the host network namespace."""
+
+ def __init__(self, name, pid=True, **kwargs):
+ if "net" in kwargs:
+ del kwargs["net"]
+ super().__init__(name, pid=pid, net=False, **kwargs)
+
+ self.logger.debug("%s: creating", self)
+
+ self.mgmt_ip = None
+ self.mgmt_ip6 = None
+ self.set_ns_cwd(self.rundir)
+
+ super().pytest_hook_open_shell()
+ self.logger.info("%s: created", self)
+
+ def get_ifname(self, netname): # pylint: disable=useless-return
+ del netname
+ return None
+
+ async def _async_delete(self):
+ self.logger.debug("%s: deleting", self)
+ await super()._async_delete()
+
+
class SSHRemote(NodeMixin, Commander):
"""SSHRemote a node representing an ssh connection to something."""
def __init__(
self,
name,
- server,
- port=22,
- user=None,
- password=None,
- idfile=None,
**kwargs,
):
super().__init__(name, **kwargs)
@@ -574,32 +619,33 @@ class SSHRemote(NodeMixin, Commander):
self.mgmt_ip = None
self.mgmt_ip6 = None
- self.port = port
-
- if user:
- self.user = user
- elif "SUDO_USER" in os.environ:
- self.user = os.environ["SUDO_USER"]
- else:
+ self.server = self.config["server"]
+ self.port = int(self.config.get("server-port", 22))
+ self.sudo_user = os.environ.get("SUDO_USER")
+ self.user = self.config.get("ssh-user")
+ if not self.user:
+ self.user = self.sudo_user
+ if not self.user:
self.user = getpass.getuser()
- self.password = password
- self.idfile = idfile
-
- self.server = f"{self.user}@{server}"
+ self.password = self.config.get("ssh-password")
+ self.idfile = self.config.get("ssh-identity-file")
+ self.use_host_network = None
# Setup our base `pre-cmd` values
#
# We maybe should add environment variable transfer here in particular
# MUNET_NODENAME. The problem is the user has to explicitly approve
# of SendEnv variables.
- self.__base_cmd = [
- get_exec_path_host("sudo"),
- "-E",
- f"-u{self.user}",
- get_exec_path_host("ssh"),
- ]
- if port != 22:
- self.__base_cmd.append(f"-p{port}")
+ self.__base_cmd = []
+ if self.idfile and self.sudo_user:
+ self.__base_cmd += [
+ get_exec_path_host("sudo"),
+ "-E",
+ f"-u{self.sudo_user}",
+ ]
+ self.__base_cmd.append(get_exec_path_host("ssh"))
+ if self.port != 22:
+ self.__base_cmd.append(f"-p{self.port}")
self.__base_cmd.append("-q")
self.__base_cmd.append("-oStrictHostKeyChecking=no")
self.__base_cmd.append("-oUserKnownHostsFile=/dev/null")
@@ -609,18 +655,34 @@ class SSHRemote(NodeMixin, Commander):
# self.__base_cmd.append("-oSendVar='TEST'")
self.__base_cmd_pty = list(self.__base_cmd)
self.__base_cmd_pty.append("-t")
- self.__base_cmd.append(self.server)
- self.__base_cmd_pty.append(self.server)
+ server_str = f"{self.user}@{self.server}"
+ self.__base_cmd.append(server_str)
+ self.__base_cmd_pty.append(server_str)
# self.set_pre_cmd(pre_cmd, pre_cmd_tty)
self.logger.info("%s: created", self)
- def has_ready_cmd(self) -> bool:
- return bool(self.config.get("ready-cmd", "").strip())
-
def _get_pre_cmd(self, use_str, use_pty, ns_only=False, **kwargs):
- pre_cmd = []
- if self.unet:
+ # None on first use, set after
+ if self.use_host_network is None:
+ # We have networks now so try and ping the server in the namespace
+ if not self.unet:
+ self.use_host_network = True
+ else:
+ rc, _, _ = self.unet.cmd_status(f"ping -w1 -c1 {self.server}")
+ if rc:
+ self.use_host_network = True
+ else:
+ self.use_host_network = False
+
+ if self.use_host_network:
+ self.logger.debug("Using host namespace for ssh connection")
+ else:
+ self.logger.debug("Using munet namespace for ssh connection")
+
+ if self.use_host_network:
+ pre_cmd = []
+ else:
pre_cmd = self.unet._get_pre_cmd(False, use_pty, ns_only=False, **kwargs)
if ns_only:
return pre_cmd
@@ -976,17 +1038,16 @@ ff02::2\tip6-allrouters
)
self.unet.rootcmd.cmd_status(f"ip link set {dname} name {hname}")
- rc, o, _ = self.unet.rootcmd.cmd_status("ip -o link show")
- m = re.search(rf"\d+:\s+{re.escape(hname)}:.*", o)
- if m:
- self.unet.rootcmd.cmd_nostatus(f"ip link set {hname} down ")
- self.unet.rootcmd.cmd_raises(f"ip link set {hname} netns {self.pid}")
+ # Make sure the interface is there.
+ self.unet.rootcmd.cmd_raises(f"ip -o link show {hname}")
+ self.unet.rootcmd.cmd_nostatus(f"ip link set {hname} down ")
+ self.unet.rootcmd.cmd_raises(f"ip link set {hname} netns {self.pid}")
+
# Wait for interface to show up in namespace
for retry in range(0, 10):
rc, o, _ = self.cmd_status(f"ip -o link show {hname}")
if not rc:
- if re.search(rf"\d+: {re.escape(hname)}:.*", o):
- break
+ break
if retry > 0:
await asyncio.sleep(1)
self.cmd_raises(f"ip link set {hname} name {lname}")
@@ -998,12 +1059,11 @@ ff02::2\tip6-allrouters
lname = self.host_intfs[hname]
self.cmd_raises(f"ip link set {lname} down")
self.cmd_raises(f"ip link set {lname} name {hname}")
- self.cmd_status(f"ip link set netns 1 dev {hname}")
- # The above is failing sometimes and not sure why
- # logging.error(
- # "XXX after setns %s",
- # self.unet.rootcmd.cmd_nostatus(f"ip link show {hname}"),
- # )
+ # We need to NOT run this command in the new pid namespace so that pid 1 is the
+ # root init process and so the interface gets returned to the root namespace
+ self.unet.rootcmd.cmd_raises(
+ f"nsenter -t {self.pid} -n ip link set netns 1 dev {hname}"
+ )
del self.host_intfs[hname]
async def add_phy_intf(self, devaddr, lname):
@@ -1522,11 +1582,14 @@ class L3ContainerNode(L3NodeMixin, LinuxNamespace):
async def async_cleanup_cmd(self):
"""Run the configured cleanup commands for this node."""
+ if self.cleanup_called:
+ return
self.cleanup_called = True
if "cleanup-cmd" not in self.config:
return
+ # The opposite of other types, the container needs cmd_p running
if not self.cmd_p:
self.logger.warning("async_cleanup_cmd: container no longer running")
return
@@ -1639,7 +1702,15 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
rundir=os.path.join(self.rundir, self.name),
configdir=self.unet.config_dirname,
)
- self.ssh_keyfile = self.qemu_config.get("sshkey")
+ self.ssh_keyfile = self.config.get("ssh-identity-file")
+ if not self.ssh_keyfile:
+ self.ssh_keyfile = self.qemu_config.get("sshkey")
+
+ self.ssh_user = self.config.get("ssh-user")
+ if not self.ssh_user:
+ self.ssh_user = self.qemu_config.get("sshuser", "root")
+
+ self.disk_created = False
@property
def is_vm(self):
@@ -1680,10 +1751,9 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
self.__base_cmd_pty = list(self.__base_cmd)
self.__base_cmd_pty.append("-t")
- user = self.qemu_config.get("sshuser", "root")
- self.__base_cmd.append(f"{user}@{mgmt_ip}")
+ self.__base_cmd.append(f"{self.ssh_user}@{mgmt_ip}")
self.__base_cmd.append("--")
- self.__base_cmd_pty.append(f"{user}@{mgmt_ip}")
+ self.__base_cmd_pty.append(f"{self.ssh_user}@{mgmt_ip}")
# self.__base_cmd_pty.append("--")
return True
@@ -1810,15 +1880,15 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
if args:
self.extra_mounts += args
- async def run_cmd(self):
+ async def _run_cmd(self, cmd_node):
"""Run the configured commands for this node inside VM."""
self.logger.debug(
"[rundir %s exists %s]", self.rundir, os.path.exists(self.rundir)
)
- cmd = self.config.get("cmd", "").strip()
+ cmd = self.config.get(cmd_node, "").strip()
if not cmd:
- self.logger.debug("%s: no `cmd` to run", self)
+ self.logger.debug("%s: no `%s` to run", self, cmd_node)
return None
shell_cmd = self.config.get("shell", "/bin/bash")
@@ -1837,15 +1907,17 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
cmd += "\n"
# Write a copy to the rundir
- cmdpath = os.path.join(self.rundir, "cmd.shebang")
+ cmdpath = os.path.join(self.rundir, f"{cmd_node}.shebang")
with open(cmdpath, mode="w+", encoding="utf-8") as cmdfile:
cmdfile.write(cmd)
commander.cmd_raises(f"chmod 755 {cmdpath}")
# Now write a copy inside the VM
- self.conrepl.cmd_status("cat > /tmp/cmd.shebang << EOF\n" + cmd + "\nEOF")
- self.conrepl.cmd_status("chmod 755 /tmp/cmd.shebang")
- cmds = "/tmp/cmd.shebang"
+ self.conrepl.cmd_status(
+ f"cat > /tmp/{cmd_node}.shebang << EOF\n" + cmd + "\nEOF"
+ )
+ self.conrepl.cmd_status(f"chmod 755 /tmp/{cmd_node}.shebang")
+ cmds = f"/tmp/{cmd_node}.shebang"
else:
cmd = cmd.replace("%CONFIGDIR%", str(self.unet.config_dirname))
cmd = cmd.replace("%RUNDIR%", str(self.rundir))
@@ -1883,20 +1955,30 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
# When run_command supports async_ arg we can use the above...
self.cmd_p = now_proc(self.cmdrepl.run_command(cmds, timeout=120))
-
- # stdout and err both combined into logfile from the spawned repl
- stdout = os.path.join(self.rundir, "_cmdcon-log.txt")
- self.pytest_hook_run_cmd(stdout, None)
else:
# If we only have a console we can't run in parallel, so run to completion
self.cmd_p = now_proc(self.conrepl.run_command(cmds, timeout=120))
return self.cmd_p
+ async def run_cmd(self):
+ if self.disk_created:
+ await self._run_cmd("initial-cmd")
+ await self._run_cmd("cmd")
+
+ # stdout and err both combined into logfile from the spawned repl
+ if self.cmdrepl:
+ stdout = os.path.join(self.rundir, "_cmdcon-log.txt")
+ self.pytest_hook_run_cmd(stdout, None)
+
# InterfaceMixin override
# We need a name unique in the shared namespace.
def get_ns_ifname(self, ifname):
- return self.name + ifname
+ ifname = self.name + ifname
+ ifname = re.sub("gigabitethernet", "GE", ifname, flags=re.I)
+ if len(ifname) >= 16:
+ ifname = ifname[0:7] + ifname[-8:]
+ return ifname
async def add_host_intf(self, hname, lname, mtu=None):
# L3QemuVM needs it's own add_host_intf for macvtap, We need to create the tap
@@ -2044,24 +2126,50 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
async def gather_coverage_data(self):
con = self.conrepl
+ gcda_root = "/sys/kernel/debug/gcov"
+ dest = "/tmp/gcov-data.tgz"
- gcda = "/sys/kernel/debug/gcov"
- tmpdir = con.cmd_raises("mktemp -d").strip()
- dest = "/gcov-data.tgz"
- con.cmd_raises(rf"find {gcda} -type d -exec mkdir -p {tmpdir}/{{}} \;")
- con.cmd_raises(
- rf"find {gcda} -name '*.gcda' -exec sh -c 'cat < $0 > {tmpdir}/$0' {{}} \;"
- )
- con.cmd_raises(
- rf"find {gcda} -name '*.gcno' -exec sh -c 'cp -d $0 {tmpdir}/$0' {{}} \;"
- )
- con.cmd_raises(rf"tar cf - -C {tmpdir} sys | gzip -c > {dest}")
- con.cmd_raises(rf"rm -rf {tmpdir}")
- self.logger.info("Saved coverage data in VM at %s", dest)
+ if gcda_root != "/sys/kernel/debug/gcov":
+ con.cmd_raises(
+ rf"cd {gcda_root} && find * -name '*.gc??' "
+ "| tar -cf - -T - | gzip -c > {dest}"
+ )
+ else:
+ # Some tars dont try and read 0 length files so we need to copy them.
+ tmpdir = con.cmd_raises("mktemp -d").strip()
+ con.cmd_raises(
+ rf"cd {gcda_root} && find -type d -exec mkdir -p {tmpdir}/{{}} \;"
+ )
+ con.cmd_raises(
+ rf"cd {gcda_root} && "
+ rf"find -name '*.gcda' -exec sh -c 'cat < $0 > {tmpdir}/$0' {{}} \;"
+ )
+ con.cmd_raises(
+ rf"cd {gcda_root} && "
+ rf"find -name '*.gcno' -exec sh -c 'cp -d $0 {tmpdir}/$0' {{}} \;"
+ )
+ con.cmd_raises(
+ rf"cd {tmpdir} && "
+ rf"find * -name '*.gc??' | tar -cf - -T - | gzip -c > {dest}"
+ )
+ con.cmd_raises(rf"rm -rf {tmpdir}")
+
+ self.logger.debug("Saved coverage data in VM at %s", dest)
+ ldest = os.path.join(self.rundir, "gcov-data.tgz")
if self.use_ssh:
- ldest = os.path.join(self.rundir, "gcov-data.tgz")
self.cmd_raises(["/bin/cat", dest], stdout=open(ldest, "wb"))
- self.logger.info("Saved coverage data on host at %s", ldest)
+ self.logger.debug("Saved coverage data on host at %s", ldest)
+ else:
+ output = con.cmd_raises(rf"base64 {dest}")
+ with open(ldest, "wb") as f:
+ f.write(base64.b64decode(output))
+ self.logger.debug("Saved coverage data on host at %s", ldest)
+ self.logger.info("Extracting coverage for %s into %s", self.name, ldest)
+
+ # We need to place the gcda files where munet expects to find them
+ gcdadir = Path(os.environ["GCOV_PREFIX"]) / self.name
+ self.unet.cmd_raises_nsonly(f"mkdir -p {gcdadir}")
+ self.unet.cmd_raises_nsonly(f"tar -C {gcdadir} -xzf {ldest}")
async def _opencons(
self,
@@ -2119,6 +2227,7 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
expects=expects,
sends=sends,
timeout=timeout,
+ init_newline=True,
trace=True,
)
)
@@ -2247,30 +2356,45 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
if not nnics:
args += ["-nic", "none"]
- dtpl = qc.get("disk-template")
+ dtplpath = dtpl = qc.get("disk-template")
diskpath = disk = qc.get("disk")
- if dtpl and not disk:
- disk = qc["disk"] = f"{self.name}-{os.path.basename(dtpl)}"
- diskpath = os.path.join(self.rundir, disk)
+ if diskpath:
+ if diskpath[0] != "/":
+ diskpath = os.path.join(self.unet.config_dirname, diskpath)
+
+ if dtpl and (not disk or not os.path.exists(diskpath)):
+ if not disk:
+ disk = qc["disk"] = f"{self.name}-{os.path.basename(dtpl)}"
+ diskpath = os.path.join(self.rundir, disk)
if self.path_exists(diskpath):
logging.debug("Disk '%s' file exists, using.", diskpath)
else:
- dtplpath = os.path.abspath(
- os.path.join(
- os.path.dirname(self.unet.config["config_pathname"]), dtpl
- )
- )
+ if dtplpath[0] != "/":
+ dtplpath = os.path.join(self.unet.config_dirname, dtpl)
logging.info("Create disk '%s' from template '%s'", diskpath, dtplpath)
self.cmd_raises(
f"qemu-img create -f qcow2 -F qcow2 -b {dtplpath} {diskpath}"
)
+ self.disk_created = True
+ disk_driver = qc.get("disk-driver", "virtio")
if diskpath:
- args.extend(
- ["-drive", f"file={diskpath},if=none,id=sata-disk0,format=qcow2"]
- )
- args.extend(["-device", "ahci,id=ahci"])
- args.extend(["-device", "ide-hd,bus=ahci.0,drive=sata-disk0"])
+ if disk_driver == "virtio":
+ args.extend(["-drive", f"file={diskpath},if=virtio,format=qcow2"])
+ else:
+ args.extend(
+ ["-drive", f"file={diskpath},if=none,id=sata-disk0,format=qcow2"]
+ )
+ args.extend(["-device", "ahci,id=ahci"])
+ args.extend(["-device", "ide-hd,bus=ahci.0,drive=sata-disk0"])
+
+ cidiskpath = qc.get("cloud-init-disk")
+ if cidiskpath:
+ if cidiskpath[0] != "/":
+ cidiskpath = os.path.join(self.unet.config_dirname, cidiskpath)
+ args.extend(["-drive", f"file={cidiskpath},if=virtio,format=qcow2"])
+
+ # args.extend(["-display", "vnc=0.0.0.0:40"])
use_stdio = cc.get("stdio", True)
has_cmd = self.config.get("cmd")
@@ -2360,6 +2484,10 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
if use_cmdcon:
confiles.append("_cmdcon")
+ password = cc.get("password", "")
+ if self.disk_created:
+ password = cc.get("initial-password", password)
+
#
# Connect to the console socket, retrying
#
@@ -2369,7 +2497,7 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
prompt=prompt,
is_bourne=not bool(prompt),
user=cc.get("user", "root"),
- password=cc.get("password", ""),
+ password=password,
expects=cc.get("expects"),
sends=cc.get("sends"),
timeout=int(cc.get("timeout", 60)),
@@ -2425,6 +2553,8 @@ class L3QemuVM(L3NodeMixin, LinuxNamespace):
async def async_cleanup_cmd(self):
"""Run the configured cleanup commands for this node."""
+ if self.cleanup_called:
+ return
self.cleanup_called = True
if "cleanup-cmd" not in self.config:
@@ -2815,7 +2945,9 @@ ff02::2\tip6-allrouters
else:
node2.set_lan_addr(node1, c2)
- if "physical" not in c1 and not node1.is_vm:
+ if isinstance(node1, ExternalNetwork):
+ pass
+ elif "physical" not in c1 and not node1.is_vm:
node1.set_intf_constraints(if1, **c1)
if "physical" not in c2 and not node2.is_vm:
node2.set_intf_constraints(if2, **c2)
@@ -2828,14 +2960,8 @@ ff02::2\tip6-allrouters
cls = L3QemuVM
elif config and config.get("server"):
cls = SSHRemote
- kwargs["server"] = config["server"]
- kwargs["port"] = int(config.get("server-port", 22))
- if "ssh-identity-file" in config:
- kwargs["idfile"] = config.get("ssh-identity-file")
- if "ssh-user" in config:
- kwargs["user"] = config.get("ssh-user")
- if "ssh-password" in config:
- kwargs["password"] = config.get("ssh-password")
+ elif config and config.get("hostnet"):
+ cls = HostnetNode
else:
cls = L3NamespaceNode
return super().add_host(name, cls=cls, config=config, **kwargs)
@@ -2845,20 +2971,113 @@ ff02::2\tip6-allrouters
if config is None:
config = {}
- cls = L3Bridge if config.get("ip") else L2Bridge
+ if config.get("external"):
+ cls = ExternalNetwork
+ elif config.get("ip"):
+ cls = L3Bridge
+ else:
+ cls = L2Bridge
mtu = kwargs.get("mtu", config.get("mtu"))
return super().add_switch(name, cls=cls, config=config, mtu=mtu, **kwargs)
- async def run(self):
+ def coverage_setup(self):
+ bdir = self.cfgopt.getoption("--cov-build-dir")
+ if not bdir:
+ # Try and find the build dir using common prefix of gcno files
+ common = None
+ cwd = os.getcwd()
+ for f in glob.iglob(rf"{cwd}/**/*.gcno", recursive=True):
+ if not common:
+ common = os.path.dirname(f)
+ else:
+ common = os.path.commonprefix([common, f])
+ if not common:
+ break
+ assert (
+ bdir
+ ), "Can't locate build directory for coverage data, use --cov-build-dir"
+
+ bdir = Path(bdir).resolve()
+ rundir = Path(self.rundir).resolve()
+ gcdadir = rundir / "gcda"
+ os.environ["GCOV_BUILD_DIR"] = str(bdir)
+ os.environ["GCOV_PREFIX_STRIP"] = str(len(bdir.parts) - 1)
+ os.environ["GCOV_PREFIX"] = str(gcdadir)
+
+ # commander.cmd_raises(f"find {bdir} -name '*.gc??' -exec chmod o+rw {{}} +")
+ group_id = bdir.stat().st_gid
+ commander.cmd_raises(f"mkdir -p {gcdadir}")
+ commander.cmd_raises(f"chown -R root:{group_id} {gcdadir}")
+ commander.cmd_raises(f"chmod 2775 {gcdadir}")
+
+ async def coverage_finish(self):
+ rundir = Path(self.rundir).resolve()
+ bdir = Path(os.environ["GCOV_BUILD_DIR"])
+ gcdadir = Path(os.environ["GCOV_PREFIX"])
+
+ # Create .gcno symlinks if they don't already exist, for kernel they will
+ self.logger.info("Creating .gcno symlinks from '%s' to '%s'", gcdadir, bdir)
+ commander.cmd_raises(
+ f'cd "{gcdadir}"; bdir="{bdir}"'
+ + """
+for f in $(find . -name '*.gcda'); do
+ f=${f#./};
+ f=${f%.gcda}.gcno;
+ if [ ! -h "$f" ]; then
+ ln -fs $bdir/$f $f;
+ touch -h -r $bdir/$f $f;
+ echo $f;
+ fi;
+done"""
+ )
+
+ # Get the results into a summary file
+ data_file = rundir / "coverage.info"
+ self.logger.info("Gathering coverage data into: %s", data_file)
+ commander.cmd_raises(
+ f"lcov --directory {gcdadir} --capture --output-file {data_file}"
+ )
+
+ # Get coverage info filtered to a specific set of files
+ report_file = rundir / "coverage.info"
+ self.logger.debug("Generating coverage summary: %s", report_file)
+ output = commander.cmd_raises(f"lcov --summary {data_file}")
+ self.logger.info("\nCOVERAGE-SUMMARY-START\n%s\nCOVERAGE-SUMMARY-END", output)
+ # terminalreporter.write(
+ # f"\nCOVERAGE-SUMMARY-START\n{output}\nCOVERAGE-SUMMARY-END\n"
+ # )
+
+ async def load_images(self, images):
tasks = []
+ for image in images:
+ logging.debug("Checking for image %s", image)
+ rc, _, _ = self.rootcmd.cmd_status(
+ f"podman image inspect {image}", warn=False
+ )
+ if not rc:
+ continue
+ logging.info("Pulling missing image %s", image)
+ aw = self.rootcmd.async_cmd_raises(f"podman pull {image}")
+ tasks.append(asyncio.create_task(aw))
+ if not tasks:
+ return
+ _, pending = await asyncio.wait(tasks, timeout=600)
+ assert not pending, "Failed to pull container images"
+ async def run(self):
+ tasks = []
hosts = self.hosts.values()
+
+ images = {x.container_image for x in hosts if hasattr(x, "container_image")}
+ await self.load_images(images)
+
launch_nodes = [x for x in hosts if hasattr(x, "launch")]
launch_nodes = [x for x in launch_nodes if x.config.get("qemu")]
- run_nodes = [x for x in hosts if hasattr(x, "has_run_cmd") and x.has_run_cmd()]
- ready_nodes = [
- x for x in hosts if hasattr(x, "has_ready_cmd") and x.has_ready_cmd()
- ]
+ run_nodes = [x for x in hosts if x.has_run_cmd()]
+ ready_nodes = [x for x in hosts if x.has_ready_cmd()]
+
+ if self.cfgopt.getoption("--coverage"):
+ self.coverage_setup()
pcapopt = self.cfgopt.getoption("--pcap")
pcapopt = pcapopt if pcapopt else ""
@@ -2920,10 +3139,10 @@ ff02::2\tip6-allrouters
await asyncio.sleep(0.25)
logging.debug("%s is ready!", x)
+ tasks = [asyncio.create_task(wait_until_ready(x)) for x in ready_nodes]
+
logging.debug("Waiting for ready on nodes: %s", ready_nodes)
- _, pending = await asyncio.wait(
- [wait_until_ready(x) for x in ready_nodes], timeout=30
- )
+ _, pending = await asyncio.wait(tasks, timeout=30)
if pending:
logging.warning("Timeout waiting for ready: %s", pending)
for nr in pending:
@@ -2940,15 +3159,6 @@ ff02::2\tip6-allrouters
self.logger.debug("%s: deleting.", self)
- if self.cfgopt.getoption("--coverage"):
- nodes = (
- x for x in self.hosts.values() if hasattr(x, "gather_coverage_data")
- )
- try:
- await asyncio.gather(*(x.gather_coverage_data() for x in nodes))
- except Exception as error:
- logging.warning("Error gathering coverage data: %s", error)
-
pause = bool(self.cfgopt.getoption("--pause-at-end"))
pause = pause or bool(self.cfgopt.getoption("--pause"))
if pause:
@@ -2959,6 +3169,25 @@ ff02::2\tip6-allrouters
except Exception as error:
self.logger.error("\n...continuing after error: %s", error)
+ # Run cleanup-cmd's.
+ nodes = (x for x in self.hosts.values() if x.has_cleanup_cmd())
+ try:
+ await asyncio.gather(*(x.async_cleanup_cmd() for x in nodes))
+ except Exception as error:
+ logging.warning("Error running cleanup cmds: %s", error)
+
+ # Gather any coverage data
+ if self.cfgopt.getoption("--coverage"):
+ nodes = (
+ x for x in self.hosts.values() if hasattr(x, "gather_coverage_data")
+ )
+ try:
+ await asyncio.gather(*(x.gather_coverage_data() for x in nodes))
+ except Exception as error:
+ logging.warning("Error gathering coverage data: %s", error)
+
+ await self.coverage_finish()
+
# XXX should we cancel launch and run tasks?
try:
diff --git a/tests/topotests/munet/parser.py b/tests/topotests/munet/parser.py
index 4fc0c75..a8b73a2 100644
--- a/tests/topotests/munet/parser.py
+++ b/tests/topotests/munet/parser.py
@@ -230,7 +230,7 @@ def load_kinds(args, search=None):
if args:
os.chdir(args.rundir)
- args_config = args.kinds_config if args else None
+ args_config = args.kinds_config if args and hasattr(args, "kinds_config") else None
try:
if search is None:
search = [cwd]
@@ -305,7 +305,7 @@ async def async_build_topology(
# create search directories from common root if given
cpath = Path(config["config_pathname"]).absolute()
- project_root = args.project_root if args else None
+ project_root = args.project_root if args and hasattr(args, "project_root") else None
if not search_root:
search_root = find_project_root(cpath, project_root)
if not search_root:
@@ -341,7 +341,11 @@ async def async_build_topology(
pytestconfig=pytestconfig,
isolated=isolated,
pid=top_level_pidns,
- unshare_inline=args.unshare_inline if args else unshare_inline,
+ unshare_inline=(
+ args.unshare_inline
+ if args and hasattr(args, "unshare_inline")
+ else unshare_inline
+ ),
logger=logger,
)
diff --git a/tests/topotests/munet/testing/fixtures.py b/tests/topotests/munet/testing/fixtures.py
index 3c6d946..3c6ddf9 100644
--- a/tests/topotests/munet/testing/fixtures.py
+++ b/tests/topotests/munet/testing/fixtures.py
@@ -25,7 +25,6 @@ from ..base import BaseMunet
from ..base import Bridge
from ..base import get_event_loop
from ..cleanup import cleanup_current
-from ..cleanup import cleanup_previous
from ..native import L3NodeMixin
from ..parser import async_build_topology
from ..parser import get_config
@@ -130,9 +129,12 @@ def session_autouse():
else:
is_worker = True
- if not is_worker:
- # This is unfriendly to multi-instance
- cleanup_previous()
+ # We dont want to kill all munet and we don't have the rundir here yet
+ # This was more useful back when we used to leave processes around a lot
+ # more.
+ # if not is_worker:
+ # # This is unfriendly to multi-instance
+ # cleanup_previous()
# We never pop as we want to keep logging
_push_log_handler("session", "/tmp/unet-test/pytest-session.log")
@@ -150,8 +152,9 @@ def session_autouse():
@pytest.fixture(autouse=True, scope="module")
def module_autouse(request):
- logpath = get_test_logdir(request.node.name, True)
- logpath = os.path.join("/tmp/unet-test", logpath, "pytest-exec.log")
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
+ logpath = get_test_logdir(request.node.nodeid, True)
+ logpath = os.path.join(root_path, logpath, "pytest-exec.log")
with log_handler("module", logpath):
sdir = os.path.dirname(os.path.realpath(request.fspath))
with chdir(sdir, "module autouse fixture"):
@@ -161,7 +164,7 @@ def module_autouse(request):
raise Exception("Base Munet was not cleaned up/deleted")
-@pytest.fixture(scope="module")
+@pytest.fixture(scope="session")
def event_loop():
"""Create an instance of the default event loop for the session."""
loop = get_event_loop()
@@ -174,7 +177,8 @@ def event_loop():
@pytest.fixture(scope="module")
def rundir_module():
- d = os.path.join("/tmp/unet-test", get_test_logdir(module=True))
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
+ d = os.path.join(root_path, get_test_logdir(module=True))
logging.debug("conftest: test module rundir %s", d)
return d
@@ -213,18 +217,14 @@ async def _unet_impl(
param,
exc_info=True,
)
- pytest.skip(
- f"unet fixture: unet build failed: {error}", allow_module_level=True
- )
- raise
+ pytest.fail(f"unet fixture: unet build failed: {error}")
try:
tasks = await _unet.run()
except Exception as error:
logging.debug("unet fixture: unet run failed: %s", error, exc_info=True)
await _unet.async_delete()
- pytest.skip(f"unet fixture: unet run failed: {error}", allow_module_level=True)
- raise
+ pytest.fail(f"unet fixture: unet run failed: {error}")
logging.debug("unet fixture: containers running")
@@ -379,7 +379,8 @@ async def astepf(pytestconfig):
@pytest.fixture(scope="function")
def rundir():
- d = os.path.join("/tmp/unet-test", get_test_logdir(module=False))
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
+ d = os.path.join(root_path, get_test_logdir(module=False))
logging.debug("conftest: test function rundir %s", d)
return d
@@ -387,9 +388,8 @@ def rundir():
# Configure logging
@pytest.hookimpl(hookwrapper=True, tryfirst=True)
def pytest_runtest_setup(item):
- d = os.path.join(
- "/tmp/unet-test", get_test_logdir(nodeid=item.nodeid, module=False)
- )
+ root_path = os.environ.get("MUNET_RUNDIR", "/tmp/unet-test")
+ d = os.path.join(root_path, get_test_logdir(nodeid=item.nodeid, module=False))
config = item.config
logging_plugin = config.pluginmanager.get_plugin("logging-plugin")
filename = Path(d, "pytest-exec.log")
diff --git a/tests/topotests/munet/testing/hooks.py b/tests/topotests/munet/testing/hooks.py
index 985eef9..f6f2115 100644
--- a/tests/topotests/munet/testing/hooks.py
+++ b/tests/topotests/munet/testing/hooks.py
@@ -18,6 +18,7 @@ import traceback
import pytest
+from ..args import add_testing_args
from ..base import BaseMunet # pylint: disable=import-error
from ..cli import cli # pylint: disable=import-error
from .util import pause_test
@@ -29,85 +30,7 @@ from .util import pause_test
def pytest_addoption(parser):
- parser.addoption(
- "--cli-on-error",
- action="store_true",
- help="CLI on test failure",
- )
-
- parser.addoption(
- "--coverage",
- action="store_true",
- help="Enable coverage gathering if supported",
- )
-
- parser.addoption(
- "--gdb",
- default="",
- metavar="HOST[,HOST...]",
- help="Comma-separated list of nodes to launch gdb on, or 'all'",
- )
- parser.addoption(
- "--gdb-breakpoints",
- default="",
- metavar="BREAKPOINT[,BREAKPOINT...]",
- help="Comma-separated list of breakpoints",
- )
- parser.addoption(
- "--gdb-use-emacs",
- action="store_true",
- help="Use emacsclient to run gdb instead of a shell",
- )
-
- parser.addoption(
- "--pcap",
- default="",
- metavar="NET[,NET...]",
- help="Comma-separated list of networks to capture packets on, or 'all'",
- )
-
- parser.addoption(
- "--pause",
- action="store_true",
- help="Pause after each test",
- )
- parser.addoption(
- "--pause-at-end",
- action="store_true",
- help="Pause before taking munet down",
- )
- parser.addoption(
- "--pause-on-error",
- action="store_true",
- help="Pause after (disables default when --shell or -vtysh given)",
- )
- parser.addoption(
- "--no-pause-on-error",
- dest="pause_on_error",
- action="store_false",
- help="Do not pause after (disables default when --shell or -vtysh given)",
- )
-
- parser.addoption(
- "--shell",
- default="",
- metavar="NODE[,NODE...]",
- help="Comma-separated list of nodes to spawn shell on, or 'all'",
- )
-
- parser.addoption(
- "--stdout",
- default="",
- metavar="NODE[,NODE...]",
- help="Comma-separated list of nodes to open tail-f stdout window on, or 'all'",
- )
-
- parser.addoption(
- "--stderr",
- default="",
- metavar="NODE[,NODE...]",
- help="Comma-separated list of nodes to open tail-f stderr window on, or 'all'",
- )
+ add_testing_args(parser.addoption)
def pytest_configure(config):
@@ -146,6 +69,18 @@ def pytest_configure(config):
elif b and not is_xdist and not have_windows:
pytest.exit(f"{winopt} use requires byobu/TMUX/SCREEN/XTerm")
+ cli_pause = (
+ config.getoption("--cli-on-error")
+ or config.getoption("--pause")
+ or config.getoption("--pause-at-end")
+ or config.getoption("--pause-on-error")
+ )
+ if config.getoption("--capture") == "fd" and cli_pause:
+ pytest.exit(
+ "CLI is not compatible with `--capture=fd`, "
+ "please run again with `-s` or other `--capture` value"
+ )
+
def pytest_runtest_makereport(item, call):
"""Pause or invoke CLI as directed by config."""
diff --git a/tests/topotests/nb_config/test_nb_config.py b/tests/topotests/nb_config/test_nb_config.py
index f699a4e..9099ef1 100644
--- a/tests/topotests/nb_config/test_nb_config.py
+++ b/tests/topotests/nb_config/test_nb_config.py
@@ -24,9 +24,7 @@ CWD = os.path.dirname(os.path.realpath(__file__))
def tgen(request):
"Setup/Teardown the environment and provide tgen argument to tests"
- topodef = {
- "s1": ("r1",)
- }
+ topodef = {"s1": ("r1",)}
tgen = Topogen(topodef, request.module.__name__)
tgen.start_topology()
@@ -46,12 +44,14 @@ def test_access_list_config_ordering(tgen):
r1 = tgen.gears["r1"]
- output = r1.vtysh_multicmd([
- "conf t",
- "access-list test seq 1 permit host 10.0.0.1"])
+ output = r1.vtysh_multicmd(
+ ["conf t", "access-list test seq 1 permit host 10.0.0.1"]
+ )
output = r1.vtysh_cmd("show ip access-list test json")
got = json.loads(output)
- expected = json.loads('{"ZEBRA":{"test":{"type":"Standard", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "address":"10.0.0.1", "mask":"0.0.0.0"}]}}}')
+ expected = json.loads(
+ '{"zebra":{"test":{"type":"Standard", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "address":"10.0.0.1", "mask":"0.0.0.0"}]}}}'
+ )
result = json_cmp(got, expected)
assert result is None
@@ -59,11 +59,11 @@ def test_access_list_config_ordering(tgen):
# If the northbound mis-orders the create/delete then this test fails.
# https://github.com/FRRouting/frr/pull/15423/commits/38b85e0c2bc555b8827dbd2cb6515b6febf548b4
#
- output = r1.vtysh_multicmd([
- "conf t",
- "access-list test seq 1 permit 10.0.0.0/8"])
+ output = r1.vtysh_multicmd(["conf t", "access-list test seq 1 permit 10.0.0.0/8"])
output = r1.vtysh_cmd("show ip access-list test json")
got = json.loads(output)
- expected = json.loads('{"ZEBRA":{"test":{"type":"Zebra", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "prefix":"10.0.0.0/8", "exact-match":false}]}}}')
+ expected = json.loads(
+ '{"zebra":{"test":{"type":"Zebra", "addressFamily":"IPv4", "rules":[{"sequenceNumber":1, "filterType":"permit", "prefix":"10.0.0.0/8", "exact-match":false}]}}}'
+ )
result = json_cmp(got, expected)
assert result is None
diff --git a/tests/topotests/nhrp_topo/test_nhrp_topo.py b/tests/topotests/nhrp_topo/test_nhrp_topo.py
index 26115de..284c58a 100644
--- a/tests/topotests/nhrp_topo/test_nhrp_topo.py
+++ b/tests/topotests/nhrp_topo/test_nhrp_topo.py
@@ -189,7 +189,7 @@ def test_protocols_convergence():
expected = {
"{}-gre0".format(rname): {
- "flags": "<UP,RUNNING>",
+ "flags": "<UP,LOWER_UP,RUNNING>",
}
}
test_func = partial(
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf
index 2a6c9ab..24cd354 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf
+++ b/tests/topotests/ospf6_ecmp_inter_area/r5/ospf6d.conf
@@ -4,31 +4,11 @@ interface r5-eth0
ipv6 ospf6 dead-interval 10
!
interface r5-eth1
- ipv6 ospf6 area 0
- ipv6 ospf6 hello-interval 2
- ipv6 ospf6 dead-interval 10
-!
-interface r5-eth2
- ipv6 ospf6 area 0
- ipv6 ospf6 hello-interval 2
- ipv6 ospf6 dead-interval 10
-!
-interface r5-eth3
ipv6 ospf6 area 1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
-interface r5-eth4
- ipv6 ospf6 area 1
- ipv6 ospf6 hello-interval 2
- ipv6 ospf6 dead-interval 10
-!
-interface r5-eth5
- ipv6 ospf6 area 0
- ipv6 ospf6 hello-interval 2
- ipv6 ospf6 dead-interval 10
-!
-interface r5-eth6
+interface r5-eth2
ipv6 ospf6 area 0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf
index a1f48b5..4efaa31 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf
+++ b/tests/topotests/ospf6_ecmp_inter_area/r6/ospf6d.conf
@@ -1,8 +1,23 @@
interface r6-eth0
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r6-eth1
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r6-eth2
ipv6 ospf6 area 1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
+interface r6-eth3
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
router ospf6
ospf6 router-id 10.254.254.6
redistribute connected
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf
index 0e49b0d..9b7756e 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf
+++ b/tests/topotests/ospf6_ecmp_inter_area/r7/ospf6d.conf
@@ -1,11 +1,22 @@
-interface lo
+interface r7-eth0
ipv6 ospf6 area 1
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
!
-interface r7-eth0
+interface r7-eth1
ipv6 ospf6 area 1
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
+interface r7-eth2
+ ipv6 ospf6 area 1
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r7-eth3
+ shutdown
+!
router ospf6
ospf6 router-id 10.254.254.7
+ redistribute connected
!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf
index a410be8..1608cad 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf
+++ b/tests/topotests/ospf6_ecmp_inter_area/r7/zebra.conf
@@ -3,3 +3,6 @@ ipv6 forwarding
interface lo
ipv6 address 2001:db8:7::1/64
!
+interface r7-eth2
+ ipv6 address 2001:db8:8007::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf
index fb5483c..33c6497 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf
+++ b/tests/topotests/ospf6_ecmp_inter_area/r8/ospf6d.conf
@@ -3,6 +3,19 @@ interface r8-eth0
ipv6 ospf6 hello-interval 2
ipv6 ospf6 dead-interval 10
!
+interface r8-eth1
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r8-eth2
+ ipv6 ospf6 area 0
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r8-eth3
+ shutdown
+!
router ospf6
ospf6 router-id 10.254.254.8
redistribute connected
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf
index 8e343d8..e756cd4 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf
+++ b/tests/topotests/ospf6_ecmp_inter_area/r8/zebra.conf
@@ -3,3 +3,6 @@ ipv6 forwarding
interface lo
ipv6 address 2001:db8:8::1/64
!
+interface r8-eth2
+ ipv6 address 2001:db8:8008::1/64
+!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf b/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf
deleted file mode 100644
index 57fa8e3..0000000
--- a/tests/topotests/ospf6_ecmp_inter_area/r9/ospf6d.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-interface lo
- ipv6 ospf6 area 0
-!
-interface r9-eth0
- ipv6 ospf6 area 0
- ipv6 ospf6 hello-interval 2
- ipv6 ospf6 dead-interval 10
-!
-router ospf6
- ospf6 router-id 10.254.254.9
-!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf b/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf
deleted file mode 100644
index e267496..0000000
--- a/tests/topotests/ospf6_ecmp_inter_area/r9/zebra.conf
+++ /dev/null
@@ -1,5 +0,0 @@
-ipv6 forwarding
-!
-interface lo
- ipv6 address 2001:db8:9::1/64
-!
diff --git a/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py
index 2eaccb8..adf289e 100644
--- a/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py
+++ b/tests/topotests/ospf6_ecmp_inter_area/test_ospf6_ecmp_inter_area.py
@@ -3,7 +3,7 @@
# test_ospf6_ecmp_inter_area.py
#
-# Copyright (c) 2021, 2022 by Martin Buck
+# Copyright (c) 2021, 2022, 2024 by Martin Buck
# Copyright (c) 2016 by
# Network Device Education Foundation, Inc. ("NetDEF")
#
@@ -11,35 +11,42 @@
r"""
test_ospf6_ecmp_inter_area.py: Test OSPFv3 ECMP inter-area nexthop update
-Check proper removal of ECMP nexthops after a path used by one nexthop
-disappears. We remove a path by bringing down a link required by that
-path which is not adjacent to the router being checked. This is important
-because when bringing down adjacent links, the kernel might remove the
-nexthops itself without ospf6d having to do anything.
+Check proper addition and removal of ECMP nexthops in 2 cases: Parallel
+paths to one ABR and parallel ABRs. We test nexthop removal triggered by
+path removal by bringing down a link required by that path which is not
+adjacent to the router being checked. This is important because when
+bringing down adjacent links, the kernel might remove the nexthops itself
+without ospf6d having to do anything.
-Useful as a regression test for #9720.
+Useful as a regression test for #9720 and #15777.
Topology:
- .
- Area 0 . Area 1
- .
- -- R2 -- . ---- R6
- / \ ./
-R1 -- R3 -- R5 ---- R7 Area 1
- \ / \\ ..............
- -- R4 -- \--- R8 Area 0
- \
- -- R9
-
-We check routes on R1, primarily those towards R6/7/8/9. Those to R6/7 are
-inter-area routes with R5 being ABR, those to R8/9 are intra-area routes
-and are used for reference. R6/R8 announce external routes, R7/R9 announce
-internal routes.
+ .
+ Area 0 . Area 1
+ .
+ -- R2 ------ R5 -----
+ / .\ \
+ / . | \
+R1 --- R3 ------ R6 ------ R7
+ \ / |. |
+ \ / |. |
+ -- R4 ---- |. |
+ / ./
+ R8 --
+ .
+
+We check routes on R1, primarily those towards R7/8. Those to R7 are
+inter-area routes with R5/6 being ABRs, those to R8 are intra-area routes
+and are used for reference. R7/R8 announce one internal and one external
+route each.
With all links up, we expect 3 ECMP paths and 3 nexthops on R1 towards each
-of R6/7/8/9. Then we bring down the R2-R5 link, causing only 2 remaining
-paths and 2 nexthops on R1. The test is successful if the number of nexthops
-for the routes on R1 is as expected.
+of R7/8. Then we bring down the R3-R6 link, causing only 2 remaining
+paths and 2 nexthops on R1. Then we bring down the R2-R5 link, causing only
+1 remaining path and 1 nexthop on R1.
+
+The test is successful if the number of nexthops for the routes on R1 is as
+expected.
"""
import os
@@ -65,20 +72,24 @@ pytestmark = [pytest.mark.ospf6d]
def build_topo(tgen):
"Build function"
- # Create 9 routers
- for routern in range(1, 10):
+ # Create 8 routers
+ for routern in range(1, 9):
tgen.add_router("r{}".format(routern))
-
tgen.gears["r1"].add_link(tgen.gears["r2"])
tgen.gears["r1"].add_link(tgen.gears["r3"])
tgen.gears["r1"].add_link(tgen.gears["r4"])
tgen.gears["r2"].add_link(tgen.gears["r5"])
- tgen.gears["r3"].add_link(tgen.gears["r5"])
- tgen.gears["r4"].add_link(tgen.gears["r5"])
- tgen.gears["r5"].add_link(tgen.gears["r6"])
+ tgen.gears["r3"].add_link(tgen.gears["r6"])
+ tgen.gears["r4"].add_link(tgen.gears["r6"])
tgen.gears["r5"].add_link(tgen.gears["r7"])
tgen.gears["r5"].add_link(tgen.gears["r8"])
- tgen.gears["r5"].add_link(tgen.gears["r9"])
+ tgen.gears["r6"].add_link(tgen.gears["r7"])
+ tgen.gears["r6"].add_link(tgen.gears["r8"])
+ # Additional "loopback" interfaces. Not used for communication, just to
+ # hold an address we use to inject intra-/inter-area routes (the one on
+ # the real "lo" loopback is used for external routes).
+ tgen.gears["r7"].add_link(tgen.gears["r7"])
+ tgen.gears["r8"].add_link(tgen.gears["r8"])
def setup_module(mod):
@@ -131,20 +142,19 @@ def test_wait_protocol_convergence():
expect_neighbor_full("r2", "10.254.254.1")
expect_neighbor_full("r2", "10.254.254.5")
expect_neighbor_full("r3", "10.254.254.1")
- expect_neighbor_full("r3", "10.254.254.5")
+ expect_neighbor_full("r3", "10.254.254.6")
expect_neighbor_full("r4", "10.254.254.1")
- expect_neighbor_full("r4", "10.254.254.5")
+ expect_neighbor_full("r4", "10.254.254.6")
expect_neighbor_full("r5", "10.254.254.2")
- expect_neighbor_full("r5", "10.254.254.3")
- expect_neighbor_full("r5", "10.254.254.4")
- expect_neighbor_full("r5", "10.254.254.6")
expect_neighbor_full("r5", "10.254.254.7")
expect_neighbor_full("r5", "10.254.254.8")
- expect_neighbor_full("r5", "10.254.254.9")
- expect_neighbor_full("r6", "10.254.254.5")
+ expect_neighbor_full("r6", "10.254.254.3")
+ expect_neighbor_full("r6", "10.254.254.7")
+ expect_neighbor_full("r6", "10.254.254.8")
expect_neighbor_full("r7", "10.254.254.5")
+ expect_neighbor_full("r7", "10.254.254.6")
expect_neighbor_full("r8", "10.254.254.5")
- expect_neighbor_full("r9", "10.254.254.5")
+ expect_neighbor_full("r8", "10.254.254.6")
def test_ecmp_inter_area():
@@ -154,9 +164,16 @@ def test_ecmp_inter_area():
pytest.skip(tgen.errors)
def num_nexthops(router):
- routes = tgen.gears[router].vtysh_cmd("show ipv6 ospf6 route json", isjson=True)
- route_prefixes_infos = sorted(routes.get("routes", {}).items())
- return [len(ri.get("nextHops", [])) for rp, ri in route_prefixes_infos]
+ # Careful: "show ipv6 ospf6 route json" doesn't work here. It will
+ # only list one route type per prefix and that might not necessarily
+ # be the best/selected route. "show ipv6 route ospf6 json" only
+ # lists selected routes, so that's more useful in this case.
+ routes = tgen.gears[router].vtysh_cmd("show ipv6 route ospf6 json", isjson=True)
+ route_prefixes_infos = sorted(routes.items())
+ # Note: ri may contain one entry per routing protocol, but since
+ # we've explicitly requested only ospf6 above, we can count on ri[0]
+ # being the entry we're looking for.
+ return [ri[0]["internalNextHopActiveNum"] for rp, ri in route_prefixes_infos]
def expect_num_nexthops(router, expected_num_nexthops, count):
"Wait until number of nexthops for routes matches expectation"
@@ -174,14 +191,22 @@ def test_ecmp_inter_area():
), "'{}' wrong number of route nexthops".format(router)
# Check nexthops pre link-down
- expect_num_nexthops("r1", [1, 1, 1, 3, 3, 3, 3, 3, 3, 3], 4)
+ # tgen.mininet_cli()
+ expect_num_nexthops("r1", [1, 1, 1, 1, 2, 3, 3, 3, 3], 4)
+
+ logger.info("triggering R3-R6 link down")
+ tgen.gears["r3"].run("ip link set r3-eth1 down")
+
+ # tgen.mininet_cli()
+ # Check nexthops post link-down
+ expect_num_nexthops("r1", [1, 1, 1, 1, 1, 2, 2, 2, 2], 8)
- logger.info("triggering R2-R4 link down")
+ logger.info("triggering R2-R5 link down")
tgen.gears["r2"].run("ip link set r2-eth1 down")
# tgen.mininet_cli()
# Check nexthops post link-down
- expect_num_nexthops("r1", [1, 1, 1, 2, 2, 2, 2, 2, 2, 2], 8)
+ expect_num_nexthops("r1", [1, 1, 1, 1, 1, 1, 1, 1, 1], 8)
def teardown_module(_mod):
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py b/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py
index bd7db64..62b8212 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_flood_reduction.py
@@ -183,7 +183,6 @@ def teardown_module(mod):
logger.info("=" * 40)
-
def red_static(dut, config=True):
"""Local def for Redstribute static routes inside ospf."""
global topo
@@ -367,7 +366,13 @@ def test_ospf_flood_red_tc1_p0(request):
},
}
result = verify_ospf_database(
- tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False
+ tgen,
+ topo,
+ dut,
+ input_dict_db,
+ lsatype="router",
+ rid="100.1.1.0",
+ expected=False,
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -573,7 +578,9 @@ def test_ospf_flood_red_tc2_p0(request):
result = verify_ospf_database(
tgen, topo, dut, input_dict_db, lsatype="router", rid=lsid
)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
step("Wait for 120 secs and verify that LSA's are not refreshed. ")
# get LSA age
@@ -636,7 +643,13 @@ def test_ospf_flood_red_tc2_p0(request):
},
}
result = verify_ospf_database(
- tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False
+ tgen,
+ topo,
+ dut,
+ input_dict_db,
+ lsatype="router",
+ rid="100.1.1.0",
+ expected=False,
)
assert result is not True, (
"Testcase {} : Failed \n "
@@ -815,7 +828,9 @@ def test_ospf_flood_red_tc3_p0(request):
result = verify_ospf_database(
tgen, topo, dut, input_dict_db, lsatype="router", rid=lsid
)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
step("Wait for 120 secs and verify that LSA's are not refreshed. ")
# get LSA age
@@ -1022,7 +1037,13 @@ def test_ospf_flood_red_tc3_p0(request):
},
}
result = verify_ospf_database(
- tgen, topo, dut, input_dict_db, lsatype="router", rid="100.1.1.0", expected=False
+ tgen,
+ topo,
+ dut,
+ input_dict_db,
+ lsatype="router",
+ rid="100.1.1.0",
+ expected=False,
)
assert result is not True, (
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
index d669e21..4a40b3e 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_nssa.py
@@ -165,7 +165,7 @@ def test_ospf_learning_tc15_p0(request):
step("Verify that Type 3 summary LSA is originated for the same Area 0")
ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
dut = "r0"
input_dict = {
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
index f0950a2..d169245 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_rte_calc.py
@@ -49,7 +49,7 @@ from lib.ospf import (
verify_ospf_interface,
)
-pytestmark = [pytest.mark.ospfd, pytest.mark.staticd]
+pytestmark = [pytest.mark.bgpd, pytest.mark.ospfd, pytest.mark.staticd]
# Global variables
@@ -177,7 +177,7 @@ def test_ospf_redistribution_tc5_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
input_dict = {
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
@@ -301,7 +301,7 @@ def test_ospf_redistribution_tc6_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
input_dict = {
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
diff --git a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
index 757d6fb..59afc7a 100644
--- a/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
+++ b/tests/topotests/ospf_basic_functionality/test_ospf_single_area.py
@@ -607,7 +607,7 @@ def test_ospf_show_p1(request):
"r0": {
"ospf": {
"ifUp": True,
- "ifFlags": "<UP,BROADCAST,RUNNING,MULTICAST>",
+ "ifFlags": "<UP,LOWER_UP,BROADCAST,RUNNING,MULTICAST>",
"ospfEnabled": True,
"ipAddressPrefixlen": 24,
"ospfIfType": "Broadcast",
@@ -634,7 +634,7 @@ def test_ospf_show_p1(request):
# show ip ospf route
ip = topo["routers"]["r0"]["links"]["r3"]["ipv4"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv4"].split("/")[0]
input_dict = {
"r1": {"static_routes": [{"network": ip_net, "no_of_ip": 1, "routeType": "N"}]}
diff --git a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
index 46c0da3..3468a65 100644
--- a/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
+++ b/tests/topotests/ospf_gr_helper/test_ospf_gr_helper2.py
@@ -190,8 +190,10 @@ def test_ospf_gr_helper_tc3_p1(request):
ospf_covergence is True
), "OSPF is not after reset config \n Error: {}".format(ospf_covergence)
- step("Configure DR priority 100 on R0 and clear ospf neighbors "
- "on all the routers.")
+ step(
+ "Configure DR priority 100 on R0 and clear ospf neighbors "
+ "on all the routers."
+ )
input_dict = {
"r0": {
diff --git a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
index 9dfe5e1..590b0d5 100644
--- a/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
+++ b/tests/topotests/ospf_instance_redistribute/test_ospf_instance_redistribute.py
@@ -64,16 +64,9 @@ def setup_module(module):
# This is a sample of configuration loading.
r1 = tgen.gears["r1"]
- r1.load_config(
- TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf")
- )
- r1.load_config(
- TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"),
- "-n 3"
- )
- r1.load_config(
- TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf")
- )
+ r1.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "r1/zebra.conf"))
+ r1.load_config(TopoRouter.RD_OSPF, os.path.join(CWD, "r1/ospfd-3.conf"), "-n 3")
+ r1.load_config(TopoRouter.RD_SHARP, os.path.join(CWD, "r1/sharpd.conf"))
tgen.start_router()
@@ -103,13 +96,15 @@ def test_install_sharp_instance_routes():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip route summ json", expected)
+ topotest.router_json_cmp, r1, "show ip route summ json", expected
+ )
logger.info("Ensuring that they exist in the rib/fib")
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" sharp routes are not installed'
assert result is None, assertmsg
+
def test_ospf_instance_redistribute():
tgen = get_topogen()
@@ -124,7 +119,8 @@ def test_ospf_instance_redistribute():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes'
@@ -139,7 +135,8 @@ def test_ospf_instance_redistribute():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" ospf instance 3 does not have the proper redistributed routes'
@@ -161,15 +158,14 @@ def test_ospf_instance_default_information():
expected = json.loads(open(json_file).read())
test_func = partial(
- topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected)
+ topotest.router_json_cmp, r1, "show ip ospf 3 data json", expected
+ )
_, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
assertmsg = '"r1" ospf instance 3 does not properly redistribute the default route'
assert result is None, assertmsg
-
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
-
diff --git a/tests/topotests/ospf_metric_propagation/r1/frr.conf b/tests/topotests/ospf_metric_propagation/r1/frr.conf
index 8523049..4966e6a 100644
--- a/tests/topotests/ospf_metric_propagation/r1/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r1/frr.conf
@@ -8,18 +8,18 @@ interface r1-eth0
ip address 10.0.1.1/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface r1-eth1 vrf blue
ip address 10.0.10.1/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
!
interface r1-eth2 vrf green
ip address 10.0.91.1/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
!
router ospf
diff --git a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-1.json b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-1.json
index 4f1ced8..2392b40 100644
--- a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-1.json
+++ b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-1.json
@@ -2,32 +2,15 @@
"10.0.94.0/24":[
{
"prefix":"10.0.94.0/24",
- "prefixLen":24,
"protocol":"bgp",
"vrfName":"green",
- "selected":true,
- "destSelected":true,
- "distance":20,
"metric":34,
"installed":true,
- "table":12,
- "internalStatus":16,
- "internalFlags":8,
- "internalNextHopNum":1,
- "internalNextHopActiveNum":1,
- "nexthopGroupId":"*",
- "installedNexthopGroupId":"*",
- "uptime":"*",
"nexthops":[
{
- "flags":3,
- "fib":true,
"ip":"10.0.10.5",
- "afi":"ipv4",
"interfaceName":"r1-eth1",
- "vrf":"blue",
- "active":true,
- "weight":1
+ "vrf":"blue"
}
]
}
diff --git a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-2.json b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-2.json
index 882d3ca..9a3d3d8 100644
--- a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-2.json
+++ b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-2.json
@@ -2,32 +2,15 @@
"10.0.94.0/24":[
{
"prefix":"10.0.94.0/24",
- "prefixLen":24,
"protocol":"bgp",
"vrfName":"green",
- "selected":true,
- "destSelected":true,
- "distance":20,
"metric":136,
"installed":true,
- "table":12,
- "internalStatus":16,
- "internalFlags":8,
- "internalNextHopNum":1,
- "internalNextHopActiveNum":1,
- "nexthopGroupId":"*",
- "installedNexthopGroupId":"*",
- "uptime":"*",
"nexthops":[
{
- "flags":3,
- "fib":true,
"ip":"10.0.1.2",
- "afi":"ipv4",
"interfaceName":"r1-eth0",
- "vrf":"default",
- "active":true,
- "weight":1
+ "vrf":"default"
}
]
}
diff --git a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-3.json b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-3.json
index cd52845..5f0331f 100644
--- a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-3.json
+++ b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-3.json
@@ -2,32 +2,15 @@
"10.0.94.0/24":[
{
"prefix":"10.0.94.0/24",
- "prefixLen":24,
"protocol":"bgp",
"vrfName":"green",
- "selected":true,
- "destSelected":true,
- "distance":20,
"metric":1138,
"installed":true,
- "table":12,
- "internalStatus":16,
- "internalFlags":8,
- "internalNextHopNum":1,
- "internalNextHopActiveNum":1,
- "nexthopGroupId":"*",
- "installedNexthopGroupId":"*",
- "uptime":"*",
"nexthops":[
{
- "flags":3,
- "fib":true,
"ip":"10.0.1.2",
- "afi":"ipv4",
"interfaceName":"r1-eth0",
- "vrf":"default",
- "active":true,
- "weight":1
+ "vrf":"default"
}
]
}
diff --git a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-4.json b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-4.json
index 133f375..f312291 100644
--- a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-4.json
+++ b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-4.json
@@ -2,32 +2,15 @@
"10.0.94.0/24":[
{
"prefix":"10.0.94.0/24",
- "prefixLen":24,
"protocol":"bgp",
"vrfName":"green",
- "selected":true,
- "destSelected":true,
- "distance":20,
"metric":1218,
"installed":true,
- "table":12,
- "internalStatus":16,
- "internalFlags":8,
- "internalNextHopNum":1,
- "internalNextHopActiveNum":1,
- "nexthopGroupId":"*",
- "installedNexthopGroupId":"*",
- "uptime":"*",
"nexthops":[
{
- "flags":3,
- "fib":true,
"ip":"10.0.1.2",
- "afi":"ipv4",
"interfaceName":"r1-eth0",
- "vrf":"default",
- "active":true,
- "weight":1
+ "vrf":"default"
}
]
}
diff --git a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-5.json b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-5.json
index 5d80509..e88c037 100644
--- a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-5.json
+++ b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-5.json
@@ -2,32 +2,15 @@
"10.0.94.0/24":[
{
"prefix":"10.0.94.0/24",
- "prefixLen":24,
"protocol":"bgp",
"vrfName":"green",
- "selected":true,
- "destSelected":true,
- "distance":20,
"metric":238,
"installed":true,
- "table":12,
- "internalStatus":16,
- "internalFlags":8,
- "internalNextHopNum":1,
- "internalNextHopActiveNum":1,
- "nexthopGroupId":"*",
- "installedNexthopGroupId":"*",
- "uptime":"*",
"nexthops":[
{
- "flags":3,
- "fib":true,
"ip":"10.0.1.2",
- "afi":"ipv4",
"interfaceName":"r1-eth0",
- "vrf":"default",
- "active":true,
- "weight":1
+ "vrf":"default"
}
]
}
diff --git a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-6.json b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-6.json
index 1b59707..f1fec86 100644
--- a/tests/topotests/ospf_metric_propagation/r1/show_ip_route-6.json
+++ b/tests/topotests/ospf_metric_propagation/r1/show_ip_route-6.json
@@ -2,32 +2,15 @@
"10.0.94.0/24":[
{
"prefix":"10.0.94.0/24",
- "prefixLen":24,
"protocol":"bgp",
"vrfName":"green",
- "selected":true,
- "destSelected":true,
- "distance":20,
"metric":136,
"installed":true,
- "table":12,
- "internalStatus":16,
- "internalFlags":8,
- "internalNextHopNum":1,
- "internalNextHopActiveNum":1,
- "nexthopGroupId":"*",
- "installedNexthopGroupId":"*",
- "uptime":"*",
"nexthops":[
{
- "flags":3,
- "fib":true,
"ip":"10.0.10.5",
- "afi":"ipv4",
"interfaceName":"r1-eth1",
- "vrf":"blue",
- "active":true,
- "weight":1
+ "vrf":"blue"
}
]
}
diff --git a/tests/topotests/ospf_metric_propagation/r2/frr.conf b/tests/topotests/ospf_metric_propagation/r2/frr.conf
index e67a374..0ac5001 100644
--- a/tests/topotests/ospf_metric_propagation/r2/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r2/frr.conf
@@ -8,18 +8,18 @@ interface r2-eth0
ip address 10.0.1.2/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface r2-eth1 vrf blue
ip address 10.0.20.2/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface r2-eth2 vrf green
ip address 10.0.70.2/24
ip ospf cost 1000
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
router ospf
ospf router-id 10.0.255.2
diff --git a/tests/topotests/ospf_metric_propagation/r3/frr.conf b/tests/topotests/ospf_metric_propagation/r3/frr.conf
index 175851d..0859173 100644
--- a/tests/topotests/ospf_metric_propagation/r3/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r3/frr.conf
@@ -8,18 +8,18 @@ interface r3-eth0
ip address 10.0.3.3/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface r3-eth1 vrf blue
ip address 10.0.30.3/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface r3-eth2 vrf green
ip address 10.0.80.3/24
ip ospf cost 1000
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
router ospf
ospf router-id 10.0.255.3
diff --git a/tests/topotests/ospf_metric_propagation/r4/frr.conf b/tests/topotests/ospf_metric_propagation/r4/frr.conf
index 70a47e3..743da27 100644
--- a/tests/topotests/ospf_metric_propagation/r4/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/r4/frr.conf
@@ -8,17 +8,17 @@ interface r4-eth0
ip address 10.0.3.4/24
ip ospf cost 100
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface r4-eth1 vrf blue
ip address 10.0.40.4/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface r4-eth2 vrf green
ip address 10.0.94.4/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
router ospf
ospf router-id 10.0.255.4
diff --git a/tests/topotests/ospf_metric_propagation/ra/frr.conf b/tests/topotests/ospf_metric_propagation/ra/frr.conf
index 7be9e5c..2434fae 100644
--- a/tests/topotests/ospf_metric_propagation/ra/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/ra/frr.conf
@@ -7,17 +7,17 @@ ip forwarding
interface ra-eth0
ip address 10.0.50.5/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface ra-eth1
ip address 10.0.10.5/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface ra-eth2
ip address 10.0.20.5/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
router ospf
ospf router-id 10.0.255.5
diff --git a/tests/topotests/ospf_metric_propagation/rb/frr.conf b/tests/topotests/ospf_metric_propagation/rb/frr.conf
index a7dbf82..b83532a 100644
--- a/tests/topotests/ospf_metric_propagation/rb/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/rb/frr.conf
@@ -7,17 +7,17 @@ ip forwarding
interface rb-eth0
ip address 10.0.50.6/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface rb-eth1
ip address 10.0.30.6/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface rb-eth2
ip address 10.0.40.6/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
router ospf
ospf router-id 10.0.255.6
diff --git a/tests/topotests/ospf_metric_propagation/rc/frr.conf b/tests/topotests/ospf_metric_propagation/rc/frr.conf
index f5a2ed7..dd8077c 100644
--- a/tests/topotests/ospf_metric_propagation/rc/frr.conf
+++ b/tests/topotests/ospf_metric_propagation/rc/frr.conf
@@ -7,12 +7,12 @@ ip forwarding
interface rc-eth0
ip address 10.0.70.7/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
interface rc-eth1
ip address 10.0.80.7/24
ip ospf hello-interval 1
- ip ospf dead-interval 30
+ ip ospf dead-interval 40
!
router ospf
ospf router-id 10.0.255.7
diff --git a/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py b/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py
index 085eb1f..ea96265 100644
--- a/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py
+++ b/tests/topotests/ospf_metric_propagation/test_ospf_metric_propagation.py
@@ -283,7 +283,7 @@ def test_link_1_2_3_4_down():
assert result is None, assertmsg
-def test_link_1_2_4_down():
+def test_link_1_2_4_down_3_up():
"Test path R1 -> R2 -> Rc -> R3 -> R4"
tgen = get_topogen()
@@ -305,7 +305,7 @@ def test_link_1_2_4_down():
assert result is None, assertmsg
-def test_link_1_4_down():
+def test_link_1_4_down_2_up():
"Test path R1 -> R2 -> Ra -> Rb -> R3 -> R4"
tgen = get_topogen()
@@ -321,13 +321,13 @@ def test_link_1_4_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=120, wait=2)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
-def test_link_4_down():
+def test_link_4_down_1_up():
"Test path R1 -> Ra -> Rb -> R3 -> R4"
tgen = get_topogen()
@@ -343,7 +343,7 @@ def test_link_4_down():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=120, wait=2)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
@@ -365,7 +365,7 @@ def test_link_1_2_3_4_up():
test_func = partial(
topotest.router_json_cmp, r1, "show ip route vrf green 10.0.94.2 json", expected
)
- _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ _, result = topotest.run_and_expect(test_func, None, count=120, wait=2)
assertmsg = "r1 JSON output mismatches"
assert result is None, assertmsg
diff --git a/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py b/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py
index 792304e..ee0a0f6 100644
--- a/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py
+++ b/tests/topotests/ospf_multi_vrf_bgp_route_leak/test_ospf_multi_vrf_bgp_route_leak.py
@@ -182,9 +182,7 @@ def test_ospf_convergence():
"show ip ospf vrf {} route".format(vrf),
expected,
)
- result, diff = topotest.run_and_expect(
- test_func, "", count=80, wait=1
- )
+ result, diff = topotest.run_and_expect(test_func, "", count=80, wait=1)
assertmsg = "OSPF did not converge on {}:\n{}".format(rname, diff)
assert result, assertmsg
@@ -207,9 +205,7 @@ def test_ospf_kernel_route():
test_func = partial(
compare_show_ip_route_vrf, router.name, expected, vrf
)
- result, diff = topotest.run_and_expect(
- test_func, "", count=80, wait=1
- )
+ result, diff = topotest.run_and_expect(test_func, "", count=80, wait=1)
assertmsg = 'OSPF IPv4 route mismatch in router "{}": {}'.format(
router.name, diff
)
diff --git a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
index 432ddf0..d8cd132 100644
--- a/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
+++ b/tests/topotests/ospf_nssa_topo1/test_ospf_nssa_topo1.py
@@ -199,9 +199,7 @@ def test_rib_step3():
pytest.skip(tgen.errors)
logger.info("Removing NSSA default on rt4")
- tgen.net["rt3"].cmd(
- 'vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"'
- )
+ tgen.net["rt3"].cmd('vtysh -c "conf t" -c "router ospf" -c "area 1 nssa"')
for rname in ["rt1", "rt2", "rt3", "rt4"]:
router_compare_json_output(
diff --git a/tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000..ca84349
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r1/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,26 @@
+!
+hostname r1
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r1-eth0
+ ip address 10.1.0.1/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r1-eth1
+ ip address 10.1.1.1/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+router ospf
+ ospf router-id 1.1.1.1
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.1.0/24 area 0
+ neighbor 10.1.0.2 poll-interval 5
+ neighbor 10.1.0.3 poll-interval 5
+ neighbor 10.1.0.4 poll-interval 5
+!
diff --git a/tests/topotests/ospf_p2mp/r1/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r1/frr-p2mp.conf
new file mode 100644
index 0000000..cb4538c
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r1/frr-p2mp.conf
@@ -0,0 +1,23 @@
+!
+hostname r1
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r1-eth0
+ ip address 10.1.0.1/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r1-eth1
+ ip address 10.1.1.1/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+router ospf
+ ospf router-id 1.1.1.1
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.1.0/24 area 0
+!
diff --git a/tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000..6e26897
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r2/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,29 @@
+!
+hostname r2
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r2-eth0
+ ip address 10.1.0.2/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r2-eth1
+ ip address 10.1.2.2/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+!
+!
+router ospf
+ ospf router-id 2.2.2.2
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.2.0/24 area 0
+ neighbor 10.1.0.1 poll-interval 5
+ neighbor 10.1.0.3 poll-interval 5
+ neighbor 10.1.0.4 poll-interval 5
+!
diff --git a/tests/topotests/ospf_p2mp/r2/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r2/frr-p2mp.conf
new file mode 100644
index 0000000..0ca8aec
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r2/frr-p2mp.conf
@@ -0,0 +1,26 @@
+!
+hostname r2
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r2-eth0
+ ip address 10.1.0.2/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+interface r2-eth1
+ ip address 10.1.2.2/24
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+!
+!
+router ospf
+ ospf router-id 2.2.2.2
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.2.0/24 area 0
+!
diff --git a/tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000..a69e055
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r3/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,28 @@
+!
+hostname r3
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r3-eth0
+ ip address 10.1.0.3/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r3-eth1
+ ip address 10.1.3.3/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 3.3.3.3
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.3.0/24 area 0
+ neighbor 10.1.0.1 poll-interval 5
+ neighbor 10.1.0.2 poll-interval 5
+ neighbor 10.1.0.4 poll-interval 5
diff --git a/tests/topotests/ospf_p2mp/r3/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r3/frr-p2mp.conf
new file mode 100644
index 0000000..41ea70d
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r3/frr-p2mp.conf
@@ -0,0 +1,25 @@
+!
+hostname r3
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r3-eth0
+ ip address 10.1.0.3/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r3-eth1
+ ip address 10.1.3.3/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 3.3.3.3
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.3.0/24 area 0
diff --git a/tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf b/tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf
new file mode 100644
index 0000000..1b83885
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r4/frr-p2mp-non-broadcast.conf
@@ -0,0 +1,28 @@
+!
+hostname r4
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r4-eth0
+ ip address 10.1.0.4/24
+ ip ospf network point-to-multipoint non-broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r4-eth1
+ ip address 10.1.4.4/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 4.4.4.4
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.4.0/24 area 0
+ neighbor 10.1.0.1 poll-interval 5
+ neighbor 10.1.0.2 poll-interval 5
+ neighbor 10.1.0.3 poll-interval 5
diff --git a/tests/topotests/ospf_p2mp/r4/frr-p2mp.conf b/tests/topotests/ospf_p2mp/r4/frr-p2mp.conf
new file mode 100644
index 0000000..21fa9c7
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/r4/frr-p2mp.conf
@@ -0,0 +1,25 @@
+!
+hostname r4
+password zebra
+log file /tmp/r1-frr.log
+ip forwarding
+!
+interface r4-eth0
+ ip address 10.1.0.4/24
+ ip ospf network point-to-multipoint
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+interface r4-eth1
+ ip address 10.1.4.4/24
+ ip ospf network broadcast
+ ip ospf hello-interval 1
+ ip ospf dead-interval 30
+!
+!
+router ospf
+ ospf router-id 4.4.4.4
+ distance 20
+ network 10.1.0.0/24 area 0
+ network 10.1.4.0/24 area 0
diff --git a/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py b/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py
new file mode 100644
index 0000000..1f0f879
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/test_ospf_p2mp_broadcast.py
@@ -0,0 +1,472 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+#
+# test_ospf_prefix_p2mp_broadcast.py
+#
+# Copyright (c) 2024 LabN Consulting
+# Acee Lindem
+#
+
+import os
+import sys
+import json
+from time import sleep
+from functools import partial
+import pytest
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from lib.common_config import (
+ run_frr_cmd,
+ shutdown_bringup_interface,
+ start_router_daemons,
+ step,
+)
+
+
+"""
+test_ospf_p2mp_broadcast.py: Test OSPF Point-to-multipoint
+"""
+
+TOPOLOGY = """
+ +-----+ +-----+
+10.1.1.0/24 | r1 | | r2 | 10.1.2.0/24
+ -----------+ | | +----------
+ +--+--+ +--+--+
+ | 10.1.0.0/24 |
+ | +-------+ |
+ +---- | |-----+
+ | P2MP |
+ +---- | |-----+
+ | +-------+ |
+ | |
+ | |
+ +--+--+ +-+---+
+10.1.3.0/24 | r3 | | r4 | 10.1.4.0/24
+ -----------+ | | +----------
+ +-----+ +-----+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.ospfd, pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 4 routers
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+ tgen.add_router("r3")
+ tgen.add_router("r4")
+
+ # Interconect them all to the P2MP network
+ switch = tgen.add_switch("s0-p2mp")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+ # Add standalone network to router 1
+ switch = tgen.add_switch("s-r1-1")
+ switch.add_link(tgen.gears["r1"])
+
+ # Add standalone network to router 2
+ switch = tgen.add_switch("s-r2-1")
+ switch.add_link(tgen.gears["r2"])
+
+ # Add standalone network to router 3
+ switch = tgen.add_switch("s-r3-1")
+ switch.add_link(tgen.gears["r3"])
+
+ # Add standalone network to router 4
+ switch = tgen.add_switch("s-r4-1")
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ logger.info("OSPF Point-to-MultiPoint:\n {}".format(TOPOLOGY))
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+
+ for rname, router in router_list.items():
+ logger.info("Loading router %s" % rname)
+ router.load_frr_config(os.path.join(CWD, "{}/frr-p2mp.conf".format(rname)))
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, nbr_filter):
+ "Verify the P2MP Configuration and interface settings"
+
+ topo_router = tgen.gears[router]
+
+ step("Test running configuration for P2MP configuration")
+ rc = 0
+ rc, _, _ = tgen.net[router].cmd_status(
+ "show running ospfd | grep 'ip ospf network point-to-multipoint'", warn=False
+ )
+ assertmsg = (
+ "'ip ospf network point-to-multipoint' applied, but not present in "
+ + router
+ + "configuration"
+ )
+ assert rc, assertmsg
+
+ step("Test OSPF interface for P2MP settings")
+ input_dict = {
+ "interfaces": {
+ "r1-eth0": {
+ "ospfEnabled": True,
+ "interfaceIp": {
+ "10.1.0.1": {
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "nbrFilterPrefixList": nbr_filter,
+ }
+ },
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "area": "0.0.0.0",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "opaqueCapable": True,
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "nbrFilterPrefixList": nbr_filter,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf interface r1-eth0 json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Interface Mismatch on router r1"
+ assert result is None, assertmsg
+
+
+def verify_non_p2mp_interface(tgen):
+ "Verify the removal of P2MP Configuration and interface settings"
+ r1 = tgen.gears["r1"]
+
+ step("Test running configuration for removal of P2MP configuration")
+ rc = 0
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf network point-to-multipoint'", warn=False
+ )
+ assertmsg = "'ip ospf network point-to-multipoint' not applied, but present in r1 configuration"
+ assert rc, assertmsg
+
+ step("Test OSPF interface for default settings")
+ input_dict = {
+ "interfaces": {
+ "r1-eth0": {
+ "ospfEnabled": True,
+ "interfaceIp": {
+ "10.1.0.1": {
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "routerId": "1.1.1.1",
+ "networkType": "BROADCAST",
+ "cost": 10,
+ "prefixSuppression": False,
+ }
+ },
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "area": "0.0.0.0",
+ "routerId": "1.1.1.1",
+ "networkType": "BROADCAST",
+ "cost": 10,
+ "opaqueCapable": True,
+ "prefixSuppression": False,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf interface r1-eth0 json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Interface Mismatch on router r1"
+ assert result is None, assertmsg
+
+
+def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify neighbor " + neighbor + " in " + state + " state")
+ input_dict = {
+ "default": {
+ neighbor: [
+ {
+ "nbrState": state,
+ "ifaceAddress": intf_addr,
+ "ifaceName": interface,
+ }
+ ],
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf neighbor " + neighbor + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Neighbor " + neighbor + " not in " + state
+ assert result is None, assertmsg
+
+
+def verify_p2mp_neighbor_missing(tgen, router, neighbor):
+ topo_router = tgen.gears[router]
+
+ step("Verify neighbor " + neighbor + " missing")
+ input_dict = {"default": {}}
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf neighbor " + neighbor + " json",
+ input_dict,
+ True, # Require exact match for missing neighbor
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Neighbor " + neighbor + " not missing"
+ assert result is None, assertmsg
+
+
+def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify router " + router + " p2mp route " + prefix + " installed")
+ input_dict = {
+ prefix: [
+ {
+ "prefix": prefix,
+ "prefixLen": prefix_len,
+ "protocol": "ospf",
+ "nexthops": [
+ {
+ "ip": nexthop,
+ "interfaceName": interface,
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip route " + prefix + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = prefix + " not installed on router " + router
+ assert result is None, assertmsg
+
+
+def test_p2mp_broadcast_interface():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Verify router r1 p2mp interface r1-eth0 neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 p2mp routes installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration removal")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf network point-to-multipoint")
+ verify_non_p2mp_interface(tgen)
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration application")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Verify restablishment of r1-eth0 p2mp neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 p2mp routes reinstalled")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+
+def test_p2mp_broadcast_neighbor_filter():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ step("Verify router r1 interface r1-eth0 p2mp configuration")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Verify router r1 p2mp interface r1-eth0 neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Add OSPF interface neighbor-filter to r1")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
+
+ step("Verify the R1 configuration of 'ip ospf neighbor-filter nbr-filter'")
+ neighbor_filter_cfg = (
+ tgen.net["r1"]
+ .cmd(
+ 'vtysh -c "show running ospfd" | grep "^ ip ospf neighbor-filter nbr-filter"'
+ )
+ .rstrip()
+ )
+ assertmsg = (
+ "'ip ospf neighbor-filter nbr-filter' applied, but not present in configuration"
+ )
+ assert neighbor_filter_cfg == " ip ospf neighbor-filter nbr-filter", assertmsg
+
+ step("Verify non-existent neighbor-filter is not applied to r1 interfaces")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Add nbr-filter prefix-list configuration to r1")
+ r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 200 permit any")
+
+ step(
+ "Verify neighbor-filter is now applied to r1 interface and neighbors still adjacent"
+ )
+ verify_p2mp_interface(tgen, "r1", 3, 3, "nbr-filter")
+
+ step("Add nbr-filter prefix-list configuration to block r4")
+ r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 10 deny 10.1.0.4/32")
+
+ step(
+ "Verify neighbor-filter is now applied to r1 interface and r4 is no longer adjacent"
+ )
+ verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
+ verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
+
+ step("Verify route to r4 subnet is now through r2")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.2", "r1-eth0")
+
+ step("Add nbr-filter prefix-list configuration to block r2")
+ r1.vtysh_cmd("conf t\nip prefix-list nbr-filter seq 20 deny 10.1.0.2/32")
+
+ step(
+ "Verify neighbor-filter is now applied to r1 interface and r2 is no longer adjacent"
+ )
+ verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
+ verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
+
+ step("Verify route to r4 and r2 subnet are now through r3")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.3", "r1-eth0")
+
+ step("Remove neighbor filter configuration and verify")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno ip ospf neighbor-filter")
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf neighbor-filter'", warn=False
+ )
+ assertmsg = "'ip ospf neighbor' not applied, but present in R1 configuration"
+ assert rc, assertmsg
+
+ step("Verify interface neighbor-filter is removed and neighbors present")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+ step("Add neighbor filter configuration and verify neighbors are filtered")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf neighbor-filter nbr-filter")
+ verify_p2mp_interface(tgen, "r1", 1, 1, "nbr-filter")
+ verify_p2mp_neighbor_missing(tgen, "r1", "2.2.2.2")
+ verify_p2mp_neighbor_missing(tgen, "r1", "4.4.4.4")
+
+ step("Remove nbr-filter prefix-list configuration to block r2 and verify neighbor")
+ r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter seq 20")
+ verify_p2mp_interface(tgen, "r1", 2, 2, "nbr-filter")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+
+ step("Delete nbr-filter prefix-list and verify neighbors are present")
+ r1.vtysh_cmd("conf t\nno ip prefix-list nbr-filter")
+ verify_p2mp_interface(tgen, "r1", 3, 3, "N/A")
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py b/tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py
new file mode 100644
index 0000000..175dca7
--- /dev/null
+++ b/tests/topotests/ospf_p2mp/test_ospf_p2mp_non_broadcast.py
@@ -0,0 +1,467 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# test_ospf_prefix_p2mp_non_broadcast.py
+#
+# Copyright (c) 2024 LabN Consulting
+# Acee Lindem
+#
+
+import os
+import sys
+import json
+from time import sleep
+from functools import partial
+import pytest
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from lib.common_config import (
+ run_frr_cmd,
+ shutdown_bringup_interface,
+ start_router_daemons,
+ step,
+)
+
+
+"""
+test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
+ Full Mesh
+"""
+
+TOPOLOGY = """
+ +-----+ +-----+
+10.1.1.0/24 | r1 | | r2 | 10.1.2.0/24
+ -----------+ | | +----------
+ +--+--+ +--+--+
+ | 10.1.0.0/24 |
+ | +-------+ |
+ +---- | |-----+
+ | P2MP |
+ +---- | |-----+
+ | +-------+ |
+ | |
+ | |
+ +--+--+ +-+---+
+10.1.3.0/24 | r3 | | r4 | 10.1.4.0/24
+ -----------+ | | +----------
+ +-----+ +-----+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# Required to instantiate the topology builder class.
+
+pytestmark = [pytest.mark.ospfd, pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 4 routers
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+ tgen.add_router("r3")
+ tgen.add_router("r4")
+
+ # Interconect them all to the P2MP network
+ switch = tgen.add_switch("s0-p2mp")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+ # Add standalone network to router 1
+ switch = tgen.add_switch("s-r1-1")
+ switch.add_link(tgen.gears["r1"])
+
+ # Add standalone network to router 2
+ switch = tgen.add_switch("s-r2-1")
+ switch.add_link(tgen.gears["r2"])
+
+ # Add standalone network to router 3
+ switch = tgen.add_switch("s-r3-1")
+ switch.add_link(tgen.gears["r3"])
+
+ # Add standalone network to router 4
+ switch = tgen.add_switch("s-r4-1")
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+
+ for rname, router in router_list.items():
+ logger.info("Loading router %s" % rname)
+ router.load_frr_config(
+ os.path.join(CWD, "{}/frr-p2mp-non-broadcast.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def verify_p2mp_interface(tgen, router, nbr_cnt, nbr_adj_cnt, non_broadcast):
+ "Verify the P2MP Configuration and interface settings"
+
+ topo_router = tgen.gears[router]
+
+ step("Test running configuration for P2MP configuration")
+ rc = 0
+ rc, _, _ = tgen.net[router].cmd_status(
+ "show running ospfd | grep 'ip ospf network point-to-multipoint'", warn=False
+ )
+ assertmsg = (
+ "'ip ospf network point-to-multipoint' applied, but not present in "
+ + router
+ + "configuration"
+ )
+ assert rc, assertmsg
+
+ step("Test OSPF interface for P2MP settings")
+ input_dict = {
+ "interfaces": {
+ "r1-eth0": {
+ "ospfEnabled": True,
+ "interfaceIp": {
+ "10.1.0.1": {
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "p2mpNonBroadcast": non_broadcast,
+ }
+ },
+ "ipAddress": "10.1.0.1",
+ "ipAddressPrefixlen": 24,
+ "ospfIfType": "Broadcast",
+ "area": "0.0.0.0",
+ "routerId": "1.1.1.1",
+ "networkType": "POINTOMULTIPOINT",
+ "cost": 10,
+ "state": "Point-To-Point",
+ "opaqueCapable": True,
+ "nbrCount": nbr_cnt,
+ "nbrAdjacentCount": nbr_adj_cnt,
+ "prefixSuppression": False,
+ "p2mpDelayReflood": False,
+ "p2mpNonBroadcast": non_broadcast,
+ }
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf interface r1-eth0 json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Interface Mismatch on router r1"
+ assert result is None, assertmsg
+
+
+def verify_p2mp_neighbor(tgen, router, neighbor, state, intf_addr, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify neighbor " + neighbor + " in " + state + " state")
+ input_dict = {
+ "default": {
+ neighbor: [
+ {
+ "nbrState": state,
+ "ifaceAddress": intf_addr,
+ "ifaceName": interface,
+ }
+ ],
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip ospf neighbor " + neighbor + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Neighbor " + neighbor + " not in " + state
+ assert result is None, assertmsg
+
+
+def verify_p2mp_route(tgen, router, prefix, prefix_len, nexthop, interface):
+ topo_router = tgen.gears[router]
+
+ step("Verify router " + router + " p2mp route " + prefix + " installed")
+ input_dict = {
+ prefix: [
+ {
+ "prefix": prefix,
+ "prefixLen": prefix_len,
+ "protocol": "ospf",
+ "nexthops": [
+ {
+ "ip": nexthop,
+ "interfaceName": interface,
+ }
+ ],
+ }
+ ]
+ }
+ test_func = partial(
+ topotest.router_json_cmp,
+ topo_router,
+ "show ip route " + prefix + " json",
+ input_dict,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = prefix + " not installed on router " + router
+ assert result is None, assertmsg
+
+
+def test_p2mp_non_broadcast_connectivity():
+ tgen = get_topogen()
+ r1 = tgen.gears["r1"]
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 3, 3, True)
+
+ step("Verify router r1 interface r1-eth0 p2mp non-broadcast configuration")
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf network point-to-multipoint non-broadcast'",
+ warn=False,
+ )
+ assertmsg = "'ip ospf network point-to-multipoint non-broadcast' applied, but not present in R1 configuration"
+ assert rc, assertmsg
+
+ step("Verify router r1 OSPF point-to-multipoint neighbors")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 OSPF point-to-multipoint routes are installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.3", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+ step("Remove r1 interface r1-eth0 p2mp non-broadcast configuration")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nip ospf network point-to-multipoint")
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep -q 'ip ospf network point-to-multipoint non-broadcast'",
+ warn=False,
+ )
+ assertmsg = "'ip ospf network point-to-multipoint non-broadcast' not applied, but present in r1 configuration"
+ assert rc, assertmsg
+
+ step("Verify router r1 interface OSPF point-to-multipoint broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 3, 3, False)
+
+ step("Add r1 interface r1-eth0 p2mp non-broadcast configuration back")
+ r1.vtysh_cmd(
+ "conf t\ninterface r1-eth0\nip ospf network point-to-multipoint non-broadcast"
+ )
+ rc, _, _ = tgen.net["r1"].cmd_status(
+ "show running ospfd | grep 'ip ospf network point-to-multipoint non-broadcast'",
+ warn=False,
+ )
+ assertmsg = "'ip ospf netrwork point-to-multipoint non-broadcast' applied, but not present in R1 configuration"
+ assert rc, assertmsg
+
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 3, 3, True)
+
+ step(
+ "Verify router r1 OSPF point-to-multipoint neighbors adjacencies restablished."
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "3.3.3.3", "Full/DROther", "10.1.0.3", "r1-eth0:10.1.0.1"
+ )
+ verify_p2mp_neighbor(
+ tgen, "r1", "4.4.4.4", "Full/DROther", "10.1.0.4", "r1-eth0:10.1.0.1"
+ )
+
+
+def test_p2mp_non_broadcast_partial_mesh_connectivity():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ """
+ test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
+ Partial Mesh
+ """
+
+ TOPOLOGY = """
+ +-----+ +------+
+ 10.1.1.0/24 | r1 | | r4 | 10.1.4.0/24
+ -----------+ | | +----------
+ +-+---+ +--+-+-+
+ | P2MP |
+ | Non-Broadcast |
+ | 10.1.0.0/24 |
+ +-+---+ +-+---+
+ 10.1.2.0/24 | r2 | | r3 | 10.1.3.0/24
+ -----------+ +--------------+ +----------
+ +-----+ +-----+
+
+
+ """
+ logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
+
+ step("Change configuration to a partial mesh")
+ step("Delete neighbors in full mesh")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.3")
+ r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.4")
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.4")
+ r3 = tgen.gears["r3"]
+ r3.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
+ r4 = tgen.gears["r4"]
+ r4.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
+ r4.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.2")
+
+ step("Flap interfaces on P2MP network to avoid transients")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nshut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nshut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nshut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nshut")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno shut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nno shut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nno shut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nno shut")
+
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 1, 1, True)
+
+ step("Verify router r1 interface r1-eth0 p2mp neighbor")
+ verify_p2mp_neighbor(
+ tgen, "r1", "2.2.2.2", "Full/DROther", "10.1.0.2", "r1-eth0:10.1.0.1"
+ )
+
+ step("Verify router r1 p2mp routes are installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.2", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.2", "r1-eth0")
+
+ """
+ test_ospf_p2mp_non_broadcast.py: Test OSPF Point-to-multipoint Non-Broadcast
+ Modified Partial Mesh
+ """
+
+ TOPOLOGY = """
+ +-----+ +------+
+ 10.1.1.0/24 | r1 | | r4 | 10.1.4.0/24
+ -----------+ +-------------+ +----------
+ +-----+ +--+-+-+
+ P2MP |
+ Non-Broadcast |
+ 10.1.0.0/24 |
+ +-+---+ +-+---+
+ 10.1.2.0/24 | r2 | | r3 | 10.1.3.0/24
+ -----------+ +--------------+ +----------
+ +-----+ +-----+
+
+
+ """
+ logger.info("OSPF Point-to-MultiPoint Non-Broadcast:\n {}".format(TOPOLOGY))
+
+ step("Change configuration to a partial mesh")
+ step("Modify neighbors in partial mesh")
+ r1 = tgen.gears["r1"]
+ r1.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.2")
+ r1.vtysh_cmd("conf t\nrouter ospf\nneighbor 10.1.0.4 poll-interval 5")
+ r2 = tgen.gears["r2"]
+ r2.vtysh_cmd("conf t\nrouter ospf\nno neighbor 10.1.0.1")
+ r4 = tgen.gears["r4"]
+ r4.vtysh_cmd("conf t\nrouter ospf\nneighbor 10.1.0.1")
+
+ step("Flap interfaces on P2MP network to avoid transients")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nshut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nshut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nshut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nshut")
+ r1.vtysh_cmd("conf t\ninterface r1-eth0\nno shut")
+ r2.vtysh_cmd("conf t\ninterface r2-eth0\nno shut")
+ r3.vtysh_cmd("conf t\ninterface r3-eth0\nno shut")
+ r4.vtysh_cmd("conf t\ninterface r4-eth0\nno shut")
+
+ step("Verify router r1 interface r1-eth0")
+ step("Verify router r1 interface OSPF point-to-multipoint non-broadcast interface")
+ verify_p2mp_interface(tgen, "r1", 1, 1, True)
+
+ step("Verify router r1 interface r1-eth0 p2mp neighbor")
+ input_dict = {
+ "neighbors": {
+ "4.4.4.4": [
+ {
+ "nbrState": "Full/DROther",
+ "ifaceAddress": "10.1.0.4",
+ "ifaceName": "r1-eth0:10.1.0.1",
+ }
+ ],
+ }
+ }
+ test_func = partial(
+ topotest.router_json_cmp, r1, "show ip ospf neighbor json", input_dict
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assertmsg = "P2MP Non-Broadcast Neighbors not adjacent on router r1"
+ assert result is None, assertmsg
+
+ step("Verify router r1 interface r1-eth0 p2mp routes are installed")
+ verify_p2mp_route(tgen, "r1", "10.1.2.0/24", 24, "10.1.0.4", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.3.0/24", 24, "10.1.0.4", "r1-eth0")
+ verify_p2mp_route(tgen, "r1", "10.1.4.0/24", 24, "10.1.0.4", "r1-eth0")
+
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_single_switch/r1_frr.conf b/tests/topotests/ospf_single_switch/r1_frr.conf
new file mode 100644
index 0000000..8fbb241
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r1_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r1
+ip forwarding
+!
+interface r1-eth0
+ ip address 203.0.113.1/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r1-eth1
+ ip address 10.0.1.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.1
+!
diff --git a/tests/topotests/ospf_single_switch/r2_frr.conf b/tests/topotests/ospf_single_switch/r2_frr.conf
new file mode 100644
index 0000000..ea75ad6
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r2_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r2
+ip forwarding
+!
+interface r2-eth0
+ ip address 203.0.113.2/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r2-eth1
+ ip address 10.0.2.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.2
+!
diff --git a/tests/topotests/ospf_single_switch/r3_frr.conf b/tests/topotests/ospf_single_switch/r3_frr.conf
new file mode 100644
index 0000000..e04e76e
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r3_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r3
+ip forwarding
+!
+interface r3-eth0
+ ip address 203.0.113.3/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r3-eth1
+ ip address 10.0.3.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.3
+!
diff --git a/tests/topotests/ospf_single_switch/r4_frr.conf b/tests/topotests/ospf_single_switch/r4_frr.conf
new file mode 100644
index 0000000..9f01158
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r4_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r4
+ip forwarding
+!
+interface r4-eth0
+ ip address 203.0.113.4/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r4-eth1
+ ip address 10.0.4.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.4
+!
diff --git a/tests/topotests/ospf_single_switch/r5_frr.conf b/tests/topotests/ospf_single_switch/r5_frr.conf
new file mode 100644
index 0000000..c9f3497
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r5_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r5
+ip forwarding
+!
+interface r5-eth0
+ ip address 203.0.113.5/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r5-eth1
+ ip address 10.0.5.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.5
+!
diff --git a/tests/topotests/ospf_single_switch/r6_frr.conf b/tests/topotests/ospf_single_switch/r6_frr.conf
new file mode 100644
index 0000000..ba4b0bd
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r6_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r6
+ip forwarding
+!
+interface r6-eth0
+ ip address 203.0.113.6/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r6-eth1
+ ip address 10.0.6.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.6
+!
diff --git a/tests/topotests/ospf_single_switch/r7_frr.conf b/tests/topotests/ospf_single_switch/r7_frr.conf
new file mode 100644
index 0000000..3b28381
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r7_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r7
+ip forwarding
+!
+interface r7-eth0
+ ip address 203.0.113.7/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r7-eth1
+ ip address 10.0.7.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.7
+!
diff --git a/tests/topotests/ospf_single_switch/r8_frr.conf b/tests/topotests/ospf_single_switch/r8_frr.conf
new file mode 100644
index 0000000..3b1b0e5
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/r8_frr.conf
@@ -0,0 +1,18 @@
+!
+hostname r8
+ip forwarding
+!
+interface r8-eth0
+ ip address 203.0.113.8/24
+ ip ospf network point-to-multipoint
+ ip ospf area 0.0.0.0
+ !ip ospf prefix-suppression
+!
+interface r8-eth1
+ ip address 10.0.8.1/24
+ ip ospf passive
+ ip ospf area 0.0.0.0
+!
+router ospf
+ ospf router-id 10.0.0.8
+!
diff --git a/tests/topotests/ospf_single_switch/test_ospf_single_switch.py b/tests/topotests/ospf_single_switch/test_ospf_single_switch.py
new file mode 100644
index 0000000..e53b5f5
--- /dev/null
+++ b/tests/topotests/ospf_single_switch/test_ospf_single_switch.py
@@ -0,0 +1,199 @@
+#!/usr/bin/env python
+# SPDX-License-Identifier: ISC
+
+#
+# Copyright (c) 2023 by
+# Adriano Marto Reis <adrianomarto@gmail.com>
+#
+
+import os
+import sys
+import json
+import subprocess
+from functools import partial
+import pytest
+
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+
+from lib.common_config import verify_rib
+from lib.ospf import verify_ospf_rib
+from _ast import Try
+
+pytestmark = pytest.mark.ospfd
+
+"""
+A large set of routers are connected to the same switch. Each router shares a
+single network. All shared networks must be reachable from all routers.
+"""
+
+TOPOLOGY = """
+ net1 net2 netN
+ --- --- ---
+ | | OSPF-passive |
+ | | |
+ +---+---+ +---+---+ +---+---+
+ | | | | | |
+ | r1 | | r2 | (...) | rN |
+ | | | | | |
+ +---+---+ +---+---+ +---+---+
+ | | OSPF-active |
+ | | |
+ +----------------+--------------------------------+
+ switch
+
+
+"""
+
+N_ROUTERS = 8
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+
+def build_topo(tgen):
+ "Build the topology"
+
+ # Create a single switch to connect all the routers
+ switch = tgen.add_switch("switch")
+
+ # Create routers
+ for router_id in range(1, N_ROUTERS + 1):
+ router = tgen.add_router(f"r{router_id}")
+ switch.add_link(router)
+
+ # The shared network needs to be connected to something
+ dummy = tgen.add_switch(f"s{router_id}")
+ dummy.add_link(router)
+
+
+def setup_module(mod):
+ logger.info("OSPF single switch:\n {}".format(TOPOLOGY))
+
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ # Starting Routers
+ router_list = tgen.routers()
+
+ for rname, router in router_list.items():
+ logger.info("Loading router %s" % rname)
+ router.load_frr_config(os.path.join(CWD, "{}_frr.conf".format(rname)))
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ "Tear-down the test environment"
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def is_iproute2_json_supported():
+ """
+ Checks if the command 'ip -j route' is supported.
+ """
+ try:
+ output = subprocess.run(
+ ["ip", "-j", "route", "get", "0.0.0.0"], stdout=subprocess.PIPE
+ ).stdout.decode()
+ json.loads(output)
+ return True
+ except json.decoder.JSONDecodeError:
+ return False
+
+
+@pytest.mark.skipif(
+ not is_iproute2_json_supported(), reason="'ip -j route' not supported"
+)
+def test_all_routes_advertised():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip("Skipped because of router(s) failure")
+
+ # networks advertised by each router and the expected next hops
+ networks = {
+ "r1": ("10.0.1.0/24", "203.0.113.1"),
+ "r2": ("10.0.2.0/24", "203.0.113.2"),
+ "r3": ("10.0.3.0/24", "203.0.113.3"),
+ "r4": ("10.0.4.0/24", "203.0.113.4"),
+ "r5": ("10.0.5.0/24", "203.0.113.5"),
+ "r6": ("10.0.6.0/24", "203.0.113.6"),
+ "r7": ("10.0.7.0/24", "203.0.113.7"),
+ "r8": ("10.0.8.0/24", "203.0.113.8"),
+ }
+
+ for router_orig in tgen.routers().keys():
+ for router_dest, network in networks.items():
+ if router_orig != router_dest:
+ input_dict = {
+ router_orig: {
+ "static_routes": [
+ {
+ "network": network[0],
+ }
+ ]
+ }
+ }
+ result = verify_ospf_rib(
+ tgen, router_orig, input_dict, next_hop=network[1]
+ )
+ assert result is True, "Error: {}".format(result)
+ result = verify_rib(
+ tgen, "ipv4", router_orig, input_dict, next_hop=network[1]
+ )
+ assert result is True, "Error: {}".format(result)
+
+ check_route(router_orig, network[0], network[1])
+
+
+def check_route(router_name, network, expected_nexthop):
+ """
+ Checks if the given network is present on the given router and has the
+ expected next hop.
+ """
+ tgen = get_topogen()
+ router = tgen.gears[router_name]
+
+ expected_response = {
+ network: [
+ {
+ "prefix": network,
+ "protocol": "ospf",
+ "nexthops": [
+ {
+ "ip": expected_nexthop,
+ "active": True,
+ },
+ ],
+ },
+ ],
+ }
+
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ f"show ip route {network} json",
+ expected_response,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=1)
+ assert (
+ result is None
+ ), f"{router_name} (ospfd): no route {network} via {expected_nexthop}"
+
+ address = network.split("/")[0]
+ output = router.cmd(f"ip -j route get {address}")
+ logger.info(output)
+ routes = json.loads(output)
+ assert (
+ routes[0]["gateway"] == expected_nexthop
+ ), f"{router_name} (kernel): no route {address} via {expected_nexthop}"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/ospf_suppress_fa/r2/ospfd.conf b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf
index ebc7d25..ecc35f7 100644
--- a/tests/topotests/ospf_suppress_fa/r2/ospfd.conf
+++ b/tests/topotests/ospf_suppress_fa/r2/ospfd.conf
@@ -10,6 +10,7 @@ interface r2-eth1
ip ospf dead-interval 10
!
router ospf
+ ospf router-id 10.0.23.2
network 10.0.12.0/24 area 0
network 10.0.23.0/24 area 1
area 1 nssa
diff --git a/tests/topotests/ospfapi/test_ospf_clientapi.py b/tests/topotests/ospfapi/test_ospf_clientapi.py
index 49dd34d..626a9d3 100644
--- a/tests/topotests/ospfapi/test_ospf_clientapi.py
+++ b/tests/topotests/ospfapi/test_ospf_clientapi.py
@@ -277,9 +277,7 @@ def _test_add_data(tgen, apibin):
"linkStateId": "230.0.0.2",
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
- "opaqueValues": {
- "opaqueData": "00000202"
- }
+ "opaqueValues": {"opaqueData": "00000202"},
},
],
}
@@ -330,8 +328,8 @@ def _test_add_data(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "00010101",
- }
+ "opaqueData": "00010101",
+ },
},
],
}
@@ -381,8 +379,8 @@ def _test_add_data(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "deadbeaf01234567",
- }
+ "opaqueData": "deadbeaf01234567",
+ },
},
]
}
@@ -434,8 +432,8 @@ def _test_add_data(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000002",
"opaqueValues": {
- "opaqueData": "ebadf00d",
- }
+ "opaqueData": "ebadf00d",
+ },
},
]
}
@@ -1664,8 +1662,8 @@ def _test_opaque_link_local_lsa_crash(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "feedaceedeadbeef",
- }
+ "opaqueData": "feedaceedeadbeef",
+ },
},
],
}
@@ -1695,8 +1693,8 @@ def _test_opaque_link_local_lsa_crash(tgen, apibin):
"advertisingRouter": "1.0.0.0",
"lsaSeqNumber": "80000001",
"opaqueValues": {
- "opaqueData": "feedaceecafebeef",
- }
+ "opaqueData": "feedaceecafebeef",
+ },
},
],
}
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
index 58608e2..00c98ac 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_authentication.py
@@ -175,7 +175,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -208,7 +208,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -266,7 +266,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -283,7 +283,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -295,7 +295,7 @@ def test_ospf6_auth_trailer_tc1_md5(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -341,7 +341,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -374,7 +374,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -432,7 +432,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -449,7 +449,7 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -461,7 +461,66 @@ def test_ospf6_auth_trailer_tc2_sha256(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
+ "show ip ospf6 neighbor cmd."
+ )
+
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut)
+ assert ospf6_covergence is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Change the key ID on R2 to not match R1")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "30",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify on R1 that R2 nbr is deleted due to key-id mismatch "
+ "after dead interval expiry"
+ )
+ # wait till the dead timer expiry
+ sleep(6)
+ dut = "r2"
+ ospf6_covergence = verify_ospf6_neighbor(
+ tgen, topo, dut=dut, expected=False, retry_timeout=5
+ )
+ assert ospf6_covergence is not True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, ospf6_covergence
+ )
+
+ step("Correct the key ID on R2 so that it matches R1")
+ r2_ospf6_auth = {
+ "r2": {
+ "links": {
+ "r1": {
+ "ospf6": {
+ "hash-algo": "hmac-sha-256",
+ "key": "ospf6",
+ "key-id": "10",
+ }
+ }
+ }
+ }
+ }
+ result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step(
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -524,7 +583,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -555,7 +614,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -600,7 +659,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -617,7 +676,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -629,7 +688,7 @@ def test_ospf6_auth_trailer_tc3_keychain_md5(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -692,7 +751,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -723,7 +782,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -768,7 +827,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 using"
+ "Verify that the neighbor is FULL between R1 and R2 using"
" show ip ospf6 neighbor cmd."
)
@@ -785,7 +844,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
dut = "r2"
step(
- "Verify that the neighbour is not FULL between R1 and R2 using "
+ "Verify that the neighbor is not FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
ospf6_covergence = verify_ospf6_neighbor(tgen, topo, dut=dut, expected=False)
@@ -797,7 +856,7 @@ def test_ospf6_auth_trailer_tc4_keychain_sha256(request):
shutdown_bringup_interface(tgen, dut, intf, True)
step(
- "Verify that the neighbour is FULL between R1 and R2 using "
+ "Verify that the neighbor is FULL between R1 and R2 using "
"show ip ospf6 neighbor cmd."
)
@@ -843,7 +902,7 @@ def test_ospf6_auth_trailer_tc5_md5_keymissmatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -876,11 +935,11 @@ def test_ospf6_auth_trailer_tc5_md5_keymissmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is not FULL between R1 and R2 "
+ "Verify that the neighbor is not FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
- step("Verify that the neighbour is FULL between R1 and R2.")
+ step("Verify that the neighbor is FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -913,7 +972,7 @@ def test_ospf6_auth_trailer_tc5_md5_keymissmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -959,7 +1018,7 @@ def test_ospf6_auth_trailer_tc6_sha256_mismatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -991,7 +1050,7 @@ def test_ospf6_auth_trailer_tc6_sha256_mismatch(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1024,7 +1083,7 @@ def test_ospf6_auth_trailer_tc6_sha256_mismatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -1095,7 +1154,7 @@ def test_ospf6_auth_trailer_tc7_keychain_md5_missmatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -1125,7 +1184,7 @@ def test_ospf6_auth_trailer_tc7_keychain_md5_missmatch(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1156,7 +1215,7 @@ def test_ospf6_auth_trailer_tc7_keychain_md5_missmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -1227,7 +1286,7 @@ def test_ospf6_auth_trailer_tc8_keychain_sha256_missmatch(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -1257,7 +1316,7 @@ def test_ospf6_auth_trailer_tc8_keychain_sha256_missmatch(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1288,7 +1347,7 @@ def test_ospf6_auth_trailer_tc8_keychain_sha256_missmatch(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
@@ -1335,7 +1394,7 @@ def test_ospf6_auth_trailer_tc9_keychain_not_configured(request):
result = config_ospf6_interface(tgen, topo, r1_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r1"
@@ -1365,7 +1424,7 @@ def test_ospf6_auth_trailer_tc9_keychain_not_configured(request):
result = config_ospf6_interface(tgen, topo, r2_ospf6_auth)
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
- step("Verify that the neighbour is not FULL between R1 and R2.")
+ step("Verify that the neighbor is not FULL between R1 and R2.")
# wait for dead time expiry.
sleep(6)
dut = "r2"
@@ -1396,7 +1455,7 @@ def test_ospf6_auth_trailer_tc10_no_auth_trailer(request):
router2 = tgen.gears["r2"]
step(
- "Verify that the neighbour is FULL between R1 and R2 "
+ "Verify that the neighbor is FULL between R1 and R2 "
"using show ipv6 ospf6 neighbor cmd."
)
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py
index 90548fb..5a6c377 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_nssa2.py
@@ -410,7 +410,7 @@ def test_ospfv3_learning_tc15_p0(request):
step("Verify that Type 3 summary LSA is originated for the same Area 0")
ip = topo["routers"]["r1"]["links"]["r3-link0"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
input_dict = {
"r1": {
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py
index 645dea8..916f655 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_rte_calc.py
@@ -262,7 +262,7 @@ def test_ospfv3_redistribution_tc5_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
llip = get_llip("r0", "r1")
assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip)
@@ -379,7 +379,7 @@ def test_ospfv3_redistribution_tc6_p0(request):
step("verify intra area route is calculated for r0-r3 interface ip in R1")
ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
llip = get_llip("r0", "r1")
assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip)
nh = llip
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
index 7199f16..3bafd27 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
@@ -1124,7 +1124,7 @@ def test_ospfv3_show_p1(request):
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
ip = topo["routers"]["r0"]["links"]["r3"]["ipv6"]
- ip_net = str(ipaddress.ip_interface(u"{}".format(ip)).network)
+ ip_net = str(ipaddress.ip_interface("{}".format(ip)).network)
nh = topo["routers"]["r0"]["links"]["r1"]["ipv6"].split("/")[0]
input_dict = {
"r1": {
diff --git a/tests/topotests/pim_basic/test_pim.py b/tests/topotests/pim_basic/test_pim.py
index 24987e5..85b49aa 100644
--- a/tests/topotests/pim_basic/test_pim.py
+++ b/tests/topotests/pim_basic/test_pim.py
@@ -18,7 +18,7 @@ import pytest
import json
from functools import partial
-pytestmark = pytest.mark.pimd
+pytestmark = [pytest.mark.pimd]
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
@@ -29,9 +29,6 @@ from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-pytestmark = [pytest.mark.pimd]
-
-
def build_topo(tgen):
"Build function"
diff --git a/tests/topotests/pim_igmp_vrf/r1/ospf_blue_route.json b/tests/topotests/pim_igmp_vrf/r1/ospf_blue_route.json
new file mode 100644
index 0000000..c5e89d1
--- /dev/null
+++ b/tests/topotests/pim_igmp_vrf/r1/ospf_blue_route.json
@@ -0,0 +1,54 @@
+{
+ "blue": {
+ "vrfName": "blue",
+ "192.168.0.1/32": {
+ "routeType": "N",
+ "transit": false,
+ "cost": 0,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": " ",
+ "directlyAttachedTo": "blue"
+ }
+ ]
+ },
+ "192.168.0.11/32": {
+ "routeType": "N",
+ "transit": false,
+ "cost": 10,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": "192.168.101.11",
+ "via": "r1-eth1",
+ "advertisedRouter": "192.168.0.11"
+ }
+ ]
+ },
+ "192.168.100.0/24": {
+ "routeType": "N",
+ "transit": false,
+ "cost": 10,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": " ",
+ "directlyAttachedTo": "r1-eth0"
+ }
+ ]
+ },
+ "192.168.101.0/24": {
+ "routeType": "N",
+ "transit": true,
+ "cost": 10,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": " ",
+ "directlyAttachedTo": "r1-eth1"
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/topotests/pim_igmp_vrf/r1/ospf_red_route.json b/tests/topotests/pim_igmp_vrf/r1/ospf_red_route.json
new file mode 100644
index 0000000..2fc340d
--- /dev/null
+++ b/tests/topotests/pim_igmp_vrf/r1/ospf_red_route.json
@@ -0,0 +1,54 @@
+{
+ "red": {
+ "vrfName": "red",
+ "192.168.0.1/32": {
+ "routeType": "N",
+ "transit": false,
+ "cost": 0,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": " ",
+ "directlyAttachedTo": "red"
+ }
+ ]
+ },
+ "192.168.0.12/32": {
+ "routeType": "N",
+ "transit": false,
+ "cost": 10,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": "192.168.101.12",
+ "via": "r1-eth3",
+ "advertisedRouter": "192.168.0.12"
+ }
+ ]
+ },
+ "192.168.100.0/24": {
+ "routeType": "N",
+ "transit": false,
+ "cost": 10,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": " ",
+ "directlyAttachedTo": "r1-eth2"
+ }
+ ]
+ },
+ "192.168.101.0/24": {
+ "routeType": "N",
+ "transit": true,
+ "cost": 10,
+ "area": "0.0.0.0",
+ "nexthops": [
+ {
+ "ip": " ",
+ "directlyAttachedTo": "r1-eth3"
+ }
+ ]
+ }
+ }
+}
diff --git a/tests/topotests/pim_igmp_vrf/r1/ospfd.conf b/tests/topotests/pim_igmp_vrf/r1/ospfd.conf
index 88eb5a8..9b9a261 100644
--- a/tests/topotests/pim_igmp_vrf/r1/ospfd.conf
+++ b/tests/topotests/pim_igmp_vrf/r1/ospfd.conf
@@ -1,6 +1,8 @@
hostname r1
!
! debug ospf event
+! debug ospf nsm
+! debug ospf packet hello
!
!
interface r1-eth1
diff --git a/tests/topotests/pim_igmp_vrf/r1/pimd.conf b/tests/topotests/pim_igmp_vrf/r1/pimd.conf
index 040c3d0..c4ddced 100644
--- a/tests/topotests/pim_igmp_vrf/r1/pimd.conf
+++ b/tests/topotests/pim_igmp_vrf/r1/pimd.conf
@@ -2,6 +2,7 @@ hostname r1
!
! debug igmp events
! debug igmp packets
+! debug mroute detail
! debug pim events
! debug pim packets
! debug pim trace
diff --git a/tests/topotests/pim_igmp_vrf/r11/ospfd.conf b/tests/topotests/pim_igmp_vrf/r11/ospfd.conf
index 86fb66d..e52737c 100644
--- a/tests/topotests/pim_igmp_vrf/r11/ospfd.conf
+++ b/tests/topotests/pim_igmp_vrf/r11/ospfd.conf
@@ -1,6 +1,8 @@
hostname r11
!
! debug ospf event
+! debug ospf nsm
+! debug ospf packet hello
!
interface r11-eth0
ip ospf hello-interval 2
diff --git a/tests/topotests/pim_igmp_vrf/r12/ospfd.conf b/tests/topotests/pim_igmp_vrf/r12/ospfd.conf
index f0dcabe..cd94406 100644
--- a/tests/topotests/pim_igmp_vrf/r12/ospfd.conf
+++ b/tests/topotests/pim_igmp_vrf/r12/ospfd.conf
@@ -1,6 +1,8 @@
hostname r12
!
! debug ospf event
+! debug ospf nsm
+! debug ospf packet hello
!
interface r12-eth0
ip ospf hello-interval 2
diff --git a/tests/topotests/pim_igmp_vrf/test_pim_vrf.py b/tests/topotests/pim_igmp_vrf/test_pim_vrf.py
index ddc4303..01c496d 100755
--- a/tests/topotests/pim_igmp_vrf/test_pim_vrf.py
+++ b/tests/topotests/pim_igmp_vrf/test_pim_vrf.py
@@ -60,7 +60,7 @@ TOPOLOGY = """
+---------+ +------------+ | +---------+
| Host H1 | 192.168.100.0/24 | | .1 | .11 | Host H2 |
| receive |------------------| VRF Blue |---------+--------| PIM RP |
-|IGMP JOIN| .10 .1 | | 192.168.101.0/24 | |
+|IGMP JOIN| .10 .1 | | 192.168.101.0/24 | |
+---------+ | | +---------+
=| = = R1 = = |=
+---------+ | | +---------+
@@ -68,7 +68,7 @@ TOPOLOGY = """
| receive |------------------| VRF Red |---------+--------| PIM RP |
|IGMP JOIN| .20 .1 | | .1 | .12 | |
+---------+ +------------+ | +---------+
- .4 |
+ .4 |
+----------+
| Host H4 |
| Source |
@@ -80,6 +80,7 @@ import functools
import os
import sys
import pytest
+import logging
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
@@ -91,7 +92,7 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
from lib.topotest import iproute2_is_vrf_capable
-from lib.common_config import required_linux_kernel_version
+from lib.common_config import required_linux_kernel_version, retry
from lib.pim import McastTesterHelper
@@ -192,6 +193,17 @@ def setup_module(module):
tgen.start_router()
+ # iproute2 needs to support VRFs for this suite to run.
+ if not iproute2_is_vrf_capable():
+ pytest.skip(
+ "Installed iproute2 version does not support VRFs", allow_module_level=True
+ )
+
+ if os.getenv("MROUTE_VRF_MISSING"):
+ pytest.skip(
+ "Kernel does not support vrf mroute tables.", allow_module_level=True
+ )
+
def teardown_module(module):
tgen = get_topogen()
@@ -202,16 +214,13 @@ def test_ospf_convergence():
"Test for OSPFv2 convergence"
tgen = get_topogen()
- # iproute2 needs to support VRFs for this suite to run.
- if not iproute2_is_vrf_capable():
- pytest.skip("Installed iproute2 version does not support VRFs")
-
# Skip if previous fatal error condition is raised
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
logger.info("Checking OSPFv2 convergence on router r1 for VRF blue")
+ # Check for blue neighbor
router = tgen.gears["r1"]
reffile = os.path.join(CWD, "r1/ospf_blue_neighbor.json")
expected = json.loads(open(reffile).read())
@@ -223,7 +232,22 @@ def test_ospf_convergence():
expected,
)
_, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
- assertmsg = "OSPF router R1 did not converge on VRF blue"
+ assertmsg = "OSPF router R1 did not converge on VRF blue (nbr)"
+ assert res is None, assertmsg
+
+ # Check for blue loopback route
+ router = tgen.gears["r1"]
+ reffile = os.path.join(CWD, "r1/ospf_blue_route.json")
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip ospf vrf blue route json",
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
+ assertmsg = "OSPF router R1 did not converge on VRF blue (route)"
assert res is None, assertmsg
logger.info("Checking OSPFv2 convergence on router r1 for VRF red")
@@ -236,7 +260,22 @@ def test_ospf_convergence():
topotest.router_json_cmp, router, "show ip ospf vrf red neighbor json", expected
)
_, res = topotest.run_and_expect(test_func, None, count=60, wait=2)
- assertmsg = "OSPF router R1 did not converge on VRF red"
+ assertmsg = "OSPF router R1 did not converge on VRF red (nbr)"
+ assert res is None, assertmsg
+
+ # Check for red loopback route
+ router = tgen.gears["r1"]
+ reffile = os.path.join(CWD, "r1/ospf_red_route.json")
+ expected = json.loads(open(reffile).read())
+
+ test_func = functools.partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip ospf vrf red route json",
+ expected,
+ )
+ _, res = topotest.run_and_expect(test_func, None, count=30, wait=2)
+ assertmsg = "OSPF router R1 did not converge on VRF red (route)"
assert res is None, assertmsg
@@ -275,10 +314,13 @@ def test_pim_convergence():
assert res is None, assertmsg
-def test_vrf_pimreg_interfaces():
+def _test_vrf_pimreg_interfaces():
"Adding PIM RP in VRF information and verify pimreg interfaces"
tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
r1 = tgen.gears["r1"]
r1.vtysh_cmd("conf\ninterface blue\nip pim")
r1.vtysh_cmd("conf\nvrf blue\nip pim rp 192.168.0.11 239.100.0.1/32\nexit-vrf")
@@ -292,7 +334,7 @@ def test_vrf_pimreg_interfaces():
"show ip pim vrf blue inter pimreg11 json",
expected,
)
- _, res = topotest.run_and_expect(test_func, None, count=5, wait=2)
+ _, res = topotest.run_and_expect(test_func, None, count=15, wait=2)
assertmsg = "PIM router R1, VRF blue (table 11) pimreg11 interface missing or incorrect status"
assert res is None, assertmsg
@@ -308,10 +350,20 @@ def test_vrf_pimreg_interfaces():
"show ip pim vrf red inter pimreg12 json",
expected,
)
- _, res = topotest.run_and_expect(test_func, None, count=5, wait=2)
+ _, res = topotest.run_and_expect(test_func, None, count=15, wait=2)
assertmsg = "PIM router R1, VRF red (table 12) pimreg12 interface missing or incorrect status"
assert res is None, assertmsg
+def test_vrf_pimreg_interfaces():
+ tgen = get_topogen()
+ r1 = tgen.gears["r1"]
+ try:
+ _test_vrf_pimreg_interfaces()
+ except Exception:
+ # get some debug info.
+ output = r1.net.cmd_nostatus("ip -o link")
+ logging.error("ip link info after failure: %s", output)
+ raise
##################################
### Test PIM / IGMP with VRF
diff --git a/tests/topotests/pytest.ini b/tests/topotests/pytest.ini
index 98fcfbc..db806fe 100644
--- a/tests/topotests/pytest.ini
+++ b/tests/topotests/pytest.ini
@@ -43,6 +43,7 @@ markers =
bfdd: Tests that run against BFDD
bgpd: Tests that run against BGPD
eigrpd: Tests that run against EIGRPD
+ fpm: Tests that run against the FPM
isisd: Tests that run against ISISD
ldpd: Tests that run against LDPD
mgmtd: Tests that run against MGMTD
diff --git a/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py b/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py
index 71c9093..d03d547 100644
--- a/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py
+++ b/tests/topotests/rip_bfd_topo1/test_rip_bfd_topo1.py
@@ -32,10 +32,7 @@ pytestmark = [
def tgen(request):
"Setup/Teardown the environment and provide tgen argument to tests"
- topodef = {
- "s1": ("r1", "r2"),
- "s2": ("r1", "r3")
- }
+ topodef = {"s1": ("r1", "r2"), "s2": ("r1", "r3")}
tgen = Topogen(topodef, request.module.__name__)
tgen.start_topology()
@@ -68,16 +65,17 @@ def show_rip_json(router):
for route in routes:
match = re.match(
- r"(.)\((.)\)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)", route)
+ r"(.)\((.)\)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)\s+([^\s]+)", route
+ )
if match is None:
continue
route_entry = {
- "code": match[1],
- "subCode": match[2],
- "nextHop": match[4],
- "metric": int(match[5]),
- "from": match[6],
+ "code": match[1],
+ "subCode": match[2],
+ "nextHop": match[4],
+ "metric": int(match[5]),
+ "from": match[6],
}
if json.get(match[3]) is None:
@@ -95,12 +93,8 @@ def expect_routes(router, routes, time_amount):
"Internal test function."
return topotest.json_cmp(show_rip_json(router), routes)
- _, result = topotest.run_and_expect(test_function,
- None,
- count=time_amount,
- wait=1)
- assert result is None, "Unexpected routing table in {}".format(
- router.name)
+ _, result = topotest.run_and_expect(test_function, None, count=time_amount, wait=1)
+ assert result is None, "Unexpected routing table in {}".format(router.name)
def expect_bfd_peers(router, peers):
@@ -119,91 +113,87 @@ def test_rip_convergence(tgen):
"Test that RIP learns the neighbor routes."
expect_routes(
- tgen.gears["r1"], {
- "10.254.254.2/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2"
- }],
- "10.254.254.3/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.2"
- }],
- "10.254.254.100/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2",
- }, {
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.2",
- }]
- }, 40)
-
- expect_bfd_peers(tgen.gears["r1"], [{
- "peer": "192.168.0.2",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }, {
- "peer": "192.168.1.2",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }])
+ tgen.gears["r1"],
+ {
+ "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.0.2"}],
+ "10.254.254.3/32": [{"code": "R", "subCode": "n", "from": "192.168.1.2"}],
+ "10.254.254.100/32": [
+ {
+ "code": "R",
+ "subCode": "n",
+ "from": "192.168.0.2",
+ },
+ {
+ "code": "R",
+ "subCode": "n",
+ "from": "192.168.1.2",
+ },
+ ],
+ },
+ 40,
+ )
+
+ expect_bfd_peers(
+ tgen.gears["r1"],
+ [
+ {
+ "peer": "192.168.0.2",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ },
+ {
+ "peer": "192.168.1.2",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ },
+ ],
+ )
expect_routes(
- tgen.gears["r2"], {
- "10.254.254.1/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.1"
- }],
- "10.254.254.3/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.1"
- }],
- "10.254.254.100/32": [{
- "code": "S",
- "subCode": "r",
- "from": "self"
- }]
- }, 40)
-
- expect_bfd_peers(tgen.gears["r2"], [{
- "peer": "192.168.0.1",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }])
+ tgen.gears["r2"],
+ {
+ "10.254.254.1/32": [{"code": "R", "subCode": "n", "from": "192.168.0.1"}],
+ "10.254.254.3/32": [{"code": "R", "subCode": "n", "from": "192.168.0.1"}],
+ "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}],
+ },
+ 40,
+ )
+
+ expect_bfd_peers(
+ tgen.gears["r2"],
+ [
+ {
+ "peer": "192.168.0.1",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ }
+ ],
+ )
expect_routes(
- tgen.gears["r3"], {
- "10.254.254.1/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.1"
- }],
- "10.254.254.2/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.1.1"
- }],
- "10.254.254.100/32": [{
- "code": "S",
- "subCode": "r",
- "from": "self"
- }]
- }, 40)
-
- expect_bfd_peers(tgen.gears["r3"], [{
- "peer": "192.168.1.1",
- "status": "up",
- "receive-interval": 1000,
- "transmit-interval": 1000,
- }])
+ tgen.gears["r3"],
+ {
+ "10.254.254.1/32": [{"code": "R", "subCode": "n", "from": "192.168.1.1"}],
+ "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.1.1"}],
+ "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}],
+ },
+ 40,
+ )
+
+ expect_bfd_peers(
+ tgen.gears["r3"],
+ [
+ {
+ "peer": "192.168.1.1",
+ "status": "up",
+ "receive-interval": 1000,
+ "transmit-interval": 1000,
+ }
+ ],
+ )
def test_rip_bfd_convergence(tgen):
@@ -212,30 +202,30 @@ def test_rip_bfd_convergence(tgen):
tgen.gears["r3"].link_enable("r3-eth0", False)
expect_routes(
- tgen.gears["r1"], {
- "10.254.254.2/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2"
- }],
+ tgen.gears["r1"],
+ {
+ "10.254.254.2/32": [{"code": "R", "subCode": "n", "from": "192.168.0.2"}],
"10.254.254.3/32": None,
- "10.254.254.100/32": [{
- "code": "R",
- "subCode": "n",
- "from": "192.168.0.2",
- }]
- }, 6)
+ "10.254.254.100/32": [
+ {
+ "code": "R",
+ "subCode": "n",
+ "from": "192.168.0.2",
+ }
+ ],
+ },
+ 6,
+ )
expect_routes(
- tgen.gears["r3"], {
+ tgen.gears["r3"],
+ {
"10.254.254.1/32": None,
"10.254.254.2/32": None,
- "10.254.254.100/32": [{
- "code": "S",
- "subCode": "r",
- "from": "self"
- }]
- }, 6)
+ "10.254.254.100/32": [{"code": "S", "subCode": "r", "from": "self"}],
+ },
+ 6,
+ )
def test_memory_leak(tgen):
diff --git a/tests/topotests/route_scale/scale_test_common.py b/tests/topotests/route_scale/scale_test_common.py
index 6227e81..b3cba1c 100644
--- a/tests/topotests/route_scale/scale_test_common.py
+++ b/tests/topotests/route_scale/scale_test_common.py
@@ -151,7 +151,7 @@ def route_install_helper(iter):
logger.info(
"Limited memory available: {}, skipping x32 testcase".format(total_mem)
)
- return;
+ return
installed_file = "{}/r1/installed.routes.json".format(CWD)
expected_installed = json.loads(open(installed_file).read())
diff --git a/tests/topotests/route_scale/test_route_scale1.py b/tests/topotests/route_scale/test_route_scale1.py
index 0f25b28..ccbdd51 100644
--- a/tests/topotests/route_scale/test_route_scale1.py
+++ b/tests/topotests/route_scale/test_route_scale1.py
@@ -30,35 +30,51 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module
+from scale_test_common import (
+ scale_build_common,
+ scale_setup_module,
+ route_install_helper,
+ scale_test_memory_leak,
+ scale_converge_protocols,
+ scale_teardown_module,
+)
pytestmark = [pytest.mark.sharpd]
+
def build(tgen):
scale_build_common(tgen)
+
def setup_module(module):
scale_setup_module(module)
+
def teardown_module(_mod):
scale_teardown_module(_mod)
+
def test_converge_protocols():
scale_converge_protocols()
+
def test_route_install_2nh():
route_install_helper(1)
+
def test_route_install_4nh():
route_install_helper(2)
+
def test_route_install_16nh():
route_install_helper(4)
+
def test_memory_leak():
scale_test_memory_leak()
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/route_scale/test_route_scale2.py b/tests/topotests/route_scale/test_route_scale2.py
index 3b55fcd..e244d4f 100644
--- a/tests/topotests/route_scale/test_route_scale2.py
+++ b/tests/topotests/route_scale/test_route_scale2.py
@@ -30,35 +30,51 @@ from lib import topotest
from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.topolog import logger
-from scale_test_common import scale_build_common, scale_setup_module, route_install_helper, scale_test_memory_leak, scale_converge_protocols, scale_teardown_module
+from scale_test_common import (
+ scale_build_common,
+ scale_setup_module,
+ route_install_helper,
+ scale_test_memory_leak,
+ scale_converge_protocols,
+ scale_teardown_module,
+)
pytestmark = [pytest.mark.sharpd]
+
def build(tgen):
scale_build_common(tgen)
+
def setup_module(module):
scale_setup_module(module)
+
def teardown_module(_mod):
scale_teardown_module(_mod)
+
def test_converge_protocols():
scale_converge_protocols()
+
def test_route_install_1nh():
route_install_helper(0)
+
def test_route_install_8nh():
route_install_helper(3)
+
def test_route_install_32nh():
route_install_helper(5)
+
def test_memory_leak():
scale_test_memory_leak()
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py b/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py
index 4239193..b8bcab8 100755
--- a/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py
+++ b/tests/topotests/srv6_encap_src_addr/test_srv6_encap_src_addr.py
@@ -63,16 +63,16 @@ def teardown_module(mod):
def test_zebra_srv6_encap_src_addr(tgen):
"Test SRv6 encapsulation source address."
- logger.info(
- "Test SRv6 encapsulation source address."
- )
+ logger.info("Test SRv6 encapsulation source address.")
r1 = tgen.gears["r1"]
# Generate expected results
json_file = "{}/r1/expected_srv6_encap_src_addr.json".format(CWD)
expected = json.loads(open(json_file).read())
- ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected)
+ ok = topotest.router_json_cmp_retry(
+ r1, "show segment-routing srv6 manager json", expected
+ )
assert ok, '"r1" JSON output mismatches'
output = r1.cmd("ip sr tunsrc show")
@@ -81,9 +81,7 @@ def test_zebra_srv6_encap_src_addr(tgen):
def test_zebra_srv6_encap_src_addr_unset(tgen):
"Test SRv6 encapsulation source address unset."
- logger.info(
- "Test SRv6 encapsulation source address unset."
- )
+ logger.info("Test SRv6 encapsulation source address unset.")
r1 = tgen.gears["r1"]
# Unset SRv6 encapsulation source address
@@ -101,7 +99,9 @@ def test_zebra_srv6_encap_src_addr_unset(tgen):
json_file = "{}/r1/expected_srv6_encap_src_addr_unset.json".format(CWD)
expected = json.loads(open(json_file).read())
- ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected)
+ ok = topotest.router_json_cmp_retry(
+ r1, "show segment-routing srv6 manager json", expected
+ )
assert ok, '"r1" JSON output mismatches'
output = r1.cmd("ip sr tunsrc show")
@@ -110,9 +110,7 @@ def test_zebra_srv6_encap_src_addr_unset(tgen):
def test_zebra_srv6_encap_src_addr_set(tgen):
"Test SRv6 encapsulation source address set."
- logger.info(
- "Test SRv6 encapsulation source address set."
- )
+ logger.info("Test SRv6 encapsulation source address set.")
r1 = tgen.gears["r1"]
# Set SRv6 encapsulation source address
@@ -130,7 +128,9 @@ def test_zebra_srv6_encap_src_addr_set(tgen):
json_file = "{}/r1/expected_srv6_encap_src_addr_set.json".format(CWD)
expected = json.loads(open(json_file).read())
- ok = topotest.router_json_cmp_retry(r1, "show segment-routing srv6 manager json", expected)
+ ok = topotest.router_json_cmp_retry(
+ r1, "show segment-routing srv6 manager json", expected
+ )
assert ok, '"r1" JSON output mismatches'
output = r1.cmd("ip sr tunsrc show")
diff --git a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
index 2efc0fd..3e03055 100644
--- a/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
+++ b/tests/topotests/static_routing_with_ebgp/test_static_routes_topo4_ebgp.py
@@ -65,8 +65,6 @@ ADDR_TYPES = check_address_types()
NETWORK = {"ipv4": "2.2.2.2/32", "ipv6": "22:22::2/128"}
NEXT_HOP_IP = {}
-pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
-
def setup_module(mod):
"""
@@ -551,7 +549,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -571,7 +569,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
dut = "r2"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
@@ -914,7 +912,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -931,7 +929,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
dut = "r1"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -945,7 +943,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
dut = "r2"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -959,7 +957,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ebgp(request):
protocol = "bgp"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
diff --git a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
index 0378240..0fc81aa 100644
--- a/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
+++ b/tests/topotests/static_routing_with_ibgp/test_static_routes_topo4_ibgp.py
@@ -547,7 +547,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -567,7 +567,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
dut = "r2"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
@@ -910,7 +910,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
protocol = "bgp"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm1"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -927,7 +927,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
dut = "r1"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -941,7 +941,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
dut = "r2"
ntwk_r2_vm1 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
+ "{}".format(topo["routers"]["r1"]["links"]["vm4"][addr_type])
).network
)
input_dict = {"r1": {"static_routes": [{"network": ntwk_r2_vm1}]}}
@@ -955,7 +955,7 @@ def test_static_routes_rmap_pfxlist_p0_tc7_ibgp(request):
protocol = "bgp"
ntwk_r2_vm6 = str(
ipaddress.ip_interface(
- u"{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
+ "{}".format(topo["routers"]["r2"]["links"]["vm6"][addr_type])
).network
)
input_dict = {"r3": {"static_routes": [{"network": ntwk_r2_vm6}]}}
diff --git a/tests/topotests/tc_basic/test_tc_basic.py b/tests/topotests/tc_basic/test_tc_basic.py
index f64e83c..822d201 100755
--- a/tests/topotests/tc_basic/test_tc_basic.py
+++ b/tests/topotests/tc_basic/test_tc_basic.py
@@ -22,9 +22,8 @@ sys.path.append(os.path.join(CWD, "../lib/"))
from lib.topogen import Topogen, TopoRouter
from lib.topolog import logger
-pytestmark = [
- pytest.mark.sharpd
-]
+pytestmark = [pytest.mark.sharpd]
+
def build_topo(tgen):
"Build function"
@@ -42,6 +41,7 @@ def build_topo(tgen):
switch = tgen.add_switch("s2")
switch.add_link(r2)
+
# New form of setup/teardown using pytest fixture
@pytest.fixture(scope="module")
def tgen(request):
@@ -79,22 +79,28 @@ def skip_on_failure(tgen):
if tgen.routers_have_failure():
pytest.skip("skipped because of previous test failure")
+
def fetch_iproute2_tc_info(r, interface):
qdisc = r.cmd("tc qdisc show dev %s" % interface)
tclass = r.cmd("tc class show dev %s" % interface)
tfilter = r.cmd("tc filter show dev %s" % interface)
return qdisc, tclass, tfilter
+
# ===================
# The tests functions
# ===================
+
def test_tc_basic(tgen):
"Test installing one pair of filter & class by sharpd"
r1 = tgen.gears["r1"]
intf = "r1-eth0"
- r1.vtysh_cmd("sharp tc dev %s source 192.168.100.0/24 destination 192.168.101.0/24 ip-protocol tcp src-port 8000 dst-port 8001 rate 20mbit" % intf)
+ r1.vtysh_cmd(
+ "sharp tc dev %s source 192.168.100.0/24 destination 192.168.101.0/24 ip-protocol tcp src-port 8000 dst-port 8001 rate 20mbit"
+ % intf
+ )
time.sleep(3)
@@ -115,6 +121,7 @@ def test_tc_basic(tgen):
assert "dst_port 8001" in tfilter
assert "src_port 8000" in tfilter
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
- sys.exit(pytest.main(args)) \ No newline at end of file
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/zebra_netlink/test_zebra_netlink.py b/tests/topotests/zebra_netlink/test_zebra_netlink.py
index 522c390..d970c04 100644
--- a/tests/topotests/zebra_netlink/test_zebra_netlink.py
+++ b/tests/topotests/zebra_netlink/test_zebra_netlink.py
@@ -94,7 +94,7 @@ def test_zebra_netlink_batching(tgen):
}
match = {}
- base = int(ipaddress.ip_address(u"2.1.3.7"))
+ base = int(ipaddress.ip_address("2.1.3.7"))
for i in range(base, base + count):
pfx = str(ipaddress.ip_network((i, 32)))
match[pfx] = [dict(entry, prefix=pfx)]
diff --git a/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py b/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py
index 6956ab7..fbef0fe 100644
--- a/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py
+++ b/tests/topotests/zebra_nht_resolution/test_verify_nh_resolution.py
@@ -33,30 +33,36 @@ sys.path.append(os.path.join(CWD, "../"))
pytestmark = [pytest.mark.sharpd]
-#GLOBAL VARIABLES
+# GLOBAL VARIABLES
NH1 = "2.2.2.32"
+
def build_topo(tgen):
tgen.add_router("r1")
switch = tgen.add_switch("sw1")
switch.add_link(tgen.gears["r1"])
+
def setup_module(mod):
tgen = Topogen(build_topo, mod.__name__)
tgen.start_topology()
router_list = tgen.routers()
for rname, router in tgen.routers().items():
- router.load_config(TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname)))
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
router.load_config(
TopoRouter.RD_SHARP, os.path.join(CWD, "{}/sharpd.conf".format(rname))
)
tgen.start_router()
+
def teardown_module(_mod):
tgen = get_topogen()
tgen.stop_topology()
+
def test_verify_zebra_nh_resolution(request):
tgen = get_topogen()
tc_name = request.node.name
@@ -67,31 +73,18 @@ def test_verify_zebra_nh_resolution(request):
step("Configure static route")
input_dict_1 = {
- "r1": {
- "static_routes": [
- {"network": "2.2.2.0/24", "next_hop": "r1-eth0"}
- ]
- }
- }
+ "r1": {"static_routes": [{"network": "2.2.2.0/24", "next_hop": "r1-eth0"}]}
+ }
result = create_static_routes(tgen, input_dict_1)
- assert result is True, "Testcase {} : Failed \n Error: {}".format(
- tc_name, result
- )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
step("Verify static routes in RIB of R1")
- input_dict_2 = {
- "r1": {
- "static_routes": [
- {"network": "2.2.2.0/24"}
- ]
- }
- }
+ input_dict_2 = {"r1": {"static_routes": [{"network": "2.2.2.0/24"}]}}
dut = "r1"
result = verify_rib(tgen, "ipv4", dut, input_dict_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("Set the connected flag on the NH tracking entry")
r1.vtysh_cmd("sharp watch nexthop 2.2.2.32 connected")
@@ -108,8 +101,7 @@ def test_verify_zebra_nh_resolution(request):
}
result = verify_ip_nht(tgen, input_dict_nh)
assert result is True, "Testcase {} : Failed \n"
- "Error: Nexthop is missing in RIB".format(
- tc_name, result)
+ "Error: Nexthop is missing in RIB".format(tc_name, result)
step("Add a .32/32 route with the NH as itself")
r1.vtysh_cmd("sharp install routes 2.2.2.32 nexthop 2.2.2.32 1")
@@ -126,11 +118,12 @@ def test_verify_zebra_nh_resolution(request):
}
result = verify_ip_nht(tgen, input_dict_nh)
assert result is True, "Testcase {} : Failed \n"
- "Error: Nexthop became unresolved".format(
- tc_name, result)
+ "Error: Nexthop became unresolved".format(tc_name, result)
- step("Add a .31/32 route with the NH as 2.2.2.32"
- "to verify the NH Resolution behaviour")
+ step(
+ "Add a .31/32 route with the NH as 2.2.2.32"
+ "to verify the NH Resolution behaviour"
+ )
r1.vtysh_cmd("sharp install routes 2.2.2.31 nexthop 2.2.2.32 1")
step("Verify that NH 2.2.2.2/32 doesn't become unresolved")
@@ -145,8 +138,8 @@ def test_verify_zebra_nh_resolution(request):
}
result = verify_ip_nht(tgen, input_dict_nh)
assert result is True, "Testcase {} : Failed \n"
- "Error: Nexthop became unresolved".format(
- tc_name, result)
+ "Error: Nexthop became unresolved".format(tc_name, result)
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
diff --git a/tests/topotests/zebra_seg6_route/r1/routes_setup.json b/tests/topotests/zebra_seg6_route/r1/routes_setup.json
new file mode 100644
index 0000000..d131e4a
--- /dev/null
+++ b/tests/topotests/zebra_seg6_route/r1/routes_setup.json
@@ -0,0 +1,28 @@
+{
+ "2001::/64":[
+ {
+ "prefix":"2001::/64",
+ "prefixLen":64,
+ "protocol":"connected",
+ "vrfName":"default",
+ "selected":true,
+ "destSelected":true,
+ "distance":0,
+ "metric":0,
+ "installed":true,
+ "internalStatus":16,
+ "internalFlags":8,
+ "internalNextHopNum":1,
+ "internalNextHopActiveNum":1,
+ "nexthops":[
+ {
+ "flags":3,
+ "fib":true,
+ "directlyConnected":true,
+ "interfaceName":"dum0",
+ "active":true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py b/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py
index f872f7a..4a4cf06 100755
--- a/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py
+++ b/tests/topotests/zebra_seg6_route/test_zebra_seg6_route.py
@@ -73,6 +73,16 @@ def test_zebra_seg6_routes():
return False
return topotest.json_cmp(output, expected)
+ def check_connected(router, dest, expected):
+ logger.info("Checking for connected")
+ output = json.loads(router.vtysh_cmd("show ipv6 route {} json".format(dest)))
+ return topotest.json_cmp(output, expected)
+
+ expected = open_json_file(os.path.join(CWD, "{}/routes_setup.json".format("r1")))
+ test_func = partial(check_connected, r1, "2001::/64", expected)
+ success, result = topotest.run_and_expect(test_func, None, count=20, wait=1)
+ assert result is None, "Failed to fully setup connected routes needed"
+
manifests = open_json_file(os.path.join(CWD, "{}/routes.json".format("r1")))
for manifest in manifests:
dest = manifest["in"]["dest"]
diff --git a/tools/checkpatch.pl b/tools/checkpatch.pl
index ecae0e9..f52f1a1 100755
--- a/tools/checkpatch.pl
+++ b/tools/checkpatch.pl
@@ -4656,19 +4656,6 @@ sub process {
$herecurr);
}
-# check for sizeof(foo)/sizeof(foo[0]) that could be ARRAY_SIZE(foo)
- if ($line =~ m@\bsizeof\s*\(\s*($Lval)\s*\)@) {
- my $array = $1;
- if ($line =~ m@\b(sizeof\s*\(\s*\Q$array\E\s*\)\s*/\s*sizeof\s*\(\s*\Q$array\E\s*\[\s*0\s*\]\s*\))@) {
- my $array_div = $1;
- if (WARN("ARRAY_SIZE",
- "Prefer ARRAY_SIZE($array)\n" . $herecurr) &&
- $fix) {
- $fixed[$fixlinenr] =~ s/\Q$array_div\E/ARRAY_SIZE($array)/;
- }
- }
- }
-
# check for function declarations without arguments like "int foo()"
if ($line =~ /(\b$Type\s*$Ident)\s*\(\s*\)/) {
if (ERROR("FUNCTION_WITHOUT_ARGS",
diff --git a/tools/cocci.h b/tools/cocci.h
index 7d6bb4c..99076b5 100644
--- a/tools/cocci.h
+++ b/tools/cocci.h
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
/* some of this stuff doesn't seem to parse properly in coccinelle
*/
diff --git a/tools/etc/iproute2/rt_protos.d/frr.conf b/tools/etc/iproute2/rt_protos.d/frr.conf
index bbb358f..3e0fc2e 100644
--- a/tools/etc/iproute2/rt_protos.d/frr.conf
+++ b/tools/etc/iproute2/rt_protos.d/frr.conf
@@ -12,3 +12,4 @@
195 pbr
196 static
197 openfabric
+198 srte
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index b06f1df..461f0e8 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -1013,16 +1013,17 @@ def bgp_delete_move_lines(lines_to_add, lines_to_del):
del_dict[ctx_keys[0]][re_pg.group(1)] = list()
found_pg_del_cmd = True
+ # move neighbor remote-as lines at the end
+ for ctx_keys, line in lines_to_del_to_app:
+ lines_to_del.remove((ctx_keys, line))
+ lines_to_del.append((ctx_keys, line))
+
if found_pg_del_cmd == False:
bgp_delete_inst_move_line(lines_to_del)
if del_nbr_dict:
bgp_remove_neighbor_cfg(lines_to_del, del_nbr_dict)
return (lines_to_add, lines_to_del)
- for ctx_keys, line in lines_to_del_to_app:
- lines_to_del.remove((ctx_keys, line))
- lines_to_del.append((ctx_keys, line))
-
# {'router bgp 65001': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']},
# 'router bgp 65001 vrf vrf1': {'PG': ['10.1.1.2'], 'PG1': ['10.1.1.21']}}
for ctx_keys, line in lines_to_del:
@@ -1082,19 +1083,34 @@ def pim_delete_move_lines(lines_to_add, lines_to_del):
# Remove all such depdendent options from delete
# pending list.
pim_disable = False
+ lines_to_del_to_del = []
+ index = -1
for ctx_keys, line in lines_to_del:
+ index = index + 1
if ctx_keys[0].startswith("interface") and line and line == "ip pim":
pim_disable = True
+ # no ip msdp peer <> does not accept source so strip it off.
+ if line and line.startswith("ip msdp peer "):
+ pim_msdp_peer = re.search("ip msdp peer (\S+) source (\S+)", line)
+ if pim_msdp_peer:
+ source_sub_str = "source %s" % pim_msdp_peer.group(2)
+ new_line = line.replace(source_sub_str, "").strip()
+ lines_to_del.remove((ctx_keys, line))
+ lines_to_del.insert(index, (ctx_keys, new_line))
+
if pim_disable:
for ctx_keys, line in lines_to_del:
if (
ctx_keys[0].startswith("interface")
and line
- and line.startswith("ip pim ")
+ and (line.startswith("ip pim ") or line.startswith("ip multicast "))
):
- lines_to_del.remove((ctx_keys, line))
+ lines_to_del_to_del.append((ctx_keys, line))
+
+ for ctx_keys, line in lines_to_del_to_del:
+ lines_to_del.remove((ctx_keys, line))
return (lines_to_add, lines_to_del)
diff --git a/tools/gcc-plugins/frr-format.c b/tools/gcc-plugins/frr-format.c
index 4e2c2d3..963741e 100644
--- a/tools/gcc-plugins/frr-format.c
+++ b/tools/gcc-plugins/frr-format.c
@@ -66,6 +66,8 @@ static GTY(()) tree local_pid_t_node;
static GTY(()) tree local_uid_t_node;
static GTY(()) tree local_gid_t_node;
static GTY(()) tree local_time_t_node;
+static GTY(()) tree local_suseconds_t_node;
+static GTY(()) tree local_suseconds64_t_node;
static GTY(()) tree local_socklen_t_node;
static GTY(()) tree local_in_addr_t_node;
@@ -85,6 +87,8 @@ static struct type_special {
{ &local_uid_t_node, NULL, &local_uid_t_node, },
{ &local_gid_t_node, NULL, &local_gid_t_node, },
{ &local_time_t_node, NULL, &local_time_t_node, },
+ { &local_suseconds_t_node, NULL, &local_suseconds_t_node, },
+ { &local_suseconds64_t_node, NULL, &local_suseconds64_t_node, },
{ NULL, NULL, NULL, }
};
@@ -4176,6 +4180,8 @@ handle_finish_parse (void *event_data, void *data)
setup_type ("uid_t", &local_uid_t_node);
setup_type ("gid_t", &local_gid_t_node);
setup_type ("time_t", &local_time_t_node);
+ setup_type ("__suseconds_t", &local_suseconds_t_node);
+ setup_type ("__suseconds64_t", &local_suseconds64_t_node);
setup_type ("socklen_t", &local_socklen_t_node);
setup_type ("in_addr_t", &local_in_addr_t_node);
diff --git a/tools/indent.py b/tools/indent.py
index fe9eb7c..dac7d3f 100755
--- a/tools/indent.py
+++ b/tools/indent.py
@@ -34,13 +34,13 @@ def wrap_file(fn):
ci = subprocess.Popen(
["clang-format"], stdin=subprocess.PIPE, stdout=subprocess.PIPE
)
- stdout, ign = ci.communicate(text)
+ stdout, ign = ci.communicate(text.encode("utf-8"))
ci.wait()
if ci.returncode != 0:
raise IOError("clang-format returned %d" % (ci.returncode))
# remove the bits we inserted above
- final = clean_re.sub("", stdout)
+ final = clean_re.sub("", stdout.decode("utf-8"))
tmpname = fn + ".indent"
with open(tmpname, "w") as ofd:
diff --git a/vtysh/vtysh.c b/vtysh/vtysh.c
index 12d22b1..b1c957d 100644
--- a/vtysh/vtysh.c
+++ b/vtysh/vtysh.c
@@ -39,7 +39,6 @@
#include "frrstr.h"
#include "json.h"
#include "ferr.h"
-#include "bgpd/bgp_vty.h"
DEFINE_MTYPE_STATIC(MVTYSH, VTYSH_CMD, "Vtysh cmd copy");
@@ -3474,6 +3473,259 @@ DEFPY (show_route_map,
return CMD_SUCCESS;
}
+static void show_prefix_list_send(afi_t afi, const char *prefix_list,
+ const char *seq, enum display_type dtype,
+ bool json)
+{
+ unsigned int i;
+ bool first = true;
+ char command_line[128];
+
+ if (afi == AFI_IP)
+ snprintf(command_line, sizeof(command_line),
+ "do show ip prefix-list ");
+ else if (afi == AFI_IP6)
+ snprintf(command_line, sizeof(command_line),
+ "do show ipv6 prefix-list ");
+ if (dtype == detail_display)
+ strlcat(command_line, "detail ", sizeof(command_line));
+ else if (dtype == summary_display)
+ strlcat(command_line, "summary ", sizeof(command_line));
+ if (prefix_list)
+ strlcat(command_line, prefix_list, sizeof(command_line));
+ if (dtype == sequential_display) {
+ strlcat(command_line, " seq ", sizeof(command_line));
+ strlcat(command_line, seq, sizeof(command_line));
+ }
+ if (json)
+ strlcat(command_line, " json", sizeof(command_line));
+
+ if (json)
+ vty_out(vty, "{");
+
+ for (i = 0; i < array_size(vtysh_client); i++) {
+ const struct vtysh_client *client = &vtysh_client[i];
+ bool is_connected = true;
+
+ if (!CHECK_FLAG(client->flag, VTYSH_PREFIX_LIST_SHOW))
+ continue;
+
+ for (; client; client = client->next)
+ if (client->fd < 0)
+ is_connected = false;
+
+ if (!is_connected)
+ continue;
+
+ if (json && !first)
+ vty_out(vty, ",");
+ else
+ first = false;
+
+ if (json)
+ vty_out(vty, "\"%s\":", vtysh_client[i].name);
+
+ vtysh_client_execute_name(vtysh_client[i].name, command_line);
+ }
+
+ if (json)
+ vty_out(vty, "}\n");
+}
+
+DEFPY (show_ip_prefix_list,
+ show_ip_prefix_list_cmd,
+ "show ip prefix-list [PREFIXLIST4_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
+ SHOW_STR
+ IP_STR
+ PREFIX_LIST_STR
+ "Name of a prefix list\n"
+ "sequence number of an entry\n"
+ "Sequence number\n"
+ JSON_STR)
+{
+ enum display_type dtype = normal_display;
+
+ if (dseq)
+ dtype = sequential_display;
+
+ show_prefix_list_send(AFI_IP, name, arg_str, dtype, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ip_prefix_list_summary,
+ show_ip_prefix_list_summary_cmd,
+ "show ip prefix-list summary [PREFIXLIST4_NAME$name] [json$uj]",
+ SHOW_STR
+ IP_STR
+ PREFIX_LIST_STR
+ "Summary of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP, name, NULL, summary_display, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ip_prefix_list_detail,
+ show_ip_prefix_list_detail_cmd,
+ "show ip prefix-list detail [PREFIXLIST4_NAME$name] [json$uj]",
+ SHOW_STR
+ IP_STR
+ PREFIX_LIST_STR
+ "Detail of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP, name, NULL, detail_display, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_prefix_list,
+ show_ipv6_prefix_list_cmd,
+ "show ipv6 prefix-list [PREFIXLIST6_NAME$name [seq$dseq (1-4294967295)$arg]] [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ PREFIX_LIST_STR
+ "Name of a prefix list\n"
+ "sequence number of an entry\n"
+ "Sequence number\n"
+ JSON_STR)
+{
+ enum display_type dtype = normal_display;
+
+ if (dseq)
+ dtype = sequential_display;
+
+ show_prefix_list_send(AFI_IP6, name, arg_str, dtype, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_prefix_list_summary,
+ show_ipv6_prefix_list_summary_cmd,
+ "show ipv6 prefix-list summary [PREFIXLIST6_NAME$name] [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ PREFIX_LIST_STR
+ "Summary of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP6, name, NULL, summary_display, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_prefix_list_detail,
+ show_ipv6_prefix_list_detail_cmd,
+ "show ipv6 prefix-list detail [PREFIXLIST6_NAME$name] [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ PREFIX_LIST_STR
+ "Detail of prefix lists\n"
+ "Name of a prefix list\n"
+ JSON_STR)
+{
+ show_prefix_list_send(AFI_IP6, name, NULL, detail_display, !!uj);
+ return CMD_SUCCESS;
+}
+
+static void show_access_list_send(afi_t afi, const char *access_list, bool json)
+{
+ unsigned int i;
+ bool first = true;
+ char command_line[128];
+
+ if (afi == AFI_IP)
+ snprintf(command_line, sizeof(command_line),
+ "do show ip access-list ");
+ else if (afi == AFI_IP6)
+ snprintf(command_line, sizeof(command_line),
+ "do show ipv6 access-list ");
+ if (access_list)
+ strlcat(command_line, access_list, sizeof(command_line));
+ if (json) {
+ strlcat(command_line, " json", sizeof(command_line));
+ vty_out(vty, "{");
+ }
+
+ for (i = 0; i < array_size(vtysh_client); i++) {
+ const struct vtysh_client *client = &vtysh_client[i];
+ bool is_connected = true;
+
+ if (!CHECK_FLAG(client->flag, VTYSH_ACCESS_LIST_SHOW))
+ continue;
+
+ for (; client; client = client->next)
+ if (client->fd < 0)
+ is_connected = false;
+
+ if (!is_connected)
+ continue;
+
+ if (json && !first)
+ vty_out(vty, ",");
+ else
+ first = false;
+
+ if (json)
+ vty_out(vty, "\"%s\":", vtysh_client[i].name);
+
+ vtysh_client_execute_name(vtysh_client[i].name, command_line);
+ }
+
+ if (json)
+ vty_out(vty, "}\n");
+}
+
+DEFPY (show_ip_access_list,
+ show_ip_access_list_cmd,
+ "show ip access-list [json$uj]",
+ SHOW_STR
+ IP_STR
+ "List IP access lists\n"
+ JSON_STR)
+{
+ show_access_list_send(AFI_IP, NULL, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ip_access_list_name,
+ show_ip_access_list_name_cmd,
+ "show ip access-list ACCESSLIST4_NAME$name [json$uj]",
+ SHOW_STR
+ IP_STR
+ "List IP access lists\n"
+ "IP access-list name\n"
+ JSON_STR)
+{
+ show_access_list_send(AFI_IP, name, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_access_list,
+ show_ipv6_access_list_cmd,
+ "show ipv6 access-list [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ "List IPv6 access lists\n"
+ JSON_STR)
+{
+ show_access_list_send(AFI_IP6, NULL, !!uj);
+ return CMD_SUCCESS;
+}
+
+DEFPY (show_ipv6_access_list_name,
+ show_ipv6_access_list_name_cmd,
+ "show ipv6 access-list ACCESSLIST6_NAME$name [json$uj]",
+ SHOW_STR
+ IPV6_STR
+ "List IPv6 access lists\n"
+ "IPv6 access-list name\n"
+ JSON_STR)
+{
+ show_access_list_send(AFI_IP6, name, !!uj);
+ return CMD_SUCCESS;
+}
+
DEFUN (vtysh_integrated_config,
vtysh_integrated_config_cmd,
"service integrated-vtysh-config",
@@ -3498,8 +3750,8 @@ DEFUN (no_vtysh_integrated_config,
static void backup_config_file(const char *fbackup)
{
char *integrate_sav = NULL;
-
size_t integrate_sav_sz = strlen(fbackup) + strlen(CONF_BACKUP_EXT) + 1;
+
integrate_sav = malloc(integrate_sav_sz);
strlcpy(integrate_sav, fbackup, integrate_sav_sz);
strlcat(integrate_sav, CONF_BACKUP_EXT, integrate_sav_sz);
@@ -4208,71 +4460,6 @@ DEFUN (vtysh_traceroute6,
return CMD_SUCCESS;
}
-#if CONFDATE > 20240201
-CPP_NOTICE("Remove HAVE_SHELL_ACCESS and it's documentation");
-#endif
-#if defined(HAVE_SHELL_ACCESS)
-DEFUN (vtysh_telnet,
- vtysh_telnet_cmd,
- "telnet WORD",
- "Open a telnet connection\n"
- "IP address or hostname of a remote system\n")
-{
- execute_command("telnet", 1, argv[1]->arg, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN (vtysh_telnet_port,
- vtysh_telnet_port_cmd,
- "telnet WORD PORT",
- "Open a telnet connection\n"
- "IP address or hostname of a remote system\n"
- "TCP Port number\n")
-{
- execute_command("telnet", 2, argv[1]->arg, argv[2]->arg);
- return CMD_SUCCESS;
-}
-
-DEFUN (vtysh_ssh,
- vtysh_ssh_cmd,
- "ssh WORD",
- "Open an ssh connection\n"
- "[user@]host\n")
-{
- execute_command("ssh", 1, argv[1]->arg, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN (vtysh_start_shell,
- vtysh_start_shell_cmd,
- "start-shell",
- "Start UNIX shell\n")
-{
- execute_command("sh", 0, NULL, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN (vtysh_start_bash,
- vtysh_start_bash_cmd,
- "start-shell bash",
- "Start UNIX shell\n"
- "Start bash\n")
-{
- execute_command("bash", 0, NULL, NULL);
- return CMD_SUCCESS;
-}
-
-DEFUN (vtysh_start_zsh,
- vtysh_start_zsh_cmd,
- "start-shell zsh",
- "Start UNIX shell\n"
- "Start Z shell\n")
-{
- execute_command("zsh", 0, NULL, NULL);
- return CMD_SUCCESS;
-}
-#endif
-
DEFUN (config_list,
config_list_cmd,
"list [permutations]",
@@ -5139,6 +5326,16 @@ void vtysh_init_vty(void)
install_element(ENABLE_NODE, &vtysh_copy_to_running_cmd);
install_element(ENABLE_NODE, &show_route_map_cmd);
+ install_element(ENABLE_NODE, &show_ip_prefix_list_cmd);
+ install_element(ENABLE_NODE, &show_ip_prefix_list_summary_cmd);
+ install_element(ENABLE_NODE, &show_ip_prefix_list_detail_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_prefix_list_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_prefix_list_summary_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_prefix_list_detail_cmd);
+ install_element(ENABLE_NODE, &show_ip_access_list_cmd);
+ install_element(ENABLE_NODE, &show_ip_access_list_name_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_access_list_cmd);
+ install_element(ENABLE_NODE, &show_ipv6_access_list_name_cmd);
/* "write terminal" command. */
install_element(ENABLE_NODE, &vtysh_write_terminal_cmd);
@@ -5169,16 +5366,6 @@ void vtysh_init_vty(void)
install_element(VIEW_NODE, &vtysh_mtrace_cmd);
install_element(VIEW_NODE, &vtysh_ping6_cmd);
install_element(VIEW_NODE, &vtysh_traceroute6_cmd);
-#if defined(HAVE_SHELL_ACCESS)
- install_element(VIEW_NODE, &vtysh_telnet_cmd);
- install_element(VIEW_NODE, &vtysh_telnet_port_cmd);
- install_element(VIEW_NODE, &vtysh_ssh_cmd);
-#endif
-#if defined(HAVE_SHELL_ACCESS)
- install_element(ENABLE_NODE, &vtysh_start_shell_cmd);
- install_element(ENABLE_NODE, &vtysh_start_bash_cmd);
- install_element(ENABLE_NODE, &vtysh_start_zsh_cmd);
-#endif
/* debugging */
install_element(VIEW_NODE, &vtysh_show_error_code_cmd);
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index 7758cea..b1d57aa 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -68,6 +68,14 @@ extern struct event_loop *master;
VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
VTYSH_BGPD | VTYSH_ISISD | VTYSH_PIMD | VTYSH_EIGRPD | \
VTYSH_FABRICD
+#define VTYSH_ACCESS_LIST_SHOW \
+ VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
+ VTYSH_BGPD | VTYSH_ISISD | VTYSH_PIMD | VTYSH_EIGRPD | \
+ VTYSH_FABRICD
+#define VTYSH_PREFIX_LIST_SHOW \
+ VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
+ VTYSH_BGPD | VTYSH_ISISD | VTYSH_PIMD | VTYSH_EIGRPD | \
+ VTYSH_FABRICD
#define VTYSH_INTERFACE_SUBSET \
VTYSH_OSPFD | VTYSH_OSPF6D | \
VTYSH_ISISD | VTYSH_PIMD | VTYSH_PIM6D | VTYSH_NHRPD | \
@@ -75,7 +83,7 @@ extern struct event_loop *master;
VTYSH_VRRPD | VTYSH_MGMTD
#define VTYSH_INTERFACE VTYSH_INTERFACE_SUBSET | VTYSH_BGPD
#define VTYSH_VRF VTYSH_INTERFACE_SUBSET | VTYSH_BGPD
-#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD
+#define VTYSH_KEYS VTYSH_MGMTD | VTYSH_EIGRPD | VTYSH_OSPF6D | VTYSH_OSPFD
/* Daemons who can process nexthop-group configs */
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
#define VTYSH_SR VTYSH_ZEBRA|VTYSH_PATHD
@@ -90,7 +98,17 @@ enum vtysh_write_integrated {
WRITE_INTEGRATED_YES
};
+enum display_type {
+ normal_display,
+ summary_display,
+ detail_display,
+ sequential_display,
+ longer_display,
+ first_match_display
+};
+
extern enum vtysh_write_integrated vtysh_write_integrated;
+extern enum display_type display_type;
extern char frr_config[];
extern char vtydir[];
diff --git a/yang/confd/confd.frr-ripd.yang b/yang/confd/confd.frr-ripd.yang
deleted file mode 100644
index 7bbe54c..0000000
--- a/yang/confd/confd.frr-ripd.yang
+++ /dev/null
@@ -1,24 +0,0 @@
-module confd.frr-ripd {
- namespace "urn:dummy";
- prefix "dummy";
-
- import tailf-common {
- prefix tailf;
- }
- import frr-ripd {
- prefix frr-ripd;
- }
-
- tailf:annotate-module "frr-ripd" {
- tailf:annotate-statement "container[name='ripd']" {
- tailf:annotate-statement "list[name='instance']" {
- tailf:annotate-statement "container[name='state']" {
- tailf:callpoint "state";
- }
- }
- }
- tailf:annotate-statement "rpc[name='clear-rip-route']" {
- tailf:actionpoint "actionpoint";
- }
- }
-}
diff --git a/yang/confd/confd.frr-ripngd.yang b/yang/confd/confd.frr-ripngd.yang
deleted file mode 100644
index 83383fb..0000000
--- a/yang/confd/confd.frr-ripngd.yang
+++ /dev/null
@@ -1,24 +0,0 @@
-module confd.frr-ripngd {
- namespace "urn:dummy";
- prefix "dummy";
-
- import tailf-common {
- prefix tailf;
- }
- import frr-ripngd {
- prefix frr-ripngd;
- }
-
- tailf:annotate-module "frr-ripngd" {
- tailf:annotate-statement "container[name='ripngd']" {
- tailf:annotate-statement "list[name='instance']" {
- tailf:annotate-statement "container[name='state']" {
- tailf:callpoint "state";
- }
- }
- }
- tailf:annotate-statement "rpc[name='clear-ripng-route']" {
- tailf:actionpoint "actionpoint";
- }
- }
-}
diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang
index c679f3b..abfb14c 100644
--- a/yang/frr-bgp-route-map.yang
+++ b/yang/frr-bgp-route-map.yang
@@ -542,7 +542,7 @@ identity set-extcommunity-color {
augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:rmap-match-condition/frr-route-map:match-condition" {
case local-preference {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-local-preference')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-local-preference')";
leaf local-preference {
type uint32 {
range "0..4294967295";
@@ -551,21 +551,21 @@ identity set-extcommunity-color {
}
case alias {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-alias')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-alias')";
leaf alias {
type string;
}
}
case script {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-script')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-script')";
leaf script {
type string;
}
}
case origin {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-origin')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-origin')";
leaf origin {
type enumeration {
enum "egp" {
@@ -588,7 +588,7 @@ identity set-extcommunity-color {
}
case rpki {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:rpki')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:rpki')";
leaf rpki {
type enumeration {
enum "invalid" {
@@ -634,7 +634,7 @@ identity set-extcommunity-color {
}
case probability {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:probability')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:probability')";
leaf probability {
type uint8 {
range "0..100";
@@ -643,14 +643,14 @@ identity set-extcommunity-color {
}
case source-vrf {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:source-vrf')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:source-vrf')";
leaf source-vrf {
type string;
}
}
case peer {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:peer')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:peer')";
choice peer {
description
"Value of the peer";
@@ -689,10 +689,10 @@ identity set-extcommunity-color {
}
case access-list-name {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:mac-address-list') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:as-path-list') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ip-route-source') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ip-route-source-prefix-list')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:mac-address-list') or "
+ + "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:as-path-list') or "
+ + "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:ip-route-source') or "
+ + "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:ip-route-source-prefix-list')";
description
"Access-list name";
leaf list-name {
@@ -701,7 +701,7 @@ identity set-extcommunity-color {
}
case evpn-default-route {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-default-route')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:evpn-default-route')";
description
"Match default EVPN type-5 route";
leaf evpn-default-route {
@@ -710,7 +710,7 @@ identity set-extcommunity-color {
}
case evpn-vni {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-vni')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:evpn-vni')";
description
"Match eVPN VNI";
leaf evpn-vni {
@@ -721,7 +721,7 @@ identity set-extcommunity-color {
}
case evpn-route-type {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-route-type')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:evpn-route-type')";
description
"Match eVPN route-type";
leaf evpn-route-type {
@@ -756,7 +756,7 @@ identity set-extcommunity-color {
}
case evpn-rd {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:evpn-rd')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:evpn-rd')";
description
"Match eVPN route-distinguisher";
leaf route-distinguisher {
@@ -765,9 +765,9 @@ identity set-extcommunity-color {
}
case comm-list-name {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-community') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-large-community') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:match-extcommunity')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-community') or "
+ + "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-large-community') or "
+ + "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:match-extcommunity')";
container comm-list {
leaf comm-list-name {
mandatory true;
@@ -790,7 +790,7 @@ identity set-extcommunity-color {
}
case ipv4-address {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ipv4-nexthop')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:ipv4-nexthop')";
leaf ipv4-address {
type inet:ipv4-address;
description
@@ -799,7 +799,7 @@ identity set-extcommunity-color {
}
case ipv6-address {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:ipv6-nexthop')";
+ when "derived-from-or-self(../frr-route-map:condition, 'frr-bgp-route-map:ipv6-nexthop')";
leaf ipv6-address {
type inet:ipv6-address;
description
@@ -817,7 +817,7 @@ identity set-extcommunity-color {
augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:rmap-set-action/frr-route-map:set-action" {
case distance {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:distance')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:distance')";
leaf distance {
type uint8 {
range "1..255";
@@ -826,7 +826,7 @@ identity set-extcommunity-color {
}
case extcommunity-none {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-none')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-none')";
description
"Value of the BGP extended community attribute";
leaf extcommunity-none {
@@ -836,7 +836,7 @@ identity set-extcommunity-color {
}
case extcommunity-rt {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-rt')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-rt')";
description
"Value of the ext-community";
leaf extcommunity-rt {
@@ -858,7 +858,7 @@ identity set-extcommunity-color {
}
case extcommunity-soo {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-soo')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-soo')";
description
"Value of the ext-community";
leaf extcommunity-soo {
@@ -869,7 +869,7 @@ identity set-extcommunity-color {
}
case extcommunity-lb {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-lb')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-lb')";
container extcommunity-lb {
description
"Value of the ext-community.";
@@ -881,9 +881,7 @@ identity set-extcommunity-color {
leaf bandwidth {
when "../lb-type = 'explicit-bandwidth'";
mandatory true;
- type uint16 {
- range "1..25600";
- }
+ type uint32;
description
"Bandwidth value in Mbps";
}
@@ -892,7 +890,7 @@ identity set-extcommunity-color {
}
case extcommunity-color {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-color')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-extcommunity-color')";
description
"Value of the ext-community";
leaf extcommunity-color {
@@ -905,7 +903,7 @@ identity set-extcommunity-color {
}
case ipv4-address {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv4-vpn-address')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:ipv4-vpn-address')";
description
"Set the IPv4 address";
leaf ipv4-address {
@@ -914,15 +912,15 @@ identity set-extcommunity-color {
}
case ipv4-nexthop {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-ipv4-nexthop')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-ipv4-nexthop')";
leaf ipv4-nexthop {
type string;
}
}
case ipv6-address {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-nexthop-global') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-vpn-address')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:ipv6-nexthop-global') or "
+ + "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:ipv6-vpn-address')";
description
"Set the IPv6 address";
leaf ipv6-address {
@@ -931,15 +929,15 @@ identity set-extcommunity-color {
}
case preference {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-prefer-global') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:ipv6-peer-address')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:ipv6-prefer-global') or "
+ + "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:ipv6-peer-address')";
leaf preference {
type boolean;
}
}
case label-index {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:label-index')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:label-index')";
leaf label-index {
type uint32 {
range "0..1048560";
@@ -948,14 +946,14 @@ identity set-extcommunity-color {
}
case local-pref {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-local-preference')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-local-preference')";
leaf local-pref {
type string;
}
}
case weight {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:weight')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:weight')";
leaf weight {
type uint32 {
range "0..4294967295";
@@ -964,7 +962,7 @@ identity set-extcommunity-color {
}
case origin {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-origin')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-origin')";
leaf origin {
type enumeration {
enum "egp" {
@@ -987,14 +985,14 @@ identity set-extcommunity-color {
}
case originator-id {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:originator-id')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:originator-id')";
leaf originator-id {
type inet:ipv4-address;
}
}
case table {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:table')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:table')";
leaf table {
type uint32 {
range "1..4294967295";
@@ -1003,7 +1001,7 @@ identity set-extcommunity-color {
}
case atomic-aggregate {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:atomic-aggregate')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:atomic-aggregate')";
leaf atomic-aggregate {
type empty;
}
@@ -1019,7 +1017,7 @@ identity set-extcommunity-color {
}
case as-path-prepend {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:as-path-prepend')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:as-path-prepend')";
choice as-path-prepend {
description
"Value of the BGP AS-path attribute";
@@ -1044,7 +1042,7 @@ identity set-extcommunity-color {
}
case as-path-exclude {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:as-path-exclude')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:as-path-exclude')";
leaf exclude-as-path {
type string;
description
@@ -1053,7 +1051,7 @@ identity set-extcommunity-color {
}
case as-path-replace {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:as-path-replace')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:as-path-replace')";
leaf replace-as-path {
type string;
description
@@ -1062,7 +1060,7 @@ identity set-extcommunity-color {
}
case community {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-community')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-community')";
choice community {
description
"Value of the BGP community attribute";
@@ -1085,7 +1083,7 @@ identity set-extcommunity-color {
}
case large-community {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:set-large-community')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:set-large-community')";
choice large-community {
description
"Value of the BGP large-community attribute";
@@ -1108,7 +1106,7 @@ identity set-extcommunity-color {
}
case aggregator {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:aggregator')";
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:aggregator')";
container aggregator {
leaf aggregator-asn {
type asn-type;
@@ -1127,9 +1125,9 @@ identity set-extcommunity-color {
}
case comm-list-name {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:comm-list-delete') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'frr-bgp-route-map:large-comm-list-delete') or "
- + "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action,
+ when "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:comm-list-delete') or "
+ + "derived-from-or-self(../frr-route-map:action, 'frr-bgp-route-map:large-comm-list-delete') or "
+ + "derived-from-or-self(../frr-route-map:action,
'frr-bgp-route-map:extended-comm-list-delete')";
leaf comm-list-name {
type bgp-filter:bgp-list-name;
@@ -1157,7 +1155,7 @@ identity set-extcommunity-color {
}
case l3vpn-nexthop-encapsulation {
when
- "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action,
+ "derived-from-or-self(../frr-route-map:action,
'frr-bgp-route-map:set-l3vpn-nexthop-encapsulation')";
description
"Accept L3VPN traffic over other than LSP encapsulation";
diff --git a/yang/frr-isisd.yang b/yang/frr-isisd.yang
index 5d7c739..d1a08fa 100644
--- a/yang/frr-isisd.yang
+++ b/yang/frr-isisd.yang
@@ -685,7 +685,7 @@ module frr-isisd {
type uint32 {
range "0..16777215";
}
- must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
+ must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide' or not(/frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style)";
default "10";
description
"Default level-1 metric for this IS-IS circuit.";
@@ -695,7 +695,7 @@ module frr-isisd {
type uint32 {
range "0..16777215";
}
- must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide'";
+ must ". < 64 or /frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style = 'wide' or not(/frr-isisd:isis/instance[area-tag = current()/../../area-tag]/metric-style)";
default "10";
description
"Default level-2 metric for this IS-IS circuit.";
diff --git a/yang/frr-ospf-route-map.yang b/yang/frr-ospf-route-map.yang
index ad7ba5c..6e7c85d 100644
--- a/yang/frr-ospf-route-map.yang
+++ b/yang/frr-ospf-route-map.yang
@@ -32,7 +32,7 @@ module frr-ospf-route-map {
augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:rmap-set-action/frr-route-map:set-action" {
case metric-type {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'metric-type')";
+ when "derived-from-or-self(../frr-route-map:action, 'metric-type')";
leaf metric-type {
type enumeration {
enum "type-1" {
diff --git a/yang/frr-ospf6-route-map.yang b/yang/frr-ospf6-route-map.yang
index e5d4969..7e2e56d 100644
--- a/yang/frr-ospf6-route-map.yang
+++ b/yang/frr-ospf6-route-map.yang
@@ -38,7 +38,7 @@ module frr-ospf6-route-map {
augment "/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:rmap-set-action/frr-route-map:set-action" {
case ipv6-address {
- when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action, 'forwarding-address')";
+ when "derived-from-or-self(../frr-route-map:action, 'forwarding-address')";
leaf ipv6-address {
type inet:ipv6-address;
}
diff --git a/yang/frr-route-map.yang b/yang/frr-route-map.yang
index 7cb13b6..26d56ac 100644
--- a/yang/frr-route-map.yang
+++ b/yang/frr-route-map.yang
@@ -268,7 +268,7 @@ module frr-route-map {
when "derived-from-or-self(../condition, 'match-tag')";
leaf tag {
type uint32 {
- range "1..4294967295";
+ range "0..4294967295";
}
}
}
diff --git a/yang/frr-test-module.yang b/yang/frr-test-module.yang
index 6cc60e8..dcf204a 100644
--- a/yang/frr-test-module.yang
+++ b/yang/frr-test-module.yang
@@ -80,6 +80,23 @@ module frr-test-module {
}
}
}
+ action ping {
+ input {
+ leaf data {
+ type string;
+ }
+ }
+ output {
+ leaf vrf {
+ type string;
+ }
+ // can't use the same name in input and output
+ // because of a bug in libyang < 2.1.148
+ leaf data-out {
+ type string;
+ }
+ }
+ }
}
}
choice achoice {
diff --git a/yang/frr-zebra.yang b/yang/frr-zebra.yang
index c338a23..79c524a 100644
--- a/yang/frr-zebra.yang
+++ b/yang/frr-zebra.yang
@@ -145,16 +145,16 @@ module frr-zebra {
"Zebra interface type bond.";
}
- identity zif-bond-slave {
+ identity zif-macvlan {
base zebra-interface-type;
description
- "Zebra interface type bond slave.";
+ "Zebra interface type macvlan.";
}
- identity zif-macvlan {
+ identity zif-gre {
base zebra-interface-type;
description
- "Zebra interface type macvlan.";
+ "Zebra interface type gre.";
}
/*
@@ -2733,6 +2733,12 @@ module frr-zebra {
description
"The VNI multicast group for BUM traffic.";
}
+
+ leaf bond {
+ type frr-interface:interface-ref;
+ description
+ "The bond interface this interface belongs to.";
+ }
}
}
}
diff --git a/yang/ietf/frr-deviations-ietf-key-chain.yang b/yang/ietf/frr-deviations-ietf-key-chain.yang
new file mode 100644
index 0000000..aa6a41f
--- /dev/null
+++ b/yang/ietf/frr-deviations-ietf-key-chain.yang
@@ -0,0 +1,29 @@
+module frr-deviations-ietf-key-chain {
+ yang-version 1.1;
+ namespace "http://frrouting.org/yang/frr-deviations-ietf-key-chain";
+ prefix frr-deviations-ietf-key-chain;
+
+ import ietf-key-chain {
+ prefix kc;
+ }
+
+ organization
+ "FRRouting";
+ contact
+ "FRR Users List: <mailto:frog@lists.frrouting.org>
+ FRR Development List: <mailto:dev@lists.frrouting.org>";
+ description
+ "This module defines deviation statements for the ietf-key-chain
+ module.";
+
+ revision 2024-03-03 {
+ description "Initial revision.";
+ reference "RFC 8177: YANG Data Model for Key Chains";
+ }
+
+ deviation /kc:key-chains/kc:key-chain/kc:key/kc:crypto-algorithm {
+ deviate replace {
+ mandatory false;
+ }
+ }
+}
diff --git a/yang/ietf/frr-deviations-ietf-routing.yang b/yang/ietf/frr-deviations-ietf-routing.yang
index 15ceb6b..5c0ae30 100644
--- a/yang/ietf/frr-deviations-ietf-routing.yang
+++ b/yang/ietf/frr-deviations-ietf-routing.yang
@@ -6,6 +6,9 @@ module frr-deviations-ietf-routing {
import ietf-routing {
prefix ietf-routing;
}
+ import ietf-rip {
+ prefix ietf-rip;
+ }
organization
"FRRouting";
diff --git a/yang/ietf/ietf-key-chain.yang b/yang/ietf/ietf-key-chain.yang
new file mode 100644
index 0000000..445d199
--- /dev/null
+++ b/yang/ietf/ietf-key-chain.yang
@@ -0,0 +1,382 @@
+module ietf-key-chain {
+ yang-version 1.1;
+ namespace "urn:ietf:params:xml:ns:yang:ietf-key-chain";
+ prefix key-chain;
+
+ import ietf-yang-types {
+ prefix yang;
+ }
+ import ietf-netconf-acm {
+ prefix nacm;
+ }
+
+ organization
+ "IETF RTGWG - Routing Area Working Group";
+ contact
+ "WG Web: <https://datatracker.ietf.org/group/rtgwg>
+ WG List: <mailto:rtgwg@ietf.org>
+
+ Editor: Acee Lindem
+ <mailto:acee@cisco.com>
+ Yingzhen Qu
+ <mailto:yingzhen.qu@huawei.com>
+ Derek Yeung
+ <mailto:derek@arrcus.com>
+ Ing-Wher Chen
+ <mailto:Ing-Wher_Chen@jabail.com>
+ Jeffrey Zhang
+ <mailto:zzhang@juniper.net>";
+
+ description
+ "This YANG module defines the generic configuration
+ data for key chains. It is intended that the module
+ will be extended by vendors to define vendor-specific
+ key chain configuration parameters.
+
+ Copyright (c) 2017 IETF Trust and the persons identified as
+ authors of the code. All rights reserved.
+
+ Redistribution and use in source and binary forms, with or
+ without modification, is permitted pursuant to, and subject
+ to the license terms contained in, the Simplified BSD License
+ set forth in Section 4.c of the IETF Trust's Legal Provisions
+ Relating to IETF Documents
+ (http://trustee.ietf.org/license-info).
+
+ This version of this YANG module is part of RFC 8177;
+ see the RFC itself for full legal notices.";
+
+ reference "RFC 8177";
+
+ revision 2017-06-15 {
+ description
+ "Initial RFC Revision";
+ reference "RFC 8177: YANG Data Model for Key Chains";
+ }
+
+ feature hex-key-string {
+ description
+ "Support hexadecimal key string.";
+ }
+
+ feature accept-tolerance {
+ description
+ "Support the tolerance or acceptance limit.";
+ }
+
+ feature independent-send-accept-lifetime {
+ description
+ "Support for independent send and accept key lifetimes.";
+ }
+
+ feature crypto-hmac-sha-1-12 {
+ description
+ "Support for TCP HMAC-SHA-1 12-byte digest hack.";
+ }
+
+ feature cleartext {
+ description
+ "Support for cleartext algorithm. Usage is
+ NOT RECOMMENDED.";
+ }
+
+ feature aes-cmac-prf-128 {
+ description
+ "Support for AES Cipher-based Message Authentication
+ Code Pseudorandom Function.";
+ }
+
+ feature aes-key-wrap {
+ description
+ "Support for Advanced Encryption Standard (AES) Key Wrap.";
+ }
+
+ feature replay-protection-only {
+ description
+ "Provide replay protection without any authentication
+ as required by protocols such as Bidirectional
+ Forwarding Detection (BFD).";
+ }
+ identity crypto-algorithm {
+ description
+ "Base identity of cryptographic algorithm options.";
+ }
+
+ identity hmac-sha-1-12 {
+ base crypto-algorithm;
+ if-feature "crypto-hmac-sha-1-12";
+ description
+ "The HMAC-SHA1-12 algorithm.";
+ }
+
+ identity aes-cmac-prf-128 {
+ base crypto-algorithm;
+ if-feature "aes-cmac-prf-128";
+ description
+ "The AES-CMAC-PRF-128 algorithm - required by
+ RFC 5926 for TCP-AO key derivation functions.";
+ }
+
+ identity md5 {
+ base crypto-algorithm;
+ description
+ "The MD5 algorithm.";
+ }
+
+ identity sha-1 {
+ base crypto-algorithm;
+ description
+ "The SHA-1 algorithm.";
+ }
+
+ identity hmac-sha-1 {
+ base crypto-algorithm;
+ description
+ "HMAC-SHA-1 authentication algorithm.";
+ }
+
+ identity hmac-sha-256 {
+ base crypto-algorithm;
+ description
+ "HMAC-SHA-256 authentication algorithm.";
+ }
+
+ identity hmac-sha-384 {
+ base crypto-algorithm;
+ description
+ "HMAC-SHA-384 authentication algorithm.";
+ }
+
+ identity hmac-sha-512 {
+ base crypto-algorithm;
+ description
+ "HMAC-SHA-512 authentication algorithm.";
+ }
+
+ identity cleartext {
+ base crypto-algorithm;
+ if-feature "cleartext";
+ description
+ "cleartext.";
+ }
+
+ identity replay-protection-only {
+ base crypto-algorithm;
+ if-feature "replay-protection-only";
+ description
+ "Provide replay protection without any authentication as
+ required by protocols such as Bidirectional Forwarding
+ Detection (BFD).";
+ }
+
+ typedef key-chain-ref {
+ type leafref {
+ path
+ "/key-chain:key-chains/key-chain:key-chain/key-chain:name";
+ }
+ description
+ "This type is used by data models that need to reference
+ configured key chains.";
+ }
+
+ grouping lifetime {
+ description
+ "Key lifetime specification.";
+ choice lifetime {
+ default "always";
+ description
+ "Options for specifying key accept or send lifetimes";
+ case always {
+ leaf always {
+ type empty;
+ description
+ "Indicates key lifetime is always valid.";
+ }
+ }
+ case start-end-time {
+ leaf start-date-time {
+ type yang:date-and-time;
+ description
+ "Start time.";
+ }
+ choice end-time {
+ default "infinite";
+ description
+ "End-time setting.";
+ case infinite {
+ leaf no-end-time {
+ type empty;
+ description
+ "Indicates key lifetime end-time is infinite.";
+ }
+ }
+ case duration {
+ leaf duration {
+ type uint32 {
+ range "1..2147483646";
+ }
+ units "seconds";
+ description
+ "Key lifetime duration, in seconds";
+ }
+ }
+ case end-date-time {
+ leaf end-date-time {
+ type yang:date-and-time;
+ description
+ "End time.";
+ }
+ }
+ }
+ }
+ }
+ }
+
+ container key-chains {
+ description
+ "All configured key-chains on the device.";
+ list key-chain {
+ key "name";
+ description
+ "List of key-chains.";
+ leaf name {
+ type string;
+ description
+ "Name of the key-chain.";
+ }
+ leaf description {
+ type string;
+ description
+ "A description of the key-chain";
+ }
+ container accept-tolerance {
+ if-feature "accept-tolerance";
+ description
+ "Tolerance for key lifetime acceptance (seconds).";
+ leaf duration {
+ type uint32;
+ units "seconds";
+ default "0";
+ description
+ "Tolerance range, in seconds.";
+ }
+ }
+ leaf last-modified-timestamp {
+ type yang:date-and-time;
+ config false;
+ description
+ "Timestamp of the most recent update to the key-chain";
+ }
+ list key {
+ key "key-id";
+ description
+ "Single key in key chain.";
+ leaf key-id {
+ type uint64;
+ description
+ "Numeric value uniquely identifying the key";
+ }
+ container lifetime {
+ description
+ "Specify a key's lifetime.";
+ choice lifetime {
+ description
+ "Options for specification of send and accept
+ lifetimes.";
+ case send-and-accept-lifetime {
+ description
+ "Send and accept key have the same lifetime.";
+ container send-accept-lifetime {
+ description
+ "Single lifetime specification for both
+ send and accept lifetimes.";
+ uses lifetime;
+ }
+ }
+ case independent-send-accept-lifetime {
+ if-feature "independent-send-accept-lifetime";
+ description
+ "Independent send and accept key lifetimes.";
+ container send-lifetime {
+ description
+ "Separate lifetime specification for send
+ lifetime.";
+ uses lifetime;
+ }
+ container accept-lifetime {
+ description
+ "Separate lifetime specification for accept
+ lifetime.";
+ uses lifetime;
+ }
+ }
+ }
+ }
+ leaf crypto-algorithm {
+ type identityref {
+ base crypto-algorithm;
+ }
+ mandatory true;
+ description
+ "Cryptographic algorithm associated with key.";
+ }
+ container key-string {
+ description
+ "The key string.";
+ nacm:default-deny-all;
+ choice key-string-style {
+ description
+ "Key string styles";
+ case keystring {
+ leaf keystring {
+ type string;
+ description
+ "Key string in ASCII format.";
+ }
+ }
+ case hexadecimal {
+ if-feature "hex-key-string";
+ leaf hexadecimal-string {
+ type yang:hex-string;
+ description
+ "Key in hexadecimal string format. When compared
+ to ASCII, specification in hexadecimal affords
+ greater key entropy with the same number of
+ internal key-string octets. Additionally, it
+ discourages usage of well-known words or
+ numbers.";
+ }
+ }
+ }
+ }
+ leaf send-lifetime-active {
+ type boolean;
+ config false;
+ description
+ "Indicates if the send lifetime of the
+ key-chain key is currently active.";
+ }
+ leaf accept-lifetime-active {
+ type boolean;
+ config false;
+ description
+ "Indicates if the accept lifetime of the
+ key-chain key is currently active.";
+ }
+ }
+ }
+ container aes-key-wrap {
+ if-feature "aes-key-wrap";
+ description
+ "AES Key Wrap encryption for key-chain key-strings. The
+ encrypted key-strings are encoded as hexadecimal key
+ strings using the hex-key-string leaf.";
+ leaf enable {
+ type boolean;
+ default "false";
+ description
+ "Enable AES Key Wrap encryption.";
+ }
+ }
+ }
+}
diff --git a/yang/subdir.am b/yang/subdir.am
index 0bdf937..71aa040 100644
--- a/yang/subdir.am
+++ b/yang/subdir.am
@@ -35,9 +35,11 @@ dist_yangmodels_DATA += yang/frr-bgp-route-map.yang
dist_yangmodels_DATA += yang/frr-vrf.yang
dist_yangmodels_DATA += yang/frr-route-types.yang
dist_yangmodels_DATA += yang/frr-routing.yang
+dist_yangmodels_DATA += yang/ietf/frr-deviations-ietf-key-chain.yang
dist_yangmodels_DATA += yang/ietf/ietf-routing-types.yang
dist_yangmodels_DATA += yang/ietf/ietf-interfaces.yang
dist_yangmodels_DATA += yang/ietf/ietf-bgp-types.yang
+dist_yangmodels_DATA += yang/ietf/ietf-key-chain.yang
dist_yangmodels_DATA += yang/ietf/ietf-netconf-acm.yang
dist_yangmodels_DATA += yang/ietf/ietf-netconf.yang
dist_yangmodels_DATA += yang/ietf/ietf-netconf-with-defaults.yang
@@ -104,31 +106,4 @@ endif
CLEANFILES += \
yang/*.c \
yang/ietf/*.c \
- yang/confd/*.c \
#
-
-if CONFD
-
-SUBMODULES = $(shell cd $(top_srcdir); grep -l belongs-to $(dist_yangmodels_DATA))
-EXCLUDED_MODULES = $(SUBMODULES) yang/frr-module-translator.yang
-YANG_MODULES = $(filter-out $(EXCLUDED_MODULES),$(dist_yangmodels_DATA))
-
-fxsdir = $(sysconfdir)/confd
-fxs_DATA = $(YANG_MODULES:.yang=.fxs)
-
-SUFFIXES += .fxs
-CLEANFILES += $(fxs_DATA)
-
-AM_V_CONFDC = $(AM_V_CONFDC_@AM_V@)
-AM_V_CONFDC_ = $(AM_V_CONFDC_@AM_DEFAULT_V@)
-AM_V_CONFDC_0 = @echo " CONFDC " $@;
-
-CONFDC_FLAGS = --yangpath $(srcdir)/yang --yangpath $(srcdir)/yang/ietf
-
-yang/%.fxs: yang/%.yang yang/confd/confd.%.yang
- $(AM_V_CONFDC)$(CONFDC) $(CONFDC_FLAGS) -c -o $@ -a $(srcdir)/yang/confd/confd.$*.yang -- $<
-
-yang/%.fxs: yang/%.yang
- $(AM_V_CONFDC)$(CONFDC) $(CONFDC_FLAGS) -c -o $@ -- $<
-
-endif
diff --git a/zebra/.gitignore b/zebra/.gitignore
index 41a86e7..f10240d 100644
--- a/zebra/.gitignore
+++ b/zebra/.gitignore
@@ -1,3 +1,4 @@
zebra
zebra.conf
client
+fpm_listener
diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c
index a7cccdb..037d0b6 100644
--- a/zebra/debug_nl.c
+++ b/zebra/debug_nl.c
@@ -534,6 +534,12 @@ const char *rtm_rta2str(int type)
return "NH_ID";
case RTA_EXPIRES:
return "EXPIRES";
+ case RTA_VIA:
+ return "VIA";
+ case RTA_ENCAP_TYPE:
+ return "RTA_ENCAP_TYPE";
+ case RTA_ENCAP:
+ return "RTA_ENCAP";
default:
return "UNKNOWN";
}
diff --git a/zebra/dpdk/zebra_dplane_dpdk.c b/zebra/dpdk/zebra_dplane_dpdk.c
index 4c32044..4111551 100644
--- a/zebra/dpdk/zebra_dplane_dpdk.c
+++ b/zebra/dpdk/zebra_dplane_dpdk.c
@@ -52,7 +52,7 @@ void zd_dpdk_stat_show(struct vty *vty)
static void zd_dpdk_flow_stat_show(struct vty *vty, int in_ifindex,
intptr_t dp_flow_ptr)
{
- struct rte_flow_action_count count = {.shared = 0, .id = 0};
+ struct rte_flow_action_count count = { .id = 0 };
const struct rte_flow_action actions[] = {
{
.type = RTE_FLOW_ACTION_TYPE_COUNT,
@@ -105,8 +105,7 @@ static int zd_dpdk_pbr_show_rules_walkcb(struct hash_bucket *bucket, void *arg)
ifp = if_lookup_by_name_vrf(rule->ifname, vrf);
if (ifp)
- zd_dpdk_flow_stat_show(vty, ifp->ifindex,
- zaction->dp_flow_ptr);
+ zd_dpdk_flow_stat_show(vty, ifp->ifindex, zaction->dp_flow_ptr);
}
return HASHWALK_CONTINUE;
}
@@ -153,8 +152,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
zlog_debug(
"PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; in_port %d missing\n",
- dplane_ctx_rule_get_ifname(ctx), seq, pri,
- unique, in_ifindex);
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, in_ifindex);
return;
}
@@ -163,8 +161,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
if (IS_ZEBRA_DEBUG_DPLANE_DPDK_DETAIL)
zlog_debug(
"PBR dpdk flow create ifname %s seq %d pri %u unique %d failed; out_port %d missing\n",
- dplane_ctx_rule_get_ifname(ctx), seq, pri,
- unique, out_ifindex);
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, out_ifindex);
return;
}
@@ -180,7 +177,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
memset(&ip, 0, sizeof(ip));
memset(&ip_mask, 0, sizeof(ip_mask));
- if (filter_bm & PBR_FILTER_SRC_IP) {
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_SRC_IP)) {
const struct prefix *src_ip;
src_ip = dplane_ctx_rule_get_src_ip(ctx);
@@ -188,7 +185,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
masklen2ip(src_ip->prefixlen, &tmp_mask);
ip_mask.hdr.src_addr = tmp_mask.s_addr;
}
- if (filter_bm & PBR_FILTER_DST_IP) {
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_DST_IP)) {
const struct prefix *dst_ip;
dst_ip = dplane_ctx_rule_get_dst_ip(ctx);
@@ -196,7 +193,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
masklen2ip(dst_ip->prefixlen, &tmp_mask);
ip_mask.hdr.dst_addr = tmp_mask.s_addr;
}
- if (filter_bm & PBR_FILTER_IP_PROTOCOL) {
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_IP_PROTOCOL)) {
ip.hdr.next_proto_id = dplane_ctx_rule_get_ipproto(ctx);
ip_mask.hdr.next_proto_id = UINT8_MAX;
}
@@ -206,17 +203,15 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
items[item_cnt].last = NULL;
++item_cnt;
- if ((filter_bm & (PBR_FILTER_SRC_PORT | PBR_FILTER_DST_PORT))) {
+ if (CHECK_FLAG(filter_bm, (PBR_FILTER_SRC_PORT | PBR_FILTER_DST_PORT))) {
memset(&udp, 0, sizeof(udp));
memset(&udp_mask, 0, sizeof(udp_mask));
- if (filter_bm & PBR_FILTER_SRC_PORT) {
- udp.hdr.src_port =
- RTE_BE16(dplane_ctx_rule_get_src_port(ctx));
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_SRC_PORT)) {
+ udp.hdr.src_port = RTE_BE16(dplane_ctx_rule_get_src_port(ctx));
udp_mask.hdr.src_port = UINT16_MAX;
}
- if (filter_bm & PBR_FILTER_DST_PORT) {
- udp.hdr.dst_port =
- RTE_BE16(dplane_ctx_rule_get_dst_port(ctx));
+ if (CHECK_FLAG(filter_bm, PBR_FILTER_DST_PORT)) {
+ udp.hdr.dst_port = RTE_BE16(dplane_ctx_rule_get_dst_port(ctx));
udp_mask.hdr.dst_port = UINT16_MAX;
}
items[item_cnt].type = RTE_FLOW_ITEM_TYPE_UDP;
@@ -273,8 +268,7 @@ static void zd_dpdk_rule_add(struct zebra_dplane_ctx *ctx)
} else {
zlog_warn(
"PBR dpdk flow create failed ifname %s seq %d pri %u unique %d; rc %d\n",
- dplane_ctx_rule_get_ifname(ctx), seq, pri, unique,
- error.type);
+ dplane_ctx_rule_get_ifname(ctx), seq, pri, unique, error.type);
}
}
@@ -504,9 +498,11 @@ static void zd_dpdk_port_show_entry(struct zd_dpdk_port *dport, struct vty *vty,
if (detail) {
vty_out(vty, "DPDK port: %u\n", dport->port_id);
vty_out(vty, " Device: %s\n",
- dev_info->device ? dev_info->device->name : "-");
+ dev_info->device ? rte_dev_name(dev_info->device) : "-");
vty_out(vty, " Driver: %s\n",
- dev_info->driver_name ? dev_info->driver_name : "-");
+ dev_info->driver_name ? rte_driver_name(rte_dev_driver(
+ dev_info->device))
+ : "-");
vty_out(vty, " Interface: %s (%d)\n",
ifindex2ifname(dev_info->if_index, VRF_DEFAULT),
dev_info->if_index);
@@ -516,9 +512,8 @@ static void zd_dpdk_port_show_entry(struct zd_dpdk_port *dport, struct vty *vty,
dev_info->switch_info.port_id);
vty_out(vty, "\n");
} else {
- vty_out(vty, "%-4u %-16s %-16s %-16d %s,%u,%u\n",
- dport->port_id,
- dev_info->device ? dev_info->device->name : "-",
+ vty_out(vty, "%-4u %-16s %-16s %-16d %s,%u,%u\n", dport->port_id,
+ dev_info->device ? rte_dev_name(dev_info->device) : "-",
ifindex2ifname(dev_info->if_index, VRF_DEFAULT),
dev_info->if_index, dev_info->switch_info.name,
dev_info->switch_info.domain_id,
@@ -562,7 +557,7 @@ void zd_dpdk_port_show(struct vty *vty, uint16_t port_id, bool uj, int detail)
for (count = 0; count < RTE_MAX_ETHPORTS; ++count) {
dport = &dpdk_ctx->dpdk_ports[count];
- if (dport->flags & ZD_DPDK_PORT_FLAG_INITED)
+ if (CHECK_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_INITED))
zd_dpdk_port_show_entry(dport, vty, detail);
}
}
@@ -592,31 +587,31 @@ static void zd_dpdk_port_init(void)
dport = &dpdk_ctx->dpdk_ports[count];
count++;
dport->port_id = port_id;
- dport->flags |= ZD_DPDK_PORT_FLAG_PROBED;
+ SET_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_PROBED);
dev_info = &dport->dev_info;
if (rte_eth_dev_info_get(port_id, dev_info) < 0) {
zlog_warn("failed to get dev info for %u, %s", port_id,
rte_strerror(rte_errno));
continue;
}
- dport->flags |= ZD_DPDK_PORT_FLAG_INITED;
+ SET_FLAG(dport->flags, ZD_DPDK_PORT_FLAG_INITED);
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
- zlog_debug(
- "port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u",
- port_id,
- dev_info->device ? dev_info->device->name : "-",
- dev_info->if_index, dev_info->switch_info.name,
- dev_info->switch_info.domain_id,
- dev_info->switch_info.port_id);
+ zlog_debug("port %u, dev %s, ifI %d, sw_name %s, sw_domain %u, sw_port %u",
+ port_id,
+ dev_info->device
+ ? rte_dev_name(dev_info->device)
+ : "-",
+ dev_info->if_index,
+ dev_info->switch_info.name,
+ dev_info->switch_info.domain_id,
+ dev_info->switch_info.port_id);
if (rte_flow_isolate(port_id, 1, &error)) {
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
zlog_debug(
- "Flow isolate on port %u failed %d",
- port_id, error.type);
+ "Flow isolate on port %u failed %d", port_id, error.type);
} else {
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
- zlog_debug("Flow isolate on port %u",
- port_id);
+ zlog_debug("Flow isolate on port %u", port_id);
}
rc = rte_eth_dev_start(port_id);
if (rc) {
@@ -625,8 +620,7 @@ static void zd_dpdk_port_init(void)
continue;
}
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
- zlog_debug("DPDK port %d started in promiscuous mode ",
- port_id);
+ zlog_debug("DPDK port %d started in promiscuous mode ", port_id);
}
if (!count) {
@@ -639,13 +633,12 @@ static void zd_dpdk_port_init(void)
static int zd_dpdk_init(void)
{
int rc;
- static const char *argv[] = {(char *)"/usr/lib/frr/zebra",
- (char *)"--"};
+ static const char *argv[] = {(char *)"/usr/lib/frr/zebra", (char *)"--"};
zd_dpdk_vty_init();
frr_with_privs (&zserv_privs) {
- rc = rte_eal_init(array_size(argv), argv);
+ rc = rte_eal_init(array_size(argv), (char **)argv);
}
if (rc < 0) {
zlog_warn("EAL init failed %s", rte_strerror(rte_errno));
@@ -674,8 +667,7 @@ static int zd_dpdk_finish(struct zebra_dplane_provider *prov, bool early)
if (early) {
if (IS_ZEBRA_DEBUG_DPLANE_DPDK)
- zlog_debug("%s early finish",
- dplane_provider_get_name(prov));
+ zlog_debug("%s early finish", dplane_provider_get_name(prov));
return 0;
}
diff --git a/zebra/dpdk/zebra_dplane_dpdk.h b/zebra/dpdk/zebra_dplane_dpdk.h
index e5a3dbe..ece72d9 100644
--- a/zebra/dpdk/zebra_dplane_dpdk.h
+++ b/zebra/dpdk/zebra_dplane_dpdk.h
@@ -20,4 +20,6 @@ extern void zd_dpdk_port_show(struct vty *vty, uint16_t port_id, bool uj,
extern void zd_dpdk_stat_show(struct vty *vty);
extern void zd_dpdk_vty_init(void);
+extern struct zebra_privs_t zserv_privs;
+
#endif
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index 7ae1b2a..9ad92d6 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -30,6 +30,7 @@
#include "lib/network.h"
#include "lib/ns.h"
#include "lib/frr_pthread.h"
+#include "lib/termtable.h"
#include "zebra/debug.h"
#include "zebra/interface.h"
#include "zebra/zebra_dplane.h"
@@ -44,6 +45,8 @@
#include "zebra/debug.h"
#include "fpm/fpm.h"
+#include "zebra/dplane_fpm_nl_clippy.c"
+
#define SOUTHBOUND_DEFAULT_ADDR INADDR_LOOPBACK
/*
@@ -322,6 +325,74 @@ DEFUN(fpm_reset_counters, fpm_reset_counters_cmd,
return CMD_SUCCESS;
}
+DEFPY(fpm_show_status,
+ fpm_show_status_cmd,
+ "show fpm status [json]$json",
+ SHOW_STR FPM_STR "FPM status\n" JSON_STR)
+{
+ struct json_object *j;
+ bool connected;
+ uint16_t port;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ char buf[BUFSIZ];
+
+ connected = gfnc->socket > 0 ? true : false;
+
+ switch (gfnc->addr.ss_family) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)&gfnc->addr;
+ snprintfrr(buf, sizeof(buf), "%pI4", &sin->sin_addr);
+ port = ntohs(sin->sin_port);
+ break;
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)&gfnc->addr;
+ snprintfrr(buf, sizeof(buf), "%pI6", &sin6->sin6_addr);
+ port = ntohs(sin6->sin6_port);
+ break;
+ default:
+ strlcpy(buf, "Unknown", sizeof(buf));
+ port = FPM_DEFAULT_PORT;
+ break;
+ }
+
+ if (json) {
+ j = json_object_new_object();
+
+ json_object_boolean_add(j, "connected", connected);
+ json_object_boolean_add(j, "useNHG", gfnc->use_nhg);
+ json_object_boolean_add(j, "useRouteReplace",
+ gfnc->use_route_replace);
+ json_object_boolean_add(j, "disabled", gfnc->disabled);
+ json_object_string_add(j, "address", buf);
+ json_object_int_add(j, "port", port);
+
+ vty_json(vty, j);
+ } else {
+ struct ttable *table = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ char *out;
+
+ ttable_rowseps(table, 0, BOTTOM, true, '-');
+ ttable_add_row(table, "Address to connect to|%s", buf);
+ ttable_add_row(table, "Port|%u", port);
+ ttable_add_row(table, "Connected|%s", connected ? "Yes" : "No");
+ ttable_add_row(table, "Use Nexthop Groups|%s",
+ gfnc->use_nhg ? "Yes" : "No");
+ ttable_add_row(table, "Use Route Replace Semantics|%s",
+ gfnc->use_route_replace ? "Yes" : "No");
+ ttable_add_row(table, "Disabled|%s",
+ gfnc->disabled ? "Yes" : "No");
+
+ out = ttable_dump(table, "\n");
+ vty_out(vty, "%s\n", out);
+ XFREE(MTYPE_TMP, out);
+
+ ttable_del(table);
+ }
+
+ return CMD_SUCCESS;
+}
+
DEFUN(fpm_show_counters, fpm_show_counters_cmd,
"show fpm counters",
SHOW_STR
@@ -583,14 +654,6 @@ static void fpm_read(struct event *t)
hdr_available_bytes = fpm.msg_len - FPM_MSG_HDR_LEN;
available_bytes -= hdr_available_bytes;
- /* Sanity check: must be at least header size. */
- if (hdr->nlmsg_len < sizeof(*hdr)) {
- zlog_warn(
- "%s: [seq=%u] invalid message length %u (< %zu)",
- __func__, hdr->nlmsg_seq, hdr->nlmsg_len,
- sizeof(*hdr));
- continue;
- }
if (hdr->nlmsg_len > fpm.msg_len) {
zlog_warn(
"%s: Received a inner header length of %u that is greater than the fpm total length of %u",
@@ -620,6 +683,14 @@ static void fpm_read(struct event *t)
switch (hdr->nlmsg_type) {
case RTM_NEWROUTE:
+ /* Sanity check: need at least route msg header size. */
+ if (hdr->nlmsg_len < sizeof(struct rtmsg)) {
+ zlog_warn("%s: [seq=%u] invalid message length %u (< %zu)",
+ __func__, hdr->nlmsg_seq,
+ hdr->nlmsg_len, sizeof(struct rtmsg));
+ break;
+ }
+
ctx = dplane_ctx_alloc();
dplane_ctx_route_init(ctx, DPLANE_OP_ROUTE_NOTIFY, NULL,
NULL);
@@ -1394,8 +1465,14 @@ static void fpm_process_queue(struct event *t)
uint64_t processed_contexts = 0;
while (true) {
+ size_t writeable_amount;
+
+ frr_with_mutex (&fnc->obuf_mutex) {
+ writeable_amount = STREAM_WRITEABLE(fnc->obuf);
+ }
+
/* No space available yet. */
- if (STREAM_WRITEABLE(fnc->obuf) < NL_PKT_BUF_SIZE) {
+ if (writeable_amount < NL_PKT_BUF_SIZE) {
no_bufs = true;
break;
}
@@ -1665,6 +1742,7 @@ static int fpm_nl_new(struct event_loop *tm)
zlog_debug("%s register status: %d", prov_name, rv);
install_node(&fpm_node);
+ install_element(ENABLE_NODE, &fpm_show_status_cmd);
install_element(ENABLE_NODE, &fpm_show_counters_cmd);
install_element(ENABLE_NODE, &fpm_show_counters_json_cmd);
install_element(ENABLE_NODE, &fpm_reset_counters_cmd);
diff --git a/zebra/fpm_listener.c b/zebra/fpm_listener.c
new file mode 100644
index 0000000..7d84c70
--- /dev/null
+++ b/zebra/fpm_listener.c
@@ -0,0 +1,814 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (C) 2012 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * 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 ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC 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.
+ */
+#include "config.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef GNU_LINUX
+#include <stdint.h>
+#include <memory.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <assert.h>
+#include <err.h>
+#include <sys/types.h>
+
+#include <linux/netlink.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_link.h>
+
+#include "rt_netlink.h"
+#include "fpm/fpm.h"
+#include "lib/libfrr.h"
+
+XREF_SETUP();
+
+struct glob {
+ int server_sock;
+ int sock;
+ bool reflect;
+ bool dump_hex;
+};
+
+struct glob glob_space;
+struct glob *glob = &glob_space;
+
+#define ARRAY_SIZE(x) (sizeof(x) / sizeof(x[0]))
+
+/*
+ * get_print_buf
+ */
+static char *
+get_print_buf(size_t *buf_len)
+{
+ static char print_bufs[16][128];
+ static int counter;
+
+ counter++;
+ if (counter >= 16)
+ counter = 0;
+
+ *buf_len = 128;
+ return &print_bufs[counter][0];
+}
+
+/*
+ * create_listen_sock
+ */
+static int create_listen_sock(int port, int *sock_p)
+{
+ int sock;
+ struct sockaddr_in addr;
+ int reuse;
+
+ sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
+ if (sock < 0) {
+ fprintf(stderr, "Failed to create socket: %s\n", strerror(errno));
+ return 0;
+ }
+
+ reuse = 1;
+ if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) <
+ 0) {
+ fprintf(stderr, "Failed to set reuse addr option: %s\n",
+ strerror(errno));
+ }
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = htonl(INADDR_ANY);
+ addr.sin_port = htons(port);
+
+ if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
+ fprintf(stderr, "Failed to bind to port %d: %s\n", port, strerror(errno));
+ close(sock);
+ return 0;
+ }
+
+ if (listen(sock, 5)) {
+ fprintf(stderr, "Failed to listen on socket: %s\n", strerror(errno));
+ close(sock);
+ return 0;
+ }
+
+ *sock_p = sock;
+ return 1;
+}
+
+/*
+ * accept_conn
+ */
+static int accept_conn(int listen_sock)
+{
+ int sock;
+ struct sockaddr_in client_addr = { 0 };
+ unsigned int client_len;
+
+ while (1) {
+ char buf[120];
+
+ fprintf(stdout, "Waiting for client connection...\n");
+ client_len = sizeof(client_addr);
+ sock = accept(listen_sock, (struct sockaddr *)&client_addr,
+ &client_len);
+
+ if (sock >= 0) {
+ fprintf(stdout, "Accepted client %s\n",
+ inet_ntop(AF_INET, &client_addr.sin_addr, buf, sizeof(buf)));
+ return sock;
+ }
+ fprintf(stderr, "Failed to accept socket: %s\n", strerror(errno));
+ }
+}
+
+/*
+ * read_fpm_msg
+ */
+static fpm_msg_hdr_t *
+read_fpm_msg(char *buf, size_t buf_len)
+{
+ char *cur, *end;
+ long need_len, bytes_read, have_len;
+ fpm_msg_hdr_t *hdr;
+ int reading_full_msg;
+
+ end = buf + buf_len;
+ cur = buf;
+ hdr = (fpm_msg_hdr_t *)buf;
+
+ while (1) {
+ reading_full_msg = 0;
+
+ have_len = cur - buf;
+
+ if (have_len < (long)FPM_MSG_HDR_LEN) {
+ need_len = FPM_MSG_HDR_LEN - have_len;
+ } else {
+ need_len = fpm_msg_len(hdr) - have_len;
+ assert(need_len >= 0 && need_len <= (end - cur));
+
+ if (!need_len)
+ return hdr;
+
+ reading_full_msg = 1;
+ }
+
+ bytes_read = read(glob->sock, cur, need_len);
+
+ if (bytes_read == 0) {
+ fprintf(stdout,
+ "Socket closed as that read returned 0\n");
+ return NULL;
+ }
+
+ if (bytes_read < 0) {
+ fprintf(stderr, "Error reading from socket: %s\n",
+ strerror(errno));
+ return NULL;
+ }
+
+ cur += bytes_read;
+
+ if (bytes_read < need_len) {
+ fprintf(stderr,
+ "Read %lu bytes but expected to read %lu bytes instead\n",
+ bytes_read, need_len);
+ return NULL;
+ }
+
+ if (reading_full_msg)
+ return hdr;
+
+ if (!fpm_msg_ok(hdr, buf_len)) {
+ assert(0);
+ fprintf(stderr, "Malformed fpm message\n");
+ return NULL;
+ }
+ }
+}
+
+/*
+ * netlink_msg_type_to_s
+ */
+static const char *
+netlink_msg_type_to_s(uint16_t type)
+{
+ switch (type) {
+
+ case RTM_NEWROUTE:
+ return "New route";
+
+ case RTM_DELROUTE:
+ return "Del route";
+
+ case RTM_NEWNEXTHOP:
+ return "New Nexthop Group";
+
+ case RTM_DELNEXTHOP:
+ return "Del Nexthop Group";
+
+ default:
+ return "Unknown";
+ }
+}
+
+/*
+ * netlink_prot_to_s
+ */
+static const char *
+netlink_prot_to_s(unsigned char prot)
+{
+ switch (prot) {
+
+ case RTPROT_KERNEL:
+ return "Kernel";
+
+ case RTPROT_BOOT:
+ return "Boot";
+
+ case RTPROT_STATIC:
+ return "Static";
+
+ case RTPROT_ZEBRA:
+ return "Zebra";
+
+ case RTPROT_DHCP:
+ return "Dhcp";
+
+ case RTPROT_BGP:
+ return "BGP";
+
+ case RTPROT_ISIS:
+ return "ISIS";
+
+ case RTPROT_OSPF:
+ return "OSPF";
+
+ case RTPROT_RIP:
+ return "RIP";
+
+ case RTPROT_RIPNG:
+ return "RIPNG";
+
+ case RTPROT_BABEL:
+ return "BABEL";
+
+ case RTPROT_NHRP:
+ return "NHRP";
+
+ case RTPROT_EIGRP:
+ return "EIGRP";
+
+ case RTPROT_SHARP:
+ return "SHARP";
+
+ case RTPROT_PBR:
+ return "PBR";
+
+ case RTPROT_ZSTATIC:
+ return "Static";
+
+ default:
+ return "Unknown";
+ }
+}
+
+#define MAX_NHS 16
+
+struct netlink_nh {
+ struct rtattr *gateway;
+ int if_index;
+ uint16_t encap_type;
+ uint32_t vxlan_vni;
+};
+
+struct netlink_msg_ctx {
+ struct nlmsghdr *hdr;
+
+ /*
+ * Stuff pertaining to route messages.
+ */
+ struct rtmsg *rtmsg;
+ struct rtattr *rtattrs[RTA_MAX + 1];
+
+ /*
+ * Nexthops.
+ */
+ struct netlink_nh nhs[MAX_NHS];
+ unsigned long num_nhs;
+
+ struct rtattr *dest;
+ struct rtattr *src;
+ int *metric;
+ unsigned int *nhgid;
+
+ const char *err_msg;
+};
+
+/*
+ * netlink_msg_ctx_init
+ */
+static inline void netlink_msg_ctx_init(struct netlink_msg_ctx *ctx)
+{
+ memset(ctx, 0, sizeof(*ctx));
+}
+
+/*
+ * netlink_msg_ctx_set_err
+ */
+static inline void netlink_msg_ctx_set_err(struct netlink_msg_ctx *ctx,
+ const char *err_msg)
+{
+ if (ctx->err_msg)
+ return;
+
+ ctx->err_msg = err_msg;
+}
+
+/*
+ * parse_rtattrs_
+ */
+static int parse_rtattrs_(struct rtattr *rta, size_t len, struct rtattr **rtas,
+ uint16_t num_rtas, const char **err_msg)
+{
+ memset(rtas, 0, num_rtas * sizeof(rtas[0]));
+
+ for (; len > 0; rta = RTA_NEXT(rta, len)) {
+ uint16_t type = rta->rta_type & NLA_TYPE_MASK;
+
+ if (!RTA_OK(rta, len)) {
+ *err_msg = "Malformed rta";
+ return 0;
+ }
+
+ if (type >= num_rtas) {
+ warn("Unknown rtattr type %d", rta->rta_type);
+ continue;
+ }
+
+ rtas[type] = rta;
+ }
+
+ return 1;
+}
+
+/*
+ * parse_rtattrs
+ */
+static int parse_rtattrs(struct netlink_msg_ctx *ctx, struct rtattr *rta,
+ size_t len)
+{
+ const char *err_msg;
+
+ err_msg = NULL;
+
+ if (!parse_rtattrs_(rta, len, ctx->rtattrs, ARRAY_SIZE(ctx->rtattrs),
+ &err_msg)) {
+ netlink_msg_ctx_set_err(ctx, err_msg);
+ return 0;
+ }
+
+ return 1;
+}
+
+/*
+ * netlink_msg_ctx_add_nh
+ */
+static int netlink_msg_ctx_add_nh(struct netlink_msg_ctx *ctx, int if_index,
+ struct rtattr *gateway, uint16_t encap_type,
+ uint32_t vxlan_vni)
+{
+ struct netlink_nh *nh;
+
+ if (ctx->num_nhs + 1 >= ARRAY_SIZE(ctx->nhs)) {
+ warn("Too many next hops");
+ return 0;
+ }
+ nh = &ctx->nhs[ctx->num_nhs];
+ ctx->num_nhs++;
+
+ nh->gateway = gateway;
+ nh->if_index = if_index;
+
+ nh->encap_type = encap_type;
+ nh->vxlan_vni = vxlan_vni;
+ return 1;
+}
+
+/*
+ * parse_multipath_attr
+ */
+static int parse_multipath_attr(struct netlink_msg_ctx *ctx,
+ struct rtattr *mpath_rtattr)
+{
+ int len;
+ struct rtnexthop *rtnh;
+ struct rtattr *rtattrs[RTA_MAX + 1];
+ struct rtattr *tb[RTA_MAX + 1];
+ struct rtattr *gateway;
+ const char *err_msg;
+
+ rtnh = RTA_DATA(mpath_rtattr);
+ len = RTA_PAYLOAD(mpath_rtattr);
+
+ for (; len > 0;
+ len -= NLMSG_ALIGN(rtnh->rtnh_len), rtnh = RTNH_NEXT(rtnh)) {
+ uint32_t vxlan_vni;
+ uint16_t encap_type;
+
+ if (!RTNH_OK(rtnh, len)) {
+ netlink_msg_ctx_set_err(ctx, "Malformed nh");
+ return 0;
+ }
+
+ if (rtnh->rtnh_len <= sizeof(*rtnh)) {
+ netlink_msg_ctx_set_err(ctx, "NH len too small");
+ return 0;
+ }
+
+ /*
+ * Parse attributes included in the nexthop.
+ */
+ err_msg = NULL;
+ if (!parse_rtattrs_(RTNH_DATA(rtnh),
+ rtnh->rtnh_len - sizeof(*rtnh), rtattrs,
+ ARRAY_SIZE(rtattrs), &err_msg)) {
+ netlink_msg_ctx_set_err(ctx, err_msg);
+ return 0;
+ }
+
+ gateway = rtattrs[RTA_GATEWAY];
+ memset(tb, 0, sizeof(tb));
+ if (rtattrs[RTA_ENCAP]) {
+ parse_rtattrs_(RTA_DATA(rtattrs[RTA_ENCAP]),
+ rtattrs[RTA_ENCAP]->rta_len -
+ sizeof(struct rtattr),
+ tb, ARRAY_SIZE(tb), &err_msg);
+ }
+
+ if (rtattrs[RTA_ENCAP_TYPE])
+ encap_type =
+ *(uint16_t *)RTA_DATA(rtattrs[RTA_ENCAP_TYPE]);
+ else
+ encap_type = 0;
+
+ if (tb[0])
+ vxlan_vni = *(uint32_t *)RTA_DATA(tb[0]);
+ else
+ vxlan_vni = 0;
+
+ netlink_msg_ctx_add_nh(ctx, rtnh->rtnh_ifindex, gateway,
+ encap_type, vxlan_vni);
+ }
+
+ return 1;
+}
+
+/*
+ * parse_route_msg
+ */
+static int parse_route_msg(struct netlink_msg_ctx *ctx)
+{
+ int len;
+ struct rtattr **rtattrs, *rtattr, *gateway, *oif;
+ int if_index;
+
+ ctx->rtmsg = NLMSG_DATA(ctx->hdr);
+
+ len = ctx->hdr->nlmsg_len - NLMSG_LENGTH(sizeof(struct rtmsg));
+ if (len < 0) {
+ netlink_msg_ctx_set_err(ctx, "Bad message length");
+ return 0;
+ }
+
+ if (!parse_rtattrs(ctx, RTM_RTA(ctx->rtmsg), len))
+ return 0;
+
+ rtattrs = ctx->rtattrs;
+
+ ctx->dest = rtattrs[RTA_DST];
+ ctx->src = rtattrs[RTA_PREFSRC];
+
+ rtattr = rtattrs[RTA_PRIORITY];
+ if (rtattr)
+ ctx->metric = (int *)RTA_DATA(rtattr);
+
+ rtattr = rtattrs[RTA_NH_ID];
+ if (rtattr)
+ ctx->nhgid = (unsigned int *)RTA_DATA(rtattr);
+
+ gateway = rtattrs[RTA_GATEWAY];
+ oif = rtattrs[RTA_OIF];
+ if (gateway || oif) {
+ struct rtattr *tb[RTA_MAX + 1] = { 0 };
+ uint16_t encap_type = 0;
+ uint32_t vxlan_vni = 0;
+
+ if_index = 0;
+ if (oif)
+ if_index = *((int *)RTA_DATA(oif));
+
+
+ if (rtattrs[RTA_ENCAP]) {
+ const char *err_msg;
+
+ parse_rtattrs_(RTA_DATA(rtattrs[RTA_ENCAP]),
+ rtattrs[RTA_ENCAP]->rta_len -
+ sizeof(struct rtattr),
+ tb, ARRAY_SIZE(tb), &err_msg);
+ }
+
+ if (rtattrs[RTA_ENCAP_TYPE])
+ encap_type =
+ *(uint16_t *)RTA_DATA(rtattrs[RTA_ENCAP_TYPE]);
+
+ if (tb[0])
+ vxlan_vni = *(uint32_t *)RTA_DATA(tb[0]);
+
+ netlink_msg_ctx_add_nh(ctx, if_index, gateway, encap_type,
+ vxlan_vni);
+ }
+
+ rtattr = rtattrs[RTA_MULTIPATH];
+ if (rtattr)
+ parse_multipath_attr(ctx, rtattr);
+
+ return 1;
+}
+
+/*
+ * addr_to_s
+ */
+static const char *
+addr_to_s(unsigned char family, void *addr)
+{
+ size_t buf_len;
+ char *buf;
+
+ buf = get_print_buf(&buf_len);
+
+ return inet_ntop(family, addr, buf, buf_len);
+}
+
+/*
+ * netlink_msg_ctx_print
+ */
+static int netlink_msg_ctx_snprint(struct netlink_msg_ctx *ctx, char *buf,
+ size_t buf_len)
+{
+ struct nlmsghdr *hdr;
+ struct rtmsg *rtmsg;
+ struct netlink_nh *nh;
+ char *cur, *end;
+ unsigned long i;
+
+ hdr = ctx->hdr;
+ rtmsg = ctx->rtmsg;
+
+ cur = buf;
+ end = buf + buf_len;
+
+ cur += snprintf(cur, end - cur, "%s %s/%d, Prot: %s(%u)",
+ netlink_msg_type_to_s(hdr->nlmsg_type),
+ addr_to_s(rtmsg->rtm_family, RTA_DATA(ctx->dest)),
+ rtmsg->rtm_dst_len,
+ netlink_prot_to_s(rtmsg->rtm_protocol),
+ rtmsg->rtm_protocol);
+
+ if (ctx->metric)
+ cur += snprintf(cur, end - cur, ", Metric: %d", *ctx->metric);
+
+ if (ctx->nhgid)
+ cur += snprintf(cur, end - cur, ", nhgid: %u", *ctx->nhgid);
+ for (i = 0; i < ctx->num_nhs; i++) {
+ cur += snprintf(cur, end - cur, "\n ");
+ nh = &ctx->nhs[i];
+
+ if (nh->gateway) {
+ cur += snprintf(cur, end - cur, " %s",
+ addr_to_s(rtmsg->rtm_family,
+ RTA_DATA(nh->gateway)));
+ }
+
+ if (nh->if_index) {
+ cur += snprintf(cur, end - cur, " via interface %d",
+ nh->if_index);
+ }
+
+ if (nh->encap_type)
+ cur += snprintf(cur, end - cur,
+ ", Encap Type: %u Vxlan vni %u",
+ nh->encap_type, nh->vxlan_vni);
+ }
+
+ return cur - buf;
+}
+
+/*
+ * print_netlink_msg_ctx
+ */
+static void print_netlink_msg_ctx(struct netlink_msg_ctx *ctx)
+{
+ char buf[1024];
+
+ netlink_msg_ctx_snprint(ctx, buf, sizeof(buf));
+ printf("%s\n", buf);
+}
+
+static void fpm_listener_hexdump(const void *mem, size_t len)
+{
+ char line[64];
+ const uint8_t *src = mem;
+ const uint8_t *end = src + len;
+
+ if (!glob->dump_hex)
+ return;
+
+ if (len == 0) {
+ printf("%016lx: (zero length / no data)\n", (long)src);
+ return;
+ }
+
+ while (src < end) {
+ struct fbuf fb = {
+ .buf = line,
+ .pos = line,
+ .len = sizeof(line),
+ };
+ const uint8_t *lineend = src + 8;
+ uint32_t line_bytes = 0;
+
+ printf("%016lx: ", (long)src);
+
+ while (src < lineend && src < end) {
+ printf("%02x ", *src++);
+ line_bytes++;
+ }
+ if (line_bytes < 8)
+ printf("%*s", (8 - line_bytes) * 3, "");
+
+ src -= line_bytes;
+ while (src < lineend && src < end && fb.pos < fb.buf + fb.len) {
+ uint8_t byte = *src++;
+
+ if (isprint(byte))
+ *fb.pos++ = byte;
+ else
+ *fb.pos++ = '.';
+ }
+ printf("\n");
+ }
+}
+
+/*
+ * parse_netlink_msg
+ */
+static void parse_netlink_msg(char *buf, size_t buf_len, fpm_msg_hdr_t *fpm)
+{
+ struct netlink_msg_ctx ctx_space, *ctx;
+ struct nlmsghdr *hdr;
+ unsigned int len;
+
+ fpm_listener_hexdump(buf, buf_len);
+ ctx = &ctx_space;
+
+ hdr = (struct nlmsghdr *)buf;
+ len = buf_len;
+ for (; NLMSG_OK(hdr, len); hdr = NLMSG_NEXT(hdr, len)) {
+
+ netlink_msg_ctx_init(ctx);
+ ctx->hdr = hdr;
+
+ switch (hdr->nlmsg_type) {
+
+ case RTM_DELROUTE:
+ case RTM_NEWROUTE:
+
+ parse_route_msg(ctx);
+ if (ctx->err_msg) {
+ fprintf(stderr,
+ "Error parsing route message: %s\n",
+ ctx->err_msg);
+ }
+
+ print_netlink_msg_ctx(ctx);
+
+ if (glob->reflect && hdr->nlmsg_type == RTM_NEWROUTE &&
+ ctx->rtmsg->rtm_protocol > RTPROT_STATIC) {
+ printf(" Route %s(%u) reflecting back\n",
+ netlink_prot_to_s(
+ ctx->rtmsg->rtm_protocol),
+ ctx->rtmsg->rtm_protocol);
+ ctx->rtmsg->rtm_flags |= RTM_F_OFFLOAD;
+ write(glob->sock, fpm, fpm_msg_len(fpm));
+ }
+ break;
+
+ default:
+ fprintf(stdout,
+ "Ignoring netlink message - Type: %s(%d)\n",
+ netlink_msg_type_to_s(hdr->nlmsg_type),
+ hdr->nlmsg_type);
+ }
+ }
+}
+
+/*
+ * process_fpm_msg
+ */
+static void process_fpm_msg(fpm_msg_hdr_t *hdr)
+{
+ fprintf(stdout, "FPM message - Type: %d, Length %d\n", hdr->msg_type,
+ ntohs(hdr->msg_len));
+
+ if (hdr->msg_type != FPM_MSG_TYPE_NETLINK) {
+ fprintf(stderr, "Unknown fpm message type %u\n", hdr->msg_type);
+ return;
+ }
+
+ parse_netlink_msg(fpm_msg_data(hdr), fpm_msg_data_len(hdr), hdr);
+}
+
+/*
+ * fpm_serve
+ */
+static void fpm_serve(void)
+{
+ char buf[FPM_MAX_MSG_LEN * 4];
+ fpm_msg_hdr_t *hdr;
+
+ while (1) {
+
+ hdr = read_fpm_msg(buf, sizeof(buf));
+ if (!hdr)
+ return;
+
+ process_fpm_msg(hdr);
+ }
+}
+
+int main(int argc, char **argv)
+{
+ pid_t daemon;
+ int r;
+ bool fork_daemon = false;
+
+ memset(glob, 0, sizeof(*glob));
+
+ while ((r = getopt(argc, argv, "rdv")) != -1) {
+ switch (r) {
+ case 'r':
+ glob->reflect = true;
+ break;
+ case 'd':
+ fork_daemon = true;
+ break;
+ case 'v':
+ glob->dump_hex = true;
+ break;
+ }
+ }
+
+ if (fork_daemon) {
+ daemon = fork();
+
+ if (daemon)
+ exit(0);
+ }
+
+ if (!create_listen_sock(FPM_DEFAULT_PORT, &glob->server_sock))
+ exit(1);
+
+ /*
+ * Server forever.
+ */
+ while (1) {
+ glob->sock = accept_conn(glob->server_sock);
+ fpm_serve();
+ fprintf(stdout, "Done serving client");
+ }
+}
+#else
+
+int main(int argc, char **argv)
+{
+ fprintf(stderr, "This program only works on linux");
+ exit(-1);
+}
+#endif
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 5f096e3..3233519 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -1473,7 +1473,6 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
ifi = NLMSG_DATA(h);
- /* assume if not default zns, then new VRF */
if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) {
/* If this is not link add/delete message so print warning. */
zlog_debug("%s: wrong kernel message %s", __func__,
diff --git a/zebra/interface.c b/zebra/interface.c
index 5ce222c..b3adc44 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -108,17 +108,6 @@ static void zebra_if_node_destroy(route_table_delegate_t *delegate,
route_node_destroy(delegate, table, node);
}
-static void zebra_if_nhg_dependents_free(struct zebra_if *zebra_if)
-{
- nhg_connected_tree_free(&zebra_if->nhg_dependents);
-}
-
-static void zebra_if_nhg_dependents_init(struct zebra_if *zebra_if)
-{
- nhg_connected_tree_init(&zebra_if->nhg_dependents);
-}
-
-
route_table_delegate_t zebra_if_table_delegate = {
.create_node = route_node_create,
.destroy_node = zebra_if_node_destroy};
@@ -137,7 +126,7 @@ static int if_zebra_new_hook(struct interface *ifp)
zebra_if->link_nsid = NS_UNKNOWN;
- zebra_if_nhg_dependents_init(zebra_if);
+ nhg_connected_tree_init(&zebra_if->nhg_dependents);
zebra_ptm_if_init(zebra_if);
@@ -187,6 +176,10 @@ static void if_nhg_dependents_release(const struct interface *ifp)
frr_each(nhg_connected_tree, &zif->nhg_dependents, rb_node_dep) {
rb_node_dep->nhe->ifp = NULL; /* Null it out */
zebra_nhg_check_valid(rb_node_dep->nhe);
+ if (CHECK_FLAG(rb_node_dep->nhe->flags,
+ NEXTHOP_GROUP_KEEP_AROUND) &&
+ rb_node_dep->nhe->refcnt == 1)
+ zebra_nhg_decrement_ref(rb_node_dep->nhe);
}
}
@@ -221,7 +214,7 @@ static int if_zebra_delete_hook(struct interface *ifp)
zebra_evpn_mac_ifp_del(ifp);
if_nhg_dependents_release(ifp);
- zebra_if_nhg_dependents_free(zebra_if);
+ nhg_connected_tree_free(&zebra_if->nhg_dependents);
XFREE(MTYPE_ZIF_DESC, zebra_if->desc);
@@ -954,47 +947,6 @@ static void if_down_del_nbr_connected(struct interface *ifp)
}
}
-void if_nhg_dependents_add(struct interface *ifp, struct nhg_hash_entry *nhe)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
- }
-}
-
-void if_nhg_dependents_del(struct interface *ifp, struct nhg_hash_entry *nhe)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
- }
-}
-
-unsigned int if_nhg_dependents_count(const struct interface *ifp)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- return nhg_connected_tree_count(&zif->nhg_dependents);
- }
-
- return 0;
-}
-
-
-bool if_nhg_dependents_is_empty(const struct interface *ifp)
-{
- if (ifp->info) {
- struct zebra_if *zif = (struct zebra_if *)ifp->info;
-
- return nhg_connected_tree_is_empty(&zif->nhg_dependents);
- }
-
- return false;
-}
-
/* Interface is up. */
void if_up(struct interface *ifp, bool install_connected)
{
@@ -1022,6 +974,14 @@ void if_up(struct interface *ifp, bool install_connected)
if (install_connected)
if_install_connected(ifp);
+ /*
+ * Interface associated NHG's have been deleted on
+ * interface down events, now that this interface
+ * is coming back up, let's resync the zebra -> dplane
+ * nhg's so that they can be continued to be used.
+ */
+ zebra_interface_nhg_reinstall(ifp);
+
/* Handle interface up for specific types for EVPN. Non-VxLAN interfaces
* are checked to see if (remote) neighbor entries need to be installed
* on them for ARP suppression.
@@ -1523,23 +1483,27 @@ static void interface_vrf_change(enum dplane_op_e op, ifindex_t ifindex,
"DPLANE_OP_INTF_UPDATE for VRF %s(%u) table %u",
name, ifindex, tableid);
- if (!vrf_lookup_by_id((vrf_id_t)ifindex)) {
- vrf_id_t exist_id;
+ /*
+ * For a given tableid, if there already exists a vrf and it
+ * is different from the current vrf to be operated, then there
+ * is a misconfiguration and zebra will exit.
+ */
+ vrf_id_t exist_id = zebra_vrf_lookup_by_table(tableid, ns_id);
- exist_id = zebra_vrf_lookup_by_table(tableid, ns_id);
- if (exist_id != VRF_DEFAULT) {
- vrf = vrf_lookup_by_id(exist_id);
+ if (exist_id != VRF_DEFAULT) {
+ vrf = vrf_lookup_by_id(exist_id);
- if (vrf)
- flog_err(EC_ZEBRA_VRF_MISCONFIGURED,
- "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting",
- name, ifindex, vrf->name,
- vrf->vrf_id);
- else
- flog_err(EC_ZEBRA_VRF_NOT_FOUND,
- "VRF %s id %u does not exist",
- name, ifindex);
+ if (!vrf_lookup_by_id((vrf_id_t)ifindex) && !vrf) {
+ flog_err(EC_ZEBRA_VRF_NOT_FOUND,
+ "VRF %s id %u does not exist", name,
+ ifindex);
+ exit(-1);
+ }
+ if (vrf && strcmp(name, vrf->name)) {
+ flog_err(EC_ZEBRA_VRF_MISCONFIGURED,
+ "VRF %s id %u table id overlaps existing vrf %s(%d), misconfiguration exiting",
+ name, ifindex, vrf->name, vrf->vrf_id);
exit(-1);
}
}
@@ -1696,8 +1660,10 @@ static void interface_if_protodown(struct interface *ifp, bool protodown,
uint32_t rc_bitfield)
{
struct zebra_if *zif = ifp->info;
- bool old_protodown;
+ bool old_protodown, reason_extern;
+ reason_extern = !!CHECK_FLAG(zif->protodown_rc,
+ ZEBRA_PROTODOWN_EXTERNAL);
/*
* Set our reason code to note it wasn't us.
* If the reason we got from the kernel is ONLY frr though, don't
@@ -1713,8 +1679,8 @@ static void interface_if_protodown(struct interface *ifp, bool protodown,
return;
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_DPLANE)
- zlog_debug("interface %s dplane change, protodown %s",
- ifp->name, protodown ? "on" : "off");
+ zlog_debug("interface %s dplane change, protodown %s curr reason_extern %u",
+ ifp->name, protodown ? "on" : "off", reason_extern);
/* Set protodown, respectively */
COND_FLAG(zif->flags, ZIF_FLAG_PROTODOWN, protodown);
@@ -1739,6 +1705,13 @@ static void interface_if_protodown(struct interface *ifp, bool protodown,
return;
}
+ if (!protodown && reason_extern) {
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("bond member %s has protodown reason external and clear the reason, skip reinstall.",
+ ifp->name);
+ return;
+ }
+
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
zlog_debug(
"bond mbr %s reinstate protodown %s in the dplane",
diff --git a/zebra/interface.h b/zebra/interface.h
index 7d633f3..8d19c18 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -331,11 +331,6 @@ void link_param_cmd_set_float(struct interface *ifp, float *field,
void link_param_cmd_unset(struct interface *ifp, uint32_t type);
/* Nexthop group connected functions */
-extern void if_nhg_dependents_add(struct interface *ifp,
- struct nhg_hash_entry *nhe);
-extern void if_nhg_dependents_del(struct interface *ifp,
- struct nhg_hash_entry *nhe);
-extern unsigned int if_nhg_dependents_count(const struct interface *ifp);
extern bool if_nhg_dependents_is_empty(const struct interface *ifp);
extern void vrf_add_update(struct vrf *vrfp);
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 8a64a1e..d2f1db6 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -619,6 +619,11 @@ static void netlink_install_filter(int sock, uint32_t pid, uint32_t dplane_pid)
safe_strerror(errno));
}
+/*
+ * Please note, the assumption with this function is that the
+ * flags passed in that are bit masked with type, we are implicitly
+ * assuming that this is handling the NLA_F_NESTED ilk.
+ */
void netlink_parse_rtattr_flags(struct rtattr **tb, int max, struct rtattr *rta,
int len, unsigned short flags)
{
@@ -638,8 +643,19 @@ void netlink_parse_rtattr(struct rtattr **tb, int max, struct rtattr *rta,
{
memset(tb, 0, sizeof(struct rtattr *) * (max + 1));
while (RTA_OK(rta, len)) {
- if (rta->rta_type <= max)
- tb[rta->rta_type] = rta;
+ /*
+ * The type may be &'ed with NLA_F_NESTED
+ * which puts data in the upper 8 bits of the
+ * rta_type. Mask it off and save the actual
+ * underlying value to be placed into the array.
+ * This way we don't accidently crash in the future
+ * when the kernel sends us new data and we try
+ * to write well beyond the end of the array.
+ */
+ uint16_t type = rta->rta_type & NLA_TYPE_MASK;
+
+ if (type <= max)
+ tb[type] = rta;
rta = RTA_NEXT(rta, len);
}
}
diff --git a/zebra/main.c b/zebra/main.c
index 27e05e7..ea1e1cb 100644
--- a/zebra/main.c
+++ b/zebra/main.c
@@ -26,6 +26,7 @@
#include "routemap.h"
#include "routing_nb.h"
#include "mgmt_be_client.h"
+#include "libagentx.h"
#include "zebra/zebra_router.h"
#include "zebra/zebra_errors.h"
@@ -203,6 +204,7 @@ static void sigint(void)
rib_update_finish();
list_delete(&zrouter.client_list);
+ list_delete(&zrouter.stale_client_list);
/*
* Besides other clean-ups zebra's vrf_disable() also enqueues installed
@@ -434,6 +436,7 @@ int main(int argc, char **argv)
zrouter.master = frr_init();
/* Zebra related initialize. */
+ libagentx_init();
zebra_router_init(asic_offload, notify_on_ack, v6_with_v4_nexthop);
zserv_init();
zebra_rib_init();
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 70ace35..11c1330 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -605,10 +605,6 @@ void zebra_interface_address_add_update(struct interface *ifp,
client, ifp, ifc);
}
}
- /* interface associated NHGs may have been deleted,
- * re-sync zebra -> dplane NHGs
- */
- zebra_interface_nhg_reinstall(ifp);
}
/* Interface address deletion. */
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index f092fc5..01b527e 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -1550,7 +1550,7 @@ static ssize_t fill_seg6ipt_encap(char *buffer, size_t buflen,
srh->first_segment = segs->num_segs - 1;
for (i = 0; i < segs->num_segs; i++) {
- memcpy(&srh->segments[i], &segs->seg[i],
+ memcpy(&srh->segments[segs->num_segs - i - 1], &segs->seg[i],
sizeof(struct in6_addr));
}
@@ -1683,6 +1683,16 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
sizeof(struct in_addr)))
return false;
break;
+ case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
+ if (!nl_attr_put32(nlmsg, req_size,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DX6))
+ return false;
+ if (!nl_attr_put(nlmsg, req_size,
+ SEG6_LOCAL_NH6, &ctx->nh6,
+ sizeof(struct in_addr)))
+ return false;
+ break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DT6:
if (!nl_attr_put32(nlmsg, req_size,
SEG6_LOCAL_ACTION,
@@ -1714,7 +1724,6 @@ static bool _netlink_route_build_singlepath(const struct prefix *p,
return false;
break;
case ZEBRA_SEG6_LOCAL_ACTION_END_DX2:
- case ZEBRA_SEG6_LOCAL_ACTION_END_DX6:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6:
case ZEBRA_SEG6_LOCAL_ACTION_END_B6_ENCAP:
case ZEBRA_SEG6_LOCAL_ACTION_END_BM:
@@ -1882,6 +1891,36 @@ static inline bool _netlink_set_tag(struct nlmsghdr *n, unsigned int maxlen,
return true;
}
+/*
+ * The function returns true if the attribute could be added
+ * to the message, otherwise false is returned.
+ */
+static int netlink_route_nexthop_encap(bool fpm, struct nlmsghdr *n,
+ size_t nlen, const struct nexthop *nh)
+{
+ struct rtattr *nest;
+
+ if (!fpm)
+ return true;
+
+ switch (nh->nh_encap_type) {
+ case NET_VXLAN:
+ if (!nl_attr_put16(n, nlen, RTA_ENCAP_TYPE, nh->nh_encap_type))
+ return false;
+
+ nest = nl_attr_nest(n, nlen, RTA_ENCAP);
+ if (!nest)
+ return false;
+
+ if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */, nh->nh_encap.vni))
+ return false;
+ nl_attr_nest_end(n, nest);
+ break;
+ }
+
+ return true;
+}
+
/* This function takes a nexthop as argument and
* appends to the given netlink msg. If the nexthop
* defines a preferred source, the src parameter
@@ -1900,10 +1939,13 @@ static inline bool _netlink_set_tag(struct nlmsghdr *n, unsigned int maxlen,
* The function returns true if the nexthop could be added
* to the message, otherwise false is returned.
*/
-static bool _netlink_route_build_multipath(
- const struct prefix *p, const char *routedesc, int bytelen,
- const struct nexthop *nexthop, struct nlmsghdr *nlmsg, size_t req_size,
- struct rtmsg *rtmsg, const union g_addr **src, route_tag_t tag)
+static bool _netlink_route_build_multipath(const struct prefix *p,
+ const char *routedesc, int bytelen,
+ const struct nexthop *nexthop,
+ struct nlmsghdr *nlmsg,
+ size_t req_size, struct rtmsg *rtmsg,
+ const union g_addr **src,
+ route_tag_t tag, bool fpm)
{
char label_buf[256];
struct vrf *vrf;
@@ -2011,6 +2053,13 @@ static bool _netlink_route_build_multipath(
if (!_netlink_set_tag(nlmsg, req_size, tag))
return false;
+ /*
+ * Add encapsulation information when installing via
+ * FPM.
+ */
+ if (!netlink_route_nexthop_encap(fpm, nlmsg, req_size, nexthop))
+ return false;
+
nl_attr_rtnh_end(nlmsg, rtnh);
return true;
}
@@ -2045,7 +2094,7 @@ _netlink_mpls_build_multipath(const struct prefix *p, const char *routedesc,
bytelen = (family == AF_INET ? 4 : 16);
return _netlink_route_build_multipath(p, routedesc, bytelen,
nhlfe->nexthop, nlmsg, req_size,
- rtmsg, src, 0);
+ rtmsg, src, 0, false);
}
static void _netlink_mpls_debug(int cmd, uint32_t label, const char *routedesc)
@@ -2141,34 +2190,6 @@ static bool nexthop_set_src(const struct nexthop *nexthop, int family,
}
/*
- * The function returns true if the attribute could be added
- * to the message, otherwise false is returned.
- */
-static int netlink_route_nexthop_encap(struct nlmsghdr *n, size_t nlen,
- struct nexthop *nh)
-{
- struct rtattr *nest;
-
- switch (nh->nh_encap_type) {
- case NET_VXLAN:
- if (!nl_attr_put16(n, nlen, RTA_ENCAP_TYPE, nh->nh_encap_type))
- return false;
-
- nest = nl_attr_nest(n, nlen, RTA_ENCAP);
- if (!nest)
- return false;
-
- if (!nl_attr_put32(n, nlen, 0 /* VXLAN_VNI */,
- nh->nh_encap.vni))
- return false;
- nl_attr_nest_end(n, nest);
- break;
- }
-
- return true;
-}
-
-/*
* Routing table change via netlink interface, using a dataplane context object
*
* Returns -1 on failure, 0 when the msg doesn't fit entirely in the buffer
@@ -2360,6 +2381,14 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
break;
setsrc = nexthop_set_src(nexthop, p->family, &src);
+ if (setsrc && IS_ZEBRA_DEBUG_KERNEL) {
+ if (p->family == AF_INET)
+ zlog_debug("%s: %pFX set src %pI4",
+ __func__, p, &src.ipv4);
+ else if (p->family == AF_INET6)
+ zlog_debug("%s: %pFX set src %pI6",
+ __func__, p, &src.ipv6);
+ }
}
if (setsrc) {
@@ -2402,6 +2431,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
setsrc = nexthop_set_src(nexthop, p->family,
&src);
+ if (setsrc && IS_ZEBRA_DEBUG_KERNEL) {
+ if (p->family == AF_INET)
+ zlog_debug("%s: %pFX set src %pI4",
+ __func__, p,
+ &src.ipv4);
+ else if (p->family == AF_INET6)
+ zlog_debug("%s: %pFX set src %pI6",
+ __func__, p,
+ &src.ipv6);
+ }
continue;
}
@@ -2422,12 +2461,10 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
* Add encapsulation information when
* installing via FPM.
*/
- if (fpm) {
- if (!netlink_route_nexthop_encap(&req->n,
- datalen,
- nexthop))
- return 0;
- }
+ if (!netlink_route_nexthop_encap(fpm, &req->n,
+ datalen,
+ nexthop))
+ return 0;
nexthop_num++;
break;
@@ -2463,6 +2500,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
setsrc = nexthop_set_src(nexthop, p->family,
&src);
+ if (setsrc && IS_ZEBRA_DEBUG_KERNEL) {
+ if (p->family == AF_INET)
+ zlog_debug("%s: %pFX set src %pI4",
+ __func__, p,
+ &src.ipv4);
+ else if (p->family == AF_INET6)
+ zlog_debug("%s: %pFX set src %pI6",
+ __func__, p,
+ &src.ipv6);
+ }
continue;
}
@@ -2472,22 +2519,16 @@ ssize_t netlink_route_multipath_msg_encode(int cmd, struct zebra_dplane_ctx *ctx
: "multipath";
nexthop_num++;
- if (!_netlink_route_build_multipath(
- p, routedesc, bytelen, nexthop,
- &req->n, datalen, &req->r, &src1,
- tag))
+ if (!_netlink_route_build_multipath(p, routedesc,
+ bytelen,
+ nexthop,
+ &req->n,
+ datalen,
+ &req->r,
+ &src1, tag,
+ fpm))
return 0;
- /*
- * Add encapsulation information when installing via
- * FPM.
- */
- if (fpm) {
- if (!netlink_route_nexthop_encap(
- &req->n, datalen, nexthop))
- return 0;
- }
-
if (!setsrc && src1) {
if (p->family == AF_INET)
src.ipv4 = src1->ipv4;
@@ -2931,6 +2972,18 @@ ssize_t netlink_nexthop_msg_encode(uint16_t cmd,
sizeof(struct in_addr)))
return 0;
break;
+ case SEG6_LOCAL_ACTION_END_DX6:
+ if (!nl_attr_put32(&req->n,
+ buflen,
+ SEG6_LOCAL_ACTION,
+ SEG6_LOCAL_ACTION_END_DX6))
+ return 0;
+ if (!nl_attr_put(&req->n, buflen,
+ SEG6_LOCAL_NH6,
+ &ctx->nh6,
+ sizeof(struct in_addr)))
+ return 0;
+ break;
case SEG6_LOCAL_ACTION_END_DT6:
if (!nl_attr_put32(
&req->n, buflen,
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index 6aca643..470391d 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -184,13 +184,13 @@ static int rtadv_recv_packet(struct zebra_vrf *zvrf, int sock, uint8_t *buf,
static void rtadv_send_packet(int sock, struct interface *ifp,
enum ipv6_nd_suppress_ra_status stop)
{
- struct msghdr msg;
- struct iovec iov;
+ struct msghdr msg = { 0 };
+ struct iovec iov = { 0 };
struct cmsghdr *cmsgptr;
struct in6_pktinfo *pkt;
- struct sockaddr_in6 addr;
- unsigned char buf[RTADV_MSG_SIZE];
- char adata[RTADV_ADATA_SIZE];
+ struct sockaddr_in6 addr = { 0 };
+ unsigned char buf[RTADV_MSG_SIZE] = { 0 };
+ char adata[RTADV_ADATA_SIZE] = { 0 };
struct nd_router_advert *rtadv;
int ret;
diff --git a/zebra/subdir.am b/zebra/subdir.am
index d9c8d90..f767447 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -19,6 +19,12 @@ if LINUX
module_LTLIBRARIES += zebra/zebra_cumulus_mlag.la
endif
+#if FPM_LISTENER
+sbin_PROGRAMS += zebra/fpm_listener
+zebra_fpm_listener_SOURCES = zebra/fpm_listener.c
+zebra_fpm_listener_LDADD = lib/libfrr.la
+#endf
+
# Dataplane sample plugin
if DEV_BUILD
module_LTLIBRARIES += zebra/dplane_sample_plugin.la
@@ -116,6 +122,7 @@ zebra_zebra_SOURCES = \
clippy_scan += \
zebra/debug.c \
+ zebra/dplane_fpm_nl.c \
zebra/interface.c \
zebra/rtadv.c \
zebra/zebra_mlag_vty.c \
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 76cabd1..d585ef9 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -1724,7 +1724,7 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
* Let's convert the weights to a scaled value
* between 1 and zrouter.nexthop_weight_scale_value
* This is a simple application of a ratio:
- * scaled_weight/zrouter.nexthop_weight_scale_value =
+ * scaled_weight/zrouter.nexthop_weight_scale_value =
* weight/max_weight
* This translates to:
* scaled_weight = weight * zrouter.nexthop_weight_scale_value
@@ -1738,9 +1738,8 @@ static bool zapi_read_nexthops(struct zserv *client, struct prefix *p,
for (i = 0; i < nexthop_num; i++) {
znh = &nhops[i];
- tmp = (uint64_t)znh->weight *
- zrouter.nexthop_weight_scale_value;
- znh->weight = MAX(1, ((uint32_t)(tmp / max_weight)));
+ tmp = znh->weight * zrouter.nexthop_weight_scale_value;
+ znh->weight = MAX(1, (tmp / max_weight));
}
}
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index 99693a5..3944876 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -39,6 +39,13 @@ DEFINE_MTYPE_STATIC(ZEBRA, DP_NS, "DPlane NSes");
# define AOK 0
#endif
+/*
+ * Dataplane API version. This must be updated when any incompatible changes
+ * are made. The minor version (at least) should be updated when new APIs
+ * are introduced.
+ */
+static uint32_t zdplane_version = MAKE_FRRVERSION(2, 0, 0);
+
/* Control for collection of extra interface info with route updates; a plugin
* can enable the extra info via a dplane api.
*/
@@ -664,6 +671,12 @@ neigh_update_internal(enum dplane_op_e op, const struct interface *ifp,
* Public APIs
*/
+/* Access the dplane API version */
+uint32_t zebra_dplane_get_version(void)
+{
+ return zdplane_version;
+}
+
/* Obtain thread_master for dataplane thread */
struct event_loop *dplane_get_thread_master(void)
{
@@ -6351,7 +6364,7 @@ dplane_provider_dequeue_out_ctx(struct zebra_dplane_provider *prov)
*/
bool dplane_provider_is_threaded(const struct zebra_dplane_provider *prov)
{
- return (prov->dp_flags & DPLANE_PROV_FLAG_THREADED);
+ return CHECK_FLAG(prov->dp_flags, DPLANE_PROV_FLAG_THREADED);
}
#ifdef HAVE_NETLINK
@@ -7428,6 +7441,11 @@ static void dplane_thread_loop(struct event *event)
zlog_debug("dplane dequeues %d completed work from provider %s",
counter, dplane_provider_get_name(prov));
+ if (event_should_yield(event)) {
+ reschedule = true;
+ break;
+ }
+
/* Locate next provider */
prov = dplane_prov_list_next(&zdplane_info.dg_providers, prov);
}
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index 2f7d218..060b1c8 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -24,6 +24,13 @@
extern "C" {
#endif
+/* Retrieve the dataplane API version number; see libfrr.h to decode major,
+ * minor, sub version values.
+ * Plugins should pay attention to the major version number, at least, to
+ * be able to detect API changes that may not be backward-compatible.
+ */
+uint32_t zebra_dplane_get_version(void);
+
/* Key netlink info from zebra ns */
struct zebra_dplane_info {
ns_id_t ns_id;
diff --git a/zebra/zebra_evpn.c b/zebra/zebra_evpn.c
index 147f5b9..ebb5a42 100644
--- a/zebra/zebra_evpn.c
+++ b/zebra/zebra_evpn.c
@@ -109,21 +109,14 @@ void zebra_evpn_print(struct zebra_evpn *zevpn, void **ctxt)
} else {
json_object_int_add(json, "vni", zevpn->vni);
json_object_string_add(json, "type", "L2");
-#if CONFDATE > 20240210
-CPP_NOTICE("Drop `vrf` from JSON output")
-#endif
- json_object_string_add(json, "vrf",
- vrf_id_to_name(zevpn->vrf_id));
- json_object_string_add(json, "tenantVrf",
- vrf_id_to_name(zevpn->vrf_id));
+ json_object_string_add(json, "tenantVrf", vrf_id_to_name(zevpn->vrf_id));
}
if (!zevpn->vxlan_if) { // unexpected
if (json == NULL)
vty_out(vty, " VxLAN interface: unknown\n");
else
- json_object_string_add(json, "vxlanInterface",
- "unknown");
+ json_object_string_add(json, "vxlanInterface", "unknown");
return;
}
num_macs = num_valid_macs(zevpn);
@@ -135,35 +128,21 @@ CPP_NOTICE("Drop `vrf` from JSON output")
(zevpn->svi_if ? zevpn->svi_if->name : ""));
vty_out(vty, " SVI ifIndex: %u\n",
(zevpn->svi_if ? zevpn->svi_if->ifindex : 0));
- vty_out(vty, " Local VTEP IP: %pI4\n",
- &zevpn->local_vtep_ip);
- vty_out(vty, " Mcast group: %pI4\n",
- &zevpn->mcast_grp);
+ vty_out(vty, " Local VTEP IP: %pI4\n", &zevpn->local_vtep_ip);
+ vty_out(vty, " Mcast group: %pI4\n", &zevpn->mcast_grp);
} else {
- json_object_string_add(json, "vxlanInterface",
- zevpn->vxlan_if->name);
-#if CONFDATE > 20240210
-CPP_NOTICE("Drop `ifindex` from JSON output")
-#endif
- json_object_int_add(json, "ifindex", zevpn->vxlan_if->ifindex);
- json_object_int_add(json, "vxlanIfindex",
- zevpn->vxlan_if->ifindex);
+ json_object_string_add(json, "vxlanInterface", zevpn->vxlan_if->name);
+ json_object_int_add(json, "vxlanIfindex", zevpn->vxlan_if->ifindex);
if (zevpn->svi_if) {
- json_object_string_add(json, "sviInterface",
- zevpn->svi_if->name);
- json_object_int_add(json, "sviIfindex",
- zevpn->svi_if->ifindex);
+ json_object_string_add(json, "sviInterface", zevpn->svi_if->name);
+ json_object_int_add(json, "sviIfindex", zevpn->svi_if->ifindex);
}
- json_object_string_addf(json, "vtepIp", "%pI4",
- &zevpn->local_vtep_ip);
- json_object_string_addf(json, "mcastGroup", "%pI4",
- &zevpn->mcast_grp);
+ json_object_string_addf(json, "vtepIp", "%pI4", &zevpn->local_vtep_ip);
+ json_object_string_addf(json, "mcastGroup", "%pI4", &zevpn->mcast_grp);
json_object_string_add(json, "advertiseGatewayMacip",
- zevpn->advertise_gw_macip ? "Yes"
- : "No");
+ zevpn->advertise_gw_macip ? "Yes" : "No");
json_object_string_add(json, "advertiseSviMacip",
- zevpn->advertise_svi_macip ? "Yes"
- : "No");
+ zevpn->advertise_svi_macip ? "Yes" : "No");
json_object_int_add(json, "numMacs", num_macs);
json_object_int_add(json, "numArpNd", num_neigh);
}
@@ -179,28 +158,21 @@ CPP_NOTICE("Drop `ifindex` from JSON output")
json_vtep_list = json_object_new_array();
for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) {
const char *flood_str = lookup_msg(
- zvtep_flood_str, zvtep->flood_control,
- VXLAN_FLOOD_STR_DEFAULT);
+ zvtep_flood_str, zvtep->flood_control, VXLAN_FLOOD_STR_DEFAULT);
if (json == NULL) {
- vty_out(vty, " %pI4 flood: %s\n",
- &zvtep->vtep_ip,
- flood_str);
+ vty_out(vty, " %pI4 flood: %s\n", &zvtep->vtep_ip, flood_str);
} else {
json_vtep = json_object_new_object();
- json_object_string_addf(json_vtep, "ip", "%pI4",
- &zvtep->vtep_ip);
- json_object_string_add(json_vtep, "flood",
- flood_str);
- json_object_array_add(json_vtep_list,
- json_vtep);
+ json_object_string_addf(json_vtep, "ip", "%pI4", &zvtep->vtep_ip);
+ json_object_string_add(json_vtep, "flood", flood_str);
+ json_object_array_add(json_vtep_list, json_vtep);
}
num_vteps++;
}
if (json) {
json_object_int_add(json, "numRemoteVteps", num_vteps);
- json_object_object_add(json, "remoteVteps",
- json_vtep_list);
+ json_object_object_add(json, "remoteVteps", json_vtep_list);
}
}
if (json == NULL) {
@@ -261,8 +233,7 @@ void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[])
json_object_int_add(json_evpn, "vni", zevpn->vni);
json_object_string_add(json_evpn, "type", "L2");
json_object_string_add(json_evpn, "vxlanIf",
- zevpn->vxlan_if ? zevpn->vxlan_if->name
- : "unknown");
+ zevpn->vxlan_if ? zevpn->vxlan_if->name : "unknown");
json_object_int_add(json_evpn, "numMacs", num_macs);
json_object_int_add(json_evpn, "numArpNd", num_neigh);
json_object_int_add(json_evpn, "numRemoteVteps", num_vteps);
@@ -272,13 +243,10 @@ void zebra_evpn_print_hash(struct hash_bucket *bucket, void *ctxt[])
json_vtep_list = json_object_new_array();
for (zvtep = zevpn->vteps; zvtep; zvtep = zvtep->next) {
json_ip_str = json_object_new_string(
- inet_ntop(AF_INET, &zvtep->vtep_ip, buf,
- sizeof(buf)));
- json_object_array_add(json_vtep_list,
- json_ip_str);
+ inet_ntop(AF_INET, &zvtep->vtep_ip, buf, sizeof(buf)));
+ json_object_array_add(json_vtep_list, json_ip_str);
}
- json_object_object_add(json_evpn, "remoteVteps",
- json_vtep_list);
+ json_object_object_add(json_evpn, "remoteVteps", json_vtep_list);
}
json_object_object_add(json, vni_str, json_evpn);
}
@@ -383,7 +351,7 @@ static int ip_prefix_send_to_client(vrf_id_t vrf_id, struct prefix *p,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, cmd, vrf_id);
stream_put(s, p, sizeof(struct prefix));
@@ -490,8 +458,7 @@ int zebra_evpn_gw_macip_del(struct interface *ifp, struct zebra_evpn *zevpn,
/* Remove neighbor from BGP. */
zebra_evpn_neigh_send_del_to_client(zevpn->vni, &n->ip, &n->emac,
- n->flags, ZEBRA_NEIGH_ACTIVE,
- false /*force*/);
+ n->flags, ZEBRA_NEIGH_ACTIVE, false /*force*/);
/* Delete this neighbor entry. */
zebra_evpn_neigh_del(zevpn, n);
@@ -521,8 +488,7 @@ void zebra_evpn_gw_macip_del_for_evpn_hash(struct hash_bucket *bucket,
*/
if (zevpn->advertise_gw_macip) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip",
- zevpn->vni);
+ zlog_debug("VNI: %u GW-MACIP enabled, retain gw-macip", zevpn->vni);
return;
}
@@ -694,8 +660,7 @@ static int zebra_evpn_map_vlan_ns(struct ns *ns,
if (zif->brslave_info.br_if != br_if)
continue;
- vni_id =
- zebra_vxlan_if_access_vlan_vni_find(zif, br_if);
+ vni_id = zebra_vxlan_if_access_vlan_vni_find(zif, br_if);
if (vni_id) {
found = 1;
break;
@@ -732,9 +697,7 @@ struct zebra_evpn *zebra_evpn_map_vlan(struct interface *ifp,
in_param.zif = zif;
p_zevpn = &zevpn;
- ns_walk_func(zebra_evpn_map_vlan_ns,
- (void *)&in_param,
- (void **)p_zevpn);
+ ns_walk_func(zebra_evpn_map_vlan_ns, (void *)&in_param, (void **)p_zevpn);
return zevpn;
}
@@ -854,9 +817,7 @@ struct zebra_evpn *zebra_evpn_from_svi(struct interface *ifp,
return zevpn;
}
-static int zvni_map_to_macvlan_ns(struct ns *ns,
- void *_in_param,
- void **_p_ifp)
+static int zvni_map_to_macvlan_ns(struct ns *ns, void *_in_param, void **_p_ifp)
{
struct zebra_ns *zns = ns->info;
struct zebra_from_svi_param *in_param =
@@ -918,9 +879,7 @@ struct interface *zebra_evpn_map_to_macvlan(struct interface *br_if,
p_ifp = &tmp_if;
/* Identify corresponding VLAN interface. */
- ns_walk_func(zvni_map_to_macvlan_ns,
- (void *)&in_param,
- (void **)p_ifp);
+ ns_walk_func(zvni_map_to_macvlan_ns, (void *)&in_param, (void **)p_ifp);
return tmp_if;
}
@@ -1125,8 +1084,7 @@ struct zebra_evpn *zebra_evpn_add(vni_t vni)
/* Create hash table for MAC */
zevpn->mac_table = zebra_mac_db_create(buffer);
- snprintf(buffer, sizeof(buffer), "Zebra EVPN Neighbor Table vni: %u",
- vni);
+ snprintf(buffer, sizeof(buffer), "Zebra EVPN Neighbor Table vni: %u", vni);
/* Create hash table for neighbors */
zevpn->neigh_table = zebra_neigh_db_create(buffer);
@@ -1182,7 +1140,7 @@ int zebra_evpn_send_add_to_client(struct zebra_evpn *zevpn)
svi_index = zevpn->svi_if ? zevpn->svi_if->ifindex : 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, ZEBRA_VNI_ADD, zebra_vrf_get_evpn_id());
stream_putl(s, zevpn->vni);
@@ -1205,8 +1163,8 @@ int zebra_evpn_send_add_to_client(struct zebra_evpn *zevpn)
client->vniadd_cnt++;
rc = zserv_send_message(client, s);
- if (!(zevpn->flags & ZEVPN_READY_FOR_BGP)) {
- zevpn->flags |= ZEVPN_READY_FOR_BGP;
+ if (!CHECK_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP)) {
+ SET_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP);
/* once the EVPN is sent the ES-EVIs can also be replayed
* to BGP
*/
@@ -1228,13 +1186,13 @@ int zebra_evpn_send_del_to_client(struct zebra_evpn *zevpn)
if (!client)
return 0;
- if (zevpn->flags & ZEVPN_READY_FOR_BGP) {
- zevpn->flags &= ~ZEVPN_READY_FOR_BGP;
+ if (CHECK_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP)) {
+ UNSET_FLAG(zevpn->flags, ZEVPN_READY_FOR_BGP);
/* the ES-EVIs must be removed from BGP before the EVPN is */
zebra_evpn_update_all_es(zevpn);
}
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
stream_reset(s);
zclient_create_header(s, ZEBRA_VNI_DEL, zebra_vrf_get_evpn_id());
@@ -1350,8 +1308,7 @@ int zebra_evpn_vtep_install(struct zebra_evpn *zevpn, struct zebra_vtep *zvtep)
if (is_vxlan_flooding_head_end() &&
(zvtep->flood_control == VXLAN_FLOOD_HEAD_END_REPL)) {
if (ZEBRA_DPLANE_REQUEST_FAILURE ==
- dplane_vtep_add(zevpn->vxlan_if,
- &zvtep->vtep_ip, zevpn->vni))
+ dplane_vtep_add(zevpn->vxlan_if, &zvtep->vtep_ip, zevpn->vni))
return -1;
}
@@ -1442,9 +1399,7 @@ static void zebra_evpn_process_sync_macip_add(struct zebra_evpn *zevpn,
zevpn->vni,
macaddr,
ipa_len ? " IP " : "",
- ipa_len ? ipaddr2str(ipaddr, ipbuf,
- sizeof(ipbuf))
- : "",
+ ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "",
sticky ? " sticky" : "",
remote_gw ? " remote_gw" : "");
return;
@@ -1459,16 +1414,13 @@ static void zebra_evpn_process_sync_macip_add(struct zebra_evpn *zevpn,
mac = zebra_evpn_mac_lookup(zevpn, macaddr);
if (!mac) {
mac = zebra_evpn_proc_sync_mac_update(zevpn, macaddr,
- ipa_len, ipaddr,
- flags, seq, esi);
+ ipa_len, ipaddr, flags, seq, esi);
}
if (!mac)
return;
n = zebra_evpn_neigh_lookup(zevpn, ipaddr);
- if (n
- && !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq,
- true))
+ if (n && !zebra_evpn_neigh_is_bgp_seq_ok(zevpn, n, macaddr, seq, true))
return;
zebra_evpn_proc_sync_neigh_update(zevpn, n, ipa_len, ipaddr,
@@ -1514,22 +1466,19 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
* SYNC - if ES is local
* REMOTE - if ES is not local
*/
- if (flags & ZEBRA_MACIP_TYPE_SYNC_PATH) {
+ if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_SYNC_PATH)) {
struct zebra_evpn_es *es;
es = zebra_evpn_es_find(esi);
- if (es && (es->flags & ZEBRA_EVPNES_READY_FOR_BGP)) {
+ if (es && CHECK_FLAG(es->flags, ZEBRA_EVPNES_READY_FOR_BGP)) {
zebra_evpn_process_sync_macip_add(zevpn, macaddr,
- ipa_len, ipaddr,
- flags, seq, esi);
+ ipa_len, ipaddr, flags, seq, esi);
} else {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES) {
char esi_str[ESI_STR_LEN];
esi_to_str(esi, esi_str, sizeof(esi_str));
- zlog_debug(
- "Ignore sync-macip add; ES %s is not ready",
- esi_str);
+ zlog_debug("Ignore sync-macip add; ES %s is not ready", esi_str);
}
}
@@ -1543,8 +1492,7 @@ void zebra_evpn_rem_macip_add(vni_t vni, const struct ethaddr *macaddr,
if (vtep_ip.s_addr) {
zvtep = zebra_evpn_vtep_find(zevpn, &vtep_ip);
if (!zvtep) {
- zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip,
- VXLAN_FLOOD_DISABLED);
+ zvtep = zebra_evpn_vtep_add(zevpn, &vtep_ip, VXLAN_FLOOD_DISABLED);
if (!zvtep) {
flog_err(
EC_ZEBRA_VTEP_ADD_FAILED,
@@ -1621,9 +1569,7 @@ void zebra_evpn_rem_macip_del(vni_t vni, const struct ethaddr *macaddr,
vnip = zebra_vxlan_if_vni_find(zif, vni);
if (!vnip) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "VNI %u not in interface upon remote MACIP DEL",
- vni);
+ zlog_debug("VNI %u not in interface upon remote MACIP DEL", vni);
return;
}
diff --git a/zebra/zebra_evpn_mac.c b/zebra/zebra_evpn_mac.c
index 6d5cd66..bfc060d 100644
--- a/zebra/zebra_evpn_mac.c
+++ b/zebra/zebra_evpn_mac.c
@@ -103,9 +103,7 @@ static void zebra_evpn_mac_ifp_unlink(struct zebra_mac *zmac)
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);
+ zmac->zevpn->vni, &zmac->macaddr, ifp->name, ifp->ifindex);
zif = ifp->info;
list_delete_node(zif->mac_list, &zmac->ifp_listnode);
@@ -122,7 +120,7 @@ void zebra_evpn_mac_ifp_del(struct interface *ifp)
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);
+ zif->ifp->name, zif->ifp->ifindex);
for (ALL_LIST_ELEMENTS_RO(zif->mac_list, node, zmac)) {
zebra_evpn_mac_ifp_unlink(zmac);
@@ -161,9 +159,7 @@ static void zebra_evpn_mac_ifp_link(struct zebra_mac *zmac,
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->zevpn->vni, &zmac->macaddr, ifp->name, ifp->ifindex);
zmac->ifp = ifp;
listnode_init(&zmac->ifp_listnode, zmac);
@@ -205,7 +201,7 @@ int zebra_evpn_rem_mac_install(struct zebra_evpn *zevpn, struct zebra_mac *mac,
return -1;
sticky = !!CHECK_FLAG(mac->flags,
- (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
+ (ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW));
/* If nexthop group for the FDB entry is inactive (not programmed in
* the dataplane) the MAC entry cannot be installed
@@ -249,7 +245,7 @@ int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn,
enum zebra_dplane_result res;
/* If the MAC was not installed there is no need to uninstall it */
- if (!force && mac->es && !(mac->es->flags & ZEBRA_EVPNES_NHG_ACTIVE))
+ if (!force && mac->es && !CHECK_FLAG(mac->es->flags, ZEBRA_EVPNES_NHG_ACTIVE))
return -1;
if (!zevpn->vxlan_if) {
@@ -282,8 +278,7 @@ int zebra_evpn_rem_mac_uninstall(struct zebra_evpn *zevpn,
ifp = zevpn->vxlan_if;
vtep_ip = mac->fwd_info.r_vtep_ip;
- res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vni->vni,
- vtep_ip);
+ res = dplane_rem_mac_del(ifp, br_ifp, vid, &mac->macaddr, vni->vni, vtep_ip);
if (res != ZEBRA_DPLANE_REQUEST_FAILURE)
return 0;
else
@@ -341,8 +336,7 @@ static void zebra_evpn_mac_get_access_info(struct zebra_mac *mac,
*vid = mac->fwd_info.local.vid;
zns = zebra_ns_lookup(mac->fwd_info.local.ns_id);
- *p_ifp = if_lookup_by_index_per_ns(zns,
- mac->fwd_info.local.ifindex);
+ *p_ifp = if_lookup_by_index_per_ns(zns, mac->fwd_info.local.ifindex);
}
}
@@ -355,26 +349,19 @@ static char *zebra_evpn_zebra_mac_flag_dump(struct zebra_mac *mac, char *buf,
return buf;
}
- snprintfrr(
- buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s",
+ snprintfrr(buf, len, "%s%s%s%s%s%s%s%s%s%s%s%s",
CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL) ? "LOC " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) ? "REM " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO) ? "AUTO " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY) ? "STICKY " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router "
- : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_RMAC) ? "REM Router " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_DEF_GW) ? "Default GW " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW "
- : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW) ? "REM DEF GW " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE) ? "DUP " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_FPM_SENT) ? "FPM " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE)
- ? "PEER Active "
- : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "PEER Active " : "",
CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "PROXY " : "",
- CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)
- ? "LOC Inactive "
- : "");
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) ? "LOC Inactive " : "");
return buf;
}
@@ -407,8 +394,7 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t)
zlog_debug(
"%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)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
mac->dad_count, listcount(mac->neigh_list));
}
@@ -418,8 +404,7 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t)
if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_LOCAL))
ZEBRA_NEIGH_SET_INACTIVE(nbr);
else if (CHECK_FLAG(nbr->flags, ZEBRA_NEIGH_REMOTE))
- zebra_evpn_rem_neigh_install(
- zevpn, nbr, false /*was_static*/);
+ zebra_evpn_rem_neigh_install(zevpn, nbr, false /*was_static*/);
}
UNSET_FLAG(nbr->flags, ZEBRA_NEIGH_DUPLICATE);
@@ -438,13 +423,11 @@ static void zebra_evpn_dad_mac_auto_recovery_exp(struct event *t)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
/* Inform to BGP */
if (zebra_evpn_mac_send_add_to_client(zevpn->vni, &mac->macaddr,
- mac->flags, mac->loc_seq,
- mac->es))
+ mac->flags, mac->loc_seq, mac->es))
return;
/* Process all neighbors associated with this MAC. */
- zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
- 0 /*es_change*/);
+ zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, 0 /*es_change*/);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
@@ -479,8 +462,7 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
zlog_debug(
"%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)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
mac->dad_count, zvrf->dad_freeze_time);
}
/* For duplicate MAC do not update
@@ -516,8 +498,7 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
zlog_debug(
"%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)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
mac->dad_count);
}
@@ -545,10 +526,10 @@ 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 %pEA detected as duplicate during %s VTEP %pI4",
- mac->zevpn->vni, &mac->macaddr,
- is_local ? "local update, last" :
- "remote update, from", &vtep_ip);
+ "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);
SET_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE);
@@ -583,15 +564,13 @@ static void zebra_evpn_dup_addr_detect_for_mac(struct zebra_vrf *zvrf,
zlog_debug(
"%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)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
zvrf->dad_freeze_time);
}
event_add_timer(zrouter.master,
- zebra_evpn_dad_mac_auto_recovery_exp,
- mac, zvrf->dad_freeze_time,
- &mac->dad_mac_auto_recovery_timer);
+ zebra_evpn_dad_mac_auto_recovery_exp, mac,
+ zvrf->dad_freeze_time, &mac->dad_mac_auto_recovery_timer);
}
/* In case of local update, do not inform to client (BGPd),
@@ -638,22 +617,18 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
json_object_string_add(json_mac, "type", "local");
if (ifp) {
- json_object_string_add(json_mac, "intf",
- ifp->name);
- json_object_int_add(json_mac, "ifindex",
- ifp->ifindex);
+ json_object_string_add(json_mac, "intf", ifp->name);
+ json_object_int_add(json_mac, "ifindex", ifp->ifindex);
}
if (vid)
json_object_int_add(json_mac, "vlan", vid);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
json_object_string_add(json_mac, "type", "remote");
if (mac->es)
- json_object_string_add(json_mac, "remoteEs",
- mac->es->esi_str);
+ json_object_string_add(json_mac, "remoteEs", mac->es->esi_str);
else
json_object_string_addf(
- json_mac, "remoteVtep", "%pI4",
- &mac->fwd_info.r_vtep_ip);
+ json_mac, "remoteVtep", "%pI4", &mac->fwd_info.r_vtep_ip);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO))
json_object_string_add(json_mac, "type", "auto");
@@ -664,12 +639,10 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
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");
+ json_object_boolean_true_add(json_mac, "defaultGateway");
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW))
- json_object_boolean_true_add(json_mac,
- "remoteGatewayMac");
+ json_object_boolean_true_add(json_mac, "remoteGatewayMac");
json_object_string_add(json_mac, "uptime", up_str);
json_object_int_add(json_mac, "localSequence", mac->loc_seq);
@@ -690,46 +663,31 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE))
json_object_boolean_true_add(json_mac, "peerActive");
if (mac->hold_timer)
- json_object_string_add(
- json_mac, "peerActiveHold",
- event_timer_to_hhmmss(thread_buf,
- sizeof(thread_buf),
- mac->hold_timer));
+ json_object_string_add(json_mac, "peerActiveHold",
+ event_timer_to_hhmmss(thread_buf, sizeof(thread_buf), mac->hold_timer));
if (mac->es)
- json_object_string_add(json_mac, "esi",
- mac->es->esi_str);
+ json_object_string_add(json_mac, "esi", mac->es->esi_str);
/* print all the associated neigh */
if (!listcount(mac->neigh_list))
json_object_string_add(json_mac, "neighbors", "none");
else {
json_object *json_active_nbrs = json_object_new_array();
- json_object *json_inactive_nbrs =
- json_object_new_array();
+ json_object *json_inactive_nbrs = json_object_new_array();
json_object *json_nbrs = json_object_new_object();
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
if (IS_ZEBRA_NEIGH_ACTIVE(n))
- json_object_array_add(
- json_active_nbrs,
- json_object_new_string(
- ipaddr2str(
- &n->ip, buf2,
- sizeof(buf2))));
+ json_object_array_add(json_active_nbrs,
+ json_object_new_string(ipaddr2str(&n->ip, buf2, sizeof(buf2))));
else
json_object_array_add(
json_inactive_nbrs,
- json_object_new_string(
- ipaddr2str(
- &n->ip, buf2,
- sizeof(buf2))));
+ json_object_new_string(ipaddr2str(&n->ip, buf2, sizeof(buf2))));
}
- json_object_object_add(json_nbrs, "active",
- json_active_nbrs);
- json_object_object_add(json_nbrs, "inactive",
- json_inactive_nbrs);
- json_object_object_add(json_mac, "neighbors",
- json_nbrs);
+ json_object_object_add(json_nbrs, "active", json_active_nbrs);
+ json_object_object_add(json_nbrs, "inactive", json_inactive_nbrs);
+ json_object_object_add(json_mac, "neighbors", json_nbrs);
}
json_object_object_add(json, buf1, json_mac);
@@ -746,18 +704,15 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
vty_out(vty, " ESI: %s\n", mac->es->esi_str);
if (ifp)
- vty_out(vty, " Intf: %s(%u)", ifp->name,
- ifp->ifindex);
+ vty_out(vty, " Intf: %s(%u)", ifp->name, ifp->ifindex);
else
vty_out(vty, " Intf: -");
vty_out(vty, " VLAN: %u", vid);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
if (mac->es)
- vty_out(vty, " Remote ES: %s",
- mac->es->esi_str);
+ vty_out(vty, " Remote ES: %s", mac->es->esi_str);
else
- vty_out(vty, " Remote VTEP: %pI4",
- &mac->fwd_info.r_vtep_ip);
+ vty_out(vty, " Remote VTEP: %pI4", &mac->fwd_info.r_vtep_ip);
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)) {
vty_out(vty, " Auto Mac ");
}
@@ -784,24 +739,18 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
vty_out(vty, " peer-active");
if (mac->hold_timer)
vty_out(vty, " (ht: %s)",
- event_timer_to_hhmmss(thread_buf,
- sizeof(thread_buf),
- mac->hold_timer));
+ event_timer_to_hhmmss(thread_buf, sizeof(thread_buf), mac->hold_timer));
vty_out(vty, "\n");
- vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq,
- mac->rem_seq);
+ vty_out(vty, " Local Seq: %u Remote Seq: %u\n", mac->loc_seq, mac->rem_seq);
vty_out(vty, " Uptime: %s\n", up_str);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE)) {
vty_out(vty, " Duplicate, detected at %s",
- time_to_string(mac->dad_dup_detect_time,
- timebuf));
+ time_to_string(mac->dad_dup_detect_time, timebuf));
} else if (mac->dad_count) {
- monotime_since(&mac->detect_start_time,
- &detect_start_time);
+ monotime_since(&mac->detect_start_time, &detect_start_time);
if (detect_start_time.tv_sec <= zvrf->dad_time) {
- time_to_string(mac->detect_start_time.tv_sec,
- timebuf);
+ time_to_string(mac->detect_start_time.tv_sec, timebuf);
vty_out(vty,
" Duplicate detection started at %s, detection count %u\n",
timebuf, mac->dad_count);
@@ -816,9 +765,7 @@ void zebra_evpn_print_mac(struct zebra_mac *mac, void *ctxt, json_object *json)
for (ALL_LIST_ELEMENTS_RO(mac->neigh_list, node, n)) {
vty_out(vty, " %s %s\n",
ipaddr2str(&n->ip, buf2, sizeof(buf2)),
- (IS_ZEBRA_NEIGH_ACTIVE(n)
- ? "Active"
- : "Inactive"));
+ (IS_ZEBRA_NEIGH_ACTIVE(n) ? "Active" : "Inactive"));
}
}
@@ -831,9 +778,9 @@ static char *zebra_evpn_print_mac_flags(struct zebra_mac *mac, char *flags_buf,
{
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" : "");
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_ACTIVE) ? "P" : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_ES_PEER_PROXY) ? "X" : "",
+ CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE) ? "I" : "");
return flags_buf;
}
@@ -870,14 +817,12 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
zebra_evpn_mac_get_access_info(mac, &ifp, &vid);
if (json_mac_hdr == NULL) {
vty_out(vty, "%-17s %-6s %-5s %-30s", buf1, "local",
- zebra_evpn_print_mac_flags(mac, flags_buf,
- sizeof(flags_buf)),
+ zebra_evpn_print_mac_flags(mac, flags_buf, sizeof(flags_buf)),
ifp ? ifp->name : "-");
} else {
json_object_string_add(json_mac, "type", "local");
if (ifp)
- json_object_string_add(json_mac, "intf",
- ifp->name);
+ json_object_string_add(json_mac, "intf", ifp->name);
}
if (vid) {
if (json_mac_hdr == NULL)
@@ -891,18 +836,13 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
vty_out(vty, " %u/%u", mac->loc_seq, mac->rem_seq);
vty_out(vty, "\n");
} else {
- json_object_int_add(json_mac, "localSequence",
- mac->loc_seq);
- json_object_int_add(json_mac, "remoteSequence",
- mac->rem_seq);
- json_object_int_add(json_mac, "detectionCount",
- mac->dad_count);
+ json_object_int_add(json_mac, "localSequence", mac->loc_seq);
+ json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
+ json_object_int_add(json_mac, "detectionCount", mac->dad_count);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
- json_object_boolean_true_add(json_mac,
- "isDuplicate");
+ json_object_boolean_true_add(json_mac, "isDuplicate");
else
- json_object_boolean_false_add(json_mac,
- "isDuplicate");
+ json_object_boolean_false_add(json_mac, "isDuplicate");
json_object_object_add(json_mac_hdr, buf1, json_mac);
}
@@ -910,19 +850,16 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
} else if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
- if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
- && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip,
- &wctx->r_vtep_ip))
+ if (CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)
+ && !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
return;
if (json_mac_hdr == NULL) {
- if ((wctx->flags & SHOW_REMOTE_MAC_FROM_VTEP)
+ if (CHECK_FLAG(wctx->flags, SHOW_REMOTE_MAC_FROM_VTEP)
&& (wctx->count == 0)) {
vty_out(vty, "\nVNI %u\n\n", wctx->zevpn->vni);
vty_out(vty, "%-17s %-6s %-5s%-30s %-5s %s\n",
- "MAC", "Type", "Flags",
- "Intf/Remote ES/VTEP", "VLAN",
- "Seq #'s");
+ "MAC", "Type", "Flags", "Intf/Remote ES/VTEP", "VLAN", "Seq #'s");
}
if (mac->es == NULL)
inet_ntop(AF_INET, &mac->fwd_info.r_vtep_ip,
@@ -930,32 +867,24 @@ void zebra_evpn_print_mac_hash(struct hash_bucket *bucket, void *ctxt)
vty_out(vty, "%-17s %-6s %-5s %-30s %-5s %u/%u\n", buf1,
"remote",
- zebra_evpn_print_mac_flags(mac, flags_buf,
- sizeof(flags_buf)),
+ zebra_evpn_print_mac_flags(mac, flags_buf, sizeof(flags_buf)),
mac->es ? mac->es->esi_str : addr_buf,
"", mac->loc_seq, mac->rem_seq);
} else {
json_object_string_add(json_mac, "type", "remote");
if (mac->es)
- json_object_string_add(json_mac, "remoteEs",
- mac->es->esi_str);
+ json_object_string_add(json_mac, "remoteEs", mac->es->esi_str);
else
json_object_string_addf(
- json_mac, "remoteVtep", "%pI4",
- &mac->fwd_info.r_vtep_ip);
+ json_mac, "remoteVtep", "%pI4", &mac->fwd_info.r_vtep_ip);
json_object_object_add(json_mac_hdr, buf1, json_mac);
- json_object_int_add(json_mac, "localSequence",
- mac->loc_seq);
- json_object_int_add(json_mac, "remoteSequence",
- mac->rem_seq);
- json_object_int_add(json_mac, "detectionCount",
- mac->dad_count);
+ json_object_int_add(json_mac, "localSequence", mac->loc_seq);
+ json_object_int_add(json_mac, "remoteSequence", mac->rem_seq);
+ json_object_int_add(json_mac, "detectionCount", mac->dad_count);
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
- json_object_boolean_true_add(json_mac,
- "isDuplicate");
+ json_object_boolean_true_add(json_mac, "isDuplicate");
else
- json_object_boolean_false_add(json_mac,
- "isDuplicate");
+ json_object_boolean_false_add(json_mac, "isDuplicate");
}
wctx->count++;
@@ -1004,7 +933,7 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, cmd, zebra_vrf_get_evpn_id());
stream_putl(s, vni);
@@ -1040,9 +969,9 @@ int zebra_evpn_macip_send_msg_to_client(vni_t vni,
zlog_debug(
"Send MACIP %s f %s state %u 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)),
- state, macaddr, ip, seq, vni, es ? es->esi_str : "-",
+ zclient_evpn_dump_macip_flags(flags, flag_buf, sizeof(flag_buf)),
+ state, macaddr, ip, seq, vni,
+ es ? es->esi_str : "-",
zebra_route_string(client->proto));
}
@@ -1076,8 +1005,7 @@ static bool mac_cmp(const void *p1, const void *p2)
if (pmac1 == NULL || pmac2 == NULL)
return false;
- return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN)
- == 0);
+ return (memcmp(pmac1->macaddr.octet, pmac2->macaddr.octet, ETH_ALEN) == 0);
}
/*
@@ -1117,10 +1045,8 @@ struct zebra_mac *zebra_evpn_mac_add(struct zebra_evpn *zevpn,
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %pEA flags %s", __func__,
- &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zlog_debug("%s: MAC %pEA flags %s", __func__, &mac->macaddr,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
return mac;
}
@@ -1135,10 +1061,8 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC) {
char mac_buf[MAC_BUF_SIZE];
- zlog_debug("%s: MAC %pEA flags %s", __func__,
- &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)));
+ zlog_debug("%s: MAC %pEA flags %s", __func__, &mac->macaddr,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* force de-ref any ES entry linked to the MAC */
@@ -1165,9 +1089,8 @@ int zebra_evpn_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
"MAC %pEA (flags 0x%x vni %u) has non-empty neigh list "
- "count %u, mark MAC as AUTO",
- &mac->macaddr, mac->flags, zevpn->vni,
- listcount(mac->neigh_list));
+ "count %u, mark MAC as AUTO", &mac->macaddr, mac->flags,
+ zevpn->vni, listcount(mac->neigh_list));
SET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
return 0;
@@ -1204,25 +1127,25 @@ struct zebra_mac *zebra_evpn_mac_add_auto(struct zebra_evpn *zevpn,
static bool zebra_evpn_check_mac_del_from_db(struct mac_walk_ctx *wctx,
struct zebra_mac *mac)
{
- if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_LOCAL))
+ if (CHECK_FLAG(wctx->flags, DEL_LOCAL_MAC)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL))
return true;
- else if ((wctx->flags & DEL_REMOTE_MAC)
- && (mac->flags & ZEBRA_MAC_REMOTE))
+ else if (CHECK_FLAG(wctx->flags, DEL_REMOTE_MAC)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE))
return true;
- else if ((wctx->flags & DEL_REMOTE_MAC_FROM_VTEP)
- && (mac->flags & ZEBRA_MAC_REMOTE)
+ else if (CHECK_FLAG(wctx->flags, DEL_REMOTE_MAC_FROM_VTEP)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
&& IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &wctx->r_vtep_ip))
return true;
- else if ((wctx->flags & DEL_LOCAL_MAC) && (mac->flags & ZEBRA_MAC_AUTO)
+ else if (CHECK_FLAG(wctx->flags, DEL_LOCAL_MAC)
+ && CHECK_FLAG(mac->flags, ZEBRA_MAC_AUTO)
&& !listcount(mac->neigh_list)) {
if (IS_ZEBRA_DEBUG_VXLAN) {
char mac_buf[MAC_BUF_SIZE];
zlog_debug(
- "%s: Del MAC %pEA flags %s", __func__,
- &mac->macaddr,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ "%s: Del MAC %pEA flags %s", __func__, &mac->macaddr,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
wctx->uninstall = 0;
@@ -1241,21 +1164,17 @@ static void zebra_evpn_mac_del_hash_entry(struct hash_bucket *bucket, void *arg)
struct zebra_mac *mac = bucket->data;
if (zebra_evpn_check_mac_del_from_db(wctx, mac)) {
- if (wctx->upd_client && (mac->flags & ZEBRA_MAC_LOCAL)) {
+ if (wctx->upd_client && CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
zebra_evpn_mac_send_del_to_client(wctx->zevpn->vni,
- &mac->macaddr,
- mac->flags, false);
+ &mac->macaddr, mac->flags, false);
}
if (wctx->uninstall) {
if (zebra_evpn_mac_is_static(mac))
- zebra_evpn_sync_mac_dp_install(
- mac, false /* set_inactive */,
- true /* force_clear_static */,
- __func__);
+ zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
+ true /* force_clear_static */, __func__);
if (mac->flags & ZEBRA_MAC_REMOTE)
- zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac,
- false /*force*/);
+ zebra_evpn_rem_mac_uninstall(wctx->zevpn, mac, false /*force*/);
}
zebra_evpn_mac_del(wctx->zevpn, mac);
@@ -1330,8 +1249,7 @@ int zebra_evpn_mac_send_add_to_client(vni_t vni, const struct ethaddr *macaddr,
SET_FLAG(flags, ZEBRA_MACIP_TYPE_GW);
return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL, flags,
- seq, ZEBRA_NEIGH_ACTIVE, es,
- ZEBRA_MACIP_ADD);
+ seq, ZEBRA_NEIGH_ACTIVE, es, ZEBRA_MACIP_ADD);
}
/*
@@ -1357,9 +1275,8 @@ int zebra_evpn_mac_send_del_to_client(vni_t vni, const struct ethaddr *macaddr,
state = ZEBRA_NEIGH_INACTIVE;
}
- return zebra_evpn_macip_send_msg_to_client(
- vni, macaddr, NULL, 0 /* flags */, 0 /* seq */, state, NULL,
- ZEBRA_MACIP_DEL);
+ return zebra_evpn_macip_send_msg_to_client(vni, macaddr, NULL,
+ 0 /* flags */, 0 /* seq */, state, NULL, ZEBRA_MACIP_DEL);
}
/*
@@ -1412,8 +1329,7 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
"%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no access-port",
caller, zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_inactive ? "inactive " : "");
}
return -1;
@@ -1429,8 +1345,7 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
"%s: dp-install sync-mac vni %u mac %pEA es %s %s%sskipped, no br",
caller, zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_inactive ? "inactive " : "");
}
return -1;
@@ -1455,19 +1370,16 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
set_static ? "install" : "uninstall",
zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_inactive ? "inactive " : "");
}
if (set_static)
/* XXX - old_static needs to be computed more
* accurately
*/
- zebra_evpn_rem_mac_install(zevpn, mac,
- true /* old_static */);
+ zebra_evpn_rem_mac_install(zevpn, mac, true /* old_static */);
else
- zebra_evpn_rem_mac_uninstall(zevpn, mac,
- false /* force */);
+ zebra_evpn_rem_mac_uninstall(zevpn, mac, false /* force */);
return 0;
}
@@ -1478,14 +1390,13 @@ int zebra_evpn_sync_mac_dp_install(struct zebra_mac *mac, bool set_inactive,
zlog_debug("dp-install sync-mac vni %u mac %pEA es %s %s%s%s",
zevpn->vni, &mac->macaddr,
mac->es ? mac->es->esi_str : "-",
- zebra_evpn_zebra_mac_flag_dump(mac, mac_buf,
- sizeof(mac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
set_static ? "static " : "",
set_inactive ? "inactive " : "");
}
dplane_local_mac_add(ifp, br_ifp, vid, &mac->macaddr, sticky,
- set_static, set_inactive);
+ set_static, set_inactive);
return 0;
}
@@ -1495,12 +1406,11 @@ void zebra_evpn_mac_send_add_del_to_client(struct zebra_mac *mac,
{
if (new_bgp_ready)
zebra_evpn_mac_send_add_to_client(mac->zevpn->vni,
- &mac->macaddr, mac->flags,
- mac->loc_seq, mac->es);
+ &mac->macaddr, mac->flags,
+ mac->loc_seq, mac->es);
else if (old_bgp_ready)
zebra_evpn_mac_send_del_to_client(mac->zevpn->vni,
- &mac->macaddr, mac->flags,
- true /* force */);
+ &mac->macaddr, mac->flags, true /* force */);
}
/* MAC hold timer is used to age out peer-active flag.
@@ -1537,8 +1447,7 @@ static void zebra_evpn_mac_hold_exp_cb(struct event *t)
"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)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* re-program the local mac in the dataplane if the mac is no
@@ -1546,13 +1455,11 @@ static void zebra_evpn_mac_hold_exp_cb(struct event *t)
*/
if (old_static != new_static)
zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
/* inform bgp if needed */
if (old_bgp_ready != new_bgp_ready)
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
}
static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac)
@@ -1567,8 +1474,7 @@ static inline void zebra_evpn_mac_start_hold_timer(struct zebra_mac *mac)
"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)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
event_add_timer(zrouter.master, zebra_evpn_mac_hold_exp_cb, mac,
zmh_info->mac_hold_time, &mac->hold_timer);
@@ -1586,8 +1492,7 @@ void zebra_evpn_mac_stop_hold_timer(struct zebra_mac *mac)
"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)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
EVENT_OFF(mac->hold_timer);
@@ -1605,8 +1510,7 @@ void zebra_evpn_sync_mac_del(struct zebra_mac *mac)
"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)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
old_static = zebra_evpn_mac_is_static(mac);
@@ -1618,8 +1522,7 @@ void zebra_evpn_sync_mac_del(struct zebra_mac *mac)
if (old_static != new_static)
/* program the local mac in the kernel */
zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
}
static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
@@ -1647,8 +1550,7 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
zlog_debug(
"%s-macip not ready vni %u %s-mac %pEA lower seq %u f 0x%x",
sync ? "sync" : "rem", zevpn->vni,
- n_type, &mac->macaddr, tmp_seq,
- mac->flags);
+ n_type, &mac->macaddr, tmp_seq, mac->flags);
return true;
}
@@ -1660,10 +1562,9 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
IS_ZEBRA_DEBUG_VXLAN) {
zlog_debug(
"%s-macip accept vni %u %s-mac %pEA lower seq %u f %s",
- sync ? "sync" : "rem", zevpn->vni,
- n_type, &mac->macaddr, tmp_seq,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ (sync ? "sync" : "rem"),
+ zevpn->vni, n_type, &mac->macaddr, tmp_seq,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
return true;
@@ -1672,10 +1573,8 @@ static inline bool zebra_evpn_mac_is_bgp_seq_ok(struct zebra_evpn *zevpn,
if (IS_ZEBRA_DEBUG_EVPN_MH_MAC || IS_ZEBRA_DEBUG_VXLAN) {
zlog_debug(
"%s-macip ignore vni %u %s-mac %pEA as existing has higher seq %u f %s",
- sync ? "sync" : "rem", zevpn->vni, n_type,
- &mac->macaddr, tmp_seq,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ (sync ? "sync" : "rem"), zevpn->vni, n_type, &mac->macaddr, tmp_seq,
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
return false;
@@ -1749,9 +1648,7 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
"Ignore sync-macip vni %u mac %pEA%s%s%s%s",
zevpn->vni, macaddr,
ipa_len ? " IP " : "",
- ipa_len ? ipaddr2str(ipaddr, ipbuf,
- sizeof(ipbuf))
- : "",
+ ipa_len ? ipaddr2str(ipaddr, ipbuf, sizeof(ipbuf)) : "",
sticky ? " sticky" : "",
remote_gw ? " remote_gw" : "");
return NULL;
@@ -1766,16 +1663,16 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
new_flags = 0;
SET_FLAG(new_flags, ZEBRA_MAC_LOCAL);
/* retain old local activity flag */
- if (old_flags & ZEBRA_MAC_LOCAL)
- new_flags |= (old_flags & ZEBRA_MAC_LOCAL_INACTIVE);
+ if (CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL))
+ SET_FLAG (new_flags, CHECK_FLAG(old_flags, ZEBRA_MAC_LOCAL_INACTIVE));
else
- new_flags |= ZEBRA_MAC_LOCAL_INACTIVE;
+ SET_FLAG(new_flags, ZEBRA_MAC_LOCAL_INACTIVE);
if (ipa_len) {
/* if mac-ip route do NOT update the peer flags
* i.e. retain only flags as is
*/
- new_flags |= (old_flags & ZEBRA_MAC_ALL_PEER_FLAGS);
+ SET_FLAG(new_flags, CHECK_FLAG(old_flags, ZEBRA_MAC_ALL_PEER_FLAGS));
} else {
/* if mac-only route update peer flags */
if (CHECK_FLAG(flags, ZEBRA_MACIP_TYPE_PROXY_ADVERT)) {
@@ -1785,10 +1682,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
* holdtimer on it. the peer-active flag is
* cleared on holdtimer expiry.
*/
- if (CHECK_FLAG(old_flags,
- ZEBRA_MAC_ES_PEER_ACTIVE)) {
- SET_FLAG(new_flags,
- ZEBRA_MAC_ES_PEER_ACTIVE);
+ if (CHECK_FLAG(old_flags, ZEBRA_MAC_ES_PEER_ACTIVE)) {
+ SET_FLAG(new_flags, ZEBRA_MAC_ES_PEER_ACTIVE);
zebra_evpn_mac_start_hold_timer(mac);
}
} else {
@@ -1811,10 +1706,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
zlog_debug(
"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(
- mac, mac_buf, sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(&omac, omac_buf, sizeof(omac_buf)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* update es */
@@ -1854,24 +1747,24 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
char mac_buf[MAC_BUF_SIZE];
zlog_debug("sync-mac %s vni %u mac %pEA es %s seq %d f %s%s%s",
- 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)),
- inform_bgp ? "inform_bgp" : "",
- inform_dataplane ? " inform_dp" : "");
+ 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)),
+ inform_bgp ? "inform_bgp" : "",
+ inform_dataplane ? " inform_dp" : "");
}
if (inform_bgp)
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
/* neighs using the mac may need to be re-sent to
* bgp with updated info
*/
if (seq_change || es_change || !old_local)
zebra_evpn_process_neigh_on_local_mac_change(
- zevpn, mac, seq_change, es_change);
+ zevpn, mac, seq_change, es_change);
if (inform_dataplane && !ipa_len) {
/* program the local mac in the kernel. when the ES
@@ -1879,9 +1772,8 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
* the activity as we are yet to establish activity
* locally
*/
- zebra_evpn_sync_mac_dp_install(
- mac, mac_inactive /* set_inactive */,
- false /* force_clear_static */, __func__);
+ zebra_evpn_sync_mac_dp_install(mac, mac_inactive /* set_inactive */,
+ false /* force_clear_static */, __func__);
}
return mac;
@@ -1891,8 +1783,7 @@ struct zebra_mac *zebra_evpn_proc_sync_mac_update(struct zebra_evpn *zevpn,
* is detected
*/
static bool zebra_evpn_local_mac_update_fwd_info(struct zebra_mac *mac,
- struct interface *ifp,
- vlanid_t vid)
+ struct interface *ifp, vlanid_t vid)
{
struct zebra_if *zif = ifp->info;
bool es_change;
@@ -1934,8 +1825,8 @@ static void zebra_evpn_send_mac_hash_entry_to_client(struct hash_bucket *bucket,
if (CHECK_FLAG(zmac->flags, ZEBRA_MAC_LOCAL))
zebra_evpn_mac_send_add_to_client(wctx->zevpn->vni,
- &zmac->macaddr, zmac->flags,
- zmac->loc_seq, zmac->es);
+ &zmac->macaddr, zmac->flags,
+ zmac->loc_seq, zmac->es);
}
/* Iterator to Notify Local MACs of a EVPN */
@@ -1949,8 +1840,7 @@ void zebra_evpn_send_mac_list_to_client(struct zebra_evpn *zevpn)
memset(&wctx, 0, sizeof(wctx));
wctx.zevpn = zevpn;
- hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client,
- &wctx);
+ hash_iterate(zevpn->mac_table, zebra_evpn_send_mac_hash_entry_to_client, &wctx);
}
void zebra_evpn_rem_mac_del(struct zebra_evpn *zevpn, struct zebra_mac *mac)
@@ -1992,8 +1882,7 @@ void zebra_evpn_print_dad_mac_hash(struct hash_bucket *bucket, void *ctxt)
}
/* Print Duplicate MAC in detail */
-void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket,
- void *ctxt)
+void zebra_evpn_print_dad_mac_hash_detail(struct hash_bucket *bucket, void *ctxt)
{
struct zebra_mac *mac;
@@ -2043,11 +1932,13 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
* If so, that needs to be updated first. Note that client could
* install MAC and MACIP separately or just install the latter.
*/
- if (!mac || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
- || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
- || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
- || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
- || memcmp(old_esi, esi, sizeof(esi_t)) || seq != mac->rem_seq)
+ if (!mac
+ || !CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
+ || sticky != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_STICKY)
+ || remote_gw != !!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW)
+ || !IPV4_ADDR_SAME(&mac->fwd_info.r_vtep_ip, &vtep_ip)
+ || memcmp(old_esi, esi, sizeof(esi_t))
+ || seq != mac->rem_seq)
update_mac = 1;
if (update_mac) {
@@ -2063,8 +1954,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
* the sequence number and ignore this update
* if appropriate.
*/
- if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq,
- false))
+ if (!zebra_evpn_mac_is_bgp_seq_ok(zevpn, mac, seq, false))
return -1;
old_es_present = !!mac->es;
@@ -2091,8 +1981,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
* MAC is already marked duplicate set dad, then
* is_dup_detect will be set to not install the entry.
*/
- if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)
- && mac->dad_count)
+ if ((!CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE) && mac->dad_count)
|| CHECK_FLAG(mac->flags, ZEBRA_MAC_DUPLICATE))
do_dad = true;
@@ -2108,14 +1997,12 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
zevpn->vni, macaddr,
mac->es ? mac->es->esi_str : "-",
mac->loc_seq,
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
zebra_evpn_mac_clear_sync_info(mac);
- zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr,
- mac->flags,
- false /* force */);
+ zebra_evpn_mac_send_del_to_client(zevpn->vni, macaddr, mac->flags,
+ false /* force */);
}
/* Set "auto" and "remote" forwarding info. */
@@ -2135,8 +2022,7 @@ int zebra_evpn_mac_remote_macip_add(struct zebra_evpn *zevpn,
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE_DEF_GW);
zebra_evpn_dup_addr_detect_for_mac(
- zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad,
- &is_dup_detect, false);
+ zvrf, mac, mac->fwd_info.r_vtep_ip, do_dad, &is_dup_detect, false);
if (!is_dup_detect) {
zebra_evpn_process_neigh_on_remote_mac_add(zevpn, mac);
@@ -2180,8 +2066,8 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug(
"ADD %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s",
- sticky ? "sticky " : "", macaddr,
- ifp->name, ifp->ifindex, vid, zevpn->vni,
+ sticky ? "sticky " : "",
+ macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni,
local_inactive ? " local-inactive" : "");
mac = zebra_evpn_mac_add(zevpn, macaddr);
@@ -2196,11 +2082,10 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
zlog_debug(
"UPD %sMAC %pEA intf %s(%u) VID %u -> VNI %u %scurFlags %s",
- sticky ? "sticky " : "", macaddr,
- ifp->name, ifp->ifindex, vid, zevpn->vni,
+ sticky ? "sticky " : "",
+ macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni,
local_inactive ? "local-inactive " : "",
- zebra_evpn_zebra_mac_flag_dump(
- mac, mac_buf, sizeof(mac_buf)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL)) {
@@ -2209,42 +2094,34 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
bool old_static;
zebra_evpn_mac_get_access_info(mac, &old_ifp, &old_vid);
- old_bgp_ready =
- zebra_evpn_mac_is_ready_for_bgp(mac->flags);
- old_local_inactive =
- !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
+ old_bgp_ready = zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ old_local_inactive = !!(mac->flags & ZEBRA_MAC_LOCAL_INACTIVE);
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);
+ es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
/*
* Update any changes and if changes are relevant to
* BGP, note it.
*/
- if (mac_sticky == sticky && old_ifp == ifp
- && old_vid == vid
- && old_local_inactive == local_inactive
- && dp_static == old_static && !es_change) {
+ if (mac_sticky == sticky && old_ifp == ifp && old_vid == vid
+ && old_local_inactive == local_inactive
+ && dp_static == old_static && !es_change) {
if (IS_ZEBRA_DEBUG_VXLAN)
zlog_debug(
" Add/Update %sMAC %pEA intf %s(%u) VID %u -> VNI %u%s, "
"entry exists and has not changed ",
sticky ? "sticky " : "",
- macaddr, ifp->name,
- ifp->ifindex, vid, zevpn->vni,
- local_inactive
- ? " local_inactive"
- : "");
+ macaddr, ifp->name, ifp->ifindex, vid, zevpn->vni,
+ local_inactive ? " local_inactive" : "");
return 0;
}
if (mac_sticky != sticky) {
if (sticky)
SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
else
- UNSET_FLAG(mac->flags,
- ZEBRA_MAC_STICKY);
+ UNSET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
inform_client = true;
}
@@ -2262,11 +2139,9 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
/* force drop the peer/sync info as it is
* simply no longer relevant
*/
- if (CHECK_FLAG(mac->flags,
- ZEBRA_MAC_ALL_PEER_FLAGS)) {
+ if (CHECK_FLAG(mac->flags, ZEBRA_MAC_ALL_PEER_FLAGS)) {
zebra_evpn_mac_clear_sync_info(mac);
- new_static =
- zebra_evpn_mac_is_static(mac);
+ new_static = zebra_evpn_mac_is_static(mac);
/* if we clear peer-flags we
* also need to notify the dataplane
* to drop the static flag
@@ -2289,16 +2164,13 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
flog_warn(
EC_ZEBRA_STICKY_MAC_ALREADY_LEARNT,
"MAC %pEA already learnt as remote sticky MAC behind VTEP %pI4 VNI %u",
- macaddr,
- &mac->fwd_info.r_vtep_ip,
- zevpn->vni);
+ macaddr, &mac->fwd_info.r_vtep_ip, zevpn->vni);
return 0;
}
/* If an actual move, compute MAC's seq number */
if (CHECK_FLAG(mac->flags, ZEBRA_MAC_REMOTE)) {
- mac->loc_seq =
- MAX(mac->rem_seq + 1, mac->loc_seq);
+ mac->loc_seq = MAX(mac->rem_seq + 1, mac->loc_seq);
vtep_ip = mac->fwd_info.r_vtep_ip;
/* Trigger DAD for remote MAC */
do_dad = true;
@@ -2307,8 +2179,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
UNSET_FLAG(mac->flags, ZEBRA_MAC_REMOTE);
UNSET_FLAG(mac->flags, ZEBRA_MAC_AUTO);
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL);
- es_change = zebra_evpn_local_mac_update_fwd_info(
- mac, ifp, vid);
+ es_change = zebra_evpn_local_mac_update_fwd_info(mac, ifp, vid);
if (sticky)
SET_FLAG(mac->flags, ZEBRA_MAC_STICKY);
else
@@ -2321,8 +2192,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
upd_neigh = true;
zebra_evpn_dup_addr_detect_for_mac(
- zvrf, mac, vtep_ip, do_dad, &is_dup_detect,
- true);
+ zvrf, mac, vtep_ip, do_dad, &is_dup_detect, true);
if (is_dup_detect) {
inform_client = false;
upd_neigh = false;
@@ -2357,8 +2227,7 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
"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)),
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)),
local_inactive ? "local-inactive" : "");
}
@@ -2374,18 +2243,15 @@ int zebra_evpn_add_update_local_mac(struct zebra_vrf *zvrf,
/* Inform dataplane if required. */
if (inform_dataplane)
zebra_evpn_sync_mac_dp_install(mac, false /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
/* Inform BGP if required. */
if (inform_client)
- zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready,
- new_bgp_ready);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
/* Process all neighbors associated with this MAC, if required. */
if (upd_neigh)
- zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0,
- es_change);
+ zebra_evpn_process_neigh_on_local_mac_change(zevpn, mac, 0, es_change);
return 0;
}
@@ -2415,23 +2281,20 @@ int zebra_evpn_del_local_mac(struct zebra_evpn *zevpn, struct zebra_mac *mac,
"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)));
+ zebra_evpn_zebra_mac_flag_dump(mac, mac_buf, sizeof(mac_buf)));
}
/* inform-bgp about change in local-activity if any */
if (!CHECK_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE)) {
SET_FLAG(mac->flags, ZEBRA_MAC_LOCAL_INACTIVE);
- new_bgp_ready =
- zebra_evpn_mac_is_ready_for_bgp(mac->flags);
+ 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);
+ mac, old_bgp_ready, new_bgp_ready);
}
/* re-install the inactive entry in the kernel */
zebra_evpn_sync_mac_dp_install(mac, true /* set_inactive */,
- false /* force_clear_static */,
- __func__);
+ false /* force_clear_static */, __func__);
return 0;
}
@@ -2519,8 +2382,7 @@ void zebra_evpn_mac_svi_del(struct interface *ifp, struct zebra_evpn *zevpn)
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_mac_send_add_del_to_client(mac, old_bgp_ready, false);
zebra_evpn_deref_ip2mac(mac->zevpn, mac);
}
}
@@ -2548,13 +2410,11 @@ void zebra_evpn_mac_svi_add(struct interface *ifp, struct zebra_evpn *zevpn)
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;
+ old_bgp_ready =
+ (mac && zebra_evpn_mac_is_ready_for_bgp(mac->flags)) ? true : false;
zebra_evpn_mac_gw_macip_add(ifp, zevpn, NULL, &mac, &macaddr, 0, false);
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);
+ zebra_evpn_mac_send_add_del_to_client(mac, old_bgp_ready, new_bgp_ready);
}
diff --git a/zebra/zebra_evpn_mh.c b/zebra/zebra_evpn_mh.c
index 35d5027..75e7e20 100644
--- a/zebra/zebra_evpn_mh.c
+++ b/zebra/zebra_evpn_mh.c
@@ -563,8 +563,9 @@ 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 bridge %s add", vid, br_if->name);
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s access vlan %d bridge %s add", __func__, vid,
+ br_if->name);
acc_bd = XCALLOC(MTYPE_ZACC_BD, sizeof(struct zebra_evpn_access_bd));
@@ -582,8 +583,8 @@ zebra_evpn_acc_vl_new(vlanid_t vid, struct interface *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 bridge %s SVI %s set", vid,
- br_if->name, vlan_if->name);
+ zlog_debug("%s vlan %d bridge %s SVI %s set", __func__,
+ vid, br_if->name, vlan_if->name);
acc_bd->vlan_zif = vlan_if->info;
}
return acc_bd;
@@ -731,6 +732,29 @@ static void zebra_evpn_acc_bd_evpn_set(struct zebra_evpn_access_bd *acc_bd,
}
}
+/* Lookup API for VxLAN_IF's Bridge, VLAN in EVPN cache */
+int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid, struct zebra_if *vxlan_zif)
+{
+ struct interface *br_if;
+ struct zebra_evpn_access_bd *acc_bd;
+
+ if (!vid)
+ return -1;
+
+ br_if = vxlan_zif->brslave_info.br_if;
+
+ if (!br_if)
+ return -1;
+
+ acc_bd = zebra_evpn_acc_vl_find(vid, br_if);
+
+ if (!acc_bd)
+ return 0;
+
+ return 1;
+}
+
+
/* handle VLAN->VxLAN_IF association */
void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id,
struct zebra_if *vxlan_zif)
@@ -768,8 +792,9 @@ void zebra_evpn_vl_vxl_ref(uint16_t vid, vni_t vni_id,
if (acc_bd->zevpn == old_zevpn)
return;
- if (IS_ZEBRA_DEBUG_EVPN_MH_ES)
- zlog_debug("access vlan %d vni %u ref", acc_bd->vid, vni_id);
+ if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_KERNEL)
+ zlog_debug("%s bridge %s access vlan %d vni %u ref", __func__,
+ br_if->name, acc_bd->vid, vni_id);
if (old_zevpn)
zebra_evpn_acc_bd_evpn_set(acc_bd, NULL, old_zevpn);
@@ -1935,7 +1960,7 @@ static int zebra_evpn_es_send_add_to_client(struct zebra_evpn_es *es)
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s, ZEBRA_LOCAL_ES_ADD, zebra_vrf_get_evpn_id());
stream_put(s, &es->esi, sizeof(esi_t));
@@ -1971,7 +1996,7 @@ static int zebra_evpn_es_send_del_to_client(struct zebra_evpn_es *es)
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
stream_reset(s);
zclient_create_header(s, ZEBRA_LOCAL_ES_DEL, zebra_vrf_get_evpn_id());
@@ -2639,7 +2664,7 @@ static int zebra_evpn_es_evi_send_to_client(struct zebra_evpn_es *es,
if (!client)
return 0;
- s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+ s = stream_new(ZEBRA_SMALL_PACKET_SIZE);
zclient_create_header(s,
add ? ZEBRA_LOCAL_ES_EVI_ADD : ZEBRA_LOCAL_ES_EVI_DEL,
@@ -3001,7 +3026,7 @@ void zebra_evpn_es_if_oper_state_change(struct zebra_if *zif, bool up)
}
static char *zebra_evpn_es_vtep_str(char *vtep_str, struct zebra_evpn_es *es,
- uint8_t vtep_str_size)
+ size_t vtep_str_size)
{
struct zebra_evpn_es_vtep *zvtep;
struct listnode *node;
diff --git a/zebra/zebra_evpn_mh.h b/zebra/zebra_evpn_mh.h
index 34ef79f..f68e2ea 100644
--- a/zebra/zebra_evpn_mh.h
+++ b/zebra/zebra_evpn_mh.h
@@ -378,7 +378,8 @@ extern void zebra_evpn_es_bypass_update(struct zebra_evpn_es *es,
extern void zebra_evpn_proc_remote_nh(ZAPI_HANDLER_ARGS);
extern struct zebra_evpn_es_evi *
zebra_evpn_es_evi_find(struct zebra_evpn_es *es, struct zebra_evpn *zevpn);
-
+extern int zebra_evpn_vl_vxl_bridge_lookup(uint16_t vid,
+ struct zebra_if *vxlan_zif);
void zebra_build_type3_esi(uint32_t lid, struct ethaddr *mac, esi_t *esi);
void zebra_evpn_es_sys_mac_update(struct zebra_if *zif, struct ethaddr *sysmac);
diff --git a/zebra/zebra_fpm_netlink.c b/zebra/zebra_fpm_netlink.c
index 1dd9634..95207ce 100644
--- a/zebra/zebra_fpm_netlink.c
+++ b/zebra/zebra_fpm_netlink.c
@@ -592,19 +592,19 @@ int zfpm_netlink_encode_mac(struct fpm_mac_info_t *mac, char *in_buf,
RTM_DELNEIGH : RTM_NEWNEIGH;
req->hdr.nlmsg_flags = NLM_F_REQUEST;
if (req->hdr.nlmsg_type == RTM_NEWNEIGH)
- req->hdr.nlmsg_flags |= (NLM_F_CREATE | NLM_F_REPLACE);
+ SET_FLAG(req->hdr.nlmsg_flags, (NLM_F_CREATE | NLM_F_REPLACE));
/* Construct ndmsg */
req->ndm.ndm_family = AF_BRIDGE;
req->ndm.ndm_ifindex = mac->vxlan_if;
req->ndm.ndm_state = NUD_REACHABLE;
- req->ndm.ndm_flags |= NTF_SELF | NTF_MASTER;
+ SET_FLAG(req->ndm.ndm_flags, (NTF_SELF | NTF_MASTER));
if (CHECK_FLAG(mac->zebra_flags,
(ZEBRA_MAC_STICKY | ZEBRA_MAC_REMOTE_DEF_GW)))
- req->ndm.ndm_state |= NUD_NOARP;
+ SET_FLAG(req->ndm.ndm_state, NUD_NOARP);
else
- req->ndm.ndm_flags |= NTF_EXT_LEARNED;
+ SET_FLAG(req->ndm.ndm_flags, NTF_EXT_LEARNED);
/* Add attributes */
nl_attr_put(&req->hdr, in_buf_len, NDA_LLADDR, &mac->macaddr, 6);
diff --git a/zebra/zebra_gr.c b/zebra/zebra_gr.c
index f4241f1..cee66cc 100644
--- a/zebra/zebra_gr.c
+++ b/zebra/zebra_gr.c
@@ -298,6 +298,16 @@ struct zebra_gr_afi_clean {
* Functions to deal with capabilities
*/
+void zebra_gr_client_final_shutdown(struct zserv *client)
+{
+ struct client_gr_info *info;
+
+ while (!TAILQ_EMPTY(&client->gr_info_queue)) {
+ info = TAILQ_FIRST(&client->gr_info_queue);
+ zebra_gr_client_info_delete(client, info);
+ }
+}
+
/*
* Function to decode and call appropriate functions
* to handle client capabilities.
diff --git a/zebra/zebra_l2.c b/zebra/zebra_l2.c
index 4f7a1cd..240f674 100644
--- a/zebra/zebra_l2.c
+++ b/zebra/zebra_l2.c
@@ -111,13 +111,13 @@ 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 old_bypass = !!CHECK_FLAG(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) {
+ if (CHECK_FLAG(bond_mbr->flags, ZIF_FLAG_LACP_BYPASS)) {
new_bypass = true;
break;
}
@@ -132,9 +132,9 @@ static void zebra_l2_bond_lacp_bypass_eval(struct zebra_if *bond_zif)
bond_zif->ifp->name, new_bypass ? "on" : "off");
if (new_bypass)
- bond_zif->flags |= ZIF_FLAG_LACP_BYPASS;
+ SET_FLAG(bond_zif->flags, ZIF_FLAG_LACP_BYPASS);
else
- bond_zif->flags &= ~ZIF_FLAG_LACP_BYPASS;
+ UNSET_FLAG(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,
@@ -174,8 +174,7 @@ void zebra_l2_map_slave_to_bond(struct zebra_if *zif, vrf_id_t vrf_id)
}
} else {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("bond mbr %s link to bond skipped",
- zif->ifp->name);
+ zlog_debug("bond mbr %s link to bond skipped", zif->ifp->name);
}
}
@@ -186,8 +185,7 @@ void zebra_l2_unmap_slave_from_bond(struct zebra_if *zif)
if (!bond_slave->bond_if) {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("bond mbr %s unlink from bond skipped",
- zif->ifp->name);
+ zlog_debug("bond mbr %s unlink from bond skipped", zif->ifp->name);
return;
}
@@ -218,8 +216,7 @@ void zebra_l2if_update_bond(struct interface *ifp, bool add)
if (add) {
if (!bond->mbr_zifs) {
if (IS_ZEBRA_DEBUG_EVPN_MH_ES || IS_ZEBRA_DEBUG_EVENT)
- zlog_debug("bond %s mbr list create",
- ifp->name);
+ zlog_debug("bond %s mbr list create", ifp->name);
bond->mbr_zifs = list_new();
}
} else {
@@ -347,7 +344,7 @@ void zebra_l2_vxlanif_add_update(struct interface *ifp,
ctx.old_vtep_ip = zif->l2info.vxl.vtep_ip;
if (!IPV4_ADDR_SAME(&ctx.old_vtep_ip, &vxlan_info->vtep_ip)) {
- chgflags |= ZEBRA_VXLIF_LOCAL_IP_CHANGE;
+ SET_FLAG(chgflags, ZEBRA_VXLIF_LOCAL_IP_CHANGE);
zif->l2info.vxl.vtep_ip = vxlan_info->vtep_ip;
}
@@ -355,7 +352,7 @@ void zebra_l2_vxlanif_add_update(struct interface *ifp,
ctx.old_vni = vxlan_info->vni_info.vni;
if (!IPV4_ADDR_SAME(&zif->l2info.vxl.vni_info.vni.mcast_grp,
&vxlan_info->vni_info.vni.mcast_grp)) {
- chgflags |= ZEBRA_VXLIF_MCAST_GRP_CHANGE;
+ SET_FLAG(chgflags, ZEBRA_VXLIF_MCAST_GRP_CHANGE);
zif->l2info.vxl.vni_info.vni.mcast_grp =
vxlan_info->vni_info.vni.mcast_grp;
}
@@ -387,7 +384,7 @@ void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
return;
old_access_vlan = zif->l2info.vxl.vni_info.vni.access_vlan;
- ;
+
if (old_access_vlan == access_vlan)
return;
@@ -441,11 +438,11 @@ void zebra_l2if_update_bridge_slave(struct interface *ifp,
if (zif->zif_type == ZEBRA_IF_VXLAN
&& chgflags != ZEBRA_BRIDGE_NO_ACTION) {
- if (chgflags & ZEBRA_BRIDGE_MASTER_MAC_CHANGE) {
+ if (CHECK_FLAG(chgflags, ZEBRA_BRIDGE_MASTER_MAC_CHANGE)) {
ctx.chgflags = ZEBRA_VXLIF_MASTER_MAC_CHANGE;
zebra_vxlan_if_update(ifp, &ctx);
}
- if (chgflags & ZEBRA_BRIDGE_MASTER_UP) {
+ if (CHECK_FLAG(chgflags, ZEBRA_BRIDGE_MASTER_UP)) {
ctx.chgflags = ZEBRA_VXLIF_MASTER_CHANGE;
zebra_vxlan_if_update(ifp, &ctx);
}
@@ -494,16 +491,16 @@ void zebra_l2if_update_bond_slave(struct interface *ifp, ifindex_t bond_ifindex,
zif = ifp->info;
assert(zif);
- old_bypass = !!(zif->flags & ZIF_FLAG_LACP_BYPASS);
+ old_bypass = !!CHECK_FLAG(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;
+ SET_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS);
else
- zif->flags &= ~ZIF_FLAG_LACP_BYPASS;
+ UNSET_FLAG(zif->flags, ZIF_FLAG_LACP_BYPASS);
bond_mbr = &zif->bondslave_info;
if (bond_mbr->bond_if) {
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 39fc678..d1c9cd5 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -329,7 +329,7 @@ static void fec_evaluate(struct zebra_vrf *zvrf)
/* Skip configured FECs and those without a label index.
*/
- if (fec->flags & FEC_FLAG_CONFIGURED
+ if (CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED)
|| fec->label_index == MPLS_INVALID_LABEL_INDEX)
continue;
@@ -2291,7 +2291,7 @@ int zebra_mpls_fec_register(struct zebra_vrf *zvrf, struct prefix *p,
new_client = true;
} else {
/* Check if the FEC has been statically defined in the config */
- is_configured_fec = fec->flags & FEC_FLAG_CONFIGURED;
+ is_configured_fec = CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED);
/* Client may register same FEC with different label index. */
new_client =
(listnode_lookup(fec->client_list, client) == NULL);
@@ -2382,8 +2382,8 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
/* If not a configured entry, delete the FEC if no other clients. Before
* deleting, see if any LSP needs to be uninstalled.
*/
- if (!(fec->flags & FEC_FLAG_CONFIGURED)
- && list_isempty(fec->client_list)) {
+ if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED) &&
+ list_isempty(fec->client_list)) {
mpls_label_t old_label = fec->label;
fec->label = MPLS_INVALID_LABEL; /* reset */
fec_change_update_lsp(zvrf, fec, old_label);
@@ -2420,7 +2420,7 @@ static int zebra_mpls_cleanup_fecs_for_client(struct zserv *client)
if (fec_client == client) {
listnode_delete(fec->client_list,
fec_client);
- if (!(fec->flags & FEC_FLAG_CONFIGURED)
+ if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED)
&& list_isempty(fec->client_list))
fec_del(fec);
break;
@@ -2476,7 +2476,7 @@ static int zebra_mpls_cleanup_zclient_labels(struct zserv *client)
* hash..
*/
struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
- mpls_label_t label)
+ struct prefix *p, mpls_label_t label)
{
struct route_node *rn;
struct zebra_fec *fec;
@@ -2491,8 +2491,11 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
if (!rn->info)
continue;
fec = rn->info;
- if (fec->label == label)
+ if (fec->label == label) {
+ if (p && prefix_same(p, &rn->p))
+ return NULL;
return fec;
+ }
}
}
@@ -2502,9 +2505,10 @@ struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
/*
* Inform if specified label is currently bound to a FEC or not.
*/
-int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label)
+int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p,
+ mpls_label_t label)
{
- return (zebra_mpls_fec_for_label(zvrf, label) ? 1 : 0);
+ return (zebra_mpls_fec_for_label(zvrf, p, label) ? 1 : 0);
}
/*
@@ -2538,7 +2542,7 @@ int zebra_mpls_static_fec_add(struct zebra_vrf *zvrf, struct prefix *p,
if (IS_ZEBRA_DEBUG_MPLS)
zlog_debug("Add fec %pFX label %u", p, in_label);
} else {
- fec->flags |= FEC_FLAG_CONFIGURED;
+ SET_FLAG(fec->flags, FEC_FLAG_CONFIGURED);
if (fec->label == in_label)
/* Duplicate config */
return 0;
@@ -2587,7 +2591,7 @@ int zebra_mpls_static_fec_del(struct zebra_vrf *zvrf, struct prefix *p)
}
old_label = fec->label;
- fec->flags &= ~FEC_FLAG_CONFIGURED;
+ UNSET_FLAG(fec->flags, FEC_FLAG_CONFIGURED);
fec->label = MPLS_INVALID_LABEL;
/* If no client exists, just delete the FEC. */
@@ -2630,7 +2634,7 @@ int zebra_mpls_write_fec_config(struct vty *vty, struct zebra_vrf *zvrf)
char lstr[BUFSIZ];
fec = rn->info;
- if (!(fec->flags & FEC_FLAG_CONFIGURED))
+ if (!CHECK_FLAG(fec->flags, FEC_FLAG_CONFIGURED))
continue;
write = 1;
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index 1ed2f9b..dd6f960 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -203,12 +203,13 @@ int zebra_mpls_fec_unregister(struct zebra_vrf *zvrf, struct prefix *p,
* hash..
*/
struct zebra_fec *zebra_mpls_fec_for_label(struct zebra_vrf *zvrf,
- mpls_label_t label);
+ struct prefix *p, mpls_label_t label);
/*
* Inform if specified label is currently bound to a FEC or not.
*/
-int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, mpls_label_t label);
+int zebra_mpls_label_already_bound(struct zebra_vrf *zvrf, struct prefix *p,
+ mpls_label_t label);
/*
* Add static FEC to label binding. If there are clients registered for this
diff --git a/zebra/zebra_mpls_openbsd.c b/zebra/zebra_mpls_openbsd.c
index 9cbe6a2..85a53dd 100644
--- a/zebra/zebra_mpls_openbsd.c
+++ b/zebra/zebra_mpls_openbsd.c
@@ -64,8 +64,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
sa_label_in.smpls_family = AF_MPLS;
sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
- hdr.rtm_addrs |= RTA_DST;
+ SET_FLAG(hdr.rtm_flags, (RTF_MPLS | RTF_MPATH));
+ SET_FLAG(hdr.rtm_addrs, RTA_DST);
hdr.rtm_msglen += sizeof(sa_label_in);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_in;
@@ -77,8 +77,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
nexthop.sin_family = AF_INET;
nexthop.sin_addr = nhlfe->nexthop->gate.ipv4;
/* adjust header */
- hdr.rtm_flags |= RTF_GATEWAY;
- hdr.rtm_addrs |= RTA_GATEWAY;
+ SET_FLAG(hdr.rtm_flags, RTF_GATEWAY);
+ SET_FLAG(hdr.rtm_addrs, RTA_GATEWAY);
hdr.rtm_msglen += sizeof(nexthop);
/* adjust iovec */
iov[iovcnt].iov_base = &nexthop;
@@ -93,8 +93,8 @@ static int kernel_send_rtmsg_v4(int action, mpls_label_t in_label,
htonl(nhlfe->nexthop->nh_label->label[0]
<< MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_addrs |= RTA_SRC;
- hdr.rtm_flags |= RTF_MPLS;
+ SET_FLAG(hdr.rtm_addrs, RTA_SRC);
+ SET_FLAG(hdr.rtm_flags, RTF_MPLS);
hdr.rtm_msglen += sizeof(sa_label_out);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_out;
@@ -159,8 +159,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
sa_label_in.smpls_family = AF_MPLS;
sa_label_in.smpls_label = htonl(in_label << MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_flags |= RTF_MPLS | RTF_MPATH;
- hdr.rtm_addrs |= RTA_DST;
+ SET_FLAG(hdr.rtm_flags, (RTF_MPLS | RTF_MPATH));
+ SET_FLAG(hdr.rtm_addrs, RTA_DST);
hdr.rtm_msglen += sizeof(sa_label_in);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_in;
@@ -184,8 +184,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
}
/* adjust header */
- hdr.rtm_flags |= RTF_GATEWAY;
- hdr.rtm_addrs |= RTA_GATEWAY;
+ SET_FLAG(hdr.rtm_flags, RTF_GATEWAY);
+ SET_FLAG(hdr.rtm_addrs, RTA_GATEWAY);
hdr.rtm_msglen += ROUNDUP(sizeof(struct sockaddr_in6));
/* adjust iovec */
iov[iovcnt].iov_base = &nexthop;
@@ -200,8 +200,8 @@ static int kernel_send_rtmsg_v6(int action, mpls_label_t in_label,
htonl(nhlfe->nexthop->nh_label->label[0]
<< MPLS_LABEL_OFFSET);
/* adjust header */
- hdr.rtm_addrs |= RTA_SRC;
- hdr.rtm_flags |= RTF_MPLS;
+ SET_FLAG(hdr.rtm_addrs, RTA_SRC);
+ SET_FLAG(hdr.rtm_flags, RTF_MPLS);
hdr.rtm_msglen += sizeof(sa_label_out);
/* adjust iovec */
iov[iovcnt].iov_base = &sa_label_out;
@@ -324,8 +324,8 @@ static enum zebra_dplane_result kmpw_install(struct zebra_dplane_ctx *ctx)
return ZEBRA_DPLANE_REQUEST_FAILURE;
}
- if (dplane_ctx_get_pw_flags(ctx) & F_PSEUDOWIRE_CWORD)
- imr.imr_flags |= IMR_FLAG_CONTROLWORD;
+ if (CHECK_FLAG(dplane_ctx_get_pw_flags(ctx), F_PSEUDOWIRE_CWORD))
+ SET_FLAG(imr.imr_flags, IMR_FLAG_CONTROLWORD);
/* pseudowire nexthop */
memset(&ss, 0, sizeof(ss));
diff --git a/zebra/zebra_mpls_vty.c b/zebra/zebra_mpls_vty.c
index 83a1aad..b31bf44 100644
--- a/zebra/zebra_mpls_vty.c
+++ b/zebra/zebra_mpls_vty.c
@@ -210,7 +210,7 @@ static int zebra_mpls_bind(struct vty *vty, int add_cmd, const char *prefix,
vty_out(vty, "%% Invalid label\n");
return CMD_WARNING_CONFIG_FAILED;
}
- if (zebra_mpls_label_already_bound(zvrf, label)) {
+ if (zebra_mpls_label_already_bound(zvrf, &p, label)) {
vty_out(vty,
"%% Label already bound to a FEC\n");
return CMD_WARNING_CONFIG_FAILED;
diff --git a/zebra/zebra_nb.c b/zebra/zebra_nb.c
index e1ca5ec..eee9323 100644
--- a/zebra/zebra_nb.c
+++ b/zebra/zebra_nb.c
@@ -803,6 +803,12 @@ const struct frr_yang_module_info frr_zebra_info = {
}
},
{
+ .xpath = "/frr-interface:lib/interface/frr-zebra:zebra/state/bond",
+ .cbs = {
+ .get_elem = lib_interface_zebra_state_bond_get_elem,
+ }
+ },
+ {
.xpath = "/frr-vrf:lib/vrf/frr-zebra:zebra/router-id",
.cbs = {
.modify = lib_vrf_zebra_router_id_modify,
diff --git a/zebra/zebra_nb.h b/zebra/zebra_nb.h
index d7cf5f4..b40ed68 100644
--- a/zebra/zebra_nb.h
+++ b/zebra/zebra_nb.h
@@ -285,6 +285,7 @@ struct yang_data *lib_interface_zebra_state_remote_vtep_get_elem(
struct nb_cb_get_elem_args *args);
struct yang_data *lib_interface_zebra_state_mcast_group_get_elem(
struct nb_cb_get_elem_args *args);
+struct yang_data *lib_interface_zebra_state_bond_get_elem(struct nb_cb_get_elem_args *args);
int lib_vrf_zebra_router_id_modify(struct nb_cb_modify_args *args);
int lib_vrf_zebra_router_id_destroy(struct nb_cb_destroy_args *args);
int lib_vrf_zebra_ipv6_router_id_modify(struct nb_cb_modify_args *args);
diff --git a/zebra/zebra_nb_config.c b/zebra/zebra_nb_config.c
index ff2529f..ae6232a 100644
--- a/zebra/zebra_nb_config.c
+++ b/zebra/zebra_nb_config.c
@@ -3102,7 +3102,7 @@ int lib_interface_zebra_ipv6_router_advertisements_rdnss_rdnss_address_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
- struct rtadv_rdnss rdnss = {0}, *p;
+ struct rtadv_rdnss rdnss = {{{{0}}}}, *p;
if (args->event != NB_EV_APPLY)
return NB_OK;
@@ -3181,7 +3181,7 @@ int lib_interface_zebra_ipv6_router_advertisements_dnssl_dnssl_domain_create(
struct nb_cb_create_args *args)
{
struct interface *ifp;
- struct rtadv_dnssl dnssl = {0}, *p;
+ struct rtadv_dnssl dnssl = {{0}}, *p;
int ret;
strlcpy(dnssl.name, yang_dnode_get_string(args->dnode, "domain"),
diff --git a/zebra/zebra_nb_rpcs.c b/zebra/zebra_nb_rpcs.c
index 083ab3f..744ba62 100644
--- a/zebra/zebra_nb_rpcs.c
+++ b/zebra/zebra_nb_rpcs.c
@@ -12,6 +12,8 @@
#include "zebra/zebra_router.h"
#include "zebra/zebra_vrf.h"
#include "zebra/zebra_vxlan.h"
+#include "zebra/zebra_vxlan_if.h"
+#include "zebra/zebra_evpn.h"
/*
* XPath: /frr-zebra:clear-evpn-dup-addr
@@ -20,48 +22,41 @@ int clear_evpn_dup_addr_rpc(struct nb_cb_rpc_args *args)
{
struct zebra_vrf *zvrf;
int ret = NB_OK;
- struct yang_data *yang_dup_choice = NULL, *yang_dup_vni = NULL,
- *yang_dup_ip = NULL, *yang_dup_mac = NULL;
-
- yang_dup_choice = yang_data_list_find(args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice");
+ if (!is_evpn_enabled()) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "%% EVPN not enabled\n");
+ return NB_ERR_VALIDATION;
+ }
zvrf = zebra_vrf_get_evpn();
- if (yang_dup_choice
- && strcmp(yang_dup_choice->value, "all-case") == 0) {
+ if (yang_dnode_exists(args->input, "all-vnis")) {
zebra_vxlan_clear_dup_detect_vni_all(zvrf);
} else {
- vni_t vni;
+ vni_t vni = yang_dnode_get_uint32(args->input, "vni-id");
struct ipaddr host_ip = {.ipa_type = IPADDR_NONE};
struct ethaddr mac;
- yang_dup_vni = yang_data_list_find(
- args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice/single-case/vni-id");
- if (yang_dup_vni) {
- vni = yang_str2uint32(yang_dup_vni->value);
-
- yang_dup_mac = yang_data_list_find(
- args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice/single-case/vni-id/mac-addr");
- yang_dup_ip = yang_data_list_find(
- args->input, "%s/%s", args->xpath,
- "input/clear-dup-choice/single-case/vni-id/vni-ipaddr");
-
- if (yang_dup_mac) {
- yang_str2mac(yang_dup_mac->value, &mac);
- ret = zebra_vxlan_clear_dup_detect_vni_mac(
- zvrf, vni, &mac, args->errmsg,
- args->errmsg_len);
- } else if (yang_dup_ip) {
- yang_str2ip(yang_dup_ip->value, &host_ip);
- ret = zebra_vxlan_clear_dup_detect_vni_ip(
- zvrf, vni, &host_ip, args->errmsg,
- args->errmsg_len);
- } else
- ret = zebra_vxlan_clear_dup_detect_vni(zvrf,
- vni);
+ if (!zebra_evpn_lookup(vni)) {
+ snprintf(args->errmsg, args->errmsg_len,
+ "%% VNI %u does not exist\n", vni);
+ return NB_ERR_VALIDATION;
+ }
+
+ if (yang_dnode_exists(args->input, "mac-addr")) {
+ yang_dnode_get_mac(&mac, args->input, "mac-addr");
+ ret = zebra_vxlan_clear_dup_detect_vni_mac(zvrf, vni,
+ &mac,
+ args->errmsg,
+ args->errmsg_len);
+ } else if (yang_dnode_exists(args->input, "vni-ipaddr")) {
+ yang_dnode_get_ip(&host_ip, args->input, "vni-ipaddr");
+ ret = zebra_vxlan_clear_dup_detect_vni_ip(zvrf, vni,
+ &host_ip,
+ args->errmsg,
+ args->errmsg_len);
+ } else {
+ ret = zebra_vxlan_clear_dup_detect_vni(zvrf, vni);
}
}
if (ret < 0)
diff --git a/zebra/zebra_nb_state.c b/zebra/zebra_nb_state.c
index 00df9bf..63ac787 100644
--- a/zebra/zebra_nb_state.c
+++ b/zebra/zebra_nb_state.c
@@ -49,8 +49,50 @@ lib_interface_zebra_state_down_count_get_elem(struct nb_cb_get_elem_args *args)
struct yang_data *
lib_interface_zebra_state_zif_type_get_elem(struct nb_cb_get_elem_args *args)
{
- /* TODO: implement me. */
- return NULL;
+ const struct interface *ifp = args->list_entry;
+ struct zebra_if *zebra_if;
+ const char *type = NULL;
+
+ zebra_if = ifp->info;
+
+ /*
+ * NOTE: when adding a new type to the switch, make sure it is defined
+ * in it's YANG model.
+ */
+ switch (zebra_if->zif_type) {
+ case ZEBRA_IF_OTHER:
+ type = "frr-zebra:zif-other";
+ break;
+ case ZEBRA_IF_VXLAN:
+ type = "frr-zebra:zif-vxlan";
+ break;
+ case ZEBRA_IF_VRF:
+ type = "frr-zebra:zif-vrf";
+ break;
+ case ZEBRA_IF_BRIDGE:
+ type = "frr-zebra:zif-bridge";
+ break;
+ case ZEBRA_IF_VLAN:
+ type = "frr-zebra:zif-vlan";
+ break;
+ case ZEBRA_IF_MACVLAN:
+ type = "frr-zebra:zif-macvlan";
+ break;
+ case ZEBRA_IF_VETH:
+ type = "frr-zebra:zif-veth";
+ break;
+ case ZEBRA_IF_BOND:
+ type = "frr-zebra:zif-bond";
+ break;
+ case ZEBRA_IF_GRE:
+ type = "frr-zebra:zif-gre";
+ break;
+ }
+
+ if (!type)
+ return NULL;
+
+ return yang_data_new_string(args->xpath, type);
}
/*
@@ -145,6 +187,28 @@ lib_interface_zebra_state_mcast_group_get_elem(struct nb_cb_get_elem_args *args)
return yang_data_new_ipv4(args->xpath, &vni->mcast_grp);
}
+/*
+ * XPath: /frr-interface:lib/interface/frr-zebra:zebra/state/bond
+ */
+struct yang_data *
+lib_interface_zebra_state_bond_get_elem(struct nb_cb_get_elem_args *args)
+{
+ const struct interface *ifp = args->list_entry;
+ struct zebra_if *zebra_if;
+ struct interface *bond;
+
+ if (!IS_ZEBRA_IF_BOND_SLAVE(ifp))
+ return NULL;
+
+ zebra_if = ifp->info;
+ bond = zebra_if->bondslave_info.bond_if;
+
+ if (!bond)
+ return NULL;
+
+ return yang_data_new_string(args->xpath, bond->name);
+}
+
const void *lib_vrf_zebra_ribs_rib_get_next(struct nb_cb_get_next_args *args)
{
struct vrf *vrf = (struct vrf *)args->parent_list_entry;
@@ -548,7 +612,7 @@ struct yang_data *lib_vrf_zebra_ribs_rib_route_route_entry_uptime_get_elem(
{
struct route_entry *re = (struct route_entry *)args->list_entry;
- return yang_data_new_date_and_time(args->xpath, re->uptime);
+ return yang_data_new_date_and_time(args->xpath, re->uptime, true);
}
/*
diff --git a/zebra/zebra_neigh.c b/zebra/zebra_neigh.c
index 941088a..a222e7f 100644
--- a/zebra/zebra_neigh.c
+++ b/zebra/zebra_neigh.c
@@ -83,7 +83,7 @@ zebra_neigh_new(ifindex_t ifindex, struct ipaddr *ip, struct ethaddr *mac)
n->ifindex = ifindex;
if (mac) {
memcpy(&n->mac, mac, sizeof(*mac));
- n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
}
/* Add to rb_tree */
@@ -118,10 +118,8 @@ static void zebra_neigh_free(struct zebra_neigh_ent *n)
/* if rules are still using the neigh mark it as inactive and
* update the dataplane
*/
- if (n->flags & ZEBRA_NEIGH_ENT_ACTIVE) {
- n->flags &= ~ZEBRA_NEIGH_ENT_ACTIVE;
- memset(&n->mac, 0, sizeof(n->mac));
- }
+ UNSET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
+ memset(&n->mac, 0, sizeof(n->mac));
zebra_neigh_pbr_rules_update(n);
return;
}
@@ -181,7 +179,7 @@ void zebra_neigh_add(struct interface *ifp, struct ipaddr *ip,
return;
memcpy(&n->mac, mac, sizeof(*mac));
- n->flags |= ZEBRA_NEIGH_ENT_ACTIVE;
+ SET_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE);
/* update rules linked to the neigh */
zebra_neigh_pbr_rules_update(n);
@@ -201,7 +199,7 @@ void zebra_neigh_deref(struct zebra_pbr_rule *rule)
rule->action.neigh = NULL;
/* remove rule from the list and free if it is inactive */
list_delete_node(n->pbr_rule_list, &rule->action.neigh_listnode);
- if (!(n->flags & ZEBRA_NEIGH_ENT_ACTIVE))
+ if (!CHECK_FLAG(n->flags, ZEBRA_NEIGH_ENT_ACTIVE))
zebra_neigh_free(n);
}
diff --git a/zebra/zebra_netns_id.c b/zebra/zebra_netns_id.c
index 1af3a3e..4cee3b8 100644
--- a/zebra/zebra_netns_id.c
+++ b/zebra/zebra_netns_id.c
@@ -42,7 +42,7 @@
#define NETLINK_SOCKET_BUFFER_SIZE 512
#define NETLINK_ALIGNTO 4
#define NETLINK_ALIGN(len) \
- (((len) + NETLINK_ALIGNTO - 1) & ~(NETLINK_ALIGNTO - 1))
+ CHECK_FLAG(((len) + NETLINK_ALIGNTO - 1), ~(NETLINK_ALIGNTO - 1))
#define NETLINK_NLATTR_LEN(_a, _b) (unsigned int)((char *)_a - (char *)_b)
#endif /* defined(HAVE_NETLINK) */
@@ -66,7 +66,7 @@ static struct nlmsghdr *initiate_nlh(char *buf, unsigned int *seq, int type)
nlh->nlmsg_type = type;
nlh->nlmsg_flags = NLM_F_REQUEST;
if (type == RTM_NEWNSID)
- nlh->nlmsg_flags |= NLM_F_ACK;
+ SET_FLAG(nlh->nlmsg_flags, NLM_F_ACK);
nlh->nlmsg_seq = *seq = frr_sequence32_next();
return nlh;
}
diff --git a/zebra/zebra_netns_notify.c b/zebra/zebra_netns_notify.c
index 1bb1292..fb326b0 100644
--- a/zebra/zebra_netns_notify.c
+++ b/zebra/zebra_netns_notify.c
@@ -15,6 +15,7 @@
#include <sched.h>
#endif
#include <dirent.h>
+#include <libgen.h>
#include <sys/inotify.h>
#include <sys/stat.h>
@@ -234,6 +235,7 @@ static void zebra_ns_ready_read(struct event *t)
{
struct zebra_netns_info *zns_info = EVENT_ARG(t);
const char *netnspath;
+ const char *netnspath_basename;
int err, stop_retry = 0;
if (!zns_info)
@@ -261,23 +263,24 @@ static void zebra_ns_ready_read(struct event *t)
zebra_ns_continue_read(zns_info, stop_retry);
return;
}
+ netnspath_basename = basename(strdupa(netnspath));
/* check default name is not already set */
- if (strmatch(VRF_DEFAULT_NAME, basename(netnspath))) {
- zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", basename(netnspath));
+ if (strmatch(VRF_DEFAULT_NAME, netnspath_basename)) {
+ zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", netnspath_basename);
zebra_ns_continue_read(zns_info, 1);
return;
}
- if (zebra_ns_notify_is_default_netns(basename(netnspath))) {
+ if (zebra_ns_notify_is_default_netns(netnspath_basename)) {
zlog_warn(
"NS notify : NS %s is default VRF. Ignore VRF creation",
- basename(netnspath));
+ netnspath_basename);
zebra_ns_continue_read(zns_info, 1);
return;
}
/* success : close fd and create zns context */
- zebra_ns_notify_create_context_from_entry_name(basename(netnspath));
+ zebra_ns_notify_create_context_from_entry_name(netnspath_basename);
zebra_ns_continue_read(zns_info, 1);
}
@@ -304,7 +307,7 @@ static void zebra_ns_notify_read(struct event *t)
char *netnspath;
struct zebra_netns_info *netnsinfo;
- if (!(event->mask & (IN_CREATE | IN_DELETE)))
+ if (!CHECK_FLAG(event->mask, (IN_CREATE | IN_DELETE)))
continue;
if (offsetof(struct inotify_event, name) + event->len
@@ -350,7 +353,7 @@ static void zebra_ns_notify_read(struct event *t)
memcpy(event_name, event->name, event->len);
event_name[event->len - 1] = 0;
- if (event->mask & IN_DELETE) {
+ if (CHECK_FLAG(event->mask, IN_DELETE)) {
zebra_ns_delete(event_name);
continue;
}
@@ -396,7 +399,7 @@ void zebra_ns_notify_parse(void)
continue;
}
/* check default name is not already set */
- if (strmatch(VRF_DEFAULT_NAME, basename(dent->d_name))) {
+ if (strmatch(VRF_DEFAULT_NAME, basename(strdupa(dent->d_name)))) {
zlog_warn("NS notify : NS %s is already default VRF.Cancel VRF Creation", dent->d_name);
continue;
}
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index ed949da..9971b19 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -309,8 +309,10 @@ static int zebra_nhg_insert_id(struct nhg_hash_entry *nhe)
static void zebra_nhg_set_if(struct nhg_hash_entry *nhe, struct interface *ifp)
{
+ struct zebra_if *zif = (struct zebra_if *)ifp->info;
+
nhe->ifp = ifp;
- if_nhg_dependents_add(ifp, nhe);
+ nhg_connected_tree_add_nhe(&zif->nhg_dependents, nhe);
}
static void
@@ -1031,31 +1033,44 @@ static struct nhg_ctx *nhg_ctx_init(uint32_t id, struct nexthop *nh,
return ctx;
}
-static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe)
+static void zebra_nhg_set_valid(struct nhg_hash_entry *nhe, bool valid)
{
struct nhg_connected *rb_node_dep;
- SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ if (valid)
+ SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ else {
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
- frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
- zebra_nhg_set_valid(rb_node_dep->nhe);
-}
+ /* If we're in shutdown, this interface event needs to clean
+ * up installed NHGs, so don't clear that flag directly.
+ */
+ if (!zebra_router_in_shutdown())
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+ }
-static void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe)
-{
- struct nhg_connected *rb_node_dep;
+ /* Update validity of nexthops depending on it */
+ frr_each (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) {
+ if (!valid) {
+ /*
+ * Grab the first nexthop from the depending nexthop group
+ * then let's find the nexthop in that group that matches
+ * my individual nexthop and mark it as no longer ACTIVE
+ */
+ struct nexthop *nexthop = rb_node_dep->nhe->nhg.nexthop;
- UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ while (nexthop) {
+ if (nexthop_same(nexthop, nhe->nhg.nexthop))
+ break;
- /* If we're in shutdown, this interface event needs to clean
- * up installed NHGs, so don't clear that flag directly.
- */
- if (!zebra_router_in_shutdown())
- UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
+ nexthop = nexthop->next;
+ }
- /* Update validity of nexthops depending on it */
- frr_each(nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep)
- zebra_nhg_check_valid(rb_node_dep->nhe);
+ if (nexthop)
+ UNSET_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+ }
+ zebra_nhg_set_valid(rb_node_dep->nhe, valid);
+ }
}
void zebra_nhg_check_valid(struct nhg_hash_entry *nhe)
@@ -1063,6 +1078,13 @@ void zebra_nhg_check_valid(struct nhg_hash_entry *nhe)
struct nhg_connected *rb_node_dep = NULL;
bool valid = false;
+ /*
+ * If I have other nhe's depending on me, then this is a
+ * singleton nhe so set this nexthops flag as appropriate.
+ */
+ if (nhg_connected_tree_count(&nhe->nhg_depends))
+ UNSET_FLAG(nhe->nhg.nexthop->flags, NEXTHOP_FLAG_ACTIVE);
+
/* If anthing else in the group is valid, the group is valid */
frr_each(nhg_connected_tree, &nhe->nhg_depends, rb_node_dep) {
if (CHECK_FLAG(rb_node_dep->nhe->flags, NEXTHOP_GROUP_VALID)) {
@@ -1071,10 +1093,7 @@ void zebra_nhg_check_valid(struct nhg_hash_entry *nhe)
}
}
- if (valid)
- zebra_nhg_set_valid(nhe);
- else
- zebra_nhg_set_invalid(nhe);
+ zebra_nhg_set_valid(nhe, valid);
}
static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe)
@@ -1082,8 +1101,11 @@ static void zebra_nhg_release_all_deps(struct nhg_hash_entry *nhe)
/* Remove it from any lists it may be on */
zebra_nhg_depends_release(nhe);
zebra_nhg_dependents_release(nhe);
- if (nhe->ifp)
- if_nhg_dependents_del(nhe->ifp, nhe);
+ if (nhe->ifp) {
+ struct zebra_if *zif = nhe->ifp->info;
+
+ nhg_connected_tree_del_nhe(&zif->nhg_dependents, nhe);
+ }
}
static void zebra_nhg_release(struct nhg_hash_entry *nhe)
@@ -1115,7 +1137,7 @@ static void zebra_nhg_handle_install(struct nhg_hash_entry *nhe, bool install)
struct nhg_connected *rb_node_dep;
frr_each_safe (nhg_connected_tree, &nhe->nhg_dependents, rb_node_dep) {
- zebra_nhg_set_valid(rb_node_dep->nhe);
+ zebra_nhg_set_valid(rb_node_dep->nhe, true);
/* install dependent NHG into kernel */
if (install) {
if (IS_ZEBRA_DEBUG_NHG_DETAIL)
@@ -1799,8 +1821,8 @@ static struct nexthop *nexthop_set_resolved(afi_t afi,
break;
}
- if (newhop->flags & NEXTHOP_FLAG_ONLINK)
- resolved_hop->flags |= NEXTHOP_FLAG_ONLINK;
+ if (CHECK_FLAG(newhop->flags, NEXTHOP_FLAG_ONLINK))
+ SET_FLAG(resolved_hop->flags, NEXTHOP_FLAG_ONLINK);
/* Copy labels of the resolved route and the parent resolving to it */
if (policy) {
@@ -3094,14 +3116,15 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
zebra_nhg_install_kernel(rb_node_dep->nhe);
}
- if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)
- && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)
- && !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) {
+ if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID) &&
+ (!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) ||
+ CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL)) &&
+ !CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED)) {
/* Change its type to us since we are installing it */
if (!ZEBRA_NHG_CREATED(nhe))
nhe->type = ZEBRA_ROUTE_NHG;
- int ret = dplane_nexthop_add(nhe);
+ enum zebra_dplane_result ret = dplane_nexthop_add(nhe);
switch (ret) {
case ZEBRA_DPLANE_REQUEST_QUEUED:
@@ -3114,8 +3137,9 @@ void zebra_nhg_install_kernel(struct nhg_hash_entry *nhe)
nhe);
break;
case ZEBRA_DPLANE_REQUEST_SUCCESS:
- SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
- zebra_nhg_handle_install(nhe, false);
+ flog_err(EC_ZEBRA_DP_INVALID_RC,
+ "DPlane returned an invalid result code for attempt of installation of %pNG into the kernel",
+ nhe);
break;
}
}
@@ -3182,8 +3206,9 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
}
UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_QUEUED);
- if (status == ZEBRA_DPLANE_REQUEST_SUCCESS) {
- SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL);
+ switch (status) {
+ case ZEBRA_DPLANE_REQUEST_SUCCESS:
SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
zebra_nhg_handle_install(nhe, true);
@@ -3192,7 +3217,9 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
zsend_nhg_notify(nhe->type, nhe->zapi_instance,
nhe->zapi_session, nhe->id,
ZAPI_NHG_INSTALLED);
- } else {
+ break;
+ case ZEBRA_DPLANE_REQUEST_FAILURE:
+ UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
/* If daemon nhg, send it an update */
if (PROTO_OWNED(nhe))
zsend_nhg_notify(nhe->type, nhe->zapi_instance,
@@ -3205,6 +3232,12 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
EC_ZEBRA_DP_INSTALL_FAIL,
"Failed to install Nexthop (%pNG) into the kernel",
nhe);
+ break;
+ case ZEBRA_DPLANE_REQUEST_QUEUED:
+ flog_err(EC_ZEBRA_DP_INVALID_RC,
+ "Dplane returned an invalid result code for a result from the dplane for %pNG into the kernel",
+ nhe);
+ break;
}
}
}
@@ -3682,12 +3715,11 @@ void zebra_interface_nhg_reinstall(struct interface *ifp)
&rb_node_dep->nhe->nhg_dependents,
rb_node_dependent) {
if (IS_ZEBRA_DEBUG_NHG)
- zlog_debug(
- "%s dependent nhe %pNG unset installed flag",
- __func__,
- rb_node_dependent->nhe);
- UNSET_FLAG(rb_node_dependent->nhe->flags,
- NEXTHOP_GROUP_INSTALLED);
+ zlog_debug("%s dependent nhe %pNG Setting Reinstall flag",
+ __func__,
+ rb_node_dependent->nhe);
+ SET_FLAG(rb_node_dependent->nhe->flags,
+ NEXTHOP_GROUP_REINSTALL);
}
}
}
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 4eddecb..3bb697a 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -85,7 +85,7 @@ struct nhg_hash_entry {
* nhg(1)->nhg_dependents is 3 in the tree
*
* nhg(2)->nhg_depends is empty
- * nhg(3)->nhg_dependents is 3 in the tree
+ * nhg(2)->nhg_dependents is 3 in the tree
*/
struct nhg_connected_tree_head nhg_depends, nhg_dependents;
@@ -144,6 +144,14 @@ struct nhg_hash_entry {
* Track FPM installation status..
*/
#define NEXTHOP_GROUP_FPM (1 << 7)
+
+/*
+ * When an interface comes up install the
+ * singleton's and schedule the NHG's that
+ * are using this nhg to be reinstalled
+ * when installation is successful.
+ */
+#define NEXTHOP_GROUP_REINSTALL (1 << 8)
};
/* Upper 4 bits of the NHG are reserved for indicating the NHG type */
diff --git a/zebra/zebra_rnh.c b/zebra/zebra_rnh.c
index b387e99..bff8258 100644
--- a/zebra/zebra_rnh.c
+++ b/zebra/zebra_rnh.c
@@ -1266,327 +1266,42 @@ failure:
*/
void show_nexthop_json_helper(json_object *json_nexthop,
const struct nexthop *nexthop,
+ const struct route_node *rn,
const struct route_entry *re)
{
- json_object *json_labels = NULL;
- json_object *json_backups = NULL;
- json_object *json_seg6local = NULL;
- json_object *json_seg6 = NULL;
- json_object *json_segs = NULL;
- int i;
-
- json_object_int_add(json_nexthop, "flags", nexthop->flags);
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
- json_object_boolean_true_add(json_nexthop, "duplicate");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_FIB))
- json_object_boolean_true_add(json_nexthop, "fib");
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- json_object_string_addf(json_nexthop, "ip", "%pI4",
- &nexthop->gate.ipv4);
- json_object_string_add(json_nexthop, "afi", "ipv4");
-
- if (nexthop->ifindex) {
- json_object_int_add(json_nexthop, "interfaceIndex",
- nexthop->ifindex);
- json_object_string_add(json_nexthop, "interfaceName",
- ifindex2ifname(nexthop->ifindex,
- nexthop->vrf_id));
- }
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- json_object_string_addf(json_nexthop, "ip", "%pI6",
- &nexthop->gate.ipv6);
- json_object_string_add(json_nexthop, "afi", "ipv6");
-
- if (nexthop->ifindex) {
- json_object_int_add(json_nexthop, "interfaceIndex",
- nexthop->ifindex);
- json_object_string_add(json_nexthop, "interfaceName",
- ifindex2ifname(nexthop->ifindex,
- nexthop->vrf_id));
- }
- break;
-
- case NEXTHOP_TYPE_IFINDEX:
- json_object_boolean_true_add(json_nexthop, "directlyConnected");
- json_object_int_add(json_nexthop, "interfaceIndex",
- nexthop->ifindex);
- json_object_string_add(
- json_nexthop, "interfaceName",
- ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- json_object_boolean_true_add(json_nexthop, "unreachable");
- switch (nexthop->bh_type) {
- case BLACKHOLE_REJECT:
- json_object_boolean_true_add(json_nexthop, "reject");
- break;
- case BLACKHOLE_ADMINPROHIB:
- json_object_boolean_true_add(json_nexthop,
- "adminProhibited");
- break;
- case BLACKHOLE_NULL:
- json_object_boolean_true_add(json_nexthop, "blackhole");
- break;
- case BLACKHOLE_UNSPEC:
- break;
- }
- break;
- }
-
- /* This nexthop is a resolver for the parent nexthop.
- * Set resolver flag for better clarity and delimiter
- * in flat list of nexthops in json.
- */
- if (nexthop->rparent)
- json_object_boolean_true_add(json_nexthop, "resolver");
-
- if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
- json_object_string_add(json_nexthop, "vrf",
- vrf_id_to_name(nexthop->vrf_id));
+ bool display_vrfid = false;
+ uint8_t rn_family;
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_DUPLICATE))
- json_object_boolean_true_add(json_nexthop, "duplicate");
+ if (re == NULL || nexthop->vrf_id != re->vrf_id)
+ display_vrfid = true;
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- json_object_boolean_true_add(json_nexthop, "active");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
- json_object_boolean_true_add(json_nexthop, "onLink");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
- json_object_boolean_true_add(json_nexthop, "linkDown");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- json_object_boolean_true_add(json_nexthop, "recursive");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
- json_backups = json_object_new_array();
- for (i = 0; i < nexthop->backup_num; i++) {
- json_object_array_add(
- json_backups,
- json_object_new_int(nexthop->backup_idx[i]));
- }
-
- json_object_object_add(json_nexthop, "backupIndex",
- json_backups);
- }
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (nexthop->src.ipv4.s_addr)
- json_object_string_addf(json_nexthop, "source", "%pI4",
- &nexthop->src.ipv4);
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
- json_object_string_addf(json_nexthop, "source", "%pI6",
- &nexthop->src.ipv6);
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_BLACKHOLE:
- break;
- }
-
- if (nexthop->nh_label && nexthop->nh_label->num_labels) {
- json_labels = json_object_new_array();
-
- for (int label_index = 0;
- label_index < nexthop->nh_label->num_labels; label_index++)
- json_object_array_add(
- json_labels,
- json_object_new_int((
- (nexthop->nh_label_type ==
- ZEBRA_LSP_EVPN)
- ? label2vni(
- &nexthop->nh_label->label
- [label_index])
- : nexthop->nh_label->label
- [label_index])));
-
- json_object_object_add(json_nexthop, "labels", json_labels);
- }
+ if (rn)
+ rn_family = rn->p.family;
+ else
+ rn_family = AF_UNSPEC;
- if (nexthop->weight)
- json_object_int_add(json_nexthop, "weight", nexthop->weight);
-
- if (nexthop->srte_color)
- json_object_int_add(json_nexthop, "srteColor",
- nexthop->srte_color);
-
- if (nexthop->nh_srv6) {
- json_seg6local = json_object_new_object();
- json_object_string_add(
- json_seg6local, "action",
- seg6local_action2str(
- nexthop->nh_srv6->seg6local_action));
- json_object_object_add(json_nexthop, "seg6local",
- json_seg6local);
- if (nexthop->nh_srv6->seg6_segs &&
- nexthop->nh_srv6->seg6_segs->num_segs == 1) {
- json_seg6 = json_object_new_object();
- json_object_string_addf(json_seg6, "segs", "%pI6",
- &nexthop->nh_srv6->seg6_segs
- ->seg[0]);
- json_object_object_add(json_nexthop, "seg6", json_seg6);
- } else {
- if (nexthop->nh_srv6->seg6_segs) {
- json_segs = json_object_new_array();
- for (int seg_idx = 0;
- seg_idx <
- nexthop->nh_srv6->seg6_segs->num_segs;
- seg_idx++)
- json_object_array_add(
- json_segs,
- json_object_new_stringf(
- "%pI6",
- &nexthop->nh_srv6
- ->seg6_segs
- ->seg[seg_idx]));
- json_object_object_add(json_nexthop, "seg6",
- json_segs);
- }
- }
- }
+ nexthop_json_helper(json_nexthop, nexthop, display_vrfid, rn_family);
}
/*
* Helper for nexthop output, used in the 'show ip route' path
*/
-void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
+void show_route_nexthop_helper(struct vty *vty, const struct route_node *rn,
+ const struct route_entry *re,
const struct nexthop *nexthop)
{
- char buf[MPLS_LABEL_STRLEN];
- char seg_buf[SRV6_SEG_STRLEN];
- struct seg6_segs segs;
- uint8_t i;
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- vty_out(vty, " via %pI4", &nexthop->gate.ipv4);
- if (nexthop->ifindex)
- vty_out(vty, ", %s",
- ifindex2ifname(nexthop->ifindex,
- nexthop->vrf_id));
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- vty_out(vty, " via %s",
- inet_ntop(AF_INET6, &nexthop->gate.ipv6, buf,
- sizeof(buf)));
- if (nexthop->ifindex)
- vty_out(vty, ", %s",
- ifindex2ifname(nexthop->ifindex,
- nexthop->vrf_id));
- break;
-
- case NEXTHOP_TYPE_IFINDEX:
- vty_out(vty, " is directly connected, %s",
- ifindex2ifname(nexthop->ifindex, nexthop->vrf_id));
- break;
- case NEXTHOP_TYPE_BLACKHOLE:
- vty_out(vty, " unreachable");
- switch (nexthop->bh_type) {
- case BLACKHOLE_REJECT:
- vty_out(vty, " (ICMP unreachable)");
- break;
- case BLACKHOLE_ADMINPROHIB:
- vty_out(vty, " (ICMP admin-prohibited)");
- break;
- case BLACKHOLE_NULL:
- vty_out(vty, " (blackhole)");
- break;
- case BLACKHOLE_UNSPEC:
- break;
- }
- break;
- }
-
- if ((re == NULL || (nexthop->vrf_id != re->vrf_id)))
- vty_out(vty, " (vrf %s)", vrf_id_to_name(nexthop->vrf_id));
-
- if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE))
- vty_out(vty, " inactive");
+ bool display_vrfid = false;
+ uint8_t rn_family;
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ONLINK))
- vty_out(vty, " onlink");
+ if (re == NULL || nexthop->vrf_id != re->vrf_id)
+ display_vrfid = true;
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_LINKDOWN))
- vty_out(vty, " linkdown");
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
- vty_out(vty, " (recursive)");
-
- switch (nexthop->type) {
- case NEXTHOP_TYPE_IPV4:
- case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (nexthop->src.ipv4.s_addr) {
- vty_out(vty, ", src %pI4", &nexthop->src.ipv4);
- /* SR-TE information */
- if (nexthop->srte_color)
- vty_out(vty, ", SR-TE color %u",
- nexthop->srte_color);
- }
- break;
- case NEXTHOP_TYPE_IPV6:
- case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
- vty_out(vty, ", src %pI6", &nexthop->src.ipv6);
- break;
- case NEXTHOP_TYPE_IFINDEX:
- case NEXTHOP_TYPE_BLACKHOLE:
- break;
- }
-
- /* Label information */
- if (nexthop->nh_label && nexthop->nh_label->num_labels) {
- vty_out(vty, ", label %s",
- mpls_label2str(nexthop->nh_label->num_labels,
- nexthop->nh_label->label, buf,
- sizeof(buf), nexthop->nh_label_type, 1));
- }
-
- if (nexthop->nh_srv6) {
- seg6local_context2str(buf, sizeof(buf),
- &nexthop->nh_srv6->seg6local_ctx,
- nexthop->nh_srv6->seg6local_action);
- if (nexthop->nh_srv6->seg6local_action !=
- ZEBRA_SEG6_LOCAL_ACTION_UNSPEC)
- vty_out(vty, ", seg6local %s %s",
- seg6local_action2str(
- nexthop->nh_srv6->seg6local_action),
- buf);
- if (nexthop->nh_srv6->seg6_segs &&
- IPV6_ADDR_CMP(&nexthop->nh_srv6->seg6_segs->seg[0],
- &in6addr_any)) {
- segs.num_segs = nexthop->nh_srv6->seg6_segs->num_segs;
- for (i = 0; i < segs.num_segs; i++)
- memcpy(&segs.segs[i],
- &nexthop->nh_srv6->seg6_segs->seg[i],
- sizeof(struct in6_addr));
- snprintf_seg6_segs(seg_buf, SRV6_SEG_STRLEN, &segs);
- vty_out(vty, ", seg6 %s", seg_buf);
- }
- }
-
- if (nexthop->weight)
- vty_out(vty, ", weight %u", nexthop->weight);
-
- if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
- vty_out(vty, ", backup %d", nexthop->backup_idx[0]);
+ if (rn)
+ rn_family = rn->p.family;
+ else
+ rn_family = AF_UNSPEC;
- for (i = 1; i < nexthop->backup_num; i++)
- vty_out(vty, ",%d", nexthop->backup_idx[i]);
- }
+ nexthop_vty_helper(vty, nexthop, display_vrfid, rn_family);
}
static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json)
@@ -1644,9 +1359,10 @@ static void print_rnh(struct route_node *rn, struct vty *vty, json_object *json)
json_object_array_add(json_nexthop_array,
json_nexthop);
show_nexthop_json_helper(json_nexthop, nexthop,
- NULL);
+ rn, NULL);
} else {
- show_route_nexthop_helper(vty, NULL, nexthop);
+ show_route_nexthop_helper(vty, rn, NULL,
+ nexthop);
vty_out(vty, "\n");
}
}
diff --git a/zebra/zebra_rnh.h b/zebra/zebra_rnh.h
index 07db7bb..f0b10d8 100644
--- a/zebra/zebra_rnh.h
+++ b/zebra/zebra_rnh.h
@@ -45,8 +45,10 @@ bool rnh_get_hide_backups(void);
void show_nexthop_json_helper(json_object *json_nexthop,
const struct nexthop *nexthop,
+ const struct route_node *rn,
const struct route_entry *re);
-void show_route_nexthop_helper(struct vty *vty, const struct route_entry *re,
+void show_route_nexthop_helper(struct vty *vty, const struct route_node *rn,
+ const struct route_entry *re,
const struct nexthop *nexthop);
#ifdef __cplusplus
diff --git a/zebra/zebra_routemap_nb_config.c b/zebra/zebra_routemap_nb_config.c
index 5bcfb72..ad012da 100644
--- a/zebra/zebra_routemap_nb_config.c
+++ b/zebra/zebra_routemap_nb_config.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#include <zebra.h>
#include "lib/command.h"
diff --git a/zebra/zebra_srv6_vty.c b/zebra/zebra_srv6_vty.c
index c5b8505..d5cd30e 100644
--- a/zebra/zebra_srv6_vty.c
+++ b/zebra/zebra_srv6_vty.c
@@ -475,16 +475,24 @@ static int zebra_sr_config(struct vty *vty)
struct listnode *node;
struct srv6_locator *locator;
char str[256];
+ bool display_source_srv6 = false;
+
+ if (srv6 && !IPV6_ADDR_SAME(&srv6->encap_src_addr, &in6addr_any))
+ display_source_srv6 = true;
vty_out(vty, "!\n");
- if (zebra_srv6_is_enable()) {
+ if (display_source_srv6 || zebra_srv6_is_enable()) {
vty_out(vty, "segment-routing\n");
vty_out(vty, " srv6\n");
+ }
+ if (display_source_srv6) {
if (!IPV6_ADDR_SAME(&srv6->encap_src_addr, &in6addr_any)) {
vty_out(vty, " encapsulation\n");
vty_out(vty, " source-address %pI6\n",
&srv6->encap_src_addr);
}
+ }
+ if (zebra_srv6_is_enable()) {
vty_out(vty, " locators\n");
for (ALL_LIST_ELEMENTS_RO(srv6->locators, node, locator)) {
inet_ntop(AF_INET6, &locator->prefix.prefix,
@@ -514,6 +522,8 @@ static int zebra_sr_config(struct vty *vty)
vty_out(vty, " !\n");
vty_out(vty, " exit\n");
vty_out(vty, " !\n");
+ }
+ if (display_source_srv6 || zebra_srv6_is_enable()) {
vty_out(vty, "exit\n");
vty_out(vty, "!\n");
}
diff --git a/zebra/zebra_trace.c b/zebra/zebra_trace.c
index fef5ad2..7b0fb32 100644
--- a/zebra/zebra_trace.c
+++ b/zebra/zebra_trace.c
@@ -1,3 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
#define TRACEPOINT_CREATE_PROBES
#define TRACEPOINT_DEFINE
diff --git a/zebra/zebra_vty.c b/zebra/zebra_vty.c
index 9a68d5a..ae82d20 100644
--- a/zebra/zebra_vty.c
+++ b/zebra/zebra_vty.c
@@ -60,28 +60,33 @@ struct route_show_ctx {
};
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, json_object *vrf_json,
- bool use_json, route_tag_t tag,
+ safi_t safi, bool use_fib, bool use_json,
+ route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
bool show_ng, struct route_show_ctx *ctx);
static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
int mcast, bool use_fib, bool show_ng);
-static void vty_show_ip_route_summary(struct vty *vty,
- struct route_table *table, bool use_json);
+static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table,
+ json_object *vrf_json, bool use_json);
static void vty_show_ip_route_summary_prefix(struct vty *vty,
struct route_table *table,
+ json_object *vrf_json,
bool use_json);
/* Helper api to format a nexthop in the 'detailed' output path. */
static void show_nexthop_detail_helper(struct vty *vty,
+ const struct route_node *rn,
const struct route_entry *re,
const struct nexthop *nexthop,
bool is_backup);
static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table);
-static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop,
- struct route_entry *re, unsigned int num);
+static void show_ip_route_nht_dump(struct vty *vty,
+ const struct nexthop *nexthop,
+ const struct route_node *rn,
+ const struct route_entry *re,
+ unsigned int num);
DEFUN (ip_multicast_mode,
ip_multicast_mode_cmd,
@@ -148,8 +153,8 @@ DEFPY (show_ip_rpf,
};
return do_show_ip_route(vty, VRF_DEFAULT_NAME, ip ? AFI_IP : AFI_IP6,
- SAFI_MULTICAST, false, NULL, uj, 0, NULL, false,
- 0, 0, 0, false, &ctx);
+ SAFI_MULTICAST, false, uj, 0, NULL, false, 0, 0,
+ 0, false, &ctx);
}
DEFPY (show_ip_rpf_addr,
@@ -210,7 +215,7 @@ static char re_status_output_char(const struct route_entry *re,
if (is_fib) {
star_p = !!CHECK_FLAG(nhop->flags,
NEXTHOP_FLAG_FIB);
- } else
+ } else if (CHECK_FLAG(nhop->flags, NEXTHOP_FLAG_ACTIVE))
star_p = true;
}
@@ -251,7 +256,7 @@ static char re_status_output_char(const struct route_entry *re,
/*
* Show backup nexthop info, in the 'detailed' output path
*/
-static void show_nh_backup_helper(struct vty *vty,
+static void show_nh_backup_helper(struct vty *vty, const struct route_node *rn,
const struct route_entry *re,
const struct nexthop *nexthop)
{
@@ -281,7 +286,7 @@ static void show_nh_backup_helper(struct vty *vty,
temp = backup;
while (backup) {
vty_out(vty, " ");
- show_nexthop_detail_helper(vty, re, backup,
+ show_nexthop_detail_helper(vty, rn, re, backup,
true /*backup*/);
vty_out(vty, "\n");
@@ -302,11 +307,11 @@ static void show_nh_backup_helper(struct vty *vty,
* output path.
*/
static void show_nexthop_detail_helper(struct vty *vty,
+ const struct route_node *rn,
const struct route_entry *re,
const struct nexthop *nexthop,
bool is_backup)
{
- char addrstr[32];
char buf[MPLS_LABEL_STRLEN];
int i;
@@ -390,23 +395,21 @@ static void show_nexthop_detail_helper(struct vty *vty,
switch (nexthop->type) {
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
- if (nexthop->src.ipv4.s_addr) {
- if (inet_ntop(AF_INET, &nexthop->src.ipv4,
- addrstr, sizeof(addrstr)))
- vty_out(vty, ", src %s",
- addrstr);
- }
+ if (nexthop->rmap_src.ipv4.s_addr)
+ vty_out(vty, ", rmapsrc %pI4", &nexthop->rmap_src.ipv4);
+ else if (nexthop->src.ipv4.s_addr)
+ vty_out(vty, ", src %pI4", &nexthop->src.ipv4);
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
- if (!IPV6_ADDR_SAME(&nexthop->src.ipv6,
- &in6addr_any)) {
- if (inet_ntop(AF_INET6, &nexthop->src.ipv6,
- addrstr, sizeof(addrstr)))
- vty_out(vty, ", src %s",
- addrstr);
- }
+ /* Allow for 5549 ipv4 prefix with ipv6 nexthop */
+ if (rn->p.family == AF_INET && nexthop->rmap_src.ipv4.s_addr)
+ vty_out(vty, ", rmapsrc %pI4", &nexthop->rmap_src.ipv4);
+ else if (!IPV6_ADDR_SAME(&nexthop->rmap_src.ipv6, &in6addr_any))
+ vty_out(vty, ", rmapsrc %pI6", &nexthop->rmap_src.ipv6);
+ else if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+ vty_out(vty, ", src %pI6", &nexthop->src.ipv6);
break;
case NEXTHOP_TYPE_IFINDEX:
@@ -590,13 +593,13 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
for (ALL_NEXTHOPS(re->nhe->nhg, nexthop)) {
/* Use helper to format each nexthop */
- show_nexthop_detail_helper(vty, re, nexthop,
+ show_nexthop_detail_helper(vty, rn, re, nexthop,
false /*not backup*/);
vty_out(vty, "\n");
/* Include backup(s), if present */
if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP))
- show_nh_backup_helper(vty, re, nexthop);
+ show_nh_backup_helper(vty, rn, re, nexthop);
}
zebra_show_ip_route_opaque(vty, re, NULL);
@@ -703,8 +706,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
json_nexthop = json_object_new_object();
- show_nexthop_json_helper(json_nexthop,
- nexthop, re);
+ show_nexthop_json_helper(json_nexthop, nexthop, rn, re);
json_object_array_add(json_nexthops,
json_nexthop);
@@ -724,8 +726,8 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
for (ALL_NEXTHOPS_PTR(nhg, nexthop)) {
json_nexthop = json_object_new_object();
- show_nexthop_json_helper(json_nexthop,
- nexthop, re);
+ show_nexthop_json_helper(json_nexthop, nexthop,
+ rn, re);
json_object_array_add(json_nexthops,
json_nexthop);
}
@@ -790,7 +792,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
len - 3 + (2 * nexthop_level(nexthop)), ' ');
}
- show_route_nexthop_helper(vty, re, nexthop);
+ show_route_nexthop_helper(vty, rn, re, nexthop);
vty_out(vty, ", %s\n", up_str);
}
@@ -821,7 +823,7 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
vty_out(vty, " b%c %*c",
(star_p ? '*' : ' '),
len - 3 + (2 * nexthop_level(nexthop)), ' ');
- show_route_nexthop_helper(vty, re, nexthop);
+ show_route_nexthop_helper(vty, rn, re, nexthop);
vty_out(vty, "\n");
}
@@ -856,19 +858,20 @@ static void vty_show_ip_route_detail_json(struct vty *vty,
vty_json(vty, json);
}
-static void
-do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
- struct route_table *table, afi_t afi, bool use_fib,
- json_object *vrf_json, route_tag_t tag,
- const struct prefix *longer_prefix_p, bool supernets_only,
- int type, unsigned short ospf_instance_id, bool use_json,
- uint32_t tableid, bool show_ng, struct route_show_ctx *ctx)
+static void do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
+ struct route_table *table, afi_t afi,
+ bool use_fib, route_tag_t tag,
+ const struct prefix *longer_prefix_p,
+ bool supernets_only, int type,
+ unsigned short ospf_instance_id, bool use_json,
+ uint32_t tableid, bool show_ng,
+ struct route_show_ctx *ctx)
{
struct route_node *rn;
struct route_entry *re;
+ bool first_json = true;
int first = 1;
rib_dest_t *dest;
- json_object *json = NULL;
json_object *json_prefix = NULL;
uint32_t addr;
char buf[BUFSIZ];
@@ -884,9 +887,6 @@ do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
* => display the VRF and table if specific
*/
- if (use_json && !vrf_json)
- json = json_object_new_object();
-
/* Show all routes. */
for (rn = route_top(table); rn; rn = srcdest_route_next(rn)) {
dest = rib_dest_from_rnode(rn);
@@ -959,28 +959,20 @@ do_show_route_helper(struct vty *vty, struct zebra_vrf *zvrf,
if (json_prefix) {
prefix2str(&rn->p, buf, sizeof(buf));
- if (!vrf_json)
- json_object_object_add(json, buf, json_prefix);
- else
- json_object_object_add(vrf_json, buf,
- json_prefix);
+ vty_json_key(vty, buf, &first_json);
+ vty_json_no_pretty(vty, json_prefix);
+
json_prefix = NULL;
}
}
- /*
- * This is an extremely expensive operation at scale
- * and non-pretty reduces memory footprint significantly.
- */
- if (use_json && !vrf_json) {
- vty_json_no_pretty(vty, json);
- json = NULL;
- }
+ if (use_json)
+ vty_json_close(vty, first_json);
}
static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
- afi_t afi, bool use_fib, json_object *vrf_json,
- bool use_json, route_tag_t tag,
+ afi_t afi, bool use_fib, bool use_json,
+ route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, bool show_ng,
@@ -1000,15 +992,15 @@ static void do_show_ip_route_all(struct vty *vty, struct zebra_vrf *zvrf,
continue;
do_show_ip_route(vty, zvrf_name(zvrf), afi, SAFI_UNICAST,
- use_fib, vrf_json, use_json, tag,
- longer_prefix_p, supernets_only, type,
- ospf_instance_id, zrt->tableid, show_ng, ctx);
+ use_fib, use_json, tag, longer_prefix_p,
+ supernets_only, type, ospf_instance_id,
+ zrt->tableid, show_ng, ctx);
}
}
static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
- safi_t safi, bool use_fib, json_object *vrf_json,
- bool use_json, route_tag_t tag,
+ safi_t safi, bool use_fib, bool use_json,
+ route_tag_t tag,
const struct prefix *longer_prefix_p,
bool supernets_only, int type,
unsigned short ospf_instance_id, uint32_t tableid,
@@ -1043,7 +1035,7 @@ static int do_show_ip_route(struct vty *vty, const char *vrf_name, afi_t afi,
return CMD_SUCCESS;
}
- do_show_route_helper(vty, zvrf, table, afi, use_fib, vrf_json, tag,
+ do_show_route_helper(vty, zvrf, table, afi, use_fib, tag,
longer_prefix_p, supernets_only, type,
ospf_instance_id, use_json, tableid, show_ng, ctx);
@@ -1225,7 +1217,12 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe,
json_object_boolean_true_add(json, "valid");
else
vty_out(vty, " Valid");
-
+ if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_REINSTALL)) {
+ if (json)
+ json_object_boolean_true_add(json, "reInstall");
+ else
+ vty_out(vty, ", Reinstall");
+ }
if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED)) {
if (json)
json_object_boolean_true_add(json, "installed");
@@ -1272,14 +1269,15 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe,
for (ALL_NEXTHOPS(nhe->nhg, nexthop)) {
if (json_nexthop_array) {
json_nexthops = json_object_new_object();
- show_nexthop_json_helper(json_nexthops, nexthop, NULL);
+ show_nexthop_json_helper(json_nexthops, nexthop, NULL,
+ NULL);
} else {
if (!CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_RECURSIVE))
vty_out(vty, " ");
else
/* Make recursive nexthops a bit more clear */
vty_out(vty, " ");
- show_route_nexthop_helper(vty, NULL, nexthop);
+ show_route_nexthop_helper(vty, NULL, NULL, nexthop);
}
if (nhe->backup_info == NULL || nhe->backup_info->nhe == NULL) {
@@ -1337,7 +1335,7 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe,
if (json_backup_nexthop_array) {
json_backup_nexthops = json_object_new_object();
show_nexthop_json_helper(json_backup_nexthops,
- nexthop, NULL);
+ nexthop, NULL, NULL);
json_object_array_add(json_backup_nexthop_array,
json_backup_nexthops);
} else {
@@ -1350,7 +1348,8 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe,
* clear
*/
vty_out(vty, " ");
- show_route_nexthop_helper(vty, NULL, nexthop);
+ show_route_nexthop_helper(vty, NULL, NULL,
+ nexthop);
vty_out(vty, "\n");
}
}
@@ -1481,17 +1480,18 @@ static void if_nexthop_group_dump_vty(struct vty *vty, struct interface *ifp)
{
struct zebra_if *zebra_if = NULL;
struct nhg_connected *rb_node_dep = NULL;
+ bool first = true;
zebra_if = ifp->info;
- if (!if_nhg_dependents_is_empty(ifp)) {
- vty_out(vty, "Interface %s:\n", ifp->name);
-
- frr_each(nhg_connected_tree, &zebra_if->nhg_dependents,
- rb_node_dep) {
- vty_out(vty, " ");
- show_nexthop_group_out(vty, rb_node_dep->nhe, NULL);
+ frr_each (nhg_connected_tree, &zebra_if->nhg_dependents, rb_node_dep) {
+ if (first) {
+ vty_out(vty, "Interface %s:\n", ifp->name);
+ first = false;
}
+
+ vty_out(vty, " ");
+ show_nexthop_group_out(vty, rb_node_dep->nhe, NULL);
}
}
@@ -1734,13 +1734,13 @@ DEFPY (show_route,
"Nexthop Group Information\n")
{
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
+ bool first_vrf_json = true;
struct vrf *vrf;
int type = 0;
struct zebra_vrf *zvrf;
struct route_show_ctx ctx = {
.multi = vrf_all || table_all,
};
- json_object *root_json = NULL;
if (!vrf_is_backend_netns()) {
if ((vrf_all || vrf_name) && (table || table_all)) {
@@ -1762,43 +1762,30 @@ DEFPY (show_route,
}
if (vrf_all) {
- if (!!json)
- root_json = json_object_new_object();
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
- json_object *vrf_json = NULL;
-
if ((zvrf = vrf->info) == NULL
|| (zvrf->table[afi][SAFI_UNICAST] == NULL))
continue;
-
- if (!!json)
- vrf_json = json_object_new_object();
-
+ if (json)
+ vty_json_key(vty, zvrf_name(zvrf),
+ &first_vrf_json);
if (table_all)
do_show_ip_route_all(vty, zvrf, afi, !!fib,
- vrf_json, !!json, tag,
+ !!json, tag,
prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, !!ng,
&ctx);
else
do_show_ip_route(vty, zvrf_name(zvrf), afi,
- SAFI_UNICAST, !!fib, vrf_json,
- !!json, tag,
- prefix_str ? prefix : NULL,
+ SAFI_UNICAST, !!fib, !!json,
+ tag, prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, table, !!ng,
&ctx);
-
- if (!!json)
- json_object_object_add(root_json,
- zvrf_name(zvrf),
- vrf_json);
- }
- if (!!json) {
- vty_json_no_pretty(vty, root_json);
- root_json = NULL;
}
+ if (json)
+ vty_json_close(vty, first_vrf_json);
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -1813,13 +1800,13 @@ DEFPY (show_route,
return CMD_SUCCESS;
if (table_all)
- do_show_ip_route_all(vty, zvrf, afi, !!fib, NULL, !!json,
- tag, prefix_str ? prefix : NULL,
+ do_show_ip_route_all(vty, zvrf, afi, !!fib, !!json, tag,
+ prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, !!ng, &ctx);
else
do_show_ip_route(vty, vrf->name, afi, SAFI_UNICAST,
- !!fib, NULL, !!json, tag,
+ !!fib, !!json, tag,
prefix_str ? prefix : NULL,
!!supernets_only, type,
ospf_instance_id, table, !!ng, &ctx);
@@ -1991,11 +1978,15 @@ DEFPY (show_route_summary,
afi_t afi = ipv4 ? AFI_IP : AFI_IP6;
struct route_table *table;
bool uj = use_json(argc, argv);
+ json_object *vrf_json = NULL;
if (vrf_all) {
struct vrf *vrf;
struct zebra_vrf *zvrf;
+ if (uj && !vrf_json)
+ vrf_json = json_object_new_object();
+
RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
if ((zvrf = vrf->info) == NULL)
continue;
@@ -2013,10 +2004,14 @@ DEFPY (show_route_summary,
if (prefix)
vty_show_ip_route_summary_prefix(vty, table,
- uj);
+ vrf_json, uj);
else
- vty_show_ip_route_summary(vty, table, uj);
+ vty_show_ip_route_summary(vty, table, vrf_json,
+ uj);
}
+
+ if (uj)
+ vty_json(vty, vrf_json);
} else {
vrf_id_t vrf_id = VRF_DEFAULT;
@@ -2032,9 +2027,9 @@ DEFPY (show_route_summary,
return CMD_SUCCESS;
if (prefix)
- vty_show_ip_route_summary_prefix(vty, table, uj);
+ vty_show_ip_route_summary_prefix(vty, table, NULL, uj);
else
- vty_show_ip_route_summary(vty, table, uj);
+ vty_show_ip_route_summary(vty, table, NULL, uj);
}
return CMD_SUCCESS;
@@ -2089,8 +2084,11 @@ DEFUN_HIDDEN (show_route_zebra_dump,
return CMD_SUCCESS;
}
-static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop,
- struct route_entry *re, unsigned int num)
+static void show_ip_route_nht_dump(struct vty *vty,
+ const struct nexthop *nexthop,
+ const struct route_node *rn,
+ const struct route_entry *re,
+ unsigned int num)
{
char buf[SRCDEST2STR_BUFFER];
@@ -2114,10 +2112,12 @@ static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop,
nexthop->vrf_id));
}
- if (nexthop->src.ipv4.s_addr
- && (inet_ntop(AF_INET, &nexthop->src.ipv4, buf,
- sizeof(buf))))
- vty_out(vty, " source: %s\n", buf);
+ if (nexthop->rmap_src.ipv4.s_addr)
+ vty_out(vty, " rmapsrc: %pI4\n",
+ &nexthop->rmap_src.ipv4);
+ else if (nexthop->src.ipv4.s_addr)
+ vty_out(vty, " source: %pI4\n",
+ &nexthop->src.ipv4.s_addr);
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -2134,11 +2134,15 @@ static void show_ip_route_nht_dump(struct vty *vty, struct nexthop *nexthop,
nexthop->vrf_id));
}
- if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any)) {
- if (inet_ntop(AF_INET6, &nexthop->src.ipv6, buf,
- sizeof(buf)))
- vty_out(vty, " source: %s\n", buf);
- }
+ /* Allow for 5549 ipv4 prefix with ipv6 nexthop */
+ if (rn->p.family == AF_INET && nexthop->rmap_src.ipv4.s_addr)
+ vty_out(vty, " rmapsrc: %pI4\n",
+ &nexthop->rmap_src.ipv4);
+ else if (!IPV6_ADDR_SAME(&nexthop->rmap_src.ipv6, &in6addr_any))
+ vty_out(vty, " rmapsrc: %pI6\n",
+ &nexthop->rmap_src.ipv6);
+ else if (!IPV6_ADDR_SAME(&nexthop->src.ipv6, &in6addr_any))
+ vty_out(vty, " source: %pI6\n", &nexthop->src.ipv6);
break;
case NEXTHOP_TYPE_IFINDEX:
vty_out(vty,
@@ -2230,7 +2234,7 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
for (ALL_NEXTHOPS_PTR(&(re->nhe->nhg), nexthop)) {
nexthop_num++;
- show_ip_route_nht_dump(vty, nexthop, re,
+ show_ip_route_nht_dump(vty, nexthop, rn, re,
nexthop_num);
}
@@ -2240,8 +2244,8 @@ static void show_ip_route_dump_vty(struct vty *vty, struct route_table *table)
}
}
-static void vty_show_ip_route_summary(struct vty *vty,
- struct route_table *table, bool use_json)
+static void vty_show_ip_route_summary(struct vty *vty, struct route_table *table,
+ json_object *vrf_json, bool use_json)
{
struct route_node *rn;
struct route_entry *re;
@@ -2255,6 +2259,8 @@ static void vty_show_ip_route_summary(struct vty *vty,
uint32_t is_ibgp;
json_object *json_route_summary = NULL;
json_object *json_route_routes = NULL;
+ const char *vrf_name = zvrf_name(
+ ((struct rib_table_info *)route_table_get_info(table))->zvrf);
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
@@ -2305,10 +2311,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
- "Routes", "FIB",
- zvrf_name(((struct rib_table_info *)
- route_table_get_info(table))
- ->zvrf));
+ "Routes", "FIB", vrf_name);
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if ((rib_cnt[i] > 0) || (i == ZEBRA_ROUTE_BGP
@@ -2400,7 +2403,11 @@ static void vty_show_ip_route_summary(struct vty *vty,
json_object_int_add(json_route_summary, "routesTotalFib",
fib_cnt[ZEBRA_ROUTE_TOTAL]);
- vty_json(vty, json_route_summary);
+ if (!vrf_json)
+ vty_json(vty, json_route_summary);
+ else
+ json_object_object_add(vrf_json, vrf_name,
+ json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
@@ -2418,6 +2425,7 @@ static void vty_show_ip_route_summary(struct vty *vty,
*/
static void vty_show_ip_route_summary_prefix(struct vty *vty,
struct route_table *table,
+ json_object *vrf_json,
bool use_json)
{
struct route_node *rn;
@@ -2431,6 +2439,8 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
int cnt;
json_object *json_route_summary = NULL;
json_object *json_route_routes = NULL;
+ const char *vrf_name = zvrf_name(
+ ((struct rib_table_info *)route_table_get_info(table))->zvrf);
memset(&rib_cnt, 0, sizeof(rib_cnt));
memset(&fib_cnt, 0, sizeof(fib_cnt));
@@ -2470,10 +2480,7 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
if (!use_json)
vty_out(vty, "%-20s %-20s %s (vrf %s)\n", "Route Source",
- "Prefix Routes", "FIB",
- zvrf_name(((struct rib_table_info *)
- route_table_get_info(table))
- ->zvrf));
+ "Prefix Routes", "FIB", vrf_name);
for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
if (rib_cnt[i] > 0) {
@@ -2548,7 +2555,11 @@ static void vty_show_ip_route_summary_prefix(struct vty *vty,
json_object_int_add(json_route_summary, "prefixRoutesTotalFib",
fib_cnt[ZEBRA_ROUTE_TOTAL]);
- vty_json(vty, json_route_summary);
+ if (!vrf_json)
+ vty_json(vty, json_route_summary);
+ else
+ json_object_object_add(vrf_json, vrf_name,
+ json_route_summary);
} else {
vty_out(vty, "------\n");
vty_out(vty, "%-20s %-20d %-20d \n", "Totals",
@@ -3531,56 +3542,17 @@ DEFPY (clear_evpn_dup_addr,
"IPv4 address\n"
"IPv6 address\n")
{
- struct ipaddr host_ip = {.ipa_type = IPADDR_NONE };
- int ret = CMD_SUCCESS;
- struct list *input;
- struct yang_data *yang_dup = NULL, *yang_dup_ip = NULL,
- *yang_dup_mac = NULL;
-
- input = list_new();
-
if (!vni_str) {
- yang_dup = yang_data_new(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice",
- "all-case");
+ nb_cli_rpc_enqueue(vty, "all-vnis", NULL);
} else {
- yang_dup = yang_data_new_uint32(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id",
- vni);
- if (!is_zero_mac(&mac->eth_addr)) {
- yang_dup_mac = yang_data_new_mac(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/mac-addr",
- &mac->eth_addr);
- if (yang_dup_mac)
- listnode_add(input, yang_dup_mac);
- } else if (ip) {
- if (sockunion_family(ip) == AF_INET) {
- host_ip.ipa_type = IPADDR_V4;
- host_ip.ipaddr_v4.s_addr = sockunion2ip(ip);
- } else {
- host_ip.ipa_type = IPADDR_V6;
- memcpy(&host_ip.ipaddr_v6, &ip->sin6.sin6_addr,
- sizeof(struct in6_addr));
- }
-
- yang_dup_ip = yang_data_new_ip(
- "/frr-zebra:clear-evpn-dup-addr/input/clear-dup-choice/single-case/vni-id/vni-ipaddr",
- &host_ip);
-
- if (yang_dup_ip)
- listnode_add(input, yang_dup_ip);
- }
- }
-
- if (yang_dup) {
- listnode_add(input, yang_dup);
- ret = nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", input,
- NULL);
+ nb_cli_rpc_enqueue(vty, "vni-id", vni_str);
+ if (mac_str)
+ nb_cli_rpc_enqueue(vty, "mac-addr", mac_str);
+ else if (ip_str)
+ nb_cli_rpc_enqueue(vty, "vni-ipaddr", ip_str);
}
- list_delete(&input);
-
- return ret;
+ return nb_cli_rpc(vty, "/frr-zebra:clear-evpn-dup-addr", NULL);
}
DEFPY_HIDDEN (evpn_accept_bgp_seq,
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index 0b75ec2..b8c11e1 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -108,10 +108,11 @@ static void zevpn_build_hash_table(void);
static unsigned int zebra_vxlan_sg_hash_key_make(const void *p);
static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2);
static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
- struct in_addr sip, struct in_addr mcast_grp);
-static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf,
- struct in_addr sip,
- struct in_addr mcast_grp);
+ const struct ipaddr *sip,
+ const struct in_addr mcast_grp);
+static struct zebra_vxlan_sg *
+zebra_vxlan_sg_do_ref(struct zebra_vrf *vrf, const struct ipaddr *sip,
+ const struct in_addr mcast_grp);
static void zebra_vxlan_cleanup_sg_table(struct zebra_vrf *zvrf);
bool zebra_evpn_do_dup_addr_detect(struct zebra_vrf *zvrf)
@@ -769,10 +770,6 @@ static void zl3vni_print(struct zebra_l3vni *zl3vni, void **ctx)
json_evpn_list = json_object_new_array();
json_object_int_add(json, "vni", zl3vni->vni);
json_object_string_add(json, "type", "L3");
-#if CONFDATE > 20240210
-CPP_NOTICE("Drop `vrf` from JSON outputs")
-#endif
- json_object_string_add(json, "vrf", zl3vni_vrf_name(zl3vni));
json_object_string_add(json, "tenantVrf",
zl3vni_vrf_name(zl3vni));
json_object_string_addf(json, "localVtepIp", "%pI4",
@@ -5895,7 +5892,10 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
zclient_create_header(s, cmd, VRF_DEFAULT);
stream_putl(s, IPV4_MAX_BYTELEN);
- stream_put(s, &sg->src.s_addr, IPV4_MAX_BYTELEN);
+ /*
+ * There is currently no support for IPv6 VTEPs with PIM.
+ */
+ stream_put(s, &sg->src.ipaddr_v4, IPV4_MAX_BYTELEN);
stream_put(s, &sg->grp.s_addr, IPV4_MAX_BYTELEN);
/* Write packet size. */
@@ -5918,9 +5918,17 @@ static int zebra_vxlan_sg_send(struct zebra_vrf *zvrf,
static unsigned int zebra_vxlan_sg_hash_key_make(const void *p)
{
const struct zebra_vxlan_sg *vxlan_sg = p;
+ uint32_t hash1;
- return (jhash_2words(vxlan_sg->sg.src.s_addr,
- vxlan_sg->sg.grp.s_addr, 0));
+ if (IS_IPADDR_V4(&vxlan_sg->sg.src)) {
+ return (jhash_2words(vxlan_sg->sg.src.ipaddr_v4.s_addr,
+ vxlan_sg->sg.grp.s_addr, 0));
+ } else {
+ hash1 = jhash_1word(vxlan_sg->sg.grp.s_addr, 0);
+ return jhash2(vxlan_sg->sg.src.ipaddr_v6.s6_addr32,
+ array_size(vxlan_sg->sg.src.ipaddr_v6.s6_addr32),
+ hash1);
+ }
}
static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
@@ -5928,8 +5936,8 @@ static bool zebra_vxlan_sg_hash_eq(const void *p1, const void *p2)
const struct zebra_vxlan_sg *sg1 = p1;
const struct zebra_vxlan_sg *sg2 = p2;
- return ((sg1->sg.src.s_addr == sg2->sg.src.s_addr)
- && (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
+ return (ipaddr_is_same(&sg1->sg.src, &sg2->sg.src) &&
+ (sg1->sg.grp.s_addr == sg2->sg.grp.s_addr));
}
static struct zebra_vxlan_sg *zebra_vxlan_sg_new(struct zebra_vrf *zvrf,
@@ -5965,7 +5973,7 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
{
struct zebra_vxlan_sg *vxlan_sg;
struct zebra_vxlan_sg *parent = NULL;
- struct in_addr sip;
+ struct ipaddr sip;
vxlan_sg = zebra_vxlan_sg_find(zvrf, sg);
if (vxlan_sg)
@@ -5976,9 +5984,9 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
* 2. the XG entry is used by pimd to setup the
* vxlan-termination-mroute
*/
- if (sg->src.s_addr != INADDR_ANY) {
+ if (!ipaddr_is_zero(&sg->src)) {
memset(&sip, 0, sizeof(sip));
- parent = zebra_vxlan_sg_do_ref(zvrf, sip, sg->grp);
+ parent = zebra_vxlan_sg_do_ref(zvrf, &sip, sg->grp);
if (!parent)
return NULL;
}
@@ -5993,7 +6001,7 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_add(struct zebra_vrf *zvrf,
static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
{
- struct in_addr sip;
+ struct ipaddr sip;
struct zebra_vrf *zvrf;
zvrf = vrf_info_lookup(VRF_DEFAULT);
@@ -6001,13 +6009,13 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
/* On SG entry deletion remove the reference to its parent XG
* entry
*/
- if (vxlan_sg->sg.src.s_addr != INADDR_ANY) {
+ if (!ipaddr_is_zero(&vxlan_sg->sg.src)) {
memset(&sip, 0, sizeof(sip));
- zebra_vxlan_sg_do_deref(zvrf, sip, vxlan_sg->sg.grp);
+ zebra_vxlan_sg_do_deref(zvrf, &sip, vxlan_sg->sg.grp);
}
- zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg,
- vxlan_sg->sg_str, ZEBRA_VXLAN_SG_DEL);
+ zebra_vxlan_sg_send(zvrf, &vxlan_sg->sg, vxlan_sg->sg_str,
+ ZEBRA_VXLAN_SG_DEL);
hash_release(vxlan_sg->zvrf->vxlan_sg_table, vxlan_sg);
@@ -6018,14 +6026,15 @@ static void zebra_vxlan_sg_del(struct zebra_vxlan_sg *vxlan_sg)
}
static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
- struct in_addr sip, struct in_addr mcast_grp)
+ const struct ipaddr *sip,
+ const struct in_addr mcast_grp)
{
struct zebra_vxlan_sg *vxlan_sg;
struct prefix_sg sg;
sg.family = AF_INET;
sg.prefixlen = IPV4_MAX_BYTELEN;
- sg.src = sip;
+ sg.src = *sip;
sg.grp = mcast_grp;
vxlan_sg = zebra_vxlan_sg_find(zvrf, &sg);
if (!vxlan_sg)
@@ -6038,16 +6047,16 @@ static void zebra_vxlan_sg_do_deref(struct zebra_vrf *zvrf,
zebra_vxlan_sg_del(vxlan_sg);
}
-static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
- struct in_addr sip,
- struct in_addr mcast_grp)
+static struct zebra_vxlan_sg *
+zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf, const struct ipaddr *sip,
+ const struct in_addr mcast_grp)
{
struct zebra_vxlan_sg *vxlan_sg;
struct prefix_sg sg;
sg.family = AF_INET;
sg.prefixlen = IPV4_MAX_BYTELEN;
- sg.src = sip;
+ sg.src = *sip;
sg.grp = mcast_grp;
vxlan_sg = zebra_vxlan_sg_add(zvrf, &sg);
if (vxlan_sg)
@@ -6056,10 +6065,10 @@ static struct zebra_vxlan_sg *zebra_vxlan_sg_do_ref(struct zebra_vrf *zvrf,
return vxlan_sg;
}
-void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
- struct in_addr mcast_grp)
+void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip, struct in_addr mcast_grp)
{
struct zebra_vrf *zvrf;
+ struct ipaddr local_vtep_ipaddr;
if (local_vtep_ip.s_addr == INADDR_ANY
|| mcast_grp.s_addr == INADDR_ANY)
@@ -6067,20 +6076,26 @@ void zebra_vxlan_sg_deref(struct in_addr local_vtep_ip,
zvrf = vrf_info_lookup(VRF_DEFAULT);
- zebra_vxlan_sg_do_deref(zvrf, local_vtep_ip, mcast_grp);
+ SET_IPADDR_V4(&local_vtep_ipaddr);
+ local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip;
+
+ zebra_vxlan_sg_do_deref(zvrf, &local_vtep_ipaddr, mcast_grp);
}
void zebra_vxlan_sg_ref(struct in_addr local_vtep_ip, struct in_addr mcast_grp)
{
struct zebra_vrf *zvrf;
+ struct ipaddr local_vtep_ipaddr;
- if (local_vtep_ip.s_addr == INADDR_ANY
- || mcast_grp.s_addr == INADDR_ANY)
+ if (local_vtep_ip.s_addr == INADDR_ANY || mcast_grp.s_addr == INADDR_ANY)
return;
zvrf = vrf_info_lookup(VRF_DEFAULT);
- zebra_vxlan_sg_do_ref(zvrf, local_vtep_ip, mcast_grp);
+ SET_IPADDR_V4(&local_vtep_ipaddr);
+ local_vtep_ipaddr.ipaddr_v4 = local_vtep_ip;
+
+ zebra_vxlan_sg_do_ref(zvrf, &local_vtep_ipaddr, mcast_grp);
}
static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
@@ -6090,7 +6105,7 @@ static void zebra_vxlan_xg_pre_cleanup(struct hash_bucket *bucket, void *arg)
/* increment the ref count against (*,G) to prevent them from being
* deleted
*/
- if (vxlan_sg->sg.src.s_addr == INADDR_ANY)
+ if (ipaddr_is_zero(&vxlan_sg->sg.src))
++vxlan_sg->ref_cnt;
}
@@ -6099,7 +6114,7 @@ static void zebra_vxlan_xg_post_cleanup(struct hash_bucket *bucket, void *arg)
struct zebra_vxlan_sg *vxlan_sg = (struct zebra_vxlan_sg *)bucket->data;
/* decrement the dummy ref count against (*,G) to delete them */
- if (vxlan_sg->sg.src.s_addr == INADDR_ANY) {
+ if (ipaddr_is_zero(&vxlan_sg->sg.src)) {
if (vxlan_sg->ref_cnt)
--vxlan_sg->ref_cnt;
if (!vxlan_sg->ref_cnt)
diff --git a/zebra/zebra_vxlan_if.c b/zebra/zebra_vxlan_if.c
index 3cc7e49..f4b859b 100644
--- a/zebra/zebra_vxlan_if.c
+++ b/zebra/zebra_vxlan_if.c
@@ -506,7 +506,7 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
if ((hashcount(ctx->old_vni_table) == 0) ||
!(old_vni = hash_release(ctx->old_vni_table, &vni_tmp))) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug("vxlan %s adding vni(%d, %d)",
+ zlog_debug("%s vxlan %s adding vni(%d, %d)", __func__,
zif->ifp->name, vni->vni, vni->access_vlan);
zebra_vxlan_if_vni_entry_add(zif, &vni_tmp);
@@ -521,17 +521,39 @@ static int zebra_vxlan_if_add_update_vni(struct zebra_if *zif,
if (old_vni->access_vlan != vni->access_vlan) {
if (IS_ZEBRA_DEBUG_VXLAN)
- zlog_debug(
- "vxlan %s updating vni(%d, %d) -> vni(%d, %d)",
- zif->ifp->name, old_vni->vni,
- old_vni->access_vlan, vni->vni,
- vni->access_vlan);
+ zlog_debug("%s vxlan %s updating vni(%d, %d) -> vni(%d, %d)",
+ __func__, zif->ifp->name, old_vni->vni,
+ old_vni->access_vlan, vni->vni,
+ vni->access_vlan);
zebra_evpn_vl_vxl_deref(old_vni->access_vlan, old_vni->vni,
zif);
zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
zebra_vxlan_vni_free(old_vni);
+ } else {
+ int ret;
+
+ ret = zebra_evpn_vl_vxl_bridge_lookup(vni->access_vlan, zif);
+ /* Here ret value 0 implied bridge vlan mapping is not present
+ * repopulated. Ignore ret value 1 as it means vlan mapping is
+ * present in bridge table.
+ */
+ if (ret < 0) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%s vxlan %s vni %u has error accessing bridge table.",
+ __func__, zif->ifp->name, vni->vni);
+ } else if (ret == 0) {
+ if (IS_ZEBRA_DEBUG_VXLAN)
+ zlog_debug("%s vxlan %s vni (%u, %u) not present in bridge table",
+ __func__, zif->ifp->name, vni->vni,
+ vni->access_vlan);
+ zebra_evpn_vl_vxl_deref(old_vni->access_vlan,
+ old_vni->vni, zif);
+ zebra_evpn_vl_vxl_ref(vni->access_vlan, vni->vni, zif);
+ zebra_vxlan_if_update_vni(zif->ifp, vni, ctx);
+ zebra_vxlan_vni_free(old_vni);
+ }
}
return 0;
@@ -768,6 +790,7 @@ vni_t zebra_vxlan_if_access_vlan_vni_find(struct zebra_if *zif,
return vni->vni;
}
+/* SVD VLAN-VNI mapping update */
int zebra_vxlan_if_vni_table_add_update(struct interface *ifp,
struct hash *vni_table)
{
diff --git a/zebra/zserv.c b/zebra/zserv.c
index 6a64176..2766853 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -306,6 +306,14 @@ zwrite_fail:
* this task reschedules itself.
*
* Any failure in any of these actions is handled by terminating the client.
+ *
+ * The client's input buffer ibuf_fifo can have a maximum items as configured
+ * in the packets_to_process. This way we are not filling up the FIFO more
+ * than the maximum when the zebra main is busy. If the fifo has space, we
+ * reschedule ourselves to read more.
+ *
+ * The main thread processes the items in ibuf_fifo and always signals the
+ * client IO thread.
*/
static void zserv_read(struct event *thread)
{
@@ -313,15 +321,25 @@ static void zserv_read(struct event *thread)
int sock;
size_t already;
struct stream_fifo *cache;
- uint32_t p2p_orig;
-
- uint32_t p2p;
+ uint32_t p2p; /* Temp p2p used to process */
+ uint32_t p2p_orig; /* Configured p2p (Default-1000) */
+ int p2p_avail; /* How much space is available for p2p */
struct zmsghdr hdr;
+ size_t client_ibuf_fifo_cnt = stream_fifo_count_safe(client->ibuf_fifo);
p2p_orig = atomic_load_explicit(&zrouter.packets_to_process,
memory_order_relaxed);
+ p2p_avail = p2p_orig - client_ibuf_fifo_cnt;
+
+ /*
+ * Do nothing if ibuf_fifo count has reached its max limit. Otherwise
+ * proceed and reschedule ourselves if there is space in the ibuf_fifo.
+ */
+ if (p2p_avail <= 0)
+ return;
+
+ p2p = p2p_avail;
cache = stream_fifo_new();
- p2p = p2p_orig;
sock = EVENT_FD(thread);
while (p2p) {
@@ -421,7 +439,7 @@ static void zserv_read(struct event *thread)
p2p--;
}
- if (p2p < p2p_orig) {
+ if (p2p < (uint32_t)p2p_avail) {
uint64_t time_now = monotime(NULL);
/* update session statistics */
@@ -435,19 +453,23 @@ static void zserv_read(struct event *thread)
while (cache->head)
stream_fifo_push(client->ibuf_fifo,
stream_fifo_pop(cache));
+ /* Need to update count as main thread could have processed few */
+ client_ibuf_fifo_cnt =
+ stream_fifo_count_safe(client->ibuf_fifo);
}
/* Schedule job to process those packets */
zserv_event(client, ZSERV_PROCESS_MESSAGES);
-
}
if (IS_ZEBRA_DEBUG_PACKET)
- zlog_debug("Read %d packets from client: %s", p2p_orig - p2p,
- zebra_route_string(client->proto));
+ zlog_debug("Read %d packets from client: %s. Current ibuf fifo count: %zu. Conf P2p %d",
+ p2p_avail - p2p, zebra_route_string(client->proto),
+ client_ibuf_fifo_cnt, p2p_orig);
- /* Reschedule ourselves */
- zserv_client_event(client, ZSERV_CLIENT_READ);
+ /* Reschedule ourselves since we have space in ibuf_fifo */
+ if (client_ibuf_fifo_cnt < p2p_orig)
+ zserv_client_event(client, ZSERV_CLIENT_READ);
stream_fifo_free(cache);
@@ -483,14 +505,20 @@ static void zserv_client_event(struct zserv *client,
* as the task argument.
*
* Each message is popped off the client's input queue and the action associated
- * with the message is executed. This proceeds until there are no more messages,
- * an error occurs, or the processing limit is reached.
+ * with the message is executed. This proceeds until an error occurs, or the
+ * processing limit is reached.
*
* The client's I/O thread can push at most zrouter.packets_to_process messages
* onto the input buffer before notifying us there are packets to read. As long
* as we always process zrouter.packets_to_process messages here, then we can
* rely on the read thread to handle queuing this task enough times to process
* everything on the input queue.
+ *
+ * If the client ibuf always schedules a wakeup to the client IO to read more
+ * items from the socked buffer. This way we ensure
+ * - Client IO thread always tries to read the socket buffer and add more
+ * items to the ibuf_fifo (until max limit)
+ * - the hidden config change (zebra zapi-packets <>) is taken into account.
*/
static void zserv_process_messages(struct event *thread)
{
@@ -524,6 +552,9 @@ static void zserv_process_messages(struct event *thread)
/* Reschedule ourselves if necessary */
if (need_resched)
zserv_event(client, ZSERV_PROCESS_MESSAGES);
+
+ /* Ensure to include the read socket in the select/poll/etc.. */
+ zserv_client_event(client, ZSERV_CLIENT_READ);
}
int zserv_send_message(struct zserv *client, struct stream *msg)
@@ -644,10 +675,14 @@ static void zserv_client_free(struct zserv *client)
* If any instance are graceful restart enabled,
* client is not deleted
*/
- if (DYNAMIC_CLIENT_GR_DISABLED(client)) {
+ if (DYNAMIC_CLIENT_GR_DISABLED(client) || zebra_router_in_shutdown()) {
if (IS_ZEBRA_DEBUG_EVENT)
zlog_debug("%s: Deleting client %s", __func__,
zebra_route_string(client->proto));
+
+ if (zebra_router_in_shutdown())
+ zebra_gr_client_final_shutdown(client);
+
zserv_client_delete(client);
} else {
/* Handle cases where client has GR instance. */
@@ -1090,12 +1125,10 @@ static void zebra_show_client_detail(struct vty *vty, struct zserv *client)
vty_out(vty, "ES-EVI %-12u%-12u%-12u\n",
client->local_es_evi_add_cnt, 0, client->local_es_evi_del_cnt);
vty_out(vty, "Errors: %u\n", client->error_cnt);
-
-#if defined DEV_BUILD
vty_out(vty, "Input Fifo: %zu:%zu Output Fifo: %zu:%zu\n",
client->ibuf_fifo->count, client->ibuf_fifo->max_count,
client->obuf_fifo->count, client->obuf_fifo->max_count);
-#endif
+
vty_out(vty, "\n");
}
diff --git a/zebra/zserv.h b/zebra/zserv.h
index e1c990f..57d6730 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -378,6 +378,7 @@ __attribute__((__noreturn__)) void zebra_finalize(struct event *event);
/*
* Graceful restart functions.
*/
+extern void zebra_gr_client_final_shutdown(struct zserv *client);
extern int zebra_gr_client_disconnect(struct zserv *client);
extern void zebra_gr_client_reconnect(struct zserv *client);
extern void zebra_gr_stale_client_cleanup(struct list *client_list);