]> git.proxmox.com Git - mirror_frr.git/commitdiff
Merge pull request #8441 from mjstapp/fix_topo_pylint1
authorDavid Lamparter <equinox@opensourcerouting.org>
Sun, 9 May 2021 17:48:33 +0000 (19:48 +0200)
committerGitHub <noreply@github.com>
Sun, 9 May 2021 17:48:33 +0000 (19:48 +0200)
506 files changed:
.travis.yml [new file with mode: 0644]
Makefile.am
alpine/APKBUILD.in
babeld/babel_main.c
babeld/babeld.c
bgpd/bgp_bfd.c
bgpd/bgp_bmp.c
bgpd/bgp_clist.c
bgpd/bgp_community.c
bgpd/bgp_community_alias.c [new file with mode: 0644]
bgpd/bgp_community_alias.h [new file with mode: 0644]
bgpd/bgp_conditional_adv.c
bgpd/bgp_dump.c
bgpd/bgp_ecommunity.c
bgpd/bgp_evpn.c
bgpd/bgp_evpn_mh.c
bgpd/bgp_filter.c
bgpd/bgp_fsm.c
bgpd/bgp_fsm.h
bgpd/bgp_io.c
bgpd/bgp_lcommunity.c
bgpd/bgp_main.c
bgpd/bgp_memory.c
bgpd/bgp_memory.h
bgpd/bgp_mplsvpn.c
bgpd/bgp_mplsvpn_snmp.c
bgpd/bgp_nb.c
bgpd/bgp_nb_config.c
bgpd/bgp_network.c
bgpd/bgp_nht.c
bgpd/bgp_nht.h
bgpd/bgp_open.c
bgpd/bgp_packet.c
bgpd/bgp_pbr.c
bgpd/bgp_route.c
bgpd/bgp_route.h
bgpd/bgp_routemap_nb.c
bgpd/bgp_routemap_nb_config.c
bgpd/bgp_rpki.c
bgpd/bgp_snmp.c
bgpd/bgp_trace.c
bgpd/bgp_vty.c
bgpd/bgp_vty.h
bgpd/bgp_zebra.c
bgpd/bgpd.c
bgpd/bgpd.h
bgpd/rfp-example/rfptest/subdir.am
bgpd/subdir.am
bgpd/valgrind.supp [deleted file]
bootstrap.sh
configure.ac [changed mode: 0755->0644]
doc/developer/building-docker.rst
doc/developer/building-frr-for-openbsd6.rst
doc/developer/lists.rst
doc/manpages/vtysh.rst
doc/user/Useful_Sysctl_Settings.md
doc/user/basic.rst
doc/user/bfd.rst
doc/user/bgp.rst
doc/user/filter.rst
doc/user/isisd.rst
doc/user/kernel.rst
doc/user/nhrpd.rst
doc/user/ospf6d.rst
doc/user/ospfd.rst
doc/user/pim.rst
doc/user/ripd.rst
doc/user/ripngd.rst
doc/user/sharp.rst
doc/user/zebra.rst
docker/alpine/Dockerfile
docker/centos-7/Dockerfile
docker/centos-8/Dockerfile
docker/debian/Dockerfile
docker/debian/docker-start
docker/ubuntu18-ci/Dockerfile [new file with mode: 0644]
docker/ubuntu18-ci/README.md [new file with mode: 0644]
docker/ubuntu18-ci/docker-start [new file with mode: 0755]
docker/ubuntu20-ci/Dockerfile [new file with mode: 0644]
docker/ubuntu20-ci/README.md [new file with mode: 0644]
docker/ubuntu20-ci/docker-start [new file with mode: 0755]
eigrpd/eigrp_hello.c
eigrpd/eigrp_main.c
eigrpd/eigrp_metric.c
eigrpd/eigrp_packet.c
eigrpd/eigrp_routemap.c
fpm/fpm_pb.h
grpc/subdir.am
include/linux/if_packet.h [new file with mode: 0644]
include/linux/if_tunnel.h [new file with mode: 0644]
isisd/isis_circuit.c
isisd/isis_circuit.h
isisd/isis_cli.c
isisd/isis_csm.c
isisd/isis_csm.h
isisd/isis_ldp_sync.c
isisd/isis_ldp_sync.h
isisd/isis_lfa.c
isisd/isis_nb.c
isisd/isis_nb.h
isisd/isis_nb_config.c
isisd/isis_snmp.c
isisd/isis_vty_fabricd.c
isisd/isis_zebra.c
isisd/isisd.c
isisd/isisd.h
isisd/subdir.am
ldpd/lde.c
ldpd/lde.h
ldpd/ldp_snmp.c
ldpd/ldp_vty.h
ldpd/ldp_vty_cmds.c
ldpd/ldp_vty_conf.c
ldpd/ldp_zebra.c
ldpd/ldpd.c
ldpd/ldpd.h
ldpd/ldpe.c
ldpd/subdir.am
lib/agentx.c
lib/assert/assert.h [new file with mode: 0644]
lib/bfd.c
lib/bfd.h
lib/clippy.c
lib/command.c
lib/command.h
lib/command_lex.l
lib/command_parse.y
lib/compiler.h
lib/defaults.c
lib/distribute.c
lib/distribute.h
lib/filter.c
lib/filter.h
lib/filter_cli.c
lib/filter_nb.c
lib/frr_pthread.c
lib/lib_errors.c
lib/lib_errors.h
lib/libfrr.c
lib/libfrr.h
lib/libfrr_trace.c
lib/link_state.c
lib/linklist.c
lib/linklist.h
lib/log.c
lib/log.h
lib/log_vty.c
lib/module.c
lib/nexthop.c
lib/nexthop.h
lib/northbound_cli.c
lib/northbound_confd.c
lib/northbound_grpc.cpp
lib/northbound_sysrepo.c
lib/pid_output.c
lib/plist.c
lib/plist_int.h
lib/printfrr.h
lib/ringbuf.c
lib/ringbuf.h
lib/routemap_northbound.c
lib/routing_nb.c
lib/routing_nb_config.c
lib/sha256.c
lib/sigevent.c
lib/sockopt.c
lib/sockopt.h
lib/subdir.am
lib/thread.c
lib/thread.h
lib/typerb.h
lib/typesafe.h
lib/version.h.in
lib/vty.c
lib/xref.h
lib/zassert.h [deleted file]
lib/zclient.c
lib/zclient.h
lib/zebra.h
lib/zlog.c
lib/zlog.h
lib/zlog_targets.c
m4/.gitignore
m4/ax_lua.m4
nhrpd/linux.c
nhrpd/netlink.h
nhrpd/netlink_arp.c
nhrpd/netlink_gre.c [deleted file]
nhrpd/nhrp_cache.c
nhrpd/nhrp_interface.c
nhrpd/nhrp_main.c
nhrpd/nhrp_multicast.c [new file with mode: 0644]
nhrpd/nhrp_peer.c
nhrpd/nhrp_route.c
nhrpd/nhrp_vty.c
nhrpd/nhrpd.h
nhrpd/os.h
nhrpd/subdir.am
nhrpd/zbuf.c
nhrpd/zbuf.h
ospf6d/ospf6_abr.c
ospf6d/ospf6_abr.h
ospf6d/ospf6_area.c
ospf6d/ospf6_area.h
ospf6d/ospf6_asbr.c
ospf6d/ospf6_bfd.c
ospf6d/ospf6_bfd.h
ospf6d/ospf6_flood.c
ospf6d/ospf6_interface.c
ospf6d/ospf6_interface.h
ospf6d/ospf6_intra.c
ospf6d/ospf6_main.c
ospf6d/ospf6_message.c
ospf6d/ospf6_message.h
ospf6d/ospf6_neighbor.c
ospf6d/ospf6_neighbor.h
ospf6d/ospf6_route.c
ospf6d/ospf6_routemap_nb.c
ospf6d/ospf6_routemap_nb_config.c
ospf6d/ospf6_snmp.c
ospf6d/ospf6_top.c
ospf6d/ospf6_top.h
ospf6d/ospf6d.c
ospf6d/ospf6d.h
ospf6d/subdir.am
ospfd/ospf_abr.c
ospfd/ospf_asbr.c
ospfd/ospf_asbr.h
ospfd/ospf_bfd.c
ospfd/ospf_dump.c
ospfd/ospf_interface.c
ospfd/ospf_interface.h
ospfd/ospf_lsa.c
ospfd/ospf_packet.c
ospfd/ospf_routemap_nb.c
ospfd/ospf_routemap_nb_config.c
ospfd/ospf_snmp.c
ospfd/ospf_spf.c
ospfd/ospf_sr.c
ospfd/ospf_te.c
ospfd/ospf_vty.c
ospfd/ospf_zebra.c
ospfd/ospf_zebra.h
ospfd/ospfd.c
ospfd/ospfd.h
ospfd/subdir.am
pathd/path_cli.c
pathd/path_debug.c
pathd/path_pcep.c
pathd/path_pcep_cli.c
pathd/path_pcep_config.c
pathd/path_pcep_controller.c
pathd/path_pcep_debug.c
pathd/path_pcep_pcc.c
pathd/path_zebra.c
pathd/subdir.am
pbrd/pbr_zebra.c
pceplib/pcep_msg_messages.c
pceplib/pcep_msg_messages_encoding.c
pceplib/pcep_msg_object_error_types.c
pceplib/pcep_msg_objects.c
pceplib/pcep_msg_objects_encoding.c
pceplib/pcep_msg_tlvs.c
pceplib/pcep_msg_tools.c
pceplib/pcep_session_logic.c
pceplib/pcep_session_logic_counters.c
pceplib/pcep_session_logic_loop.c
pceplib/pcep_session_logic_states.c
pceplib/pcep_socket_comm_loop.c
pceplib/pcep_socket_comm_mock.c
pceplib/pcep_timers.c
pceplib/pcep_timers_event_loop.c
pceplib/pcep_utils_double_linked_list.c
pceplib/pcep_utils_logging.c
pceplib/pcep_utils_memory.c
pceplib/pcep_utils_ordered_list.c
pceplib/pcep_utils_queue.c
pceplib/subdir.am
pceplib/test/pcep_msg_messages_test.c
pceplib/test/pcep_msg_messages_tests.c
pceplib/test/pcep_msg_object_error_types_test.c
pceplib/test/pcep_msg_objects_test.c
pceplib/test/pcep_msg_tools_test.c
pceplib/test/pcep_pcc_api_test.c
pceplib/test/pcep_pcc_api_tests.c
pceplib/test/pcep_session_logic_loop_test.c
pceplib/test/pcep_session_logic_states_test.c
pceplib/test/pcep_session_logic_test.c
pceplib/test/pcep_session_logic_tests.c
pceplib/test/pcep_socket_comm_loop_test.c
pceplib/test/pcep_socket_comm_test.c
pceplib/test/pcep_socket_comm_tests.c
pceplib/test/pcep_timers_event_loop_test.c
pceplib/test/pcep_timers_test.c
pceplib/test/pcep_timers_tests.c
pceplib/test/pcep_utils_counters_test.c
pceplib/test/pcep_utils_double_linked_list_test.c
pceplib/test/pcep_utils_memory_test.c
pceplib/test/pcep_utils_ordered_list_test.c
pceplib/test/pcep_utils_queue_test.c
pceplib/test/pcep_utils_tests.c
pceplib/test/subdir.am
pimd/pim_assert.c
pimd/pim_bfd.c
pimd/pim_bfd.h
pimd/pim_bsm.c
pimd/pim_bsm.h
pimd/pim_cmd.c
pimd/pim_hello.c
pimd/pim_iface.c
pimd/pim_iface.h
pimd/pim_ifchannel.c
pimd/pim_igmp.c
pimd/pim_igmpv2.c
pimd/pim_igmpv3.c
pimd/pim_join.c
pimd/pim_main.c
pimd/pim_msdp.c
pimd/pim_msdp.h
pimd/pim_nb.c
pimd/pim_nb.h
pimd/pim_nb_config.c
pimd/pim_neighbor.c
pimd/pim_neighbor.h
pimd/pim_oil.c
pimd/pim_pim.c
pimd/pim_rp.c
pimd/pim_ssmpingd.c
pimd/pim_time.c
pimd/pim_tlv.c
pimd/pim_upstream.c
pimd/pim_upstream.h
pimd/pim_vty.c
pimd/pim_zebra.c
pimd/pim_zlookup.c
pimd/pimd.c
python/firstheader.py
python/vtysh-cmd-check.py [new file with mode: 0644]
qpb/subdir.am
ripd/rip_cli.c
ripd/rip_snmp.c
ripd/ripd.c
ripd/subdir.am
ripngd/ripng_cli.c
ripngd/ripngd.c
sharpd/sharp_vty.c
sharpd/sharp_zebra.c
sharpd/sharp_zebra.h
staticd/static_nb.c
staticd/static_nb_config.c
tests/.gitignore
tests/bgpd/test_aspath.c
tests/bgpd/test_capability.c
tests/bgpd/test_mp_attr.c
tests/isisd/test_isis_spf.c
tests/lib/cxxcompat.c
tests/lib/test_assert.c [new file with mode: 0644]
tests/lib/test_assert.py [new file with mode: 0644]
tests/lib/test_nexthop.c [new file with mode: 0644]
tests/lib/test_nexthop.py [new file with mode: 0644]
tests/lib/test_ringbuf.c
tests/lib/test_seqlock.c
tests/lib/test_typelist.h
tests/subdir.am
tests/topotests/Dockerfile
tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post4.1.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post5.0.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv4-post6.1.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv6-post4.1.ref
tests/topotests/all-protocol-startup/r1/show_bgp_ipv6_post6.1.ref
tests/topotests/all-protocol-startup/r1/show_ip_ospf_interface.ref
tests/topotests/bfd-bgp-cbit-topo3/r1/peers_down.json
tests/topotests/bfd-profiles-topo1/r4/bfd-peers-initial.json
tests/topotests/bfd-profiles-topo1/r4/bfdd.conf
tests/topotests/bfd-profiles-topo1/r4/ospf6d.conf
tests/topotests/bfd-profiles-topo1/r5/bfd-peers-initial.json
tests/topotests/bfd-profiles-topo1/r5/ospf6d.conf
tests/topotests/bgp-auth/test_bgp_auth.py
tests/topotests/bgp-community-alias/__init__.py [new file with mode: 0644]
tests/topotests/bgp-community-alias/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp-community-alias/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp-community-alias/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp-community-alias/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp-community-alias/test_bgp-community-alias.py [new file with mode: 0644]
tests/topotests/bgp-default-ipv4-ipv6-unicast/test_bgp-default-ipv4-ipv6-unicast.py
tests/topotests/bgp-ebgp-common-subnet-nexthop-unchanged/test_bgp-ebgp-common-subnet-nexthop-unchanged.py
tests/topotests/bgp_gr_functionality_topo1/test_bgp_gr_functionality_topo1.py
tests/topotests/bgp_gr_functionality_topo2/test_bgp_gr_functionality_topo2.py
tests/topotests/bgp_ipv6_rtadv/test_bgp_ipv6_rtadv.py
tests/topotests/bgp_multi_vrf_topo1/test_bgp_multi_vrf_topo1.py
tests/topotests/bgp_multi_vrf_topo2/test_bgp_multi_vrf_topo2.py
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post4.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_1-post6.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post4.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_2-post6.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post4.1.ref
tests/topotests/bgp_multiview_topo1/r1/show_ip_bgp_view_3-post6.1.ref
tests/topotests/bgp_recursive_route_ebgp_multi_hop/test_bgp_recursive_route_ebgp_multi_hop.py
tests/topotests/bgp_tcp_mss/__init__.py [new file with mode: 0644]
tests/topotests/bgp_tcp_mss/r1/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_tcp_mss/r1/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_tcp_mss/r2/bgpd.conf [new file with mode: 0644]
tests/topotests/bgp_tcp_mss/r2/zebra.conf [new file with mode: 0644]
tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py [new file with mode: 0644]
tests/topotests/bgp_vrf_dynamic_route_leak/test_bgp_vrf_dynamic_route_leak_topo1.py
tests/topotests/conftest.py
tests/topotests/isis-snmp/test_isis_snmp.py
tests/topotests/isis-sr-topo1/test_isis_sr_topo1.py
tests/topotests/isis-topo1/r1/r1_topology.json
tests/topotests/isis-topo1/r2/r2_topology.json
tests/topotests/isis-topo1/r3/r3_topology.json
tests/topotests/isis-topo1/r4/r4_topology.json
tests/topotests/isis-topo1/r5/r5_topology.json
tests/topotests/isis-topo1/test_isis_topo1.py
tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync.ref
tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r1_eth1_shutdown.ref
tests/topotests/ldp-sync-isis-topo1/r3/show_isis_ldp_sync_r2_eth1_shutdown.ref
tests/topotests/lib/bgp.py
tests/topotests/lib/common_config.py
tests/topotests/lib/pim.py
tests/topotests/lib/topotest.py
tests/topotests/ospf6-topo1-vrf/README.md [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r1/ip_6_address.nhg.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r1/ip_6_address.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r1/ospf6d.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r1/show_ipv6_vrf_route.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r1/zebra.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r2/ip_6_address.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r2/ospf6d.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r2/show_ipv6_vrf_route.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r2/zebra.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r3/ip_6_address.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r3/ospf6d.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r3/show_ipv6_vrf_route.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r3/zebra.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r4/ip_6_address.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r4/ospf6d.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r4/show_ipv6_vrf_route.ref [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/r4/zebra.conf [new file with mode: 0644]
tests/topotests/ospf6-topo1-vrf/test_ospf6_topo1_vrf.py [new file with mode: 0755]
tests/topotests/pim-basic-topo2/__init__.py [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r1/bfdd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r1/pimd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r1/zebra.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r2/bfdd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r2/pimd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r2/zebra.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r3/bfdd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r3/pimd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r3/zebra.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r4/bfdd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r4/pimd.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/r4/zebra.conf [new file with mode: 0644]
tests/topotests/pim-basic-topo2/test_pim_basic_topo2.dot [new file with mode: 0644]
tests/topotests/pim-basic-topo2/test_pim_basic_topo2.png [new file with mode: 0644]
tests/topotests/pim-basic-topo2/test_pim_basic_topo2.py [new file with mode: 0644]
tools/frr-reload.py
tools/subdir.am
tools/valgrind.supp [new file with mode: 0644]
version.h [new file with mode: 0644]
vtysh/extract.pl.in
vtysh/vtysh.c
vtysh/vtysh_config.c
vtysh/vtysh_main.c
yang/frr-isisd.yang
yang/frr-pim.yang
zebra/connected.c
zebra/debug.c
zebra/if_netlink.c
zebra/if_netlink.h
zebra/interface.c
zebra/interface.h
zebra/irdp_main.c
zebra/kernel_netlink.c
zebra/redistribute.c
zebra/rib.h
zebra/rt.h
zebra/rt_socket.c
zebra/rtadv.c
zebra/subdir.am
zebra/zapi_msg.c
zebra/zebra_dplane.c
zebra/zebra_dplane.h
zebra/zebra_errors.h
zebra/zebra_evpn.c
zebra/zebra_evpn_mac.c
zebra/zebra_evpn_mh.c
zebra/zebra_evpn_neigh.c
zebra/zebra_fpm.c
zebra/zebra_l2.c
zebra/zebra_l2.h
zebra/zebra_mlag_private.c
zebra/zebra_mpls.c
zebra/zebra_mroute.c
zebra/zebra_nhg.c
zebra/zebra_nhg.h
zebra/zebra_ptm.c
zebra/zebra_rib.c
zebra/zebra_routemap.c
zebra/zebra_routemap_nb.c
zebra/zebra_snmp.c
zebra/zebra_vrf.c
zebra/zebra_vrf.h
zebra/zebra_vty.c
zebra/zebra_vxlan.c
zebra/zserv.c

diff --git a/.travis.yml b/.travis.yml
new file mode 100644 (file)
index 0000000..d8e450a
--- /dev/null
@@ -0,0 +1,40 @@
+dist: focal
+os: linux
+language: c
+services:
+  - docker
+jobs:
+  include:
+   - script:
+       - docker/centos-7/build.sh
+       - docker images
+     name: centos7
+   - script:
+       - docker/centos-8/build.sh
+       - docker images
+     name: centos8
+   - script:
+       - sudo apt install -y linux-modules-extra-$(uname -r)
+       - docker build -t frr-ubuntu18:latest -f docker/ubuntu18-ci/Dockerfile .
+       - docker images
+       - uname -a
+       - docker run -d --privileged --name frr-ubuntu18 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu18:latest
+       - docker ps
+       - docker exec frr-ubuntu18 bash -c 'cd ~/frr ; make check'
+       - docker exec frr-ubuntu18 bash -c 'ps agxu ; lsmod | grep mpls || true'
+       - docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+       - docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/bgp_l3vpn_to_bgp_vrf ; sudo pytest test_bgp_l3vpn_to_bgp_vrf.py'
+     name: ubuntu18+minimalCI
+   - script:
+       - sudo apt install -y linux-modules-extra-$(uname -r)
+       - docker build -t frr-ubuntu20:latest -f docker/ubuntu20-ci/Dockerfile .
+       - docker images
+       - uname -a
+       - docker run -d --privileged --name frr-ubuntu20 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu20:latest
+       - docker ps
+       - docker exec frr-ubuntu20 bash -c 'cd ~/frr ; make check'
+       - docker exec frr-ubuntu20 bash -c 'ps agxu ; lsmod | grep mpls || true'
+       - docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+       - docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/bgp_l3vpn_to_bgp_vrf ; sudo pytest test_bgp_l3vpn_to_bgp_vrf.py'
+     name: ubuntu20+minimalCI
+
index 0dff83e505a2a6f10341f5029310af831c6aa1a4..a5101df2f0eec2b11f4e199e4d953af42b692f1b 100644 (file)
@@ -1,20 +1,29 @@
 ## Process this file with automake to produce Makefile.in.
 
 AUTOMAKE_OPTIONS = subdir-objects 1.12
-ACLOCAL_AMFLAGS = -I m4
+ACLOCAL_AMFLAGS = -I m4 -Wall,no-override
 
 AM_CFLAGS = \
+       $(AC_CFLAGS) \
        $(LIBYANG_CFLAGS) \
        $(SQLITE3_CFLAGS) \
        $(UNWIND_CFLAGS) \
        $(SAN_FLAGS) \
        $(WERROR) \
        # end
-AM_CPPFLAGS = \
+
+# CPPFLAGS_BASE does not contain the include path for overriding assert.h,
+# therefore should be used in tools that do *not* link libfrr or do not want
+# assert() overridden
+CPPFLAGS_BASE = \
        -I$(top_srcdir) -I$(top_srcdir)/include -I$(top_srcdir)/lib \
-       -I$(top_builddir) -I$(top_builddir)/include -I$(top_builddir)/lib \
+       -I$(top_builddir) \
        $(LUA_INCLUDE) \
        # end
+AM_CPPFLAGS = \
+       -I$(top_srcdir)/lib/assert \
+       $(CPPFLAGS_BASE) \
+       # end
 AM_LDFLAGS = \
        -export-dynamic \
        $(AC_LDFLAGS) \
index d6c6c5f0afb3ec018ee019d73183428625cfa942..dfedf0b52b27763c60d09832f52be6e91df32a3d 100644 (file)
@@ -18,7 +18,7 @@ makedepends="ncurses-dev net-snmp-dev gawk texinfo perl
     ncurses-libs ncurses-terminfo ncurses-terminfo-base patch pax-utils pcre
     perl pkgconf python3 python3-dev readline readline-dev sqlite-libs
     squashfs-tools sudo tar texinfo xorriso xz-libs py-pip rtrlib rtrlib-dev
-    py3-sphinx"
+    py3-sphinx elfutils elfutils-dev"
 checkdepends="pytest py-setuptools"
 install="$pkgname.pre-install $pkgname.pre-deinstall $pkgname.post-deinstall"
 subpackages="$pkgname-dev $pkgname-doc $pkgname-dbg"
index 71ac35658545654b3d9342cd5970ca49dfc238cf..df1998c4fcc3aa8291693397ce388d98e88cc062 100644 (file)
@@ -28,7 +28,7 @@ THE SOFTWARE.
 #include "thread.h"
 #include "privs.h"
 #include "sigevent.h"
-#include "version.h"
+#include "lib/version.h"
 #include "command.h"
 #include "vty.h"
 #include "memory.h"
index 72080bd7eb48e52b4025155399a033eadaa6b0aa..4d4dd2e19490f651681ccd37eb8b9b5092ca26a1 100644 (file)
@@ -712,6 +712,92 @@ DEFUN (babel_set_smoothing_half_life,
     return CMD_SUCCESS;
 }
 
+DEFUN (babel_distribute_list,
+       babel_distribute_list_cmd,
+       "distribute-list [prefix] WORD <in|out> [WORD]",
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_parser(prefix, true, argv[2 + prefix]->text,
+                                     argv[1 + prefix]->arg, ifname);
+}
+
+DEFUN (babel_no_distribute_list,
+       babel_no_distribute_list_cmd,
+       "no distribute-list [prefix] WORD <in|out> [WORD]",
+       NO_STR
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_no_parser(vty, prefix, true,
+                                        argv[3 + prefix]->text,
+                                        argv[2 + prefix]->arg, ifname);
+}
+
+DEFUN (babel_ipv6_distribute_list,
+       babel_ipv6_distribute_list_cmd,
+       "ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
+       "IPv6\n"
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_parser(prefix, false, argv[3 + prefix]->text,
+                                     argv[2 + prefix]->arg, ifname);
+}
+
+DEFUN (babel_no_ipv6_distribute_list,
+       babel_no_ipv6_distribute_list_cmd,
+       "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
+       NO_STR
+       "IPv6\n"
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_no_parser(vty, prefix, false,
+                                        argv[4 + prefix]->text,
+                                        argv[3 + prefix]->arg, ifname);
+}
+
 void
 babeld_quagga_init(void)
 {
@@ -728,6 +814,11 @@ babeld_quagga_init(void)
     install_element(BABEL_NODE, &babel_set_resend_delay_cmd);
     install_element(BABEL_NODE, &babel_set_smoothing_half_life_cmd);
 
+    install_element(BABEL_NODE, &babel_distribute_list_cmd);
+    install_element(BABEL_NODE, &babel_no_distribute_list_cmd);
+    install_element(BABEL_NODE, &babel_ipv6_distribute_list_cmd);
+    install_element(BABEL_NODE, &babel_no_ipv6_distribute_list_cmd);
+
     babel_if_init();
 
     /* Access list install. */
@@ -739,9 +830,6 @@ babeld_quagga_init(void)
     prefix_list_init ();
     prefix_list_add_hook (babel_distribute_update_all);
     prefix_list_delete_hook (babel_distribute_update_all);
-
-    /* Distribute list install. */
-    distribute_list_init(BABEL_NODE);
 }
 
 /* Stubs to adapt Babel's filtering calls to Quagga's infrastructure. */
index 958d7cf0ed68d37ca02b5c449fcf636af8fd7315..6004070e68b4224726c43b60b460d026da7598c4 100644 (file)
@@ -308,8 +308,6 @@ void bgp_peer_configure_bfd(struct peer *p, bool manual)
        if (p->nexthop.ifp)
                bfd_sess_set_interface(p->bfd_config->session,
                                       p->nexthop.ifp->name);
-
-       bfd_sess_enable(p->bfd_config->session, true);
 }
 
 static void bgp_peer_remove_bfd(struct peer *p)
index 0e5f506b3aef1b0dafb295ca2c34aa93df2b4469..abe97571c568c43b565a83c9b5df2a0346180af7 100644 (file)
@@ -34,7 +34,7 @@
 #include "lib_errors.h"
 #include "stream.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "jhash.h"
 #include "termtable.h"
 
index e17cce3ff65b3ecd5d6c6a6e26f5c8ae8651238a..50122ad7da6cb3edac230e53c699993fb05bb14e 100644 (file)
@@ -1117,9 +1117,6 @@ int lcommunity_list_set(struct community_list_handler *ch, const char *name,
        }
 
        if (str) {
-               if (!lcommunity_list_valid(str, style))
-                       return COMMUNITY_LIST_ERR_MALFORMED_VAL;
-
                if (style == LARGE_COMMUNITY_LIST_STANDARD)
                        lcom = lcommunity_str2com(str);
                else
index 43138b82f68fe32e8d6b09c55d942ea1805b4274..b034ec9f7bf9da119745a6ab652cb474af660582 100644 (file)
@@ -28,6 +28,7 @@
 
 #include "bgpd/bgp_memory.h"
 #include "bgpd/bgp_community.h"
+#include "bgpd/bgp_community_alias.h"
 
 /* Hash of community attribute. */
 static struct hash *comhash;
@@ -292,7 +293,7 @@ static void set_community_string(struct community *com, bool make_json)
                        len += strlen(" no-peer");
                        break;
                default:
-                       len += strlen(" 65536:65535");
+                       len = BUFSIZ;
                        break;
                }
        }
@@ -450,7 +451,7 @@ static void set_community_string(struct community *com, bool make_json)
                        val = comval & 0xFFFF;
                        char buf[32];
                        snprintf(buf, sizeof(buf), "%u:%d", as, val);
-                       strlcat(str, buf, len);
+                       strlcat(str, bgp_community2alias(buf), len);
                        if (make_json) {
                                json_string = json_object_new_string(buf);
                                json_object_array_add(json_community_list,
diff --git a/bgpd/bgp_community_alias.c b/bgpd/bgp_community_alias.c
new file mode 100644 (file)
index 0000000..6e510a0
--- /dev/null
@@ -0,0 +1,154 @@
+/* BGP community, large-community aliasing.
+ *
+ * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com>
+ *
+ * This file is part of FRRouting (FRR).
+ *
+ * FRR 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, or (at your option) any later version.
+ *
+ * FRR 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 "memory.h"
+#include "lib/jhash.h"
+
+#include "bgpd/bgpd.h"
+#include "bgpd/bgp_community_alias.h"
+
+static struct hash *bgp_ca_alias_hash;
+static struct hash *bgp_ca_community_hash;
+
+static unsigned int bgp_ca_community_hash_key(const void *p)
+{
+       const struct community_alias *ca = p;
+
+       return jhash(ca->community, sizeof(ca->community), 0);
+}
+
+static bool bgp_ca_community_hash_cmp(const void *p1, const void *p2)
+{
+       const struct community_alias *ca1 = p1;
+       const struct community_alias *ca2 = p2;
+
+       return (strncmp(ca1->community, ca2->community,
+                       sizeof(struct community_alias))
+               == 0);
+}
+
+static unsigned int bgp_ca_alias_hash_key(const void *p)
+{
+       const struct community_alias *ca = p;
+
+       return jhash(ca->alias, sizeof(ca->alias), 0);
+}
+
+static bool bgp_ca_alias_hash_cmp(const void *p1, const void *p2)
+{
+       const struct community_alias *ca1 = p1;
+       const struct community_alias *ca2 = p2;
+
+       return (strncmp(ca1->alias, ca2->alias, sizeof(struct community_alias))
+               == 0);
+}
+
+static void *bgp_community_alias_alloc(void *p)
+{
+       const struct community_alias *ca = p;
+       struct communtiy_alias *new;
+
+       new = XCALLOC(MTYPE_COMMUNITY_ALIAS, sizeof(struct community_alias));
+       memcpy(new, ca, sizeof(struct community_alias));
+
+       return new;
+}
+
+void bgp_community_alias_init(void)
+{
+       bgp_ca_community_hash = hash_create(bgp_ca_community_hash_key,
+                                              bgp_ca_community_hash_cmp,
+                                              "BGP community alias (community)");
+       bgp_ca_alias_hash =
+               hash_create(bgp_ca_alias_hash_key, bgp_ca_alias_hash_cmp,
+                           "BGP community alias (alias)");
+}
+
+void bgp_community_alias_finish(void)
+{
+       hash_free(bgp_ca_community_hash);
+       hash_free(bgp_ca_alias_hash);
+}
+
+static void bgp_community_alias_show_iterator(struct hash_bucket *hb,
+                                             struct vty *vty)
+{
+       struct community_alias *ca = hb->data;
+
+       vty_out(vty, "bgp community alias %s %s\n", ca->community, ca->alias);
+}
+
+int bgp_community_alias_write(struct vty *vty)
+{
+       hash_iterate(bgp_ca_community_hash,
+                    (void (*)(struct hash_bucket *,
+                              void *))bgp_community_alias_show_iterator,
+                    vty);
+       return 1;
+}
+
+void bgp_ca_community_insert(struct community_alias *ca)
+{
+       hash_get(bgp_ca_community_hash, ca, bgp_community_alias_alloc);
+}
+
+void bgp_ca_alias_insert(struct community_alias *ca)
+{
+       hash_get(bgp_ca_alias_hash, ca, bgp_community_alias_alloc);
+}
+
+void bgp_ca_community_delete(struct community_alias *ca)
+{
+       struct community_alias *data = hash_release(bgp_ca_community_hash, ca);
+
+       XFREE(MTYPE_COMMUNITY_ALIAS, data);
+}
+
+void bgp_ca_alias_delete(struct community_alias *ca)
+{
+       struct community_alias *data = hash_release(bgp_ca_alias_hash, ca);
+
+       XFREE(MTYPE_COMMUNITY_ALIAS, data);
+}
+
+struct community_alias *bgp_ca_community_lookup(struct community_alias *ca)
+{
+       return hash_lookup(bgp_ca_community_hash, ca);
+}
+
+struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca)
+{
+       return hash_lookup(bgp_ca_alias_hash, ca);
+}
+
+const char *bgp_community2alias(char *community)
+{
+       struct community_alias ca;
+       struct community_alias *find;
+
+       memset(&ca, 0, sizeof(ca));
+       strlcpy(ca.community, community, sizeof(ca.community));
+
+       find = bgp_ca_community_lookup(&ca);
+       if (find)
+               return find->alias;
+
+       return community;
+}
diff --git a/bgpd/bgp_community_alias.h b/bgpd/bgp_community_alias.h
new file mode 100644 (file)
index 0000000..c84119a
--- /dev/null
@@ -0,0 +1,46 @@
+/* BGP community, large-community aliasing.
+ *
+ * Copyright (C) 2021 Donatas Abraitis <donatas.abraitis@gmail.com>
+ *
+ * This file is part of FRRouting (FRR).
+ *
+ * FRR 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, or (at your option) any later version.
+ *
+ * FRR 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 "bgpd/bgp_lcommunity.h"
+
+#ifndef FRR_BGP_COMMUNITY_ALIAS_H
+#define FRR_BGP_COMMUNITY_ALIAS_H
+
+struct community_alias {
+       /* Human readable community string */
+       char community[LCOMMUNITY_SIZE * 3];
+
+       /* Human readable community alias */
+       char alias[BUFSIZ];
+};
+
+extern void bgp_community_alias_init(void);
+extern void bgp_community_alias_finish(void);
+extern struct community_alias *bgp_ca_alias_lookup(struct community_alias *ca);
+extern struct community_alias *
+bgp_ca_community_lookup(struct community_alias *ca);
+extern void bgp_ca_community_insert(struct community_alias *ca);
+extern void bgp_ca_alias_insert(struct community_alias *ca);
+extern void bgp_ca_community_delete(struct community_alias *ca);
+extern void bgp_ca_alias_delete(struct community_alias *ca);
+extern int bgp_community_alias_write(struct vty *vty);
+extern const char *bgp_community2alias(char *community);
+
+#endif /* FRR_BGP_COMMUNITY_ALIAS_H */
index b9ea26e862c86e017fb44a1751b2a9ed90e6b070..6e80765f8671ce734bd53e1f6c9a1e82978e3b0a 100644 (file)
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "bgpd/bgp_conditional_adv.h"
 #include "bgpd/bgp_vty.h"
 
index 944a5848ec9335c63f0a35ef06a1177b9d88bd19..299ee305beafe17e429d860078f55349f93702d4 100644 (file)
@@ -389,7 +389,8 @@ bgp_dump_route_node_record(int afi, struct bgp_dest *dest,
                bgp_dump_routes_attr(obuf, path->attr, p);
 
                cur_endp = stream_get_endp(obuf);
-               if (cur_endp > BGP_MAX_PACKET_SIZE + BGP_DUMP_MSG_HEADER
+               if (cur_endp > BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE
+                                      + BGP_DUMP_MSG_HEADER
                                       + BGP_DUMP_HEADER_SIZE) {
                        stream_set_endp(obuf, endp);
                        break;
@@ -868,8 +869,8 @@ void bgp_dump_init(void)
        memset(&bgp_dump_routes, 0, sizeof(struct bgp_dump));
 
        bgp_dump_obuf =
-               stream_new((BGP_MAX_PACKET_SIZE << 1) + BGP_DUMP_MSG_HEADER
-                          + BGP_DUMP_HEADER_SIZE);
+               stream_new((BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE * 2)
+                          + BGP_DUMP_MSG_HEADER + BGP_DUMP_HEADER_SIZE);
 
        install_node(&bgp_dump_node);
 
index 7f6f61e1417aef8c5d5d6bfdb984556eaa7ad960..923c9b0d7e875b7fe6bdf63ebb2c4e863ffd08b0 100644 (file)
@@ -1294,15 +1294,19 @@ bool ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
 
        /* Delete the selected value */
        ecom->size--;
-       p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ecom->unit_size);
-       if (c != 0)
-               memcpy(p, ecom->val, c * ecom->unit_size);
-       if ((ecom->size - c) != 0)
-               memcpy(p + (c)*ecom->unit_size,
-                      ecom->val + (c + 1) * ecom->unit_size,
-                      (ecom->size - c) * ecom->unit_size);
-       XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
-       ecom->val = p;
+       if (ecom->size) {
+               p = XMALLOC(MTYPE_ECOMMUNITY_VAL, ecom->size * ecom->unit_size);
+               if (c != 0)
+                       memcpy(p, ecom->val, c * ecom->unit_size);
+               if ((ecom->size - c) != 0)
+                       memcpy(p + (c)*ecom->unit_size,
+                              ecom->val + (c + 1) * ecom->unit_size,
+                              (ecom->size - c) * ecom->unit_size);
+               XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
+               ecom->val = p;
+       } else
+               ecom->val = NULL;
+
        return true;
 }
 
index 2d4fea413a1a4f1fc9c189d5f6ac55edd0decd0f..fae3f1000f15af3d07df307bbb51ed69a65f50b0 100644 (file)
@@ -586,7 +586,7 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
                                       uint8_t flags, uint32_t seq, esi_t *esi)
 {
        struct stream *s;
-       int ipa_len;
+       uint16_t ipa_len;
        static struct in_addr zero_remote_vtep_ip;
 
        /* Check socket. */
@@ -614,11 +614,11 @@ static int bgp_zebra_send_remote_macip(struct bgp *bgp, struct bgpevpn *vpn,
        stream_put(s, &p->prefix.macip_addr.mac.octet, ETH_ALEN); /* Mac Addr */
        /* IP address length and IP address, if any. */
        if (is_evpn_prefix_ipaddr_none(p))
-               stream_putl(s, 0);
+               stream_putw(s, 0);
        else {
                ipa_len = is_evpn_prefix_ipaddr_v4(p) ? IPV4_MAX_BYTELEN
                                                      : IPV6_MAX_BYTELEN;
-               stream_putl(s, ipa_len);
+               stream_putw(s, ipa_len);
                stream_put(s, &p->prefix.macip_addr.ip.ip.addr, ipa_len);
        }
        /* If the ESI is valid that becomes the nexthop; tape out the
@@ -1670,8 +1670,9 @@ static inline bool bgp_evpn_route_add_l3_ecomm_ok(struct bgpevpn *vpn,
 {
        return p->prefix.route_type == BGP_EVPN_MAC_IP_ROUTE
               && (is_evpn_prefix_ipaddr_v4(p)
-                  || !IN6_IS_ADDR_LINKLOCAL(
-                          &p->prefix.macip_addr.ip.ipaddr_v6))
+                  || (is_evpn_prefix_ipaddr_v6(p)
+                      && !IN6_IS_ADDR_LINKLOCAL(
+                              &p->prefix.macip_addr.ip.ipaddr_v6)))
               && CHECK_FLAG(vpn->flags, VNI_FLAG_USE_TWO_LABELS)
               && bgpevpn_get_l3vni(vpn) && bgp_evpn_es_add_l3_ecomm_ok(esi);
 }
@@ -5382,11 +5383,12 @@ int bgp_evpn_local_l3vni_add(vni_t l3vni, vrf_id_t vrf_id,
                switch (ret) {
                case BGP_ERR_AS_MISMATCH:
                        flog_err(EC_BGP_EVPN_AS_MISMATCH,
-                                "BGP is already running; AS is %u", as);
+                                "BGP instance is already running; AS is %u",
+                                as);
                        return -1;
                case BGP_ERR_INSTANCE_MISMATCH:
                        flog_err(EC_BGP_EVPN_INSTANCE_MISMATCH,
-                                "BGP instance name and AS number mismatch");
+                                "BGP instance type mismatch");
                        return -1;
                }
 
index 868238ebddd46e26e51cd4560b108f0bcf53ad30..6467ff8a283c97c1af0f9ac2bd1c152308a2adef 100644 (file)
@@ -2493,6 +2493,10 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf,
                if (!CHECK_FLAG(es_vtep->flags, BGP_EVPNES_VTEP_ACTIVE))
                        continue;
 
+               /* Don't overrun the zapi buffer. */
+               if (api_nhg.nexthop_num == MULTIPATH_NUM)
+                       break;
+
                /* overwrite the gw */
                if (v4_nhg)
                        nh.gate.ipv4 = es_vtep->vtep_ip;
@@ -2514,9 +2518,6 @@ static void bgp_evpn_l3nhg_zebra_add_v4_or_v6(struct bgp_evpn_es_vrf *es_vrf,
        if (!api_nhg.nexthop_num)
                return;
 
-       if (api_nhg.nexthop_num > MULTIPATH_NUM)
-               return;
-
        zclient_nhg_send(zclient, ZEBRA_NHG_ADD, &api_nhg);
 }
 
index 5d1a7a98d7c9853963450e8c6944e21dfc7e3424..8d6691945fe24d38f590ec89e9841f4a67194830 100644 (file)
@@ -40,9 +40,6 @@ struct as_list_list {
 
 /* AS path filter master. */
 struct as_list_master {
-       /* List of access_list which name is number. */
-       struct as_list_list num;
-
        /* List of access_list which name is string. */
        struct as_list_list str;
 
@@ -71,8 +68,6 @@ struct as_filter {
 struct as_list {
        char *name;
 
-       enum access_type type;
-
        struct as_list *next;
        struct as_list *prev;
 
@@ -115,7 +110,6 @@ static struct as_filter *bgp_aslist_seq_check(struct as_list *list, int64_t seq)
 /* as-path access-list 10 permit AS1. */
 
 static struct as_list_master as_list_master = {{NULL, NULL},
-                                              {NULL, NULL},
                                               NULL,
                                               NULL};
 
@@ -237,10 +231,6 @@ struct as_list *as_list_lookup(const char *name)
        if (name == NULL)
                return NULL;
 
-       for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
-               if (strcmp(aslist->name, name) == 0)
-                       return aslist;
-
        for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
                if (strcmp(aslist->name, name) == 0)
                        return aslist;
@@ -263,8 +253,6 @@ static void as_list_free(struct as_list *aslist)
    the name. */
 static struct as_list *as_list_insert(const char *name)
 {
-       size_t i;
-       long number;
        struct as_list *aslist;
        struct as_list *point;
        struct as_list_list *list;
@@ -274,36 +262,13 @@ static struct as_list *as_list_insert(const char *name)
        aslist->name = XSTRDUP(MTYPE_AS_STR, name);
        assert(aslist->name);
 
-       /* If name is made by all digit character.  We treat it as
-          number. */
-       for (number = 0, i = 0; i < strlen(name); i++) {
-               if (isdigit((unsigned char)name[i]))
-                       number = (number * 10) + (name[i] - '0');
-               else
-                       break;
-       }
-
-       /* In case of name is all digit character */
-       if (i == strlen(name)) {
-               aslist->type = ACCESS_TYPE_NUMBER;
-
-               /* Set access_list to number list. */
-               list = &as_list_master.num;
-
-               for (point = list->head; point; point = point->next)
-                       if (atol(point->name) >= number)
-                               break;
-       } else {
-               aslist->type = ACCESS_TYPE_STRING;
-
-               /* Set access_list to string list. */
-               list = &as_list_master.str;
+       /* Set access_list to string list. */
+       list = &as_list_master.str;
 
-               /* Set point to insertion point. */
-               for (point = list->head; point; point = point->next)
-                       if (strcmp(point->name, name) >= 0)
-                               break;
-       }
+       /* Set point to insertion point. */
+       for (point = list->head; point; point = point->next)
+               if (strcmp(point->name, name) >= 0)
+                       break;
 
        /* In case of this is the first element of master. */
        if (list->head == NULL) {
@@ -371,10 +336,7 @@ static void as_list_delete(struct as_list *aslist)
                as_filter_free(filter);
        }
 
-       if (aslist->type == ACCESS_TYPE_NUMBER)
-               list = &as_list_master.num;
-       else
-               list = &as_list_master.str;
+       list = &as_list_master.str;
 
        if (aslist->next)
                aslist->next->prev = aslist->prev;
@@ -667,17 +629,6 @@ static void as_list_show_all(struct vty *vty)
        struct as_list *aslist;
        struct as_filter *asfilter;
 
-       for (aslist = as_list_master.num.head; aslist; aslist = aslist->next) {
-               vty_out(vty, "AS path access list %s\n", aslist->name);
-
-               for (asfilter = aslist->head; asfilter;
-                    asfilter = asfilter->next) {
-                       vty_out(vty, "    %s %s\n",
-                               filter_type_str(asfilter->type),
-                               asfilter->reg_str);
-               }
-       }
-
        for (aslist = as_list_master.str.head; aslist; aslist = aslist->next) {
                vty_out(vty, "AS path access list %s\n", aslist->name);
 
@@ -740,18 +691,6 @@ static int config_write_as_list(struct vty *vty)
        struct as_filter *asfilter;
        int write = 0;
 
-       for (aslist = as_list_master.num.head; aslist; aslist = aslist->next)
-               for (asfilter = aslist->head; asfilter;
-                    asfilter = asfilter->next) {
-                       vty_out(vty,
-                               "bgp as-path access-list %s seq %" PRId64
-                               " %s %s\n",
-                               aslist->name, asfilter->seq,
-                               filter_type_str(asfilter->type),
-                               asfilter->reg_str);
-                       write++;
-               }
-
        for (aslist = as_list_master.str.head; aslist; aslist = aslist->next)
                for (asfilter = aslist->head; asfilter;
                     asfilter = asfilter->next) {
@@ -794,19 +733,11 @@ void bgp_filter_reset(void)
        struct as_list *aslist;
        struct as_list *next;
 
-       for (aslist = as_list_master.num.head; aslist; aslist = next) {
-               next = aslist->next;
-               as_list_delete(aslist);
-       }
-
        for (aslist = as_list_master.str.head; aslist; aslist = next) {
                next = aslist->next;
                as_list_delete(aslist);
        }
 
-       assert(as_list_master.num.head == NULL);
-       assert(as_list_master.num.tail == NULL);
-
        assert(as_list_master.str.head == NULL);
        assert(as_list_master.str.tail == NULL);
 }
index 45a856a4591fc5f0f7a834fe88acd7eaf7a73c2b..6bcb31e652f1ff96701ab1ffef29de2549329137 100644 (file)
@@ -101,7 +101,7 @@ static int bgp_delayopen_timer(struct thread *);
 static int bgp_start(struct peer *);
 
 /* Register peer with NHT */
-static int bgp_peer_reg_with_nht(struct peer *peer)
+int bgp_peer_reg_with_nht(struct peer *peer)
 {
        int connected = 0;
 
@@ -294,7 +294,6 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
        }
 
        FOREACH_AFI_SAFI (afi, safi) {
-               peer->af_flags[afi][safi] = from_peer->af_flags[afi][safi];
                peer->af_sflags[afi][safi] = from_peer->af_sflags[afi][safi];
                peer->af_cap[afi][safi] = from_peer->af_cap[afi][safi];
                peer->afc_nego[afi][safi] = from_peer->afc_nego[afi][safi];
@@ -340,6 +339,8 @@ static struct peer *peer_xfer_conn(struct peer *from_peer)
         * needed, even on a passive connection.
         */
        bgp_peer_reg_with_nht(peer);
+       if (from_peer)
+               bgp_replace_nexthop_by_peer(from_peer, peer);
 
        bgp_reads_on(peer);
        bgp_writes_on(peer);
index bcf697e153fb4275d3d777d4c4c54c6b820fc555..12cbad3eb83b0e164a70888fa92268ff5b0fb606 100644 (file)
@@ -179,4 +179,5 @@ const char *print_peer_gr_mode(enum peer_mode pr_mode);
 const char *print_peer_gr_cmd(enum peer_gr_command pr_gr_cmd);
 const char *print_global_gr_mode(enum global_mode gl_mode);
 const char *print_global_gr_cmd(enum global_gr_command gl_gr_cmd);
+int bgp_peer_reg_with_nht(struct peer *peer);
 #endif /* _QUAGGA_BGP_FSM_H */
index a696d956977aba5b4fc05bd52c5af5d9e88d668f..e9b0f9e46a103f41ca03b96663a0ed2bb2720473 100644 (file)
@@ -32,7 +32,6 @@
 #include "stream.h"            // for stream_get_endp, stream_getw_from, str...
 #include "ringbuf.h"           // for ringbuf_remain, ringbuf_peek, ringbuf_...
 #include "thread.h"            // for THREAD_OFF, THREAD_ARG, thread...
-#include "zassert.h"           // for assert
 
 #include "bgpd/bgp_io.h"
 #include "bgpd/bgp_debug.h"    // for bgp_debug_neighbor_events, bgp_type_str
@@ -180,8 +179,8 @@ static int bgp_process_reads(struct thread *thread)
        bool more = true;               // whether we got more data
        bool fatal = false;             // whether fatal error occurred
        bool added_pkt = false;         // whether we pushed onto ->ibuf
+       int code = 0;                   // FSM code if error occurred
        /* clang-format on */
-       int code;
 
        peer = THREAD_ARG(thread);
 
@@ -455,14 +454,20 @@ done : {
 /*
  * Reads a chunk of data from peer->fd into peer->ibuf_work.
  *
+ * code_p
+ *    Pointer to location to store FSM event code in case of fatal error.
+ *
  * @return status flag (see top-of-file)
  */
 static uint16_t bgp_read(struct peer *peer, int *code_p)
 {
+       size_t readsize; // how many bytes we want to read
        ssize_t nbytes;  // how many bytes we actually read
        uint16_t status = 0;
 
-       nbytes = ringbuf_read(peer->ibuf_work, peer->fd);
+       readsize =
+               MIN(ringbuf_space(peer->ibuf_work), sizeof(peer->ibuf_scratch));
+       nbytes = read(peer->fd, peer->ibuf_scratch, readsize);
 
        /* EAGAIN or EWOULDBLOCK; come back later */
        if (nbytes < 0 && ERRNO_IO_RETRY(errno)) {
@@ -490,6 +495,9 @@ static uint16_t bgp_read(struct peer *peer, int *code_p)
                        *code_p = TCP_connection_closed;
 
                SET_FLAG(status, BGP_IO_FATAL_ERR);
+       } else {
+               assert(ringbuf_put(peer->ibuf_work, peer->ibuf_scratch, nbytes)
+                      == (size_t)nbytes);
        }
 
        return status;
index 88a85c979e74c06c330a51c51bd139718df11cc3..ff34937efc73dabf686838f80732a2ff97882191 100644 (file)
@@ -30,6 +30,7 @@
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_lcommunity.h"
+#include "bgpd/bgp_community_alias.h"
 #include "bgpd/bgp_aspath.h"
 
 /* Hash of community attribute. */
@@ -213,7 +214,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
        }
 
        /* 1 space + lcom->size lcom strings + null terminator */
-       size_t str_buf_sz = (LCOMMUNITY_STRLEN * lcom->size) + 2;
+       size_t str_buf_sz = BUFSIZ;
        str_buf = XCALLOC(MTYPE_LCOMMUNITY_STR, str_buf_sz);
 
        for (i = 0; i < lcom->size; i++) {
@@ -231,7 +232,7 @@ static void set_lcommunity_string(struct lcommunity *lcom, bool make_json)
                snprintf(lcsb, sizeof(lcsb), "%u:%u:%u", global, local1,
                         local2);
 
-               len = strlcat(str_buf, lcsb, str_buf_sz);
+               len = strlcat(str_buf, bgp_community2alias(lcsb), str_buf_sz);
                assert((unsigned int)len < str_buf_sz);
 
                if (make_json) {
index ea74a82cec5576ef15561eadc590d488dd47da48..995917b6bdc5c62727a90bdee194a441e014e3dc 100644 (file)
@@ -66,6 +66,7 @@
 #include "bgpd/bgp_evpn_mh.h"
 #include "bgpd/bgp_nht.h"
 #include "bgpd/bgp_routemap_nb.h"
+#include "bgpd/bgp_community_alias.h"
 
 #ifdef ENABLE_BGP_VNC
 #include "bgpd/rfapi/rfapi_backend.h"
@@ -220,6 +221,9 @@ static __attribute__((__noreturn__)) void bgp_exit(int status)
        /* reverse bgp_dump_init */
        bgp_dump_finish();
 
+       /* BGP community aliases */
+       bgp_community_alias_finish();
+
        /* reverse bgp_route_init */
        bgp_route_finish();
 
index 36bdc05eb784a503228f8f0a8851dcbed9a2f867..fc508496cca86d1f392f3f9fd81093fc7552e034 100644 (file)
@@ -65,6 +65,8 @@ DEFINE_MTYPE(BGPD, AS_LIST, "BGP AS list");
 DEFINE_MTYPE(BGPD, AS_FILTER, "BGP AS filter");
 DEFINE_MTYPE(BGPD, AS_FILTER_STR, "BGP AS filter str");
 
+DEFINE_MTYPE(BGPD, COMMUNITY_ALIAS, "community");
+
 DEFINE_MTYPE(BGPD, COMMUNITY, "community");
 DEFINE_MTYPE(BGPD, COMMUNITY_VAL, "community val");
 DEFINE_MTYPE(BGPD, COMMUNITY_STR, "community str");
index 29923424e33c46a8f4aa4df9700370110a4662fb..40802480381cafe2bf1d00cc780721d81c89180e 100644 (file)
@@ -61,6 +61,8 @@ DECLARE_MTYPE(AS_LIST);
 DECLARE_MTYPE(AS_FILTER);
 DECLARE_MTYPE(AS_FILTER_STR);
 
+DECLARE_MTYPE(COMMUNITY_ALIAS);
+
 DECLARE_MTYPE(COMMUNITY);
 DECLARE_MTYPE(COMMUNITY_VAL);
 DECLARE_MTYPE(COMMUNITY_STR);
index 62fed931f95950440428f4149ec1fef820b04bfa..eb68d84c069780532cb011406a4fa10bea692560 100644 (file)
@@ -540,6 +540,17 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
        if (bpi) {
                bool labelssame = labels_same(bpi, label, num_labels);
 
+               if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)
+                   && CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
+                       if (debug) {
+                               zlog_debug(
+                                       "%s: ->%s(s_flags: 0x%x b_flags: 0x%x): %pFX: Found route, being removed, not leaking",
+                                       __func__, bgp->name_pretty,
+                                       source_bpi->flags, bpi->flags, p);
+                       }
+                       return NULL;
+               }
+
                if (attrhash_cmp(bpi->attr, new_attr) && labelssame
                    && !CHECK_FLAG(bpi->flags, BGP_PATH_REMOVED)) {
 
@@ -613,6 +624,16 @@ leak_update(struct bgp *bgp, /* destination bgp instance */
                return bpi;
        }
 
+       if (CHECK_FLAG(source_bpi->flags, BGP_PATH_REMOVED)) {
+               if (debug) {
+                       zlog_debug(
+                               "%s: ->%s(s_flags: 0x%x): %pFX: New route, being removed, not leaking",
+                               __func__, bgp->name_pretty,
+                               source_bpi->flags, p);
+               }
+               return NULL;
+       }
+
        new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
                bgp->peer_self, new_attr, bn);
 
@@ -1027,6 +1048,8 @@ void vpn_leak_from_vrf_withdraw_all(struct bgp *bgp_vpn, /* to */
                                        if (debug)
                                                zlog_debug("%s: deleting it",
                                                           __func__);
+                                       /* withdraw from leak-to vrfs as well */
+                                       vpn_leak_to_vrf_withdraw(bgp_vpn, bpi);
                                        bgp_aggregate_decrement(
                                                bgp_vpn,
                                                bgp_dest_get_prefix(bn), bpi,
@@ -1101,7 +1124,10 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *bgp_vrf,           /* to */
        if (!ecom_intersect(
                    bgp_vrf->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
                    path_vpn->attr->ecommunity)) {
-
+               if (debug)
+                       zlog_debug(
+                               "from vpn to vrf %s, skipping after no intersection of route targets",
+                               bgp_vrf->name_pretty);
                return;
        }
 
@@ -1532,7 +1558,8 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
                                 bool is_config)
 {
        afi_t afi;
-       int debug;
+       int debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF)
+                    | BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
        char *vname;
        const char *export_name;
        char buf[RD_ADDRSTRLEN];
@@ -1541,14 +1568,23 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
        struct ecommunity *ecom;
        vpn_policy_direction_t idir, edir;
 
+       /*
+        * Router-id change that is not explicitly configured
+        * (a change from zebra, frr restart for example)
+        * should not replace a configured vpn RD/RT.
+        */
+       if (!is_config) {
+               if (debug)
+                       zlog_debug("%s: skipping non explicit router-id change",
+                                  __func__);
+               return;
+       }
+
        if (bgp->inst_type != BGP_INSTANCE_TYPE_DEFAULT
            && bgp->inst_type != BGP_INSTANCE_TYPE_VRF)
                return;
 
        export_name = bgp->name ? bgp->name : VRF_DEFAULT_NAME;
-       debug = (BGP_DEBUG(vpn, VPN_LEAK_TO_VRF) |
-                    BGP_DEBUG(vpn, VPN_LEAK_FROM_VRF));
-
        idir = BGP_VPN_POLICY_DIR_FROMVPN;
        edir = BGP_VPN_POLICY_DIR_TOVPN;
 
@@ -1574,26 +1610,12 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
                                if (!bgp_import)
                                        continue;
 
-                               ecommunity_del_val(bgp_import->vpn_policy[afi].
-                                                  rtlist[idir],
+                               ecommunity_del_val(
+                                       bgp_import->vpn_policy[afi]
+                                               .rtlist[idir],
                                        (struct ecommunity_val *)ecom->val);
-
                        }
                } else {
-                       /*
-                        * Router-id changes that are not explicit config
-                        * changes should not replace configured RD/RT.
-                        */
-                       if (!is_config) {
-                               if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
-                                              BGP_VPN_POLICY_TOVPN_RD_SET)) {
-                                       if (debug)
-                                               zlog_debug("%s: auto router-id change skipped",
-                                                          __func__);
-                                       goto postchange;
-                               }
-                       }
-
                        /* New router-id derive auto RD and RT and export
                         * to VPN
                         */
@@ -1624,10 +1646,8 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
                                else
                                        bgp_import->vpn_policy[afi].rtlist[idir]
                                                = ecommunity_dup(ecom);
-
                        }
 
-postchange:
                        /* Update routes to VPN */
                        vpn_leak_postchange(BGP_VPN_POLICY_DIR_TOVPN,
                                            afi, bgp_get_default(),
index 6f75856d543144bfec4438e341914d6dce23823b..7a2f618ce67df31cc6f9a5d643f689342c0b98da 100644 (file)
@@ -32,7 +32,7 @@
 #include "filter.h"
 #include "hook.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_route.h"
index 2547439499a2127c148f15e778ad3235187ab143..21810b634d4d4050092c99bd2306ec62d9df60bc 100644 (file)
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "northbound.h"
 #include "libfrr.h"
 #include "bgpd/bgp_nb.h"
index 5a88bd08d969a724ef7eed628214c602f9a29653..ff2c8ce93e7519a5637ee73884dd95620357ee89 100644 (file)
@@ -18,6 +18,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "northbound.h"
 #include "libfrr.h"
 #include "log.h"
@@ -105,16 +107,22 @@ int bgp_router_create(struct nb_cb_create_args *args)
 
                if (inst_type == BGP_INSTANCE_TYPE_DEFAULT)
                        is_new_bgp = (bgp_lookup(as, name) == NULL);
+               else
+                       is_new_bgp = (bgp_lookup_by_name(name) == NULL);
 
                ret = bgp_get_vty(&bgp, &as, name, inst_type);
-               if (ret == BGP_ERR_INSTANCE_MISMATCH) {
-                       snprintf(
-                               args->errmsg, args->errmsg_len,
-                               "BGP instance name and AS number mismatch\nBGP instance is already running; AS is %u, input-as %u",
-                               bgp->as, as);
-
+               switch (ret) {
+               case BGP_ERR_AS_MISMATCH:
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "BGP instance is already running; AS is %u",
+                                as);
+                       return NB_ERR_INCONSISTENCY;
+               case BGP_ERR_INSTANCE_MISMATCH:
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "BGP instance type mismatch");
                        return NB_ERR_INCONSISTENCY;
                }
+
                /*
                 * If we just instantiated the default instance, complete
                 * any pending VRF-VPN leaking that was configured via
@@ -123,7 +131,12 @@ int bgp_router_create(struct nb_cb_create_args *args)
                if (is_new_bgp && inst_type == BGP_INSTANCE_TYPE_DEFAULT)
                        vpn_leak_postchange_all();
 
-               if (inst_type == BGP_INSTANCE_TYPE_VRF)
+               /*
+                * Check if we need to export to other VRF(s).
+                * Leak the routes to importing bgp vrf instances,
+                * only when new bgp vrf instance is configured.
+                */
+               if (is_new_bgp)
                        bgp_vpn_leak_export(bgp);
 
                UNSET_FLAG(bgp->vrf_flags, BGP_VRF_AUTO);
@@ -239,15 +252,17 @@ int bgp_global_local_as_modify(struct nb_cb_modify_args *args)
                        inst_type = BGP_INSTANCE_TYPE_VIEW;
 
                ret = bgp_lookup_by_as_name_type(&bgp, &as, name, inst_type);
-               if (ret == BGP_ERR_INSTANCE_MISMATCH) {
-                       snprintf(
-                               args->errmsg, args->errmsg_len,
-                               "BGP instance name and AS number mismatch\nBGP instance is already running; input-as %u",
-                               as);
-
+               switch (ret) {
+               case BGP_ERR_AS_MISMATCH:
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "BGP instance is already running; AS is %u",
+                                as);
+                       return NB_ERR_VALIDATION;
+               case BGP_ERR_INSTANCE_MISMATCH:
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "BGP instance type mismatch");
                        return NB_ERR_VALIDATION;
                }
-
                break;
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
index 4821ce8ddbf4000fe04bebba50a86c152e683a5a..f3857162c37c042ee782377b45ac5caf0557832d 100644 (file)
@@ -376,7 +376,6 @@ static int bgp_accept(struct thread *thread)
                             accept_sock);
                return -1;
        }
-       listener->thread = NULL;
 
        thread_add_read(bm->master, bgp_accept, listener, accept_sock,
                        &listener->thread);
@@ -443,6 +442,11 @@ static int bgp_accept(struct thread *thread)
                if (peer1) {
                        /* Dynamic neighbor has been created, let it proceed */
                        peer1->fd = bgp_sock;
+
+                       /* Set the user configured MSS to TCP socket */
+                       if (CHECK_FLAG(peer1->flags, PEER_FLAG_TCP_MSS))
+                               sockopt_tcp_mss_set(bgp_sock, peer1->tcp_mss);
+
                        bgp_fsm_change_status(peer1, Active);
                        BGP_TIMER_OFF(
                                peer1->t_start); /* created in peer_create() */
@@ -569,6 +573,7 @@ static int bgp_accept(struct thread *thread)
        peer1->doppelganger = peer;
        peer->fd = bgp_sock;
        vrf_bind(peer->bgp->vrf_id, bgp_sock, bgp_get_bound_name(peer));
+       bgp_peer_reg_with_nht(peer);
        bgp_fsm_change_status(peer, Active);
        BGP_TIMER_OFF(peer->t_start); /* created in peer_create() */
 
@@ -713,6 +718,10 @@ int bgp_connect(struct peer *peer)
 
        set_nonblocking(peer->fd);
 
+       /* Set the user configured MSS to TCP socket */
+       if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS))
+               sockopt_tcp_mss_set(peer->fd, peer->tcp_mss);
+
        bgp_socket_set_buffer_size(peer->fd);
 
        if (bgp_set_socket_ttl(peer, peer->fd) < 0)
@@ -837,7 +846,6 @@ static int bgp_listener(int sock, struct sockaddr *sa, socklen_t salen,
                listener->bgp = bgp;
 
        memcpy(&listener->su, sa, salen);
-       listener->thread = NULL;
        thread_add_read(bm->master, bgp_accept, listener, sock,
                        &listener->thread);
        listnode_add(bm->listen_sockets, listener);
index 9c8d7878c513ac2bca0105b44f0672873d13a7c4..dc2b0b679b1a529d512853eb429114d44c719884 100644 (file)
@@ -60,13 +60,15 @@ static int bgp_nht_ifp_initial(struct thread *thread);
 static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
 {
        return (bgp_zebra_num_connects() == 0
-               || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)));
+               || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_VALID)
+                   && bnc->nexthop_num > 0));
 }
 
 static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc)
 {
        return (bgp_zebra_num_connects() == 0
-               || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)));
+               || (bnc && CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
+                   && bnc->nexthop_num > 0));
 }
 
 static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
@@ -98,6 +100,31 @@ void bgp_unlink_nexthop(struct bgp_path_info *path)
        bgp_unlink_nexthop_check(bnc);
 }
 
+void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to)
+{
+       struct prefix pp;
+       struct prefix pt;
+       struct bgp_nexthop_cache *bncp, *bnct;
+       afi_t afi;
+
+       if (!sockunion2hostprefix(&from->su, &pp))
+               return;
+
+       afi = family2afi(pp.family);
+       bncp = bnc_find(&from->bgp->nexthop_cache_table[afi], &pp, 0);
+
+       if (!sockunion2hostprefix(&to->su, &pt))
+               return;
+
+       bnct = bnc_find(&to->bgp->nexthop_cache_table[afi], &pt, 0);
+
+       if (bnct != bncp)
+               return;
+
+       if (bnct)
+               bnct->nht_info = to;
+}
+
 void bgp_unlink_nexthop_by_peer(struct peer *peer)
 {
        struct prefix p;
@@ -273,8 +300,16 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
                        (bgp_path_info_extra_get(pi))->igpmetric = bnc->metric;
                else if (pi->extra)
                        pi->extra->igpmetric = 0;
-       } else if (peer)
-               bnc->nht_info = (void *)peer; /* NHT peer reference */
+       } else if (peer) {
+               /*
+                * Let's not accidently save the peer data for a peer
+                * we are going to throw away in a second or so.
+                * When we come back around we'll fix up this
+                * data properly in replace_nexthop_by_peer
+                */
+               if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
+                       bnc->nht_info = (void *)peer; /* NHT peer reference */
+       }
 
        /*
         * We are cheating here.  Views have no associated underlying
@@ -444,6 +479,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
                bnc->nexthop = nhlist_head;
        } else {
                bnc->flags &= ~BGP_NEXTHOP_VALID;
+               bnc->flags &= ~BGP_NEXTHOP_LABELED_VALID;
                bnc->nexthop_num = nhr->nexthop_num;
 
                /* notify bgp fsm if nbr ip goes from valid->invalid */
index a1683e15114edb8a7da51da2157d5549e26c2e3a..9268b225ca02888cb3eb95c9aa0bbd21883685b0 100644 (file)
@@ -51,7 +51,7 @@ extern int bgp_find_or_add_nexthop(struct bgp *bgp_route,
  */
 extern void bgp_unlink_nexthop(struct bgp_path_info *p);
 void bgp_unlink_nexthop_by_peer(struct peer *peer);
-
+void bgp_replace_nexthop_by_peer(struct peer *from, struct peer *to);
 /**
  * bgp_delete_connected_nexthop() - Reset the 'peer' pointer for a connected
  * nexthop entry. If no paths reference the nexthop, it will be unregistered
index 76426402184925a2e0f36e8c773f31bbe547ea95..94d905127dec84870c67710f816ebac00f41c0f8 100644 (file)
@@ -1122,7 +1122,7 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
 {
        int ret = 0;
        uint8_t *error;
-       uint8_t error_data[BGP_MAX_PACKET_SIZE];
+       uint8_t error_data[BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE];
        struct stream *s = BGP_INPUT(peer);
        size_t end = stream_get_getp(s) + length;
 
@@ -1217,8 +1217,8 @@ int bgp_open_option_parse(struct peer *peer, uint8_t length, int *mp_capability)
        /* Extended Message Support */
        peer->max_packet_size =
                CHECK_FLAG(peer->cap, PEER_CAP_EXTENDED_MESSAGE_RCV)
-                       ? BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE
-                       : BGP_MAX_PACKET_SIZE;
+                       ? BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE
+                       : BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE;
 
        /* Check there are no common AFI/SAFIs and send Unsupported Capability
           error. */
index 24df324633854ec2e9a32575fee5029f35c1e0db..62982881d8011a5876c27e8a7ad17466ee96081f 100644 (file)
@@ -545,7 +545,7 @@ void bgp_keepalive_send(struct peer *peer)
 {
        struct stream *s;
 
-       s = stream_new(BGP_MAX_PACKET_SIZE);
+       s = stream_new(BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE);
 
        /* Make keepalive packet. */
        bgp_packet_set_marker(s, BGP_MSG_KEEPALIVE);
@@ -586,7 +586,7 @@ void bgp_open_send(struct peer *peer)
        else
                local_as = peer->local_as;
 
-       s = stream_new(BGP_MAX_PACKET_SIZE);
+       s = stream_new(BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE);
 
        /* Make open packet. */
        bgp_packet_set_marker(s, BGP_MSG_OPEN);
@@ -752,7 +752,7 @@ void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
         */
        if (peer->curr) {
                size_t packetsize = stream_get_endp(peer->curr);
-               assert(packetsize <= sizeof(peer->last_reset_cause));
+               assert(packetsize <= peer->max_packet_size);
                memcpy(peer->last_reset_cause, peer->curr->data, packetsize);
                peer->last_reset_cause_size = packetsize;
        }
@@ -1000,98 +1000,90 @@ static int bgp_collision_detect(struct peer *new, struct in_addr remote_id)
 {
        struct peer *peer;
 
-       /* Upon receipt of an OPEN message, the local system must examine
-          all of its connections that are in the OpenConfirm state.  A BGP
-          speaker may also examine connections in an OpenSent state if it
-          knows the BGP Identifier of the peer by means outside of the
-          protocol.  If among these connections there is a connection to a
-          remote BGP speaker whose BGP Identifier equals the one in the
-          OPEN message, then the local system performs the following
-          collision resolution procedure: */
-
-       if ((peer = new->doppelganger) != NULL) {
-               /* Do not accept the new connection in Established or Clearing
-                * states.
-                * Note that a peer GR is handled by closing the existing
-                * connection
-                * upon receipt of new one.
+       /*
+        * Upon receipt of an OPEN message, the local system must examine
+        * all of its connections that are in the OpenConfirm state.  A BGP
+        * speaker may also examine connections in an OpenSent state if it
+        * knows the BGP Identifier of the peer by means outside of the
+        * protocol.  If among these connections there is a connection to a
+        * remote BGP speaker whose BGP Identifier equals the one in the
+        * OPEN message, then the local system performs the following
+        * collision resolution procedure:
+        */
+       peer = new->doppelganger;
+       if (peer == NULL)
+               return 0;
+
+       /*
+        * Do not accept the new connection in Established or Clearing
+        * states. Note that a peer GR is handled by closing the existing
+        * connection upon receipt of new one.
+        */
+       if (peer->status == Established || peer->status == Clearing) {
+               bgp_notify_send(new, BGP_NOTIFY_CEASE,
+                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+               return -1;
+       }
+
+       if ((peer->status != OpenConfirm) && (peer->status != OpenSent))
+               return 0;
+
+       /*
+        * 1. The BGP Identifier of the local system is
+        * compared to the BGP Identifier of the remote
+        * system (as specified in the OPEN message).
+        *
+        * If the BGP Identifiers of the peers
+        * involved in the connection collision
+        * are identical, then the connection
+        * initiated by the BGP speaker with the
+        * larger AS number is preserved.
+        */
+       if (ntohl(peer->local_id.s_addr) < ntohl(remote_id.s_addr)
+           || (ntohl(peer->local_id.s_addr) == ntohl(remote_id.s_addr)
+               && peer->local_as < peer->as))
+               if (!CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) {
+                       /*
+                        * 2. If the value of the local BGP
+                        * Identifier is less than the remote one,
+                        * the local system closes BGP connection
+                        * that already exists (the one that is
+                        * already in the OpenConfirm state),
+                        * and accepts BGP connection initiated by
+                        * the remote system.
+                        */
+                       bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+                                       BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                       return 1;
+               } else {
+                       bgp_notify_send(new, BGP_NOTIFY_CEASE,
+                                       BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                       return -1;
+               }
+       else {
+               if (ntohl(peer->local_id.s_addr) == ntohl(remote_id.s_addr)
+                   && peer->local_as == peer->as)
+                       flog_err(EC_BGP_ROUTER_ID_SAME,
+                                "Peer's router-id %pI4 is the same as ours",
+                                &remote_id);
+
+               /*
+                * 3. Otherwise, the local system closes newly
+                * created BGP connection (the one associated with the
+                * newly received OPEN message), and continues to use
+                * the existing one (the one that is already in the
+                * OpenConfirm state).
                 */
-               if (peer->status == Established || peer->status == Clearing) {
+               if (CHECK_FLAG(peer->sflags, PEER_STATUS_ACCEPT_PEER)) {
+                       bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+                                       BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
+                       return 1;
+               } else {
                        bgp_notify_send(new, BGP_NOTIFY_CEASE,
                                        BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
                        return -1;
-               } else if ((peer->status == OpenConfirm)
-                          || (peer->status == OpenSent)) {
-                       /* 1. The BGP Identifier of the local system is
-                        * compared to the BGP Identifier of the remote
-                        * system (as specified in the OPEN message).
-                        *
-                        * If the BGP Identifiers of the peers
-                        * involved in the connection collision
-                        * are identical, then the connection
-                        * initiated by the BGP speaker with the
-                        * larger AS number is preserved.
-                        */
-                       if (ntohl(peer->local_id.s_addr)
-                                   < ntohl(remote_id.s_addr)
-                           || (ntohl(peer->local_id.s_addr)
-                                              == ntohl(remote_id.s_addr)
-                                      && peer->local_as < peer->as))
-                               if (!CHECK_FLAG(peer->sflags,
-                                               PEER_STATUS_ACCEPT_PEER)) {
-                                       /* 2. If the value of the local BGP
-                                          Identifier is less
-                                          than the remote one, the local system
-                                          closes BGP
-                                          connection that already exists (the
-                                          one that is
-                                          already in the OpenConfirm state),
-                                          and accepts BGP
-                                          connection initiated by the remote
-                                          system. */
-                                       bgp_notify_send(
-                                               peer, BGP_NOTIFY_CEASE,
-                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-                                       return 1;
-                               } else {
-                                       bgp_notify_send(
-                                               new, BGP_NOTIFY_CEASE,
-                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-                                       return -1;
-                               }
-                       else {
-                               if (ntohl(peer->local_id.s_addr)
-                                           == ntohl(remote_id.s_addr)
-                                   && peer->local_as == peer->as)
-                                       flog_err(
-                                               EC_BGP_ROUTER_ID_SAME,
-                                               "Peer's router-id %pI4 is the same as ours",
-                                               &remote_id);
-
-                               /* 3. Otherwise, the local system closes newly
-                                  created
-                                  BGP connection (the one associated with the
-                                  newly
-                                  received OPEN message), and continues to use
-                                  the
-                                  existing one (the one that is already in the
-                                  OpenConfirm state). */
-                               if (CHECK_FLAG(peer->sflags,
-                                              PEER_STATUS_ACCEPT_PEER)) {
-                                       bgp_notify_send(
-                                               peer, BGP_NOTIFY_CEASE,
-                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-                                       return 1;
-                               } else {
-                                       bgp_notify_send(
-                                               new, BGP_NOTIFY_CEASE,
-                                               BGP_NOTIFY_CEASE_COLLISION_RESOLUTION);
-                                       return -1;
-                               }
-                       }
                }
        }
-       return 0;
 }
 
 /* Packet processing routines ---------------------------------------------- */
@@ -1269,9 +1261,6 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
                return BGP_Stop;
        }
 
-       /* Set remote router-id */
-       peer->remote_id = remote_id;
-
        /* Peer BGP version check. */
        if (version != BGP_VERSION_4) {
                uint16_t maxver = htons(BGP_VERSION_4);
@@ -1331,6 +1320,25 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
                return BGP_Stop;
        }
 
+       /*
+        * When collision is detected and this peer is closed.
+        * Return immediately.
+        */
+       ret = bgp_collision_detect(peer, remote_id);
+       if (ret < 0)
+               return BGP_Stop;
+
+       /* Get sockname. */
+       if (bgp_getsockname(peer) < 0) {
+               flog_err_sys(EC_LIB_SOCKET,
+                            "%s: bgp_getsockname() failed for peer: %s",
+                            __func__, peer->host);
+               return BGP_Stop;
+       }
+
+       /* Set remote router-id */
+       peer->remote_id = remote_id;
+
        /* From the rfc: Upon receipt of an OPEN message, a BGP speaker MUST
           calculate the value of the Hold Timer by using the smaller of its
           configured Hold Time and the Hold Time received in the OPEN message.
@@ -1411,21 +1419,6 @@ static int bgp_open_receive(struct peer *peer, bgp_size_t size)
                        peer->afc[AFI_IP6][SAFI_FLOWSPEC];
        }
 
-       /* When collision is detected and this peer is closed.
-        * Return immediately.
-        */
-       ret = bgp_collision_detect(peer, remote_id);
-       if (ret < 0)
-               return BGP_Stop;
-
-       /* Get sockname. */
-       if (bgp_getsockname(peer) < 0) {
-               flog_err_sys(EC_LIB_SOCKET,
-                            "%s: bgp_getsockname() failed for peer: %s",
-                            __func__, peer->host);
-               return BGP_Stop;
-       }
-
        /* Verify valid local address present based on negotiated
         * address-families. */
        if (peer->afc_nego[AFI_IP][SAFI_UNICAST]
index 2c6c2c3861fadeff0642d676acd67803d619d4f3..01443c778fc6e365a0d93f16cc04bf415ed43cfa 100644 (file)
@@ -2034,6 +2034,9 @@ static void bgp_pbr_icmp_action(struct bgp *bgp, struct bgp_path_info *path,
                return;
        if (bpf->protocol != IPPROTO_ICMP)
                return;
+
+       memset(&srcp, 0, sizeof(srcp));
+       memset(&dstp, 0, sizeof(dstp));
        bpf->src_port = &srcp;
        bpf->dst_port = &dstp;
        /* parse icmp type and lookup appropriate icmp code
@@ -2684,6 +2687,7 @@ static void bgp_pbr_handle_entry(struct bgp *bgp, struct bgp_path_info *path,
        struct bgp_pbr_or_filter bpof;
        struct bgp_pbr_val_mask bpvm;
 
+       memset(&range, 0, sizeof(range));
        memset(&nh, 0, sizeof(struct nexthop));
        memset(&bpf, 0, sizeof(struct bgp_pbr_filter));
        memset(&bpof, 0, sizeof(struct bgp_pbr_or_filter));
index 1c2ad7fc73b9c41d962f135572695311ce6d4f26..77a0b5fea7f103486ea381336b8f13735771e325 100644 (file)
@@ -51,6 +51,7 @@
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_regex.h"
 #include "bgpd/bgp_community.h"
+#include "bgpd/bgp_community_alias.h"
 #include "bgpd/bgp_ecommunity.h"
 #include "bgpd/bgp_lcommunity.h"
 #include "bgpd/bgp_clist.h"
@@ -8342,8 +8343,11 @@ bgp_path_selection_reason2str(enum bgp_path_selection_reason reason)
 /* Print the short form route status for a bgp_path_info */
 static void route_vty_short_status_out(struct vty *vty,
                                       struct bgp_path_info *path,
+                                      const struct prefix *p,
                                       json_object *json_path)
 {
+       enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
+
        if (json_path) {
 
                /* Route status display. */
@@ -8389,6 +8393,17 @@ static void route_vty_short_status_out(struct vty *vty,
                return;
        }
 
+       /* RPKI validation state */
+       rpki_state =
+               hook_call(bgp_rpki_prefix_status, path->peer, path->attr, p);
+
+       if (rpki_state == RPKI_VALID)
+               vty_out(vty, "V");
+       else if (rpki_state == RPKI_INVALID)
+               vty_out(vty, "I");
+       else if (rpki_state == RPKI_NOTFOUND)
+               vty_out(vty, "N");
+
        /* Route status display. */
        if (CHECK_FLAG(path->flags, BGP_PATH_REMOVED))
                vty_out(vty, "R");
@@ -8457,7 +8472,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
                json_path = json_object_new_object();
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json_path);
+       route_vty_short_status_out(vty, path, p, json_path);
 
        if (!json_paths) {
                /* print prefix and mask */
@@ -9103,7 +9118,7 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
                json_out = json_object_new_object();
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json_out);
+       route_vty_short_status_out(vty, path, p, json_out);
 
        /* print prefix and mask */
        if (json == NULL) {
@@ -9206,7 +9221,7 @@ void route_vty_out_overlay(struct vty *vty, const struct prefix *p,
        }
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json_path);
+       route_vty_short_status_out(vty, path, p, json_path);
 
        /* print prefix and mask */
        if (!display)
@@ -9310,7 +9325,7 @@ static void damp_route_vty_out(struct vty *vty, const struct prefix *p,
        char timebuf[BGP_UPTIME_LEN];
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json);
+       route_vty_short_status_out(vty, path, p, json);
 
        /* print prefix and mask */
        if (!use_json) {
@@ -9381,7 +9396,7 @@ static void flap_route_vty_out(struct vty *vty, const struct prefix *p,
        bdi = path->extra->damp_info;
 
        /* short status lead text */
-       route_vty_short_status_out(vty, path, json);
+       route_vty_short_status_out(vty, path, p, json);
 
        /* print prefix and mask */
        if (!use_json) {
@@ -10246,7 +10261,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
                vty_out(vty, "\n");
 
        /* Line 4 display Community */
-       if (attr->community) {
+       if (attr->flag & ATTR_FLAG_BIT(BGP_ATTR_COMMUNITIES)) {
                if (json_paths) {
                        if (!attr->community->json)
                                community_str(attr->community, true);
@@ -10803,6 +10818,7 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                                vty_out(vty, BGP_SHOW_SCODE_HEADER);
                                vty_out(vty, BGP_SHOW_NCODE_HEADER);
                                vty_out(vty, BGP_SHOW_OCODE_HEADER);
+                               vty_out(vty, BGP_SHOW_RPKI_HEADER);
                                if (type == bgp_show_type_dampend_paths
                                    || type == bgp_show_type_damp_neighbor)
                                        vty_out(vty, BGP_SHOW_DAMP_HEADER);
@@ -10830,9 +10846,17 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
                                flap_route_vty_out(vty, dest_p, pi, display,
                                                   AFI_IP, safi, use_json,
                                                   json_paths);
-                       else
-                               route_vty_out(vty, dest_p, pi, display, safi,
-                                             json_paths, wide);
+                       else {
+                               if (CHECK_FLAG(show_flags, BGP_SHOW_OPT_DETAIL))
+                                       route_vty_out_detail(
+                                               vty, bgp, dest, pi,
+                                               family2afi(dest_p->family),
+                                               safi, RPKI_NOT_BEING_USED,
+                                               json_paths);
+                               else
+                                       route_vty_out(vty, dest_p, pi, display,
+                                                     safi, json_paths, wide);
+                       }
                        display++;
                }
 
@@ -11597,13 +11621,13 @@ DEFUN (show_ip_bgp_large_community_list,
        struct bgp *bgp = NULL;
        bool uj = use_json(argc, argv);
 
-        if (uj)
-                argc--;
+       if (uj)
+               argc--;
 
-        bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
-                                            &bgp, uj);
-        if (!idx)
-                return CMD_WARNING;
+       bgp_vty_find_and_parse_afi_safi_bgp(vty, argv, argc, &idx, &afi, &safi,
+                                           &bgp, uj);
+       if (!idx)
+               return CMD_WARNING;
 
        argv_find(argv, argc, "large-community-list", &idx);
 
@@ -11905,7 +11929,7 @@ DEFPY (show_ip_bgp_json,
                      |route-filter-translated-v4] [exact-match]\
           |rpki <invalid|valid|notfound>\
           |version (1-4294967295)\
-          ] [json$uj | wide$wide]",
+          ] [json$uj [detail$detail] | wide$wide]",
        SHOW_STR
        IP_STR
        BGP_STR
@@ -11941,6 +11965,7 @@ DEFPY (show_ip_bgp_json,
        "Display prefixes with matching version numbers\n"
        "Version number and above\n"
        JSON_STR
+       "Display detailed version of JSON output\n"
        "Increase table width for longer prefixes\n")
 {
        afi_t afi = AFI_IP6;
@@ -11960,6 +11985,9 @@ DEFPY (show_ip_bgp_json,
                SET_FLAG(show_flags, BGP_SHOW_OPT_JSON);
        }
 
+       if (detail)
+               SET_FLAG(show_flags, BGP_SHOW_OPT_DETAIL);
+
        /* [<ipv4|ipv6> [all]] */
        if (all) {
                SET_FLAG(show_flags, BGP_SHOW_OPT_AFI_ALL);
@@ -13179,6 +13207,7 @@ static void show_adj_route_header(struct vty *vty, struct bgp *bgp,
                        vty_out(vty, BGP_SHOW_SCODE_HEADER);
                        vty_out(vty, BGP_SHOW_NCODE_HEADER);
                        vty_out(vty, BGP_SHOW_OCODE_HEADER);
+                       vty_out(vty, BGP_SHOW_RPKI_HEADER);
                }
                *header1 = 0;
        }
@@ -13265,6 +13294,7 @@ show_adj_route(struct vty *vty, struct peer *peer, struct bgp_table *table,
                        vty_out(vty, BGP_SHOW_SCODE_HEADER);
                        vty_out(vty, BGP_SHOW_NCODE_HEADER);
                        vty_out(vty, BGP_SHOW_OCODE_HEADER);
+                       vty_out(vty, BGP_SHOW_RPKI_HEADER);
 
                        vty_out(vty, "Originating default network %s\n\n",
                                (afi == AFI_IP) ? "0.0.0.0/0" : "::/0");
index 1bf5dcf186cb7dcabc2acbf8e32fad623fb2fd1e..e58213a6881b812121db1243ba6ae10d9187781d 100644 (file)
@@ -73,8 +73,11 @@ enum bgp_show_adj_route_type {
        "Status codes:  s suppressed, d damped, "                              \
        "h history, * 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\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"
 
@@ -586,6 +589,7 @@ DECLARE_HOOK(bgp_process,
 #define BGP_SHOW_OPT_AFI_IP6 (1 << 4)
 #define BGP_SHOW_OPT_ESTABLISHED (1 << 5)
 #define BGP_SHOW_OPT_FAILED (1 << 6)
+#define BGP_SHOW_OPT_DETAIL (1 << 7)
 
 /* Prototypes. */
 extern void bgp_rib_remove(struct bgp_dest *dest, struct bgp_path_info *pi,
index fc591221846c0c78db9a6942701dddbd19bc3fa2..b165c5d0eebf13a9f34e068d8a26d357b79f4c05 100644 (file)
@@ -18,6 +18,8 @@
  */
 
 
+#include <zebra.h>
+
 #include "lib/command.h"
 #include "lib/log.h"
 #include "lib/northbound.h"
index ec6284273e8e23eebc06831d353c5dd03d73a9a9..ff08c16a829231dfab0ec75201c1a3317253c6ec 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "lib/command.h"
 #include "lib/log.h"
 #include "lib/northbound.h"
index bb85ad393dbeee94faaea7816ca91dfb89680386..816ed88eecd01b99808d7e2bb7ddda05c48f88ae 100644 (file)
@@ -57,7 +57,7 @@
 #endif
 #include "hook.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #ifndef VTYSH_EXTRACT_PL
 #include "bgpd/bgp_rpki_clippy.c"
index 3afdbea908ba61a6534eb729844e616088796302..61a6467ab647ef68a45ba0d817eed0c86b237a06 100644 (file)
@@ -32,7 +32,7 @@
 #include "filter.h"
 #include "hook.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #include "bgpd/bgpd.h"
 #include "bgpd/bgp_table.h"
index 2ebc63b6b501bc1b35f0eba9fd048ce6a8c95acb..02afbeb46feac606c7be3726ad03f6ad464c80d1 100644 (file)
@@ -1,4 +1,6 @@
 #define TRACEPOINT_CREATE_PROBES
 #define TRACEPOINT_DEFINE
 
+#include <zebra.h>
+
 #include "bgp_trace.h"
index 1e465d2620f91f1dc20795db56c541843b6cd341..36aa3e1a3e9ff1cacf8724f4af70256695f4e0e4 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "command.h"
 #include "lib/json.h"
+#include "lib/sockopt.h"
 #include "lib_errors.h"
 #include "lib/zclient.h"
 #include "lib/printfrr.h"
@@ -45,6 +46,7 @@
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_aspath.h"
 #include "bgpd/bgp_community.h"
+#include "bgpd/bgp_community_alias.h"
 #include "bgpd/bgp_ecommunity.h"
 #include "bgpd/bgp_lcommunity.h"
 #include "bgpd/bgp_damp.h"
@@ -130,10 +132,6 @@ DEFINE_HOOK(bgp_inst_config_write,
                (bgp, vty));
 DEFINE_HOOK(bgp_snmp_update_last_changed, (struct bgp *bgp), (bgp));
 
-#define GR_NO_OPER                                                             \
-       "The Graceful Restart No Operation was executed as cmd same as previous one."
-#define GR_INVALID                                                             \
-       "The Graceful Restart command used is not valid at this moment."
 static struct peer_group *listen_range_exists(struct bgp *bgp,
                                              struct prefix *range, int exact);
 
@@ -748,9 +746,6 @@ int bgp_nb_errmsg_return(char *errmsg, size_t errmsg_len, int ret)
        case BGP_ERR_GR_OPERATION_FAILED:
                str = "The Graceful Restart Operation failed due to an err.";
                break;
-       case BGP_GR_NO_OPERATION:
-               str = GR_NO_OPER;
-               break;
        case BGP_ERR_PEER_GROUP_MEMBER:
                str = "Peer-group member cannot override remote-as of peer-group";
                break;
@@ -840,9 +835,6 @@ int bgp_vty_return(struct vty *vty, int ret)
        case BGP_ERR_GR_OPERATION_FAILED:
                str = "The Graceful Restart Operation failed due to an err.";
                break;
-       case BGP_GR_NO_OPERATION:
-               str = GR_NO_OPER;
-               break;
        }
        if (str) {
                vty_out(vty, "%% %s\n", str);
@@ -1499,6 +1491,62 @@ void cli_show_router_bgp_router_id(struct vty *vty, struct lyd_node *dnode,
        vty_out(vty, " bgp router-id %s\n", yang_dnode_get_string(dnode, NULL));
 }
 
+DEFPY(bgp_community_alias, bgp_community_alias_cmd,
+      "[no$no] bgp community alias WORD$community WORD$alias",
+      NO_STR BGP_STR
+      "Add community specific parameters\n"
+      "Create an alias for a community\n"
+      "Community (AA:BB or AA:BB:CC)\n"
+      "Alias name\n")
+{
+       struct community_alias ca1;
+       struct community_alias ca2;
+       struct community_alias *lookup_community;
+       struct community_alias *lookup_alias;
+
+       if (!community_str2com(community) && !lcommunity_str2com(community)) {
+               vty_out(vty, "Invalid community format\n");
+               return CMD_WARNING;
+       }
+
+       memset(&ca1, 0, sizeof(ca1));
+       memset(&ca2, 0, sizeof(ca2));
+       strlcpy(ca1.community, community, sizeof(ca1.community));
+       strlcpy(ca1.alias, alias, sizeof(ca1.alias));
+
+       lookup_community = bgp_ca_community_lookup(&ca1);
+       lookup_alias = bgp_ca_alias_lookup(&ca1);
+
+       if (no) {
+               bgp_ca_alias_delete(&ca1);
+               bgp_ca_community_delete(&ca1);
+       } else {
+               if (lookup_alias) {
+                       /* Lookup if community hash table has an item
+                        * with the same alias name.
+                        */
+                       strlcpy(ca2.community, lookup_alias->community,
+                               sizeof(ca2.community));
+                       if (bgp_ca_community_lookup(&ca2)) {
+                               vty_out(vty,
+                                       "community (%s) already has this alias (%s)\n",
+                                       lookup_alias->community,
+                                       lookup_alias->alias);
+                               return CMD_WARNING;
+                       }
+                       bgp_ca_alias_delete(&ca1);
+               }
+
+               if (lookup_community)
+                       bgp_ca_community_delete(&ca1);
+
+               bgp_ca_alias_insert(&ca1);
+               bgp_ca_community_insert(&ca1);
+       }
+
+       return CMD_SUCCESS;
+}
+
 DEFPY (bgp_global_suppress_fib_pending,
        bgp_global_suppress_fib_pending_cmd,
        "[no] bgp suppress-fib-pending",
@@ -12597,6 +12645,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
        uint8_t *msg;
        json_object *json_neigh = NULL;
        time_t epoch_tbuf;
+       uint32_t sync_tcp_mss;
 
        bgp = p->bgp;
 
@@ -12858,6 +12907,15 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
                                            p->v_delayopen * 1000);
                }
 
+               /* Configured and Synced tcp-mss value for peer */
+               if (CHECK_FLAG(p->flags, PEER_FLAG_TCP_MSS)) {
+                       sync_tcp_mss = sockopt_tcp_mss_get(p->fd);
+                       json_object_int_add(json_neigh, "bgpTcpMssConfigured",
+                                           p->tcp_mss);
+                       json_object_int_add(json_neigh, "bgpTcpMssSynced",
+                                           sync_tcp_mss);
+               }
+
                if (CHECK_FLAG(p->flags, PEER_FLAG_TIMER)) {
                        json_object_int_add(json_neigh,
                                            "bgpTimerConfiguredHoldTimeMsecs",
@@ -12941,6 +12999,13 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
                        vty_out(vty,
                                "  Configured DelayOpenTime is %d seconds\n",
                                p->delayopen);
+
+               /* Configured and synced tcp-mss value for peer */
+               if (CHECK_FLAG(p->flags, PEER_FLAG_TCP_MSS)) {
+                       sync_tcp_mss = sockopt_tcp_mss_get(p->fd);
+                       vty_out(vty, "  Configured tcp-mss is %d", p->tcp_mss);
+                       vty_out(vty, ", synced tcp-mss is %d\n", sync_tcp_mss);
+               }
        }
        /* Capability. */
        if (p->status == Established) {
@@ -16360,6 +16425,55 @@ void cli_show_bgp_global_afi_safi_ip_unicast_redistribution_list(
        vty_out(vty, "\n");
 }
 
+/* Neighbor update tcp-mss. */
+static int peer_tcp_mss_vty(struct vty *vty, const char *peer_str,
+                           const char *tcp_mss_str)
+{
+       struct peer *peer;
+       uint32_t tcp_mss_val = 0;
+
+       peer = peer_and_group_lookup_vty(vty, peer_str);
+       if (!peer)
+               return CMD_WARNING_CONFIG_FAILED;
+
+       if (tcp_mss_str) {
+               tcp_mss_val = strtoul(tcp_mss_str, NULL, 10);
+               peer_tcp_mss_set(peer, tcp_mss_val);
+       } else {
+               peer_tcp_mss_unset(peer);
+       }
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(neighbor_tcp_mss, neighbor_tcp_mss_cmd,
+      "neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss (1-65535)",
+      NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+      "TCP max segment size\n"
+      "TCP MSS value\n")
+{
+       int peer_index = 1;
+       int mss_index = 3;
+
+       vty_out(vty,
+               " Warning: Reset BGP session for tcp-mss value to take effect\n");
+       return peer_tcp_mss_vty(vty, argv[peer_index]->arg,
+                               argv[mss_index]->arg);
+}
+
+DEFUN(no_neighbor_tcp_mss, no_neighbor_tcp_mss_cmd,
+      "no neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss [(1-65535)]",
+      NO_STR NEIGHBOR_STR NEIGHBOR_ADDR_STR2
+      "TCP max segment size\n"
+      "TCP MSS value\n")
+{
+       int peer_index = 2;
+
+       vty_out(vty,
+               " Warning: Reset BGP session for tcp-mss value to take effect\n");
+       return peer_tcp_mss_vty(vty, argv[peer_index]->arg, NULL);
+}
+
 static void bgp_config_write_redistribute(struct vty *vty, struct bgp *bgp,
                                          afi_t afi, safi_t safi)
 {
@@ -16809,6 +16923,10 @@ static void bgp_config_write_peer_global(struct vty *vty, struct bgp *bgp,
                vty_out(vty, " neighbor %s interface %s\n", addr, peer->ifname);
        }
 
+       /* TCP max segment size */
+       if (CHECK_FLAG(peer->flags, PEER_FLAG_TCP_MSS))
+               vty_out(vty, " neighbor %s tcp-mss %d\n", addr, peer->tcp_mss);
+
        /* passive */
        if (peergroup_flag_check(peer, PEER_FLAG_PASSIVE))
                vty_out(vty, " neighbor %s passive\n", addr);
@@ -17234,6 +17352,9 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
                                        : "");
                }
        }
+
+       if (peer_af_flag_check(peer, afi, safi, PEER_FLAG_CONFIG_DAMPENING))
+               bgp_config_write_peer_damp(vty, peer, afi, safi);
 }
 
 /* Address family based peer configuration display.  */
@@ -17287,23 +17408,11 @@ 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, 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 (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);
 
        for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
-               /* Skip dynamic neighbors. */
-               if (peer_dynamic_neighbor(peer))
-                       continue;
-
                /* Do not display doppelganger peers */
                if (CHECK_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE))
                        bgp_config_write_peer_af(vty, bgp, peer, afi, safi);
@@ -19202,6 +19311,8 @@ void bgp_vty_init(void)
        /* Community-list. */
        community_list_vty();
 
+       community_alias_vty();
+
        /* vpn-policy commands */
        install_element(BGP_IPV4_NODE, &af_rd_vpn_export_cmd);
        install_element(BGP_IPV6_NODE, &af_rd_vpn_export_cmd);
@@ -19229,6 +19340,10 @@ void bgp_vty_init(void)
        install_element(BGP_IPV6_NODE, &af_no_route_map_vpn_imexport_cmd);
        install_element(BGP_IPV4_NODE, &af_no_import_vrf_route_map_cmd);
        install_element(BGP_IPV6_NODE, &af_no_import_vrf_route_map_cmd);
+
+       /* tcp-mss command */
+       install_element(BGP_NODE, &neighbor_tcp_mss_cmd);
+       install_element(BGP_NODE, &no_neighbor_tcp_mss_cmd);
 }
 
 #include "memory.h"
@@ -20404,3 +20519,18 @@ static void community_list_vty(void)
        install_element(VIEW_NODE, &show_bgp_lcommunity_list_cmd);
        install_element(VIEW_NODE, &show_bgp_lcommunity_list_arg_cmd);
 }
+
+static struct cmd_node community_alias_node = {
+       .name = "community alias",
+       .node = COMMUNITY_ALIAS_NODE,
+       .prompt = "",
+       .config_write = bgp_community_alias_write,
+};
+
+void community_alias_vty(void)
+{
+       install_node(&community_alias_node);
+
+       /* Community-list.  */
+       install_element(CONFIG_NODE, &bgp_community_alias_cmd);
+}
index 251bdc3fe3a2e11375608833db23fed16a438eda..051b2e958010d9063fb9fd9621dacfff627d11ab 100644 (file)
@@ -154,6 +154,7 @@ struct bgp;
        } while (0)
 
 extern void bgp_vty_init(void);
+extern void community_alias_vty(void);
 extern const char *get_afi_safi_str(afi_t afi, safi_t safi, bool for_json);
 extern int bgp_get_vty(struct bgp **bgp, as_t *as, const char *name,
                       enum bgp_instance_type inst_type);
index d1912db01ffb5b5984c2bf5017c812d5810187bc..288c2851b37c43ec2dbb37991ec33bd8666f8a33 100644 (file)
@@ -1700,9 +1700,6 @@ int bgp_redistribute_set(struct bgp *bgp, afi_t afi, int type,
 
                redist_add_instance(&zclient->mi_redist[afi][type], instance);
        } else {
-               if (vrf_bitmap_check(zclient->redist[afi][type], bgp->vrf_id))
-                       return CMD_WARNING;
-
 #ifdef ENABLE_BGP_VNC
                if (EVPN_ENABLED(bgp) && type == ZEBRA_ROUTE_VNC_DIRECT) {
                        vnc_export_bgp_enable(
@@ -1978,7 +1975,7 @@ void bgp_zebra_instance_deregister(struct bgp *bgp)
 
 void bgp_zebra_initiate_radv(struct bgp *bgp, struct peer *peer)
 {
-       int ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL;
+       uint32_t ra_interval = BGP_UNNUM_DEFAULT_RA_INTERVAL;
 
        /* Don't try to initiate if we're not connected to Zebra */
        if (zclient->sock < 0)
index d37b9fa48c04782f7d6a9f04dd49d696965f6705..21abfeb001a1abe51ac0979c120c6d8ce200d9cc 100644 (file)
@@ -43,6 +43,7 @@
 #include "jhash.h"
 #include "table.h"
 #include "lib/json.h"
+#include "lib/sockopt.h"
 #include "frr_pthread.h"
 #include "bitfield.h"
 
@@ -54,6 +55,7 @@
 #include "bgpd/bgp_debug.h"
 #include "bgpd/bgp_errors.h"
 #include "bgpd/bgp_community.h"
+#include "bgpd/bgp_community_alias.h"
 #include "bgpd/bgp_conditional_adv.h"
 #include "bgpd/bgp_attr.h"
 #include "bgpd/bgp_regex.h"
@@ -1347,7 +1349,7 @@ struct peer *peer_new(struct bgp *bgp)
        peer->bgp = bgp_lock(bgp);
        peer = peer_lock(peer); /* initial reference */
        peer->password = NULL;
-       peer->max_packet_size = BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE;
+       peer->max_packet_size = BGP_MAX_PACKET_SIZE;
 
        /* Set default flags. */
        FOREACH_AFI_SAFI (afi, safi) {
@@ -1382,7 +1384,7 @@ struct peer *peer_new(struct bgp *bgp)
 
        /* We use a larger buffer for peer->obuf_work in the event that:
         * - We RX a BGP_UPDATE where the attributes alone are just
-        *   under BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE.
+        *   under BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE.
         * - The user configures an outbound route-map that does many as-path
         *   prepends or adds many communities. At most they can have
         *   CMD_ARGC_MAX args in a route-map so there is a finite limit on how
@@ -1392,12 +1394,12 @@ struct peer *peer_new(struct bgp *bgp)
         * bounds checking for every single attribute as we construct an
         * UPDATE.
         */
-       peer->obuf_work = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE
-                                    + BGP_MAX_PACKET_SIZE_OVERFLOW);
-       peer->ibuf_work = ringbuf_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE
-                                     * BGP_READ_PACKET_MAX);
+       peer->obuf_work =
+               stream_new(BGP_MAX_PACKET_SIZE + BGP_MAX_PACKET_SIZE_OVERFLOW);
+       peer->ibuf_work =
+               ringbuf_new(BGP_MAX_PACKET_SIZE * BGP_READ_PACKET_MAX);
 
-       peer->scratch = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
+       peer->scratch = stream_new(BGP_MAX_PACKET_SIZE);
 
        bgp_sync_init(peer);
 
@@ -1439,6 +1441,8 @@ void peer_xfer_config(struct peer *peer_dst, struct peer *peer_src)
 
        peer_dst->local_as = peer_src->local_as;
        peer_dst->port = peer_src->port;
+       /* copy tcp_mss value */
+       peer_dst->tcp_mss = peer_src->tcp_mss;
        (void)peer_sort(peer_dst);
        peer_dst->rmap_type = peer_src->rmap_type;
 
@@ -3376,7 +3380,7 @@ int bgp_lookup_by_as_name_type(struct bgp **bgp_val, as_t *as, const char *name,
        if (bgp) {
                if (bgp->as != *as) {
                        *as = bgp->as;
-                       return BGP_ERR_INSTANCE_MISMATCH;
+                       return BGP_ERR_AS_MISMATCH;
                }
                if (bgp->inst_type != inst_type)
                        return BGP_ERR_INSTANCE_MISMATCH;
@@ -3397,13 +3401,8 @@ int bgp_get(struct bgp **bgp_val, as_t *as, const char *name,
        int ret = 0;
 
        ret = bgp_lookup_by_as_name_type(bgp_val, as, name, inst_type);
-       switch (ret) {
-       case BGP_ERR_INSTANCE_MISMATCH:
+       if (ret || *bgp_val)
                return ret;
-       case BGP_SUCCESS:
-               if (*bgp_val)
-                       return ret;
-       }
 
        bgp = bgp_create(as, name, inst_type);
        if (bgp_option_check(BGP_OPT_NO_ZEBRA) && name)
@@ -5121,6 +5120,26 @@ void peer_port_unset(struct peer *peer)
        peer->port = BGP_PORT_DEFAULT;
 }
 
+/* Set the TCP-MSS value in the peer structure,
+ * This gets applied only after connection reset
+ * So this value will be used in bgp_connect.
+ */
+void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss)
+{
+       peer->tcp_mss = tcp_mss;
+       SET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
+}
+
+/* Reset the TCP-MSS value in the peer structure,
+ * This gets applied only after connection reset
+ * So this value will be used in bgp_connect.
+ */
+void peer_tcp_mss_unset(struct peer *peer)
+{
+       UNSET_FLAG(peer->flags, PEER_FLAG_TCP_MSS);
+       peer->tcp_mss = 0;
+}
+
 /*
  * Helper function that is called after the name of the policy
  * being used by a peer has changed (AF specific). Automatically
@@ -7679,6 +7698,7 @@ void bgp_init(unsigned short instance)
        /* BGP inits. */
        bgp_attr_init();
        bgp_debug_init();
+       bgp_community_alias_init();
        bgp_dump_init();
        bgp_route_init();
        bgp_route_map_init();
index 51134dc8c57f4086d5a5417ec183be453cba2389..38c6a70b8b780aa347184513a9acfd98569f65c9 100644 (file)
@@ -44,6 +44,7 @@
 #include "bgp_addpath_types.h"
 #include "bgp_nexthop.h"
 #include "bgp_damp.h"
+#include "bgp_io.h"
 
 #include "lib/bfd.h"
 
@@ -865,8 +866,9 @@ typedef enum {
 /* BGP message header and packet size.  */
 #define BGP_MARKER_SIZE                                16
 #define BGP_HEADER_SIZE                                19
-#define BGP_MAX_PACKET_SIZE                   4096
-#define BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE 65535
+#define BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE 4096
+#define BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE 65535
+#define BGP_MAX_PACKET_SIZE BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE
 #define BGP_MAX_PACKET_SIZE_OVERFLOW          1024
 
 /*
@@ -1047,6 +1049,9 @@ struct peer {
        struct stream_fifo *ibuf; // packets waiting to be processed
        struct stream_fifo *obuf; // packets waiting to be written
 
+       /* used as a block to deposit raw wire data to */
+       uint8_t ibuf_scratch[BGP_EXTENDED_MESSAGE_MAX_PACKET_SIZE
+                            * BGP_READ_PACKET_MAX];
        struct ringbuf *ibuf_work; // WiP buffer used by bgp_read() only
        struct stream *obuf_work;  // WiP buffer used to construct packets
 
@@ -1237,6 +1242,8 @@ struct peer {
 #define PEER_FLAG_GRACEFUL_RESTART          (1U << 24) /* Graceful Restart */
 #define PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT (1U << 25) /* Global-Inherit */
 #define PEER_FLAG_RTT_SHUTDOWN (1U << 26) /* shutdown rtt */
+#define PEER_FLAG_TIMER_DELAYOPEN (1U << 27) /* delayopen timer */
+#define PEER_FLAG_TCP_MSS (1U << 28)    /* tcp-mss */
 
        /*
         *GR-Disabled mode means unset PEER_FLAG_GRACEFUL_RESTART
@@ -1244,8 +1251,6 @@ struct peer {
         *and PEER_FLAG_GRACEFUL_RESTART_GLOBAL_INHERIT
         */
 
-#define PEER_FLAG_TIMER_DELAYOPEN (1 << 27) /* delayopen timer */
-
        struct bgp_peer_gr PEER_GR_FSM[BGP_PEER_GR_MODE][BGP_PEER_GR_EVENT_CMD];
        enum peer_mode peer_gr_present_state;
        /* Non stop forwarding afi-safi count for BGP gr feature*/
@@ -1602,6 +1607,9 @@ struct peer {
        bool advmap_config_change[AFI_MAX][SAFI_MAX];
        bool advmap_table_change;
 
+       /* set TCP max segment size */
+       uint32_t tcp_mss;
+
        QOBJ_FIELDS;
 };
 DECLARE_QOBJ_TYPE(peer);
@@ -2405,4 +2413,6 @@ DECLARE_HOOK(bgp_rpki_prefix_status,
 
 void peer_nsf_stop(struct peer *peer);
 
+void peer_tcp_mss_set(struct peer *peer, uint32_t tcp_mss);
+void peer_tcp_mss_unset(struct peer *peer);
 #endif /* _QUAGGA_BGPD_H */
index 9f6d33a855d8a52410479e280f5dfc69352daec3..1b5024a30b19b7a4dc0d373d76c2e5621d5d40f4 100644 (file)
@@ -6,7 +6,10 @@ if ENABLE_BGP_VNC
 noinst_PROGRAMS += bgpd/rfp-example/rfptest/rfptest
 endif
 
-bgpd_rfp_example_rfptest_rfptest_CFLAGS = -I$(top_srcdir)/bgpd/rfapi
+bgpd_rfp_example_rfptest_rfptest_CFLAGS = \
+       $(AM_CFLAGS) \
+       -I$(top_srcdir)/bgpd/rfapi \
+       # end
 bgpd_rfp_example_rfptest_rfptest_SOURCES = \
        bgpd/rfp-example/rfptest/rfptest.c \
        # end
index 07e71ba601207c3af03e3ccc5949a5ab20935231..b54c41cabee9b6f60877ce839f941088fbae267f 100644 (file)
@@ -57,6 +57,7 @@ bgpd_libbgp_a_SOURCES = \
        bgpd/bgp_bfd.c \
        bgpd/bgp_clist.c \
        bgpd/bgp_community.c \
+       bgpd/bgp_community_alias.c \
        bgpd/bgp_conditional_adv.c \
        bgpd/bgp_damp.c \
        bgpd/bgp_debug.c \
@@ -137,6 +138,7 @@ noinst_HEADERS += \
        bgpd/bgp_bfd.h \
        bgpd/bgp_clist.h \
        bgpd/bgp_community.h \
+       bgpd/bgp_community_alias.h \
        bgpd/bgp_conditional_adv.h \
        bgpd/bgp_damp.h \
        bgpd/bgp_debug.h \
@@ -211,20 +213,17 @@ noinst_HEADERS += \
 bgpd_bgpd_SOURCES = bgpd/bgp_main.c
 bgpd_bgp_btoa_SOURCES = bgpd/bgp_btoa.c
 
-bgpd_bgpd_CFLAGS = $(AM_CFLAGS)
-bgpd_bgp_btoa_CFLAGS = $(AM_CFLAGS)
-
 # RFPLDADD is set in bgpd/rfp-example/librfp/subdir.am
 bgpd_bgpd_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM) $(UST_LIBS)
 bgpd_bgp_btoa_LDADD = bgpd/libbgp.a $(RFPLDADD) lib/libfrr.la $(LIBCAP) $(LIBM) $(UST_LIBS)
 
 bgpd_bgpd_snmp_la_SOURCES = bgpd/bgp_snmp.c  bgpd/bgp_mplsvpn_snmp.c
-bgpd_bgpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+bgpd_bgpd_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 bgpd_bgpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 bgpd_bgpd_snmp_la_LIBADD = lib/libfrrsnmp.la
 
 bgpd_bgpd_rpki_la_SOURCES = bgpd/bgp_rpki.c
-bgpd_bgpd_rpki_la_CFLAGS = $(WERROR) $(RTRLIB_CFLAGS)
+bgpd_bgpd_rpki_la_CFLAGS = $(AM_CFLAGS) $(RTRLIB_CFLAGS)
 bgpd_bgpd_rpki_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 bgpd_bgpd_rpki_la_LIBADD = $(RTRLIB_LIBS)
 
diff --git a/bgpd/valgrind.supp b/bgpd/valgrind.supp
deleted file mode 100644 (file)
index 31f2477..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-{
-   <zlog_keep_working_at_exit>
-   Memcheck:Leak
-   match-leak-kinds: reachable
-   fun:calloc
-   fun:qcalloc
-   fun:zlog_target_clone
-}
-{
-   <libyang1_1.0.184>
-   Memcheck:Leak
-   match-leak-kinds: reachable
-   fun:calloc
-   fun:_dlerror_run
-   fun:dlopen@@GLIBC_2.2.5
-   obj:/usr/lib/x86_64-linux-gnu/libyang.so.1.9.2
-   fun:ly_load_plugins
-}
index c0b95d3dd0b6aa7e6f2ec1ef9fca8add8f26849f..212e7d1d45bda0e4dbb8b77cac2d3505ca5c3f29 100755 (executable)
@@ -4,4 +4,4 @@
 # and so that those used to the presence of bootstrap.sh or autogen.sh
 # will have an eaiser time.
 
-autoreconf -i
+exec autoreconf -is -Wall,no-override
old mode 100755 (executable)
new mode 100644 (file)
index f9516e5..c082a9e
@@ -5,7 +5,7 @@
 ##  Copyright (c) 1996, 97, 98, 99, 2000 Kunihiro Ishiguro <kunihiro@zebra.org>
 ##  Portions Copyright (c) 2003 Paul Jakma <paul@dishone.st>
 ##
-AC_PREREQ([2.60])
+AC_PREREQ([2.69])
 
 AC_INIT([frr], [7.7-dev], [https://github.com/frrouting/frr/issues])
 PACKAGE_URL="https://frrouting.org/"
@@ -18,6 +18,7 @@ AC_SUBST([CONFIG_ARGS])
 
 AC_CONFIG_SRCDIR([lib/zebra.h])
 AC_CONFIG_MACRO_DIR([m4])
+AC_CONFIG_AUX_DIR([m4/ac])
 
 dnl -----------------------------------
 dnl Get hostname and other information.
@@ -205,6 +206,7 @@ AC_SUBST([SED])
 dnl try and enable CFLAGS that are useful for FRR
 dnl - specifically, options to control warnings
 
+AC_SUBST([AC_CFLAGS])
 AC_USE_SYSTEM_EXTENSIONS
 AC_DEFUN([AC_C_FLAG], [{
     m4_pushdef([cachename],[m4_translit([frr_cv_$1],[ =-+/{}$],[________])])
@@ -223,7 +225,7 @@ AC_DEFUN([AC_C_FLAG], [{
        AC_LANG_POP([C])
     ])
     if test "$cachename" = "yes"; then
-       m4_if([$3], [], [CFLAGS="$CFLAGS $1"], [$3])
+       m4_if([$3], [], [AC_CFLAGS="$AC_CFLAGS $1"], [$3])
     else
        :
        $2
@@ -275,7 +277,7 @@ if test "$enable_gcov" = "yes"; then
       AC_C_FLAG([-O0])
    fi
 
-   LDFLAGS="${LDFLAGS} -lgcov"
+   AC_LDFLAGS="${AC_LDFLAGS} -lgcov"
 fi
 
 if test "$enable_clang_coverage" = "yes"; then
@@ -302,17 +304,19 @@ if test "$enable_scripting" = "yes"; then
    ])
 fi
 
+dnl the following flags go in CFLAGS rather than AC_CFLAGS since they make
+dnl sense to be overridden by the user
 if test "$enable_dev_build" = "yes"; then
    AC_DEFINE([DEV_BUILD], [1], [Build for development])
    if test "$orig_cflags" = ""; then
-      AC_C_FLAG([-g3])
-      AC_C_FLAG([-O0])
-      AC_C_FLAG([-ggdb3])
+      AC_C_FLAG([-O0],,[CFLAGS="$CFLAGS -O0"])
+      AC_C_FLAG([-g3],,[CFLAGS="$CFLAGS -g3"])
+      AC_C_FLAG([-ggdb3],,[CFLAGS="$CFLAGS -ggdb3"])
    fi
 else
    if test "$orig_cflags" = ""; then
-      AC_C_FLAG([-g])
-      AC_C_FLAG([-O2])
+      AC_C_FLAG([-g],,[CFLAGS="$CFLAGS -g"])
+      AC_C_FLAG([-O2],,[CFLAGS="$CFLAGS -O2"])
    fi
 fi
 
@@ -449,12 +453,15 @@ dnl ----------
 
 AX_PTHREAD([
   CC="$PTHREAD_CC"
-  CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+  AC_CFLAGS="$AC_CFLAGS $PTHREAD_CFLAGS"
   LIBS="$PTHREAD_LIBS $LIBS"
 ], [
   AC_MSG_FAILURE([This FRR version needs pthreads])
 ])
 
+orig_cflags="$CFLAGS"
+CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
+
 AC_SEARCH_LIBS([pthread_condattr_setclock], [],
                [frr_cv_pthread_condattr_setclock=yes],
                [frr_cv_pthread_condattr_setclock=no])
@@ -462,6 +469,13 @@ if test "$frr_cv_pthread_condattr_setclock" = "yes"; then
   AC_DEFINE([HAVE_PTHREAD_CONDATTR_SETCLOCK], [1], [Have pthread.h pthread_condattr_setclock])
 fi
 
+AC_CHECK_HEADERS([pthread_np.h],,, [
+#include <pthread.h>
+])
+AC_CHECK_FUNCS([pthread_setname_np pthread_set_name_np pthread_getthreadid_np])
+
+CFLAGS="$orig_cflags"
+
 dnl --------------
 dnl Check programs
 dnl --------------
@@ -969,7 +983,7 @@ dnl -------------------------
 dnl Check other header files.
 dnl -------------------------
 AC_CHECK_HEADERS([stropts.h sys/ksym.h \
-       linux/version.h asm/types.h])
+       linux/version.h asm/types.h endian.h sys/endian.h])
 
 ac_stdatomic_ok=false
 AC_DEFINE([FRR_AUTOCONF_ATOMIC], [1], [did autoconf checks for atomic funcs])
@@ -1037,11 +1051,6 @@ int main(int argc, char **argv) {
   ])
 ])
 
-AC_CHECK_HEADERS([pthread_np.h],,, [
-#include <pthread.h>
-])
-AC_CHECK_FUNCS([pthread_setname_np pthread_set_name_np pthread_getthreadid_np])
-
 needsync=true
 
 AS_IF([$needsync], [
@@ -1262,11 +1271,6 @@ if test "$enable_realms" = "yes"; then
     esac
 fi
 
-dnl -------------------------------
-dnl Endian-ness check
-dnl -------------------------------
-AC_WORDS_BIGENDIAN
-
 dnl ---------------
 dnl other functions
 dnl ---------------
@@ -1521,24 +1525,22 @@ FRR_INCLUDES
 #endif
 ])dnl
 
-AC_MSG_CHECKING([for BSD struct ip_mreq hack])
-AC_TRY_COMPILE([#include <sys/param.h>],
-[#if (defined(__FreeBSD__) && ((__FreeBSD_version >= 500022 && __FreeBSD_version < 700000) || (__FreeBSD_version < 500000 && __FreeBSD_version >= 440000))) || (defined(__NetBSD__) && defined(__NetBSD_Version__) && __NetBSD_Version__ >= 106010000) || defined(__OpenBSD__) || defined(__APPLE__) || defined(__DragonFly__) || defined(__sun)
-  return (0);
-#else
-  #error No support for BSD struct ip_mreq hack detected
-#endif],[AC_MSG_RESULT([yes])
-AC_DEFINE([HAVE_BSD_STRUCT_IP_MREQ_HACK], [1], [Can pass ifindex in struct ip_mreq])],
-AC_MSG_RESULT([no]))
-
 AC_MSG_CHECKING([for RFC3678 protocol-independed API])
-AC_TRY_COMPILE([
-#include <sys/types.h>
-#include <netinet/in.h>
-], [struct group_req gr; int sock; setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void*)&gr, sizeof(gr));
-], [AC_MSG_RESULT([yes])
-AC_DEFINE([HAVE_RFC3678], [1], [Have RFC3678 protocol-independed API])],
-AC_MSG_RESULT([no]))
+AC_COMPILE_IFELSE(
+[ AC_LANG_PROGRAM([[
+      #include <sys/types.h>
+      #include <netinet/in.h>
+  ]], [[
+      struct group_req gr;
+      int sock;
+      setsockopt(sock, IPPROTO_IP, MCAST_JOIN_GROUP, (void*)&gr, sizeof(gr));
+  ]])
+],[
+  AC_MSG_RESULT([yes])
+  AC_DEFINE([HAVE_RFC3678], [1], [Have RFC3678 protocol-independed API])
+],[
+  AC_MSG_RESULT(no)
+])
 
 dnl ---------------------------------------------------------------
 dnl figure out how to check link-state
@@ -1864,7 +1866,7 @@ AC_SUBST([SNMP_CFLAGS])
 dnl ---------------
 dnl libyang
 dnl ---------------
-PKG_CHECK_MODULES([LIBYANG], [libyang >= 1.0.184], , [
+PKG_CHECK_MODULES([LIBYANG], [libyang >= 1.0.184 libyang < 2.0], , [
   AC_MSG_ERROR([libyang (>= 1.0.184) was not found on your system.])
 ])
 ac_cflags_save="$CFLAGS"
@@ -2135,12 +2137,16 @@ dnl -----------------------
 dnl checking for IP_PKTINFO
 dnl -----------------------
 AC_MSG_CHECKING([for IP_PKTINFO])
-AC_TRY_COMPILE([#include <netdb.h>], [
-  int opt = IP_PKTINFO;
-], [
+AC_COMPILE_IFELSE(
+[ AC_LANG_PROGRAM([[
+        #include <netdb.h>
+   ]], [[
+        int opt = IP_PKTINFO;
+   ]])
+],[
   AC_MSG_RESULT([yes])
   AC_DEFINE([HAVE_IP_PKTINFO], [1], [Have IP_PKTINFO])
-], [
+],[
   AC_MSG_RESULT([no])
 ])
 
@@ -2148,12 +2154,16 @@ dnl ---------------------------
 dnl checking for IP_RECVDSTADDR
 dnl ---------------------------
 AC_MSG_CHECKING([for IP_RECVDSTADDR])
-AC_TRY_COMPILE([#include <netinet/in.h>], [
-  int opt = IP_RECVDSTADDR;
-], [
+AC_COMPILE_IFELSE(
+[ AC_LANG_PROGRAM([[
+        #include <netinet/in.h>
+  ]], [[
+        int opt = IP_RECVDSTADDR;
+  ]])
+],[
   AC_MSG_RESULT([yes])
   AC_DEFINE([HAVE_IP_RECVDSTADDR], [1], [Have IP_RECVDSTADDR])
-], [
+],[
   AC_MSG_RESULT([no])
 ])
 
@@ -2161,12 +2171,16 @@ dnl ----------------------
 dnl checking for IP_RECVIF
 dnl ----------------------
 AC_MSG_CHECKING([for IP_RECVIF])
-AC_TRY_COMPILE([#include <netinet/in.h>], [
-  int opt = IP_RECVIF;
-], [
+AC_COMPILE_IFELSE(
+[ AC_LANG_PROGRAM([[
+        #include <netinet/in.h>
+  ]], [[
+        int opt = IP_RECVIF;
+  ]])
+],[
   AC_MSG_RESULT([yes])
   AC_DEFINE([HAVE_IP_RECVIF], [1], [Have IP_RECVIF])
-], [
+],[
   AC_MSG_RESULT([no])
 ])
 
@@ -2174,12 +2188,16 @@ dnl ----------------------
 dnl checking for SO_BINDANY
 dnl ----------------------
 AC_MSG_CHECKING([for SO_BINDANY])
-AC_TRY_COMPILE([#include <sys/socket.h>], [
-  int opt = SO_BINDANY;
-], [
+AC_COMPILE_IFELSE(
+[ AC_LANG_PROGRAM([[
+        #include <sys/socket.h>
+  ]], [[
+        int opt = SO_BINDANY;
+  ]])
+],[
   AC_MSG_RESULT([yes])
   AC_DEFINE([HAVE_SO_BINDANY], [1], [Have SO_BINDANY])
-], [
+],[
   AC_MSG_RESULT([no])
 ])
 
@@ -2187,20 +2205,30 @@ dnl ----------------------
 dnl checking for IP_FREEBIND
 dnl ----------------------
 AC_MSG_CHECKING([for IP_FREEBIND])
-AC_TRY_COMPILE([#include <netinet/in.h>], [
-  int opt = IP_FREEBIND;
-], [
+AC_COMPILE_IFELSE(
+[ AC_LANG_PROGRAM([[
+        #include <netinet/in.h>
+  ]], [[
+        int opt = IP_FREEBIND;
+  ]])
+],[
   AC_MSG_RESULT([yes])
   AC_DEFINE([HAVE_IP_FREEBIND], [1], [Have IP_FREEBIND])
-], [
+],[
   AC_MSG_RESULT([no])
 ])
 
 dnl --------------------------------------
 dnl checking for be32dec existence or not
 dnl --------------------------------------
-AC_CHECK_DECLS([be32enc, be32dec], [], [],
-              [#include <sys/endian.h>])
+AC_CHECK_DECLS([be32enc, be32dec], [], [], [
+        #ifdef HAVE_SYS_ENDIAN_H
+        #include <sys/endian.h>
+        #endif
+        #ifdef HAVE_ENDIAN_H
+        #include <endian.h>
+        #endif
+])
 
 dnl --------------------------------------
 dnl checking for clock_time monotonic struct and call
@@ -2288,12 +2316,17 @@ dnl capabilities checks
 dnl -------------------
 if test "$enable_capabilities" != "no"; then
   AC_MSG_CHECKING([whether prctl PR_SET_KEEPCAPS is available])
-  AC_TRY_COMPILE([#include <sys/prctl.h>], [prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);],
-    [AC_MSG_RESULT([yes])
+  AC_COMPILE_IFELSE(
+  [ AC_LANG_PROGRAM([[
+        #include <sys/prctl.h>
+    ]], [[
+        prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0);
+    ]])
+  ],[AC_MSG_RESULT([yes])
      AC_DEFINE([HAVE_PR_SET_KEEPCAPS], [1], [prctl])
-     frr_ac_keepcaps="yes"],
-     AC_MSG_RESULT([no])
-  )
+     frr_ac_keepcaps="yes"
+  ],[AC_MSG_RESULT(no)
+  ])
   if test "$frr_ac_keepcaps" = "yes"; then
     AC_CHECK_HEADERS([sys/capability.h])
   fi
@@ -2652,7 +2685,7 @@ FRR version             : ${PACKAGE_VERSION}
 host operating system   : ${host_os}
 source code location    : ${srcdir}
 compiler                : ${CC}
-compiler flags          : ${CFLAGS} ${SAN_FLAGS}
+compiler flags          : ${CFLAGS} ${AC_CFLAGS} ${SAN_FLAGS}
 make                    : ${MAKE-make}
 linker flags            : ${LDFLAGS} ${SAN_FLAGS} ${LIBS} ${LIBCAP} ${LIBREADLINE} ${LIBM}
 state file directory    : ${frr_statedir}
index 852a295fd0d069fdacbb9062db13c5ba0e0a2acd..35b51cd9c04361e2173f3be97c3b713e4f7f65d7 100644 (file)
@@ -12,6 +12,13 @@ source-built FRR on the following base platforms:
 * Centos 7
 * Centos 8
 
+The following platform images are used to support Travis CI and can also
+be used to reproduce topotest failures when the docker host is Ubuntu
+(tested on 18.04 and 20.04):
+
+* Ubuntu 18.04
+* Ubuntu 20.04
+
 The following platform images may also be built, but these simply install a
 binary package from an existing repository and do not perform source builds:
 
@@ -99,3 +106,60 @@ No script::
 No script, multi-arch (ex. amd64, arm64)::
 
    docker buildx build --platform linux/amd64,linux/arm64 -f docker/centos-8/Dockerfile -t frr-centos8:latest .
+
+
+
+Building Ubuntu 18.04 Image
+---------------------------
+
+Build image (from project root directory)::
+
+   docker build -t frr-ubuntu18:latest  -f docker/ubuntu18-ci/Dockerfile .
+
+Start the container::
+
+   docker run -d --privileged --name frr-ubuntu18 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu18:latest
+
+Running a topotest (when the docker host is Ubuntu)::
+
+   docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+
+Starting an interactive bash session::
+
+   docker exec -it frr-ubuntu18 bash
+
+Stopping an removing a container::
+
+   docker stop frr-ubuntu18 ; docker rm frr-ubuntu18
+
+Removing the built image::
+
+   docker rmi frr-ubuntu18:latest
+
+
+Building Ubuntu 20.04 Image
+---------------------------
+
+Build image (from project root directory)::
+
+   docker build -t frr-ubuntu20:latest  -f docker/ubuntu20-ci/Dockerfile .
+
+Start the container::
+
+   docker run -d --privileged --name frr-ubuntu20 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu20:latest
+
+Running a topotest (when the docker host is Ubuntu)::
+
+   docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+
+Starting an interactive bash session::
+
+   docker exec -it frr-ubuntu20 bash
+
+Stopping an removing a container::
+
+   docker stop frr-ubuntu20 ; docker rm frr-ubuntu20
+
+Removing the built image::
+
+   docker rmi frr-ubuntu20:latest
index f307cacdfcf8f7296633b3f581a7527abc486741..88446685e06784479b3adc4f1472b47d789fe261 100644 (file)
@@ -14,6 +14,7 @@ Add packages:
 
 ::
 
+    pkg_add clang libcares python3
     pkg_add git autoconf-2.69p2 automake-1.15.1 libtool bison
     pkg_add gmake json-c py-test py-sphinx libexecinfo
 
@@ -47,6 +48,19 @@ Download Source, configure and compile it
 (You may prefer different options on configure statement. These are just
 an example)
 
+.. warning::
+
+   In openbsd the proper links for the libyang library may not have been created.
+
+::
+
+    ln -s /usr/lib/libyang.so.1.10.17 /usr/lib/libyang.so
+
+.. warning::
+
+   ``openbsd`` since version 6.2 has ``clang`` as the default compiler so to 
+   build frr, clang must be used (the included gcc version is very old).
+
 ::
 
     git clone https://github.com/frrouting/frr.git frr
@@ -67,7 +81,8 @@ an example)
         --enable-logfile-mask=0640 \
         --enable-fpm \
         --with-pkg-git-version \
-        --with-pkg-extra-version=-MyOwnFRRVersion
+        --with-pkg-extra-version=-MyOwnFRRVersion \
+        CC=clang
     gmake
     gmake check
     doas gmake install
index 86db788c0e47766da8f90df8e50cb1702f8c9651..553bd1f596a8805a982e857cd7ec9c665b857f94 100644 (file)
@@ -108,6 +108,8 @@ Functions provided:
 | _first, _next, _next_safe,         | yes  | yes  | yes  | yes     | yes        |
 | _const_first, _const_next          |      |      |      |         |            |
 +------------------------------------+------+------+------+---------+------------+
+| _swap_all                          | yes  | yes  | yes  | yes     | yes        |
++------------------------------------+------+------+------+---------+------------+
 | _add_head, _add_tail, _add_after   | yes  | --   | --   | --      | --         |
 +------------------------------------+------+------+------+---------+------------+
 | _add                               | --   | yes  | yes  | yes     | yes        |
@@ -322,6 +324,14 @@ The following documentation assumes that a list has been defined using
       return ``item``.  The function may also call ``assert()`` (but most
       don't.)
 
+.. c:function:: itemtype *Z_swap_all(struct Z_head *, struct Z_head *)
+
+   Swap the contents of 2 containers (of identical type).  This exchanges the
+   contents of the two head structures and updates pointers if necessary for
+   the particular data structure.  Fast for all structures.
+
+   (Not currently available on atomic containers.)
+
 .. todo::
 
    ``Z_del_after()`` / ``Z_del_hint()``?
index 3e496956c23d63f143987d6ab53c8c1b3db16ee7..b930cb915de147f7ead770330060401a3f5e35e1 100644 (file)
@@ -53,6 +53,10 @@ OPTIONS available for the vtysh command:
 
    When executing cli that does not invoke a vtysh shell, if an error ocurrs ignore it for purposes of return codes from vtysh.
 
+.. option:: -H, --histfile
+
+   Override the history file for vtysh commands. You can set ``vtysh -H /dev/null`` to turn logging of at all.
+
 .. option:: -u, --user
 
    Restrict access to configuration commands by preventing use of the "enable" command. This option provides the same limited "security" as password-protected telnet access. *This security should not be relied on in production environments.*
@@ -68,6 +72,10 @@ ENVIRONMENT VARIABLES
 VTYSH_PAGER
    This should be the name of the pager to use. Default is more.
 
+VTYSH_HISTFILE
+   Override the history file for vtysh commands. Logging can be turned off using ``VTYSH_HISTFILE=/dev/null vtysh``.
+   Environment is prefered way to override the history file path over command line argument (-H/--histfile).
+
 FILES
 =====
 |INSTALL_PREFIX_SBIN|/vtysh
index 4244b5fdfb5b76e5bce7397c322af0cc389c9dda..eaf97b969cc78e5430773284093d0313db557c12 100644 (file)
@@ -37,6 +37,7 @@ net.ipv4.icmp_errors_use_inbound_ifaddr=1
 
 #   Keep ipv6 permanent addresses on an admin down
 net.ipv6.conf.all.keep_addr_on_down=1
+net.ipv6.route.skip_notify_on_dev_down=1
 
 # igmp
 net.ipv4.igmp_max_memberships=1000
index 519f30d5e669a9d0a171eaab8f5e41d39af18120..2def835f0bbab8a9de7db5b65b89694a7c80e0cd 100644 (file)
@@ -188,6 +188,12 @@ Basic Config Commands
    This command clears all current filters in the log-filter table. Can be
    daemon independent.
 
+
+.. clicmd:: log immediate-mode
+
+   Use unbuffered output for log and debug messages; normally there is
+   some internal buffering.
+
 .. clicmd:: service password-encryption
 
    Encrypt password.
index 6f797f7cc1841c7779ae96b2896e6af800b5a77e..99c024d1183683166b578c3703f6e365e3f113c3 100644 (file)
@@ -326,12 +326,15 @@ OSPF6 BFD Configuration
 
 The following commands are available inside the interface configuration node.
 
-.. clicmd:: ipv6 ospf6 bfd
+.. clicmd:: ipv6 ospf6 bfd [profile BFDPROF]
 
    Listen for BFD events on peers created on the interface. Every time
    a new neighbor is found a BFD peer is created to monitor the link
    status for fast convergence.
 
+   Optionally uses the BFD profile ``BFDPROF`` in the created sessions under
+   that interface.
+
 
 .. _bfd-pim-peer-config:
 
@@ -340,12 +343,15 @@ PIM BFD Configuration
 
 The following commands are available inside the interface configuration node.
 
-.. clicmd:: ip pim bfd
+.. clicmd:: ip pim bfd [profile BFDPROF]
 
    Listen for BFD events on peers created on the interface. Every time
    a new neighbor is found a BFD peer is created to monitor the link
    status for fast convergence.
 
+   Optionally uses the BFD profile ``BFDPROF`` in the created sessions under
+   that interface.
+
 
 .. _bfd-configuration:
 
index adb87d386d02d733ced5fd34248a796e9402eaa4..14b2389ca921d7e5c9c23389f3f1303aee32b805 100644 (file)
@@ -2022,6 +2022,24 @@ expanded
    attribute in BGP updates. The expanded community is only used to filter,
    not `set` actions.
 
+.. clicmd:: bgp community alias NAME ALIAS
+
+   This command creates an alias name for a community that will be used
+   later in various CLI outputs in a human-readable format.
+
+   .. code-block:: frr
+
+      ~# show ip bgp 172.16.16.1/32
+      BGP routing table entry for 172.16.16.1/32, version 21
+      Paths: (2 available, best #2, table default)
+        Advertised to non peer-group peers:
+        65030
+          192.168.0.2 from 192.168.0.2 (172.16.16.1)
+            Origin incomplete, metric 0, valid, external, best (Neighbor IP)
+            Community: 65001:12 65001:13 community-1 65001:65534
+            Large Community: lcommunity-1 65001:123:2
+            Last update: Fri Apr 16 12:51:27 2021
+
 .. deprecated:: 5.0
    It is recommended to use the more explicit versions of this command.
 
@@ -2567,6 +2585,24 @@ address-family:
 Ethernet Virtual Network - EVPN
 -------------------------------
 
+Note: When using EVPN features and if you have a large number of hosts, make
+sure to adjust the size of the arp  neighbor cache to avoid neighbor table
+overflow and/or excessive garbage collection. On Linux, the size of the table
+and garbage collection frequency can be controlled via the following
+sysctl configurations:
+
+.. code-block:: shell
+
+   net.ipv4.neigh.default.gc_thresh1
+   net.ipv4.neigh.default.gc_thresh2
+   net.ipv4.neigh.default.gc_thresh3
+
+   net.ipv6.neigh.default.gc_thresh1
+   net.ipv6.neigh.default.gc_thresh2
+   net.ipv6.neigh.default.gc_thresh3
+
+For more information, see ``man 7 arp``.
+
 .. _bgp-evpn-advertise-pip:
 
 EVPN advertise-PIP
@@ -2592,10 +2628,10 @@ other EVPN routes.
 To support this feature there needs to have ability to co-exist a
 (system-MAC, system-IP) pair with a (anycast-MAC, anycast-IP) pair with the
 ability to terminate VxLAN-encapsulated packets received for either pair on
-the same L3VNI (i.e associated VLAN). This capability is need per tenant
+the same L3VNI (i.e associated VLAN). This capability is needed per tenant
 VRF instance.
 
-To derive the system-MAC and the anycast MAC, there needs to have a
+To derive the system-MAC and the anycast MAC, there must be a
 separate/additional MAC-VLAN interface corresponding to L3VNI’s SVI.
 The SVI interface’s MAC address can be interpreted as system-MAC
 and MAC-VLAN interface's MAC as anycast MAC.
@@ -2607,7 +2643,7 @@ User has an option to configure the system-IP and/or system-MAC value if the
 auto derived value is not preferred.
 
 Note: By default, advertise-pip feature is enabled and user has an option to
-disable the feature via configuration CLI. Once the feature is disable under
+disable the feature via configuration CLI. Once the feature is disabled under
 bgp vrf instance or MAC-VLAN interface is not configured, all the routes follow
 the same behavior of using same next-hop and RMAC values.
 
@@ -2616,6 +2652,19 @@ the same behavior of using same next-hop and RMAC values.
 Enables or disables advertise-pip feature, specifiy system-IP and/or system-MAC
 parameters.
 
+EVPN advertise-svi-ip
+^^^^^^^^^^^^^^^^^^^^^
+Typically, the SVI IP address is reused on VTEPs across multiple racks. However,
+if you have unique SVI IP addresses that you want to be reachable you can use the
+advertise-svi-ip option. This option advertises the SVI IP/MAC address as a type-2
+route and eliminates the need for any flooding over VXLAN to reach the IP from a
+remote VTEP.
+
+.. clicmd:: advertise-svi-ip
+
+Note that you should not enable both the advertise-svi-ip and the advertise-default-gw
+at the same time.
+
 EVPN Multihoming
 ^^^^^^^^^^^^^^^^
 
@@ -2849,6 +2898,7 @@ When default route is present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/3
                   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
    *> 0.0.0.0/0        10.10.10.1               0             0 1 i
@@ -2878,6 +2928,7 @@ When default route is present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2.1/3
                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
    *> 0.0.0.0/0        0.0.0.0                                0 1 i
@@ -2896,6 +2947,7 @@ When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2
                   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
    *> 10.139.224.0/20  10.10.10.1               0             0 1 ?
@@ -2925,6 +2977,7 @@ When default route is not present in R2'2 BGP table, 10.139.224.0/20 and 192.0.2
                   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
    *> 10.139.224.0/20  0.0.0.0                                0 1 ?
@@ -3115,11 +3168,11 @@ daemon project, while :clicmd:`show bgp` command is the new format. The choice
 has been done to keep old format with IPv4 routing table, while new format
 displays IPv6 routing table.
 
-.. clicmd:: show ip bgp [all] [wide|json]
+.. clicmd:: show ip bgp [all] [wide|json [detail]]
 
 .. clicmd:: show ip bgp A.B.C.D [json]
 
-.. clicmd:: show bgp [all] [wide|json]
+.. clicmd:: show bgp [all] [wide|json [detail]]
 
 .. clicmd:: show bgp X:X::X:X [json]
 
@@ -3148,6 +3201,9 @@ displays IPv6 routing table.
 
    If ``json`` option is specified, output is displayed in JSON format.
 
+   If ``detail`` option is specified after ``json``, more verbose JSON output
+   will be displayed.
+
 Some other commands provide additional options for filtering the output.
 
 .. clicmd:: show [ip] bgp regexp LINE
@@ -3870,6 +3926,147 @@ Example of how to set up a 6-Bone connection.
    log file bgpd.log
    !
 
+.. _bgp-tcp-mss:
+
+BGP tcp-mss support
+===================
+TCP provides a mechanism for the user to specify the max segment size.
+setsockopt API is used to set the max segment size for TCP session. We
+can configure this as part of BGP neighbor configuration.
+
+This document explains how to avoid ICMP vulnerability issues by limiting
+TCP max segment size when you are using MTU discovery. Using MTU discovery
+on TCP paths is one method of avoiding BGP packet fragmentation.
+
+TCP negotiates a maximum segment size (MSS) value during session connection
+establishment between two peers. The MSS value negotiated is primarily based
+on the maximum transmission unit (MTU) of the interfaces to which the
+communicating peers are directly connected. However, due to variations in
+link MTU on the path taken by the TCP packets, some packets in the network
+that are well within the MSS value might be fragmented when the packet size
+exceeds the link's MTU.
+
+This feature is supported with TCP over IPv4 and TCP over IPv6.
+
+CLI Configuration:
+------------------
+Below configuration can be done in router bgp mode and allows the user to
+configure the tcp-mss value per neighbor. The configuration gets applied
+only after hard reset is performed on that neighbor. If we configure tcp-mss
+on both the neighbors then both neighbors need to be reset.
+
+The configuration takes effect based on below rules, so there is a configured
+tcp-mss and a synced tcp-mss value per TCP session.
+
+By default if the configuration is not done then the TCP max segment size is
+set to the Maximum Transmission unit (MTU) â€“ (IP/IP6 header size + TCP header
+size + ethernet header). For IPv4 its MTU â€“ (20 bytes IP header + 20 bytes TCP
+header + 12 bytes ethernet header) and for IPv6 its MTU â€“ (40 bytes IPv6 header
++ 20 bytes TCP header + 12 bytes ethernet header).
+
+If the config is done then it reduces 12-14 bytes for the ether header and
+uses it after synchronizing in TCP handshake.
+
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> tcp-mss (1-65535)
+
+When tcp-mss is configured kernel reduces 12-14 bytes for ethernet header.
+E.g. if tcp-mss is configured as 150 the synced value will be 138.
+
+Note: configured and synced value is different since TCP module will reduce
+12 bytes for ethernet header.
+
+Running config:
+---------------
+
+.. code-block:: frr
+
+   frr# show running-config
+   Building configuration...
+
+   Current configuration:
+   !
+   router bgp 100
+    bgp router-id 192.0.2.1
+    neighbor 198.51.100.2 remote-as 100
+    neighbor 198.51.100.2 tcp-mss 150       => new entry
+    neighbor 2001:DB8::2 remote-as 100
+    neighbor 2001:DB8::2 tcp-mss 400        => new entry
+
+Show command:
+-------------
+
+.. code-block:: frr
+
+   frr# show bgp neighbors 198.51.100.2
+   BGP neighbor is 198.51.100.2, remote AS 100, local AS 100, internal link
+   Hostname: frr
+     BGP version 4, remote router ID 192.0.2.2, local router ID 192.0.2.1
+     BGP state = Established, up for 02:15:28
+     Last read 00:00:28, Last write 00:00:28
+     Hold time is 180, keepalive interval is 60 seconds
+     Configured tcp-mss is 150, synced tcp-mss is 138     => new display
+
+.. code-block:: frr
+
+   frr# show bgp neighbors 2001:DB8::2
+   BGP neighbor is 2001:DB8::2, remote AS 100, local AS 100, internal link
+   Hostname: frr
+     BGP version 4, remote router ID 192.0.2.2, local router ID 192.0.2.1
+     BGP state = Established, up for 02:16:34
+     Last read 00:00:34, Last write 00:00:34
+     Hold time is 180, keepalive interval is 60 seconds
+     Configured tcp-mss is 400, synced tcp-mss is 388      => new display
+
+Show command json output:
+-------------------------
+
+.. code-block:: frr
+
+   frr# show bgp neighbors 2001:DB8::2 json
+   {
+     "2001:DB8::2":{
+       "remoteAs":100,
+       "localAs":100,
+       "nbrInternalLink":true,
+       "hostname":"frr",
+       "bgpVersion":4,
+       "remoteRouterId":"192.0.2.2",
+       "localRouterId":"192.0.2.1",
+       "bgpState":"Established",
+       "bgpTimerUpMsec":8349000,
+       "bgpTimerUpString":"02:19:09",
+       "bgpTimerUpEstablishedEpoch":1613054251,
+       "bgpTimerLastRead":9000,
+       "bgpTimerLastWrite":9000,
+       "bgpInUpdateElapsedTimeMsecs":8347000,
+       "bgpTimerHoldTimeMsecs":180000,
+       "bgpTimerKeepAliveIntervalMsecs":60000,
+       "bgpTcpMssConfigured":400,                                   => new entry
+       "bgpTcpMssSynced":388,                                  => new entry
+
+.. code-block:: frr
+
+   frr# show bgp neighbors 198.51.100.2 json
+   {
+     "198.51.100.2":{
+       "remoteAs":100,
+       "localAs":100,
+       "nbrInternalLink":true,
+       "hostname":"frr",
+       "bgpVersion":4,
+       "remoteRouterId":"192.0.2.2",
+       "localRouterId":"192.0.2.1",
+       "bgpState":"Established",
+       "bgpTimerUpMsec":8370000,
+       "bgpTimerUpString":"02:19:30",
+       "bgpTimerUpEstablishedEpoch":1613054251,
+       "bgpTimerLastRead":30000,
+       "bgpTimerLastWrite":30000,
+       "bgpInUpdateElapsedTimeMsecs":8368000,
+       "bgpTimerHoldTimeMsecs":180000,
+       "bgpTimerKeepAliveIntervalMsecs":60000,
+       "bgpTcpMssConfigured":150,                                  => new entry
+       "bgpTcpMssSynced":138,                                  => new entry
 
 .. include:: routeserver.rst
 
index 78043e779baa2467a645aca8e982908fa5bf1e1a..1fb9beccdc1794f3a527fe65183c93d8ca732e3e 100644 (file)
@@ -106,17 +106,6 @@ ip prefix-list description
    description to the prefix list.
 
 
-.. _ip-prefix-list-sequential-number-control:
-
-ip prefix-list sequential number control
-----------------------------------------
-
-.. clicmd:: ip prefix-list sequence-number
-
-   With this command, the IP prefix list sequential number is displayed.
-   This is the default behavior.
-
-
 .. _showing-ip-prefix-list:
 
 Showing ip prefix-list
index ef2bf16166e0d2ec5a3294c1b7b63d84e3227d49..66f8fd56789a71f0e678fb36d1151eb30f357a40 100644 (file)
@@ -77,7 +77,7 @@ writing, *isisd* does not support multiple ISIS processes.
    - transition
      Send and accept both styles of TLVs during transition
    - wide
-     Use new style of TLVs to carry wider metric
+     Use new style of TLVs to carry wider metric. FRR uses this as a default value
 
 .. clicmd:: set-overload-bit
 
@@ -172,7 +172,7 @@ ISIS interface
 
 .. _ip-router-isis-word:
 
-.. clicmd:: <ip|ipv6> router isis WORD [vrf NAME]
+.. clicmd:: <ip|ipv6> router isis WORD
 
    Activate ISIS adjacency on this interface. Note that the name of ISIS
    instance must be the same as the one used to configure the ISIS process (see
@@ -261,10 +261,11 @@ ISIS interface
 
    Limit Remote LFA PQ node selection within the specified metric.
 
-.. clicmd:: isis fast-reroute ti-lfa [level-1|level-2] [node-protection]
+.. clicmd:: isis fast-reroute ti-lfa [level-1|level-2] [node-protection [link-fallback]]
 
    Enable per-prefix TI-LFA fast reroute link or node protection.
-
+   When node protection is used, option link-fallback enables the computation and use of
+   link-protecting LFAs for destinations unprotected by node protection.
 
 .. _showing-isis-information:
 
index 4c2c7a500863295d89a9894e54b21c32d11157c5..210ede7e9157f68b551eeecbcc2411c481a83929 100644 (file)
@@ -6,6 +6,9 @@ Kernel Interface
 
 There are several different methods for reading kernel routing table
 information, updating kernel routing tables, and for looking up interfaces.
+FRR relies heavily on the Netlink (``man 7 netlink``) interface to
+communicate with the Kernel. However, other interfaces are still used
+in some parts of the code.
 
 - ioctl
      This method is a very traditional way for reading or writing kernel
@@ -27,16 +30,7 @@ information, updating kernel routing tables, and for looking up interfaces.
      kernel information.
 
 - routing socket / Netlink
-     On recent Linux kernels (2.0.x and 2.2.x), there is a kernel/user
-     communication support called `Netlink`. It makes asynchronous communication
-     between kernel and FRR possible, similar to a routing socket on BSD systems.
-
-     Before you use this feature, be sure to select (in kernel configuration) the
-     kernel/Netlink support option 'Kernel/User network link driver' and 'Routing
-     messages'.
-
-     Today, the :file:`/dev/route` special device file is obsolete.  Netlink
-     communication is done by reading/writing over Netlink socket.
-
-     After the kernel configuration, please reconfigure and rebuild FRR.  You can
-     use Netlink as a dynamic routing update channel between FRR and the kernel.
+     Netlink first appeard in Linux kernel 2.0. It makes asynchronous
+     communication between the kernel and FRR possible, similar to a routing
+     socket on BSD systems. Netlink communication is done by reading/writing
+     over Netlink socket.
index b02e761accb0c9624d903db7322ef5fdb861dcb4..cbbc2dc10a5d56ecf5c724cd552bcfd11928bd51 100644 (file)
@@ -180,6 +180,37 @@ https://git-old.alpinelinux.org/user/tteras/strongswan/
 Actively maintained patches are also available at:
 https://gitlab.alpinelinux.org/alpine/aports/-/tree/master/main/strongswan
 
+.. _multicast-functionality:
+
+Multicast Functionality
+=======================
+
+nhrpd can be configured to forward multicast packets, allowing routing
+protocols that use multicast (such as OSPF) to be supported in the DMVPN
+network.
+
+This support requires an iptables NFLOG rule to allow nhrpd to intercept
+multicast packets. A second iptables rule is also usually used to drop the
+original multicast packet.
+
+ .. code-block:: shell
+
+   iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j NFLOG --nflog-group 2
+   iptables -A OUTPUT -d 224.0.0.0/24 -o gre1 -j DROP
+
+.. index::  nhrp multicast-nflog-group (1-65535)
+.. clicmd:: nhrp multicast-nflog-group (1-65535)
+
+   Sets the nflog group that nhrpd will listen on for multicast packets. This
+   value must match the nflog-group value set in the iptables rule.
+
+.. index::  ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
+.. clicmd:: ip nhrp map multicast A.B.C.D|X:X::X:X A.B.C.D|dynamic
+
+   Sends multicast packets to the specified NBMA address. If dynamic is
+   specified then destination NBMA address (or addresses) are learnt
+   dynamically.
+
 .. _nhrp-events:
 
 NHRP Events
index 43c0f62ea35fa363b6c171b603a1b568bc023944..573b9c8d7ee41d42eff4201b50d8fc5937eb318e 100644 (file)
@@ -12,7 +12,7 @@ described in :rfc:`2740`.
 OSPF6 router
 ============
 
-.. clicmd:: router ospf6
+.. clicmd:: router ospf6 [vrf NAME]
 
 .. clicmd:: ospf6 router-id A.B.C.D
 
@@ -151,57 +151,53 @@ Redistribute routes to OSPF6
 Showing OSPF6 information
 =========================
 
-.. clicmd:: show ipv6 ospf6 [INSTANCE_ID] [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] [json]
 
-   INSTANCE_ID is an optional OSPF instance ID. To see router ID and OSPF
-   instance ID, simply type "show ipv6 ospf6 <cr>". JSON output can be
-   obtained by appending 'json' to the end of command.
+   Show information on a variety of general OSPFv3 and area state and
+   configuration information. JSON output can be obtained by appending 'json'
+   to the end of command.
 
-.. clicmd:: show ipv6 ospf6 database [<detail|dump|internal>] [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] database [<detail|dump|internal>] [json]
 
    This command shows LSAs present in the LSDB. There are three view options.
    These options helps in viewing all the parameters of the LSAs. JSON output
    can be obtained by appending 'json' to the end of command. JSON option is
    not applicable with 'dump' option.
 
-.. clicmd:: show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [json]
 
    These options filters out the LSA based on its type. The three views options
    works here as well. JSON output can be obtained by appending 'json' to the
    end of command.
 
-.. clicmd:: show ipv6 ospf6 database adv-router A.B.C.D linkstate-id A.B.C.D [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] database adv-router A.B.C.D linkstate-id A.B.C.D [json]
 
    The LSAs additinally can also be filtered with the linkstate-id and
    advertising-router fields. We can use the LSA type filter and views with
    this command as well and visa-versa. JSON output can be obtained by
    appending 'json' to the end of command.
 
-.. clicmd:: show ipv6 ospf6 database self-originated [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] database self-originated [json]
 
    This command is used to filter the LSAs which are originated by the present
    router. All the other filters are applicable here as well.
 
-.. clicmd:: show ipv6 ospf6 interface [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] interface [json]
 
    To see OSPF interface configuration like costs. JSON output can be
    obtained by appending "json" in the end.
 
-.. clicmd:: show ipv6 ospf6 neighbor [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] neighbor [json]
 
    Shows state and chosen (Backup) DR of neighbor. JSON output can be
    obtained by appending 'json' at the end.
 
-.. clicmd:: show ipv6 ospf6 interface traffic [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] interface traffic [json]
 
    Shows counts of different packets that have been recieved and transmitted
    by the interfaces. JSON output can be obtained by appending "json" at the
    end.
 
-.. clicmd:: show ipv6 ospf6 request-list A.B.C.D
-
-   Shows requestlist of neighbor.
-
 .. clicmd:: show ipv6 route ospf6
 
    This command shows internal routing table.
@@ -211,12 +207,12 @@ Showing OSPF6 information
    Shows state about what is being redistributed between zebra and OSPF6.
    JSON output can be obtained by appending "json" at the end.
 
-.. clicmd:: show ipv6 ospf6 redistribute [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] redistribute [json]
 
    Shows the routes which are redistributed by the router. JSON output can
    be obtained by appending 'json' at the end.
 
-.. clicmd:: show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]
 
    This command displays the ospfv3 routing table as determined by the most
    recent SPF calculations. Options are provided to view the different types
@@ -224,18 +220,18 @@ Showing OSPF6 information
    and summary. JSON output can be obtained by appending 'json' to the end of
    command.
 
-.. clicmd:: show ipv6 ospf6 route X:X::X:X/M match [detail] [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M match [detail] [json]
 
    The additional match option will match the given address to the destination
    of the routes, and return the result accordingly.
 
-.. clicmd:: show ipv6 ospf6 interface [IFNAME] prefix [detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]] [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] prefix [detail|<X:X::X:X|X:X::X:X/M> [<match|detail>]] [json]
 
    This command shows the prefixes present in the interface routing table.
    Interface name can also be given. JSON output can be obtained by appending
    'json' to the end of command.
 
-.. clicmd:: show ipv6 ospf6 spf tree [json]
+.. clicmd:: show ipv6 ospf6 [vrf <NAME|all>] spf tree [json]
 
    This commands shows the spf tree from the recent spf calculation with the
    calling router as the root. If json is appended in the end, we can get the
index 800530901eabeb05e9f877098e9edd529b7ae970..ba9917f72f178594890eb5454dc61fd93b922292 100644 (file)
@@ -299,15 +299,11 @@ To start OSPF process you have to specify the OSPF router.
    command can be used when the neighbor state get stuck at some state and
    this can be used to recover it from that state.
 
-.. index:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
-.. clicmd:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
+.. clicmd:: maximum-paths (1-64)
 
-.. index:: maximum-paths " CMD_RANGE_STR(1, MULTIPATH_NUM)
-.. clicmd:: no maximum-paths
-
-   CLI to control maximum number of equal cost paths to reach a specific
-   destination.(ECMP)
-   Reset CLI, resets the maximum supported multi path to the default value.
+   Use this command to control the maximum number of equal cost paths to reach
+   a specific destination. The upper limit may differ if you change the value
+   of MULTIPATH_NUM during compilation. The default is MULTIPATH_NUM (64).
 
 .. _ospf-area:
 
@@ -587,7 +583,7 @@ Interfaces
    :clicmd:`ip ospf dead-interval minimal hello-multiplier (2-20)` is also
    specified for the interface.
 
-.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point)
+.. clicmd:: ip ospf network (broadcast|non-broadcast|point-to-multipoint|point-to-point [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
@@ -595,6 +591,9 @@ Interfaces
    net.ipv4.conf.<interface name>.rp_filter value to 0.  In order for
    the ospf multicast packets to be delivered by the kernel.
 
+   When used in a DMVPN network at a spoke, this OSPF will be configured in
+   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.
 
    Set explicitly network type for specified interface.
 
index 6b7cae2c5dad4c4b4248f811925833bc0376007f..103760933cf8f0ad6a5a0c137119962bead2b838 100644 (file)
@@ -154,20 +154,6 @@ Certain signals have special meanings to *pimd*.
    urib-only
       Lookup in the Unicast Rib only.
 
-.. clicmd:: ip msdp mesh-group [WORD]
-
-   Create or Delete a multicast source discovery protocol mesh-group using
-   [WORD] as the group name.
-
-.. clicmd:: ip msdp mesh-group WORD member A.B.C.D
-
-   Attach or Delete A.B.C.D to the MSDP mesh group WORD specified.
-
-.. clicmd:: ip msdp mesh-group WORD source A.B.C.D
-
-   For the address specified A.B.C.D use that as the source address for
-   mesh group packets being sent.
-
 .. clicmd:: ip igmp generate-query-once [version (2-3)]
 
    Generate IGMP query (v2/v3) on user requirement. This will not depend on
@@ -308,27 +294,43 @@ caution. Most of the time this will not be necessary.
 Multicast Source Discovery Protocol (MSDP) Configuration
 ========================================================
 
-.. clicmd:: ip msdp mesh-group [WORD] member A.B.C.D
+MSDP can be setup in different ways:
 
-   Include a MSDP peer as a member of a MSDP mesh-group.
+* MSDP meshed-group: where all peers are connected with each other creating
+  a fully meshed network. SAs (source active) messages are not forwarded in
+  this mode because the origin is able to send SAs to all members.
 
-.. clicmd:: ip msdp mesh-group [WORD] source A.B.C.D
+  This setup is commonly used with anycast.
 
-   Create a MSDP mesh-group, defining a name for it and an associated local source
-   address.
+* MSDP peering: when there is one or more peers that are not fully meshed. SAs
+  may be forwarded depending on the result of filtering and RPF checks.
 
-.. clicmd:: ip msdp peer A.B.C.D source A.B.C.D
+  This setup is commonly consistent with BGP peerings (for RPF checks).
 
-   Establish a MSDP connection with a peer.
+* MSDP default peer: there is only one peer and all SAs will be forwarded
+  there.
 
+.. note::
 
-   Remove a MSDP peer member from a MSDP mesh-group.
+   MSDP default peer and SA filtering is not implemented.
 
 
-   Delete a MSDP mesh-group.
+Commands available for MSDP:
+
+
+.. clicmd:: ip msdp mesh-group WORD member A.B.C.D
+
+   Create or update a mesh group to include the specified MSDP peer.
+
+.. clicmd:: ip msdp mesh-group WORD source A.B.C.D
+
+   Create or update a mesh group to set the source address used to connect to
+   peers.
+
+.. clicmd:: ip msdp peer A.B.C.D source A.B.C.D
 
+   Create a regular MSDP session with peer using the specified source address.
 
-   Delete a MSDP peer connection.
 
 .. _show-pim-information:
 
index 83c8c93b1c93da1d2982411756865706e5ee8677..0a155bf4892ed12356debd7c9d542aa805beee98 100644 (file)
@@ -236,11 +236,13 @@ Filtering RIP Routes
 
 RIP routes can be filtered by a distribute-list.
 
-.. clicmd:: distribute-list ACCESS_LIST DIRECT IFNAME
+.. clicmd:: distribute-list [prefix] LIST <in|out> IFNAME
 
    You can apply access lists to the interface with a `distribute-list` command.
-   ACCESS_LIST is the access list name. DIRECT is ``in`` or ``out``. If DIRECT
-   is ``in`` the access list is applied to input packets.
+   If prefix is specified LIST is a prefix-list.  If prefix is not specified
+   then LIST is the access list name.  `in` specifies packets being received,
+   and `out` specifies outgoing packets.  Finally if an interface is specified
+   it will be applied against a specific interface.
 
    The `distribute-list` command can be used to filter the RIP path.
    `distribute-list` can apply access-lists to a chosen interface.  First, one
@@ -261,13 +263,6 @@ RIP routes can be filtered by a distribute-list.
 
    `distribute-list` can be applied to both incoming and outgoing data.
 
-.. clicmd:: distribute-list prefix PREFIX_LIST (in|out) IFNAME
-
-   You can apply prefix lists to the interface with a `distribute-list`
-   command. PREFIX_LIST is the prefix list name. Next is the direction of
-   ``in`` or ``out``. If DIRECT is ``in`` the access list is applied to input
-   packets.
-
 .. _rip-metric-manipulation:
 
 RIP Metric Manipulation
index b273eb3bfa0c28ecb9bccb9945c3be36338371c7..c7ca22bf9568f12d2f04a71e99d2091c5b304d3a 100644 (file)
@@ -62,14 +62,34 @@ ripngd Terminal Mode Commands
 ripngd Filtering Commands
 =========================
 
-.. clicmd:: distribute-list ACCESS_LIST (in|out) IFNAME
+RIPng routes can be filtered by a distribute-list.
 
-   You can apply an access-list to the interface using the `distribute-list`
-   command. ACCESS_LIST is an access-list name. `direct` is ``in`` or
-   ``out``. If `direct` is ``in``, the access-list is applied only to incoming
-   packets.::
+.. clicmd:: distribute-list [prefix] LIST <in|out> IFNAME
 
-      distribute-list local-only out sit1
+   You can apply access lists to the interface with a `distribute-list` command.
+   If prefix is specified LIST is a prefix-list.  If prefix is not specified
+   then LIST is the access list name.  `in` specifies packets being received,
+   and `out` specifies outgoing packets.  Finally if an interface is specified
+   it will be applied against a specific interface.
+
+   The ``distribute-list`` command can be used to filter the RIPNG path.
+   ``distribute-list`` can apply access-lists to a chosen interface.  First, one
+   should specify the access-list. Next, the name of the access-list is used in
+   the distribute-list command. For example, in the following configuration
+   ``eth0`` will permit only the paths that match the route 10.0.0.0/8
+
+   .. code-block:: frr
+
+      !
+      router ripng
+       distribute-list private in eth0
+      !
+      access-list private permit 10 10.0.0.0/8
+      access-list private deny any
+      !
+
+
+   `distribute-list` can be applied to both incoming and outgoing data.
 
 
 Sample configuration
index bef2748afab5321c2a2bbcc6f975682b5a713ff9..0542a593aee3796ef69413418f6f7443c2306f1f 100644 (file)
@@ -83,6 +83,11 @@ keyword. At present, no sharp commands will be preserved in the config.
    Allow end user to dump associated data with the nexthop tracking that
    may have been turned on.
 
+.. clicmd:: sharp watch [vrf NAME] redistribute ROUTETYPE
+
+   Allow end user to monitor redistributed routes of ROUTETYPE
+   origin.
+
 .. clicmd:: sharp lsp [update] (0-100000) nexthop-group NAME [prefix A.B.C.D/M TYPE [instance (0-255)]]
 
    Install an LSP using the specified in-label, with nexthops as
index 205b25e53e04461de82857bfbbbf3648187a5fea..ac1686dd27fcb34915f9209d83489465a7c399ca 100644 (file)
@@ -463,6 +463,78 @@ be updated with the new name. To illustrate, if you want to recompile with
 
    ./configure --with-defaultvrfname=global
 
+.. _zebra-ecmp:
+
+ECMP
+====
+
+FRR supports ECMP as part of normal operations and is generally compiled
+with a limit of 64 way ECMP.  This of course can be modified via configure
+options on compilation if the end operator desires to do so.  Individual
+protocols each have their own way of dictating ECMP policy and their
+respective documentation should be read.
+
+ECMP can be inspected in zebra by doing a `show ip route X` command.
+
+.. code-block:: shell
+
+   eva# show ip route 4.4.4.4/32
+   Codes: K - kernel route, C - connected, 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,
+          > - selected route, * - FIB route, q - queued, r - rejected, b - backup
+          t - trapped, o - offload failure
+
+   D>* 4.4.4.4/32 [150/0] via 192.168.161.1, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.2, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.3, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.4, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.5, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.6, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.7, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.8, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.9, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.10, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.11, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.12, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.13, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.14, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.15, enp39s0, weight 1, 00:00:02
+     *                    via 192.168.161.16, enp39s0, weight 1, 00:00:02
+
+In this example we have 16 way ecmp for the 4.4.4.4/32 route.  The `*` character
+tells us that the route is installed in the Data Plane, or FIB.
+
+If you are using the Linux kernel as a Data Plane, this can be inspected
+via a `ip route show X` command:
+
+.. code-block:: shell
+
+   sharpd@eva ~/f/doc(ecmp_doc_change)> ip route show 4.4.4.4/32
+   4.4.4.4 nhid 185483868 proto sharp metric 20
+      nexthop via 192.168.161.1 dev enp39s0 weight 1
+      nexthop via 192.168.161.10 dev enp39s0 weight 1
+      nexthop via 192.168.161.11 dev enp39s0 weight 1
+      nexthop via 192.168.161.12 dev enp39s0 weight 1
+      nexthop via 192.168.161.13 dev enp39s0 weight 1
+      nexthop via 192.168.161.14 dev enp39s0 weight 1
+      nexthop via 192.168.161.15 dev enp39s0 weight 1
+      nexthop via 192.168.161.16 dev enp39s0 weight 1
+      nexthop via 192.168.161.2 dev enp39s0 weight 1
+      nexthop via 192.168.161.3 dev enp39s0 weight 1
+      nexthop via 192.168.161.4 dev enp39s0 weight 1
+      nexthop via 192.168.161.5 dev enp39s0 weight 1
+      nexthop via 192.168.161.6 dev enp39s0 weight 1
+      nexthop via 192.168.161.7 dev enp39s0 weight 1
+      nexthop via 192.168.161.8 dev enp39s0 weight 1
+      nexthop via 192.168.161.9 dev enp39s0 weight 1
+
+Once installed into the FIB, FRR currently has little control over what
+nexthops are choosen to forward packets on.  Currently the Linux kernel
+has a `fib_multipath_hash_policy` sysctl which dictates how the hashing
+algorithm is used to forward packets.
+
 .. _zebra-mpls:
 
 MPLS Commands
@@ -1021,6 +1093,35 @@ For protocols requiring an IPv6 router-id, the following commands are available:
 
    Display the user configured IPv6 router-id.
 
+Expected sysctl settings
+========================
+
+The linux kernel has a variety of sysctl's that affect it's operation as a router.  This
+section is meant to act as a starting point for those sysctl's that must be used in
+order to provide FRR with smooth operation as a router.  This section is not meant
+as the full documentation for sysctl's.  The operator must use the sysctl documentation
+with the linux kernel for that.
+
+.. option:: net.ipv4.ip_forward = 1
+
+   This option allows the linux kernel to forward ipv4 packets incoming from one interface
+   to an outgoing interface.  Without this no forwarding will take place from off box packets.
+
+.. option:: net.ipv6.conf.all_forwarding=1
+
+   This option allows the linux kernel to forward ipv6 packets incoming from one interface
+   to an outgoing interface.  Without this no forwarding will take place from off box packets.
+
+.. option:: net.ipv6.conf.all.keep_addr_on_down=1
+
+   When an interface is taken down, do not remove the v6 addresses associated with the interface.
+   This option is recommended because this is the default behavior for v4 as well.
+
+.. option:: net.ipv6.route.skip_notify_on_dev_down=1
+
+   When an interface is taken down, the linux kernel will not notify, via netlink, about routes
+   that used that interface being removed from the FIB.  This option is recommended because this
+   is the default behavior for v4 as well.
 
 Debugging
 =========
index 126710f8c267464fef3a6c61df4de518f601b052..cb2b3eb69e30dfd7091819adb8fe99c723cc3af2 100644 (file)
@@ -1,5 +1,5 @@
 # This stage builds a dist tarball from the source
-FROM alpine:latest as source-builder
+FROM alpine:3.13 as source-builder
 
 RUN mkdir -p /src/alpine
 COPY alpine/APKBUILD.in /src/alpine
@@ -21,7 +21,7 @@ RUN cd /src \
        && make dist
 
 # This stage builds an apk from the dist tarball
-FROM alpine:latest as alpine-builder
+FROM alpine:3.13 as alpine-builder
 # Don't use nocache here so that abuild can use the cache
 RUN apk add \
                --update-cache \
@@ -44,7 +44,7 @@ RUN cd /dist \
        && abuild -r -P /pkgs/apk
 
 # This stage installs frr from the apk
-FROM alpine:latest
+FROM alpine:3.13
 RUN mkdir -p /pkgs/apk
 COPY --from=alpine-builder /pkgs/apk/ /pkgs/apk/
 RUN apk add \
@@ -56,4 +56,4 @@ RUN apk add \
                --allow-untrusted /pkgs/apk/*/*.apk \
        && rm -rf /pkgs
 COPY docker/alpine/docker-start /usr/lib/frr/docker-start
-ENTRYPOINT [ "/sbin/tini", "--", "/usr/lib/frr/docker-start" ]
+CMD [ "/sbin/tini", "--", "/usr/lib/frr/docker-start" ]
index a92326fcf3b35ec898a42b241bb754e66e25e574..d2ec9f974b858d7806ae1d8d484a8e9a3a0d29e2 100644 (file)
@@ -40,4 +40,4 @@ COPY --from=centos-7-builder /rpmbuild/RPMS/ /pkgs/rpm/
 RUN yum install -y /pkgs/rpm/*/*.rpm \
     && rm -rf /pkgs
 COPY docker/centos-7/docker-start /usr/lib/frr/docker-start
-ENTRYPOINT [ "/usr/lib/frr/docker-start" ]
+CMD [ "/usr/lib/frr/docker-start" ]
index 7ed7948927a8f458459b81516a8cf20451cdfbb3..104501aabc30f04ea2e4f9d948d2e6739f5860df 100644 (file)
@@ -41,4 +41,4 @@ COPY --from=centos-8-builder /rpmbuild/RPMS/ /pkgs/rpm/
 RUN yum install -y /pkgs/rpm/*/*.rpm \
     && rm -rf /pkgs
 COPY docker/centos-8/docker-start /usr/lib/frr/docker-start
-ENTRYPOINT [ "/usr/lib/frr/docker-start" ]
+CMD [ "/usr/lib/frr/docker-start" ]
index 3f830348bcaf3390e8f7ddaaeb9d1b7d36bb12a1..cc9217f10342a376a3040e33752652b4d1a705f4 100644 (file)
@@ -17,4 +17,4 @@ RUN apt-get update && \
     rm -rf /var/lib/apt/lists/*
 
 ADD docker-start /usr/sbin/docker-start
-ENTRYPOINT ["/usr/sbin/docker-start"]
+CMD ["/usr/sbin/docker-start"]
index 43854ab1429f75a1e0329ef75d3e0bd559996fac..a0f31f5ac52217fd4ae5ca6524b497f3b8c8ca0c 100755 (executable)
@@ -7,4 +7,6 @@ set -e
 ##
 chown -R frr:frr /etc/frr
 /etc/init.d/frr start
-exec sleep 10000d
+
+# Sleep forever
+exec tail -f /dev/null
diff --git a/docker/ubuntu18-ci/Dockerfile b/docker/ubuntu18-ci/Dockerfile
new file mode 100644 (file)
index 0000000..f6fa910
--- /dev/null
@@ -0,0 +1,71 @@
+FROM ubuntu:18.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
+# Update Ubuntu Software repository
+RUN apt update && \
+    apt-get install -y \
+      git autoconf automake libtool make libreadline-dev texinfo \
+      pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
+      libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
+      install-info build-essential libsystemd-dev libsnmp-dev perl libcap-dev \
+      libelf-dev \
+      sudo gdb iputils-ping time \
+      mininet python-pip iproute2 iperf && \
+      pip install ipaddr && \
+      pip install "pytest<5" && \
+      pip install "scapy>=2.4.2" && \
+      pip install exabgp==3.4.17
+
+RUN groupadd -r -g 92 frr && \
+      groupadd -r -g 85 frrvty && \
+      adduser --system --ingroup frr --home /home/frr \
+              --gecos "FRR suite" --shell /bin/bash frr && \
+      usermod -a -G frrvty frr && \
+      useradd -d /var/run/exabgp/ -s /bin/false exabgp && \
+      echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \
+      mkdir -p /home/frr && chown frr.frr /home/frr
+
+#for libyang 1
+RUN apt-get install -y cmake libpcre3-dev
+
+USER frr:frr
+
+# build and install libyang1
+RUN cd && pwd && ls -al && \
+    git clone https://github.com/CESNET/libyang.git && \
+    cd libyang && \
+    git checkout v1.0.225 && \
+    mkdir build; cd build && \
+    cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+          -D CMAKE_BUILD_TYPE:String="Release" .. && \
+    make -j $(nproc) && \
+    sudo make install
+
+COPY --chown=frr:frr . /home/frr/frr/
+
+RUN cd && ls -al && ls -al frr
+
+RUN cd ~/frr && \
+    ./bootstrap.sh  && \
+    ./configure \
+       --prefix=/usr \
+       --localstatedir=/var/run/frr \
+       --sbindir=/usr/lib/frr \
+       --sysconfdir=/etc/frr \
+       --enable-vtysh \
+       --enable-pimd \
+       --enable-sharpd \
+       --enable-multipath=64 \
+       --enable-user=frr \
+       --enable-group=frr \
+       --enable-vty-group=frrvty \
+       --enable-snmp=agentx \
+       --with-pkg-extra-version=-my-manual-build && \
+    make -j $(nproc) && \
+    sudo make install
+
+RUN cd ~/frr && make check || true
+
+COPY docker/ubuntu18-ci/docker-start /usr/sbin/docker-start
+CMD ["/usr/sbin/docker-start"]
diff --git a/docker/ubuntu18-ci/README.md b/docker/ubuntu18-ci/README.md
new file mode 100644 (file)
index 0000000..4e8ab89
--- /dev/null
@@ -0,0 +1,44 @@
+# Ubuntu 18.04
+
+This builds an ubuntu 18.04 container for dev / test
+
+# Build
+
+```
+docker build -t frr-ubuntu18:latest  -f docker/ubuntu18-ci/Dockerfile .
+```
+
+# Running
+
+```
+docker run -d --privileged --name frr-ubuntu18 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu18:latest
+```
+
+# make check
+
+```
+docker exec frr-ubuntu18 bash -c 'cd ~/frr ; make check'
+```
+
+# interactive bash
+```
+docker exec -it frr-ubuntu18 bash
+```
+
+# topotest -- when Host O/S is Ubuntu only
+
+```
+docker exec frr-ubuntu18 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+```
+
+# stop & remove container
+
+```
+docker stop frr-ubuntu18 ; docker rm frr-ubuntu18
+```
+
+# remove image
+
+```
+docker rmi frr-ubuntu18:latest
+```
diff --git a/docker/ubuntu18-ci/docker-start b/docker/ubuntu18-ci/docker-start
new file mode 100755 (executable)
index 0000000..9a45c72
--- /dev/null
@@ -0,0 +1,8 @@
+#!/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
+fi
+while true ; do sleep 365d ; done
diff --git a/docker/ubuntu20-ci/Dockerfile b/docker/ubuntu20-ci/Dockerfile
new file mode 100644 (file)
index 0000000..0b08c2f
--- /dev/null
@@ -0,0 +1,74 @@
+FROM ubuntu:20.04
+
+ARG DEBIAN_FRONTEND=noninteractive
+ENV APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=DontWarn
+# Update Ubuntu Software repository
+RUN apt update && \
+    apt-get install -y \
+      git autoconf automake libtool make libreadline-dev texinfo \
+      pkg-config libpam0g-dev libjson-c-dev bison flex python3-pytest \
+      libc-ares-dev python3-dev libsystemd-dev python-ipaddress python3-sphinx \
+      install-info build-essential libsystemd-dev libsnmp-dev perl \
+      libcap-dev python2 libelf-dev \
+      sudo gdb curl iputils-ping time \
+      mininet iproute2 iperf && \
+      curl https://bootstrap.pypa.io/pip/2.7/get-pip.py --output /tmp/get-pip.py && \
+      python2 /tmp/get-pip.py && \
+      rm -f  /tmp/get-pip.py && \
+      pip2 install ipaddr && \
+      pip2 install "pytest<5" && \
+      pip2 install "scapy>=2.4.2" && \
+      pip2 install exabgp==3.4.17
+
+RUN groupadd -r -g 92 frr && \
+      groupadd -r -g 85 frrvty && \
+      adduser --system --ingroup frr --home /home/frr \
+              --gecos "FRR suite" --shell /bin/bash frr && \
+      usermod -a -G frrvty frr && \
+      useradd -d /var/run/exabgp/ -s /bin/false exabgp && \
+      echo 'frr ALL = NOPASSWD: ALL' | tee /etc/sudoers.d/frr && \
+      mkdir -p /home/frr && chown frr.frr /home/frr
+
+#for libyang 1
+RUN apt-get install -y cmake libpcre3-dev
+
+USER frr:frr
+
+# build and install libyang1
+RUN cd && pwd && ls -al && \
+    git clone https://github.com/CESNET/libyang.git && \
+    cd libyang && \
+    git checkout v1.0.225 && \
+    mkdir build; cd build && \
+    cmake -DENABLE_LYD_PRIV=ON -DCMAKE_INSTALL_PREFIX:PATH=/usr \
+          -D CMAKE_BUILD_TYPE:String="Release" .. && \
+    make -j $(nproc) && \
+    sudo make install
+
+COPY --chown=frr:frr . /home/frr/frr/
+
+RUN cd && ls -al && ls -al frr
+
+RUN cd ~/frr && \
+    ./bootstrap.sh  && \
+    ./configure \
+       --prefix=/usr \
+       --localstatedir=/var/run/frr \
+       --sbindir=/usr/lib/frr \
+       --sysconfdir=/etc/frr \
+       --enable-vtysh \
+       --enable-pimd \
+       --enable-sharpd \
+       --enable-multipath=64 \
+       --enable-user=frr \
+       --enable-group=frr \
+       --enable-vty-group=frrvty \
+       --enable-snmp=agentx \
+       --with-pkg-extra-version=-my-manual-build && \
+    make -j $(nproc) && \
+    sudo make install
+
+RUN cd ~/frr && make check || true
+
+COPY docker/ubuntu20-ci/docker-start /usr/sbin/docker-start
+CMD ["/usr/sbin/docker-start"]
diff --git a/docker/ubuntu20-ci/README.md b/docker/ubuntu20-ci/README.md
new file mode 100644 (file)
index 0000000..11138c6
--- /dev/null
@@ -0,0 +1,45 @@
+# Ubuntu 20.04
+
+This builds an ubuntu 20.04 container for dev / test
+
+# Build
+
+```
+docker build -t frr-ubuntu20:latest  -f docker/ubuntu20-ci/Dockerfile .
+```
+
+# Running
+
+```
+docker run -d --privileged --name frr-ubuntu20 --mount type=bind,source=/lib/modules,target=/lib/modules frr-ubuntu20:latest
+```
+
+# make check
+
+```
+docker exec frr-ubuntu20 bash -c 'cd ~/frr ; make check'
+```
+
+# interactive bash
+
+```
+docker exec -it frr-ubuntu20 bash
+```
+
+# topotest -- when Host O/S is Ubuntu only
+
+```
+docker exec frr-ubuntu20 bash -c 'cd ~/frr/tests/topotests/ospf-topo1 ; sudo pytest test_ospf_topo1.py'
+```
+
+# stop & remove container
+
+```
+docker stop frr-ubuntu20 ; docker rm frr-ubuntu18
+```
+
+# remove image
+
+```
+docker rmi frr-ubuntu20:latest
+```
diff --git a/docker/ubuntu20-ci/docker-start b/docker/ubuntu20-ci/docker-start
new file mode 100755 (executable)
index 0000000..9a45c72
--- /dev/null
@@ -0,0 +1,8 @@
+#!/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
+fi
+while true ; do sleep 365d ; done
index 13a2c4206fbe73f8004970ecea772aed22f32fb3..e3680b31a33ffd745abd935b29eb2c4b05a49ac0 100644 (file)
@@ -125,6 +125,10 @@ eigrp_hello_parameter_decode(struct eigrp_neighbor *nbr,
        struct eigrp *eigrp = nbr->ei->eigrp;
        struct TLV_Parameter_Type *param = (struct TLV_Parameter_Type *)tlv;
 
+       /* First validate TLV length */
+       if (tlv->length < sizeof(struct TLV_Parameter_Type))
+               return NULL;
+
        /* copy over the values passed in by the neighbor */
        nbr->K1 = param->K1;
        nbr->K2 = param->K2;
@@ -194,13 +198,22 @@ eigrp_hello_authentication_decode(struct stream *s,
 
        md5 = (struct TLV_MD5_Authentication_Type *)tlv_header;
 
-       if (md5->auth_type == EIGRP_AUTH_TYPE_MD5)
+       if (md5->auth_type == EIGRP_AUTH_TYPE_MD5) {
+               /* Validate tlv length */
+               if (md5->length < sizeof(struct TLV_MD5_Authentication_Type))
+                       return 0;
+
                return eigrp_check_md5_digest(s, md5, nbr,
                                              EIGRP_AUTH_BASIC_HELLO_FLAG);
-       else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256)
+       } else if (md5->auth_type == EIGRP_AUTH_TYPE_SHA256) {
+               /* Validate tlv length */
+               if (md5->length < sizeof(struct TLV_SHA256_Authentication_Type))
+                       return 0;
+
                return eigrp_check_sha256_digest(
                        s, (struct TLV_SHA256_Authentication_Type *)tlv_header,
                        nbr, EIGRP_AUTH_BASIC_HELLO_FLAG);
+       }
 
        return 0;
 }
@@ -223,6 +236,10 @@ static void eigrp_sw_version_decode(struct eigrp_neighbor *nbr,
 {
        struct TLV_Software_Type *version = (struct TLV_Software_Type *)tlv;
 
+       /* Validate TLV length */
+       if (tlv->length < sizeof(struct TLV_Software_Type))
+               return;
+
        nbr->os_rel_major = version->vender_major;
        nbr->os_rel_minor = version->vender_minor;
        nbr->tlv_rel_major = version->eigrp_major;
@@ -250,6 +267,10 @@ static void eigrp_peer_termination_decode(struct eigrp_neighbor *nbr,
        struct TLV_Peer_Termination_type *param =
                (struct TLV_Peer_Termination_type *)tlv;
 
+       /* Validate TLV length */
+       if (tlv->length < sizeof(struct TLV_Peer_Termination_type))
+               return;
+
        uint32_t my_ip = nbr->ei->address.u.prefix4.s_addr;
        uint32_t received_ip = param->neighbor_ip;
 
@@ -346,6 +367,10 @@ void eigrp_hello_receive(struct eigrp *eigrp, struct ip *iph,
                type = ntohs(tlv_header->type);
                length = ntohs(tlv_header->length);
 
+               /* Validate length against packet size */
+               if (length > size)
+                       return;
+
                if ((length > 0) && (length <= size)) {
                        if (IS_DEBUG_EIGRP_PACKET(0, RECV))
                                zlog_debug(
index 0ed7e94968f7f3ff768a5f5b3d02cccdf2aab152..b775c841f025c8c691e3af0b2985693a236d71ce 100644 (file)
@@ -227,8 +227,6 @@ int main(int argc, char **argv, char **envp)
          route_map_add_hook (eigrp_rmap_update);
          route_map_delete_hook (eigrp_rmap_update);*/
        /*if_rmap_init (EIGRP_NODE); */
-       /* Distribute list install. */
-       distribute_list_init(EIGRP_NODE);
 
        frr_config_fork();
        frr_run(master);
index 2b05db71d5cb1f4dd1c2af0edc56c98bc1d65ff8..ea62f9d1becc8105f95fe978b7e1ad57c408426c 100644 (file)
@@ -21,6 +21,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "eigrpd/eigrp_structs.h"
 #include "eigrpd/eigrpd.h"
 #include "eigrpd/eigrp_types.h"
index 0b37733990ebaa401a94764f4098e08d4c493cdf..39e384c121f56c82fc0cfdb25d23fb4a669ac4e3 100644 (file)
@@ -572,9 +572,14 @@ int eigrp_read(struct thread *thread)
            && IS_DEBUG_EIGRP_TRANSMIT(0, PACKET_DETAIL))
                eigrp_header_dump(eigrph);
 
-       //  if (MSG_OK != eigrp_packet_examin(eigrph, stream_get_endp(ibuf) -
-       //  stream_get_getp(ibuf)))
-       //    return -1;
+       if (ntohs(eigrph->ASNumber) != eigrp->AS) {
+               if (IS_DEBUG_EIGRP_TRANSMIT(0, RECV))
+                       zlog_debug(
+                               "ignoring packet from router %u sent to %pI4, wrong AS Number received: %u",
+                               ntohs(eigrph->vrid), &iph->ip_dst,
+                               ntohs(eigrph->ASNumber));
+               return 0;
+       }
 
        /* If incoming interface is passive one, ignore it. */
        if (eigrp_if_is_passive(ei)) {
index 5183e645e596c65123c5e12c7aba52dcb579d12f..90913a5b2877c4c2872b88b55a853bae0ea42d71 100644 (file)
@@ -1130,6 +1130,48 @@ ALIAS(no_set_tag, no_set_tag_val_cmd, "no set tag (0-65535)", NO_STR SET_STR
       "Tag value for routing protocol\n"
       "Tag value\n")
 
+DEFUN (eigrp_distribute_list,
+       eigrp_distribute_list_cmd,
+       "distribute-list [prefix] WORD <in|out> [WORD]",
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_parser(prefix, true, argv[2 + prefix]->text,
+                                     argv[1 + prefix]->arg, ifname);
+}
+
+DEFUN (eigrp_no_distribute_list,
+       eigrp_no_distribute_list_cmd,
+       "no distribute-list [prefix] WORD <in|out> [WORD]",
+       NO_STR
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_no_parser(vty, prefix, true,
+                                        argv[3 + prefix]->text,
+                                        argv[2 + prefix]->arg, ifname);
+}
+
 
 /* Route-map init */
 void eigrp_route_map_init()
@@ -1139,6 +1181,9 @@ void eigrp_route_map_init()
        route_map_add_hook(eigrp_route_map_update);
        route_map_delete_hook(eigrp_route_map_update);
 
+       install_element(EIGRP_NODE, &eigrp_distribute_list_cmd);
+       install_element(EIGRP_NODE, &eigrp_no_distribute_list_cmd);
+
        /*route_map_install_match (&route_match_metric_cmd);
          route_map_install_match (&route_match_interface_cmd);*/
        /*route_map_install_match (&route_match_ip_next_hop_cmd);
index 2e265511f20880b4eb3cbf2d37f82d38be9e37d5..659b5a64ac233a3fd0eb9464f223a06a1435c67e 100644 (file)
@@ -29,7 +29,7 @@
 #ifndef _FPM_PB_H
 #define _FPM_PB_H
 
-#include "route_types.h"
+#include "lib/route_types.h"
 #include "qpb/qpb.h"
 
 #include "fpm/fpm.pb-c.h"
index 045848aee7f18c0c36622f2f16f6398a60bb6c5a..d9ec365ba841ef37ad16899506dde7142f6e2945 100644 (file)
@@ -23,12 +23,12 @@ EXTRA_DIST += grpc/frr-northbound.proto
 
 AM_V_PROTOC = $(am__v_PROTOC_$(V))
 am__v_PROTOC_ = $(am__v_PROTOC_$(AM_DEFAULT_VERBOSITY))
-am__v_PROTOC_0 = @echo "  PROTOC" $@;
+am__v_PROTOC_0 = @echo "  PROTOC  " $@;
 am__v_PROTOC_1 =
 
 SUFFIXES += .pb.h .pb.cc .grpc.pb.cc
 
 .proto.pb.cc:
-       $(AM_V_PROTOC)$(PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^
+       $(AM_V_PROTOC)$(PROTOC) -I$(top_srcdir) --cpp_out=$(top_builddir) $^
 .proto.grpc.pb.cc:
-       $(AM_V_PROTOC)$(PROTOC) -I$(top_srcdir) --grpc_out=$(top_srcdir) --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` $(top_srcdir)/$^
+       $(AM_V_PROTOC)$(PROTOC) -I$(top_srcdir) --grpc_out=$(top_builddir) --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` $^
diff --git a/include/linux/if_packet.h b/include/linux/if_packet.h
new file mode 100644 (file)
index 0000000..057edb3
--- /dev/null
@@ -0,0 +1,16 @@
+#ifndef __LINUX_IF_PACKET_H
+#define __LINUX_IF_PACKET_H
+
+#include <linux/types.h>
+
+struct sockaddr_ll {
+       unsigned short sll_family;
+       __be16 sll_protocol;
+       int sll_ifindex;
+       unsigned short sll_hatype;
+       unsigned char sll_pkttype;
+       unsigned char sll_halen;
+       unsigned char sll_addr[8];
+};
+
+#endif
diff --git a/include/linux/if_tunnel.h b/include/linux/if_tunnel.h
new file mode 100644 (file)
index 0000000..982a1b6
--- /dev/null
@@ -0,0 +1,71 @@
+#ifndef _IF_TUNNEL_H_
+#define _IF_TUNNEL_H_
+
+#include <linux/types.h>
+#include <linux/if.h>
+#include <linux/ip.h>
+#include <linux/in6.h>
+#include <asm/byteorder.h>
+
+
+#define SIOCGETTUNNEL   (SIOCDEVPRIVATE + 0)
+#define SIOCADDTUNNEL   (SIOCDEVPRIVATE + 1)
+#define SIOCDELTUNNEL   (SIOCDEVPRIVATE + 2)
+#define SIOCCHGTUNNEL   (SIOCDEVPRIVATE + 3)
+#define SIOCGETPRL      (SIOCDEVPRIVATE + 4)
+#define SIOCADDPRL      (SIOCDEVPRIVATE + 5)
+#define SIOCDELPRL      (SIOCDEVPRIVATE + 6)
+#define SIOCCHGPRL      (SIOCDEVPRIVATE + 7)
+
+#define GRE_CSUM       __cpu_to_be16(0x8000)
+#define GRE_ROUTING    __cpu_to_be16(0x4000)
+#define GRE_KEY                __cpu_to_be16(0x2000)
+#define GRE_SEQ                __cpu_to_be16(0x1000)
+#define GRE_STRICT     __cpu_to_be16(0x0800)
+#define GRE_REC                __cpu_to_be16(0x0700)
+#define GRE_FLAGS      __cpu_to_be16(0x00F8)
+#define GRE_VERSION    __cpu_to_be16(0x0007)
+
+struct ip_tunnel_parm {
+       char                    name[IFNAMSIZ];
+       int                     link;
+       __be16                  i_flags;
+       __be16                  o_flags;
+       __be32                  i_key;
+       __be32                  o_key;
+       struct iphdr            iph;
+};
+
+/* SIT-mode i_flags */
+#define        SIT_ISATAP      0x0001
+
+struct ip_tunnel_prl {
+       __be32                  addr;
+       __u16                   flags;
+       __u16                   __reserved;
+       __u32                   datalen;
+       __u32                   __reserved2;
+       /* data follows */
+};
+
+/* PRL flags */
+#define        PRL_DEFAULT             0x0001
+
+enum {
+       IFLA_GRE_UNSPEC,
+       IFLA_GRE_LINK,
+       IFLA_GRE_IFLAGS,
+       IFLA_GRE_OFLAGS,
+       IFLA_GRE_IKEY,
+       IFLA_GRE_OKEY,
+       IFLA_GRE_LOCAL,
+       IFLA_GRE_REMOTE,
+       IFLA_GRE_TTL,
+       IFLA_GRE_TOS,
+       IFLA_GRE_PMTUDISC,
+       __IFLA_GRE_MAX,
+};
+
+#define IFLA_GRE_MAX   (__IFLA_GRE_MAX - 1)
+
+#endif /* _IF_TUNNEL_H_ */
index a637429e848b51844df7e669f3011cda74ebe05d..7fd9c07ed248670b4c21abaa7f7ca2f2c347c116 100644 (file)
@@ -73,61 +73,42 @@ DEFINE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp));
 int isis_if_new_hook(struct interface *);
 int isis_if_delete_hook(struct interface *);
 
-static int isis_circuit_smmp_id_gen(struct isis_circuit *circuit)
-{
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
-       struct isis *isis = NULL;
-       uint32_t id;
-       uint32_t i;
-
-       isis = isis_lookup_by_vrfid(vrf->vrf_id);
-       if (isis == NULL)
-               return 0;
-
-       id = isis->snmp_circuit_id_last;
-       id++;
+DEFINE_HOOK(isis_circuit_new_hook, (struct isis_circuit *circuit), (circuit));
+DEFINE_HOOK(isis_circuit_del_hook, (struct isis_circuit *circuit), (circuit));
 
-       /* find next unused entry */
-       for (i = 0; i < SNMP_CIRCUITS_MAX; i++) {
-               if (id >= SNMP_CIRCUITS_MAX) {
-                       id = 0;
-                       continue;
-               }
-
-               if (id == 0)
-                       continue;
+static void isis_circuit_enable(struct isis_circuit *circuit)
+{
+       struct isis_area *area;
+       struct interface *ifp = circuit->interface;
 
-               if (isis->snmp_circuits[id] == NULL)
-                       break;
+       area = isis_area_lookup(circuit->tag, ifp->vrf_id);
+       if (area)
+               isis_area_add_circuit(area, circuit);
 
-               id++;
-       }
+       if (if_is_operative(ifp))
+               isis_csm_state_change(IF_UP_FROM_Z, circuit, ifp);
+}
 
-       if (i == SNMP_CIRCUITS_MAX) {
-               zlog_warn("Could not allocate a smmp-circuit-id");
-               return 0;
-       }
+static void isis_circuit_disable(struct isis_circuit *circuit)
+{
+       struct isis_area *area = circuit->area;
+       struct interface *ifp = circuit->interface;
 
-       isis->snmp_circuits[id] = circuit;
-       isis->snmp_circuit_id_last = id;
-       circuit->snmp_id = id;
+       if (if_is_operative(ifp))
+               isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp);
 
-       return 1;
+       if (area)
+               isis_area_del_circuit(area, circuit);
 }
 
-struct isis_circuit *isis_circuit_new(struct isis *isis)
+struct isis_circuit *isis_circuit_new(struct interface *ifp, const char *tag)
 {
        struct isis_circuit *circuit;
        int i;
 
        circuit = XCALLOC(MTYPE_ISIS_CIRCUIT, sizeof(struct isis_circuit));
 
-       circuit->isis = isis;
-       /*
-        * Note: if snmp-id generation failed circuit will fail
-        * up operation
-        */
-       isis_circuit_smmp_id_gen(circuit);
+       circuit->tag = XSTRDUP(MTYPE_ISIS_CIRCUIT, tag);
 
        /*
         * Default values
@@ -193,31 +174,39 @@ struct isis_circuit *isis_circuit_new(struct isis *isis)
        isis_lfa_excluded_ifaces_init(circuit, ISIS_LEVEL1);
        isis_lfa_excluded_ifaces_init(circuit, ISIS_LEVEL2);
 
+       circuit->ldp_sync_info = ldp_sync_info_create();
+       circuit->ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
+
        QOBJ_REG(circuit, isis_circuit);
 
+       isis_circuit_if_bind(circuit, ifp);
+
+       if (ifp->ifindex != IFINDEX_INTERNAL)
+               isis_circuit_enable(circuit);
+
        return circuit;
 }
 
 void isis_circuit_del(struct isis_circuit *circuit)
 {
-       struct isis *isis = NULL;
-
        if (!circuit)
                return;
 
-       QOBJ_UNREG(circuit);
-
-       if (circuit->interface) {
-               isis = isis_lookup_by_vrfid(circuit->interface->vrf_id);
-               isis->snmp_circuits[circuit->snmp_id] = NULL;
-       }
+       if (circuit->interface->ifindex != IFINDEX_INTERNAL)
+               isis_circuit_disable(circuit);
 
        isis_circuit_if_unbind(circuit, circuit->interface);
 
+       QOBJ_UNREG(circuit);
+
+       ldp_sync_info_free(&circuit->ldp_sync_info);
+
        circuit_mt_finish(circuit);
        isis_lfa_excluded_ifaces_clear(circuit, ISIS_LEVEL1);
        isis_lfa_excluded_ifaces_clear(circuit, ISIS_LEVEL2);
 
+       XFREE(MTYPE_ISIS_CIRCUIT, circuit->tag);
+
        /* and lastly the circuit itself */
        XFREE(MTYPE_ISIS_CIRCUIT, circuit);
 
@@ -228,6 +217,7 @@ void isis_circuit_configure(struct isis_circuit *circuit,
                            struct isis_area *area)
 {
        assert(area);
+       circuit->isis = area->isis;
        circuit->area = area;
 
        /*
@@ -247,12 +237,16 @@ void isis_circuit_configure(struct isis_circuit *circuit,
 
        circuit->idx = flags_get_index(&area->flags);
 
+       hook_call(isis_circuit_new_hook, circuit);
+
        return;
 }
 
 void isis_circuit_deconfigure(struct isis_circuit *circuit,
                              struct isis_area *area)
 {
+       hook_call(isis_circuit_del_hook, circuit);
+
        /* Free the index of SRM and SSN flags */
        flags_free_index(&area->flags, circuit->idx);
        circuit->idx = 0;
@@ -260,6 +254,7 @@ void isis_circuit_deconfigure(struct isis_circuit *circuit,
        assert(circuit->area == area);
        listnode_delete(area->circuit_list, circuit);
        circuit->area = NULL;
+       circuit->isis = NULL;
 
        return;
 }
@@ -284,29 +279,7 @@ struct isis_circuit *circuit_lookup_by_ifp(struct interface *ifp,
 
 struct isis_circuit *circuit_scan_by_ifp(struct interface *ifp)
 {
-       struct isis_area *area;
-       struct listnode *node;
-       struct isis_circuit *circuit;
-       struct isis *isis = NULL;
-
-       if (ifp->info)
-               return (struct isis_circuit *)ifp->info;
-
-       isis = isis_lookup_by_vrfid(ifp->vrf_id);
-       if (isis == NULL) {
-               zlog_warn(" %s : ISIS routing instance not found", __func__);
-               return NULL;
-       }
-
-       if (isis->area_list) {
-               for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
-                       circuit =
-                               circuit_lookup_by_ifp(ifp, area->circuit_list);
-                       if (circuit)
-                               return circuit;
-               }
-       }
-       return circuit_lookup_by_ifp(ifp, isis->init_circ_list);
+       return (struct isis_circuit *)ifp->info;
 }
 
 DEFINE_HOOK(isis_circuit_add_addr_hook, (struct isis_circuit *circuit),
@@ -516,8 +489,6 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp)
        struct listnode *node, *nnode;
        struct connected *conn;
 
-       isis_circuit_if_bind(circuit, ifp);
-
        if (if_is_broadcast(ifp)) {
                if (fabricd || circuit->circ_type_config == CIRCUIT_T_P2P)
                        circuit->circ_type = CIRCUIT_T_P2P;
@@ -681,13 +652,6 @@ int isis_circuit_up(struct isis_circuit *circuit)
                return ISIS_OK;
        }
 
-       if (circuit->snmp_id == 0) {
-               /* We cannot bring circuit up if does not have snmp-id */
-               flog_err(EC_ISIS_CONFIG,
-                        "No snnmp-id: there are too many circuits:");
-               return ISIS_ERROR;
-       }
-
        if (circuit->area->lsp_mtu > isis_circuit_pdu_size(circuit)) {
                flog_err(
                        EC_ISIS_CONFIG,
@@ -789,6 +753,11 @@ int isis_circuit_up(struct isis_circuit *circuit)
 
        circuit->last_uptime = time(NULL);
 
+       if (circuit->area->mta && circuit->area->mta->status)
+               isis_link_params_update(circuit, circuit->interface);
+
+       isis_if_ldp_sync_enable(circuit);
+
 #ifndef FABRICD
        /* send northbound notification */
        isis_notif_if_state_change(circuit, false);
@@ -804,6 +773,8 @@ void isis_circuit_down(struct isis_circuit *circuit)
        isis_notif_if_state_change(circuit, true);
 #endif /* ifndef FABRICD */
 
+       isis_if_ldp_sync_disable(circuit);
+
        /* log adjacency changes if configured to do so */
        if (circuit->area->log_adj_changes) {
                struct isis_adjacency *adj = NULL;
@@ -1345,23 +1316,6 @@ static int isis_interface_config_write(struct vty *vty)
 }
 #endif /* ifdef FABRICD */
 
-struct isis_circuit *isis_circuit_create(struct isis_area *area,
-                                        struct interface *ifp)
-{
-       struct isis_circuit *circuit = circuit_scan_by_ifp(ifp);
-
-       if (circuit && circuit->area)
-               return NULL;
-       circuit = isis_csm_state_change(ISIS_ENABLE, circuit, area);
-       if (circuit->state != C_STATE_CONF && circuit->state != C_STATE_UP)
-               return circuit;
-       isis_circuit_if_bind(circuit, ifp);
-       if (circuit->area->mta && circuit->area->mta->status)
-               isis_link_params_update(circuit, ifp);
-
-       return circuit;
-}
-
 void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router,
                         bool ipv6_router)
 {
@@ -1377,24 +1331,13 @@ void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router,
        circuit->ipv6_router = ipv6_router;
        circuit_update_nlpids(circuit);
 
-       /* the area should always be there if we get here, but in the past
-        * there were corner cases where the area was NULL (e.g. because the
-        * circuit was deconfigured following a validation error). Do not
-        * segfault if this happens again.
-        */
-       if (!area) {
-               zlog_err("%s: NULL area for circuit %u", __func__,
-                        circuit->circuit_id);
-               return;
-       }
-
-       area->ip_circuits += ip_router - old_ipr;
-       area->ipv6_circuits += ipv6_router - old_ipv6r;
+       if (area) {
+               area->ip_circuits += ip_router - old_ipr;
+               area->ipv6_circuits += ipv6_router - old_ipv6r;
 
-       if (!ip_router && !ipv6_router)
-               isis_csm_state_change(ISIS_DISABLE, circuit, area);
-       else
-               lsp_regenerate_schedule(area, circuit->is_type, 0);
+               if (ip_router || ipv6_router)
+                       lsp_regenerate_schedule(area, circuit->is_type, 0);
+       }
 }
 
 ferr_r isis_circuit_passive_set(struct isis_circuit *circuit, bool passive)
@@ -1516,8 +1459,9 @@ int isis_circuit_mt_enabled_set(struct isis_circuit *circuit, uint16_t mtid,
        setting = circuit_get_mt_setting(circuit, mtid);
        if (setting->enabled != enabled) {
                setting->enabled = enabled;
-               lsp_regenerate_schedule(circuit->area, IS_LEVEL_1 | IS_LEVEL_2,
-                                       0);
+               if (circuit->area)
+                       lsp_regenerate_schedule(circuit->area,
+                                               IS_LEVEL_1 | IS_LEVEL_2, 0);
        }
 
        return CMD_SUCCESS;
@@ -1530,27 +1474,19 @@ int isis_if_new_hook(struct interface *ifp)
 
 int isis_if_delete_hook(struct interface *ifp)
 {
-       struct isis_circuit *circuit;
-       /* Clean up the circuit data */
-       if (ifp && ifp->info) {
-               circuit = ifp->info;
-               isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp);
-       }
+       if (ifp->info)
+               isis_circuit_del(ifp->info);
 
        return 0;
 }
 
 static int isis_ifp_create(struct interface *ifp)
 {
-       struct vrf *vrf = NULL;
+       struct isis_circuit *circuit = ifp->info;
+
+       if (circuit)
+               isis_circuit_enable(circuit);
 
-       if (if_is_operative(ifp)) {
-               vrf = vrf_lookup_by_id(ifp->vrf_id);
-               if (vrf)
-                       isis_global_instance_create(vrf->name);
-               isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp),
-                                     ifp);
-       }
        hook_call(isis_if_new_hook, ifp);
 
        return 0;
@@ -1558,34 +1494,33 @@ static int isis_ifp_create(struct interface *ifp)
 
 static int isis_ifp_up(struct interface *ifp)
 {
-       isis_csm_state_change(IF_UP_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
+       struct isis_circuit *circuit = ifp->info;
+
+       if (circuit)
+               isis_csm_state_change(IF_UP_FROM_Z, circuit, ifp);
 
        return 0;
 }
 
 static int isis_ifp_down(struct interface *ifp)
 {
-       struct isis_circuit *circuit;
+       struct isis_circuit *circuit = ifp->info;
+
+       if (circuit) {
+               isis_csm_state_change(IF_DOWN_FROM_Z, circuit, ifp);
 
-       circuit = isis_csm_state_change(IF_DOWN_FROM_Z,
-                                       circuit_scan_by_ifp(ifp), ifp);
-       if (circuit)
                SET_FLAG(circuit->flags, ISIS_CIRCUIT_FLAPPED_AFTER_SPF);
+       }
 
        return 0;
 }
 
 static int isis_ifp_destroy(struct interface *ifp)
 {
-       if (if_is_operative(ifp))
-               zlog_warn("Zebra: got delete of %s, but interface is still up",
-                         ifp->name);
-
-       isis_csm_state_change(IF_DOWN_FROM_Z, circuit_scan_by_ifp(ifp), ifp);
+       struct isis_circuit *circuit = ifp->info;
 
-       /* Cannot call if_delete because we should retain the pseudo interface
-          in case there is configuration info attached to it. */
-       if_delete_retain(ifp);
+       if (circuit)
+               isis_circuit_disable(circuit);
 
        return 0;
 }
index cbe4040b64d6cbaa66dd4822af9f7e2cc119aeb2..84c3ca3ff2b43f47a7e5f843373fad4b8f74e5f8 100644 (file)
@@ -31,6 +31,7 @@
 
 #include "isis_constants.h"
 #include "isis_common.h"
+#include "isis_csm.h"
 
 DECLARE_HOOK(isis_if_new_hook, (struct interface *ifp), (ifp));
 
@@ -77,7 +78,7 @@ struct isis_circuit_arg {
 };
 
 struct isis_circuit {
-       int state;
+       enum isis_circuit_state state;
        uint8_t circuit_id;       /* l1/l2 bcast CircuitID */
        time_t last_uptime;
        struct isis *isis;
@@ -121,6 +122,7 @@ struct isis_circuit {
        /*
         * Configurables
         */
+       char *tag;                     /* area tag */
        struct isis_passwd passwd;     /* Circuit rx/tx password */
        int is_type;                   /* circuit is type == level of circuit
                                        * differentiated from circuit type (media) */
@@ -150,6 +152,7 @@ struct isis_circuit {
        struct hash *lfa_excluded_ifaces[ISIS_LEVELS];
        bool tilfa_protection[ISIS_LEVELS];
        bool tilfa_node_protection[ISIS_LEVELS];
+       bool tilfa_link_fallback[ISIS_LEVELS];
        /*
         * Counters as in 10589--11.2.5.9
         */
@@ -179,7 +182,7 @@ struct isis_circuit {
 DECLARE_QOBJ_TYPE(isis_circuit);
 
 void isis_circuit_init(void);
-struct isis_circuit *isis_circuit_new(struct isis *isis);
+struct isis_circuit *isis_circuit_new(struct interface *ifp, const char *tag);
 void isis_circuit_del(struct isis_circuit *circuit);
 struct isis_circuit *circuit_lookup_by_ifp(struct interface *ifp,
                                           struct list *list);
@@ -206,8 +209,6 @@ void isis_circuit_print_vty(struct isis_circuit *circuit, struct vty *vty,
 size_t isis_circuit_pdu_size(struct isis_circuit *circuit);
 void isis_circuit_stream(struct isis_circuit *circuit, struct stream **stream);
 
-struct isis_circuit *isis_circuit_create(struct isis_area *area,
-                                        struct interface *ifp);
 void isis_circuit_af_set(struct isis_circuit *circuit, bool ip_router,
                         bool ipv6_router);
 ferr_r isis_circuit_passive_set(struct isis_circuit *circuit, bool passive);
@@ -237,4 +238,7 @@ DECLARE_HOOK(isis_circuit_config_write,
 DECLARE_HOOK(isis_circuit_add_addr_hook, (struct isis_circuit *circuit),
             (circuit));
 
+DECLARE_HOOK(isis_circuit_new_hook, (struct isis_circuit *circuit), (circuit));
+DECLARE_HOOK(isis_circuit_del_hook, (struct isis_circuit *circuit), (circuit));
+
 #endif /* _ZEBRA_ISIS_CIRCUIT_H */
index b108210686486617594d512209d7b648db0e261c..f316e0279ce83394e2e30d717f2dbba3d19f1c4e 100644 (file)
@@ -62,19 +62,7 @@ DEFPY_YANG_NOSH(router_isis, router_isis_cmd,
                 "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
                 vrf_name);
        nb_cli_enqueue_change(vty, ".", NB_OP_CREATE, NULL);
-       /* default value in yang for is-type is level-1, but in FRR
-        * the first instance is assigned is-type level-1-2. We
-        * need to make sure to set it in the yang model so that it
-        * is consistent with what FRR sees.
-        */
-
-       if (!im) {
-               return CMD_SUCCESS;
-       }
 
-       if (listcount(im->isis) == 0)
-               nb_cli_enqueue_change(vty, "./is-type", NB_OP_MODIFY,
-                                     "level-1-2");
        ret = nb_cli_apply_changes(vty, base_xpath);
        if (ret == CMD_SUCCESS)
                VTY_PUSH_XPATH(ISIS_NODE, base_xpath);
@@ -82,16 +70,42 @@ DEFPY_YANG_NOSH(router_isis, router_isis_cmd,
        return ret;
 }
 
+struct if_iter {
+       struct vty *vty;
+       const char *tag;
+};
+
+static int if_iter_cb(const struct lyd_node *dnode, void *arg)
+{
+       struct if_iter *iter = arg;
+       const char *tag;
+
+       if (!yang_dnode_exists(dnode, "frr-isisd:isis/area-tag"))
+               return YANG_ITER_CONTINUE;
+
+       tag = yang_dnode_get_string(dnode, "frr-isisd:isis/area-tag");
+       if (strmatch(tag, iter->tag)) {
+               char xpath[XPATH_MAXLEN];
+               const char *name = yang_dnode_get_string(dnode, "name");
+               const char *vrf = yang_dnode_get_string(dnode, "vrf");
+
+               snprintf(
+                       xpath, XPATH_MAXLEN,
+                       "/frr-interface:lib/interface[name='%s'][vrf='%s']/frr-isisd:isis",
+                       name, vrf);
+               nb_cli_enqueue_change(iter->vty, xpath, NB_OP_DESTROY, NULL);
+       }
+
+       return YANG_ITER_CONTINUE;
+}
+
 DEFPY_YANG(no_router_isis, no_router_isis_cmd,
           "no router isis WORD$tag [vrf NAME$vrf_name]",
           NO_STR ROUTER_STR
           "ISO IS-IS\n"
           "ISO Routing area tag\n" VRF_CMD_HELP_STR)
 {
-       char temp_xpath[XPATH_MAXLEN];
-       struct listnode *node, *nnode;
-       struct isis_circuit *circuit = NULL;
-       struct isis_area *area = NULL;
+       struct if_iter iter;
 
        if (!vrf_name)
                vrf_name = VRF_DEFAULT_NAME;
@@ -104,24 +118,13 @@ DEFPY_YANG(no_router_isis, no_router_isis_cmd,
                return CMD_ERR_NOTHING_TODO;
        }
 
+       iter.vty = vty;
+       iter.tag = tag;
+
+       yang_dnode_iterate(if_iter_cb, &iter, vty->candidate_config->dnode,
+                          "/frr-interface:lib/interface[vrf='%s']", vrf_name);
+
        nb_cli_enqueue_change(vty, ".", NB_OP_DESTROY, NULL);
-       area = isis_area_lookup_by_vrf(tag, vrf_name);
-       if (area && area->circuit_list && listcount(area->circuit_list)) {
-               for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
-                                      circuit)) {
-                       /* add callbacks to delete each of the circuits listed
-                        */
-                       const char *vrf_name =
-                               vrf_lookup_by_id(circuit->interface->vrf_id)
-                                       ->name;
-                       snprintf(
-                               temp_xpath, XPATH_MAXLEN,
-                               "/frr-interface:lib/interface[name='%s'][vrf='%s']/frr-isisd:isis",
-                               circuit->interface->name, vrf_name);
-                       nb_cli_enqueue_change(vty, temp_xpath, NB_OP_DESTROY,
-                                             NULL);
-               }
-       }
 
        return nb_cli_apply_changes(
                vty, "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
@@ -150,95 +153,48 @@ void cli_show_router_isis(struct vty *vty, struct lyd_node *dnode,
  * XPath: /frr-isisd:isis/instance
  */
 DEFPY_YANG(ip_router_isis, ip_router_isis_cmd,
-          "ip router isis WORD$tag [vrf NAME$vrf_name]",
+          "ip router isis WORD$tag",
           "Interface Internet Protocol config commands\n"
           "IP router interface commands\n"
           "IS-IS routing protocol\n"
-          "Routing process tag\n" VRF_CMD_HELP_STR)
+          "Routing process tag\n")
 {
-       char temp_xpath[XPATH_MAXLEN];
-       const char *circ_type;
-       struct isis_area *area = NULL;
+       char inst_xpath[XPATH_MAXLEN];
+       struct lyd_node *if_dnode, *inst_dnode;
+       const char *circ_type = NULL;
+       const char *vrf_name;
        struct interface *ifp;
-       struct vrf *vrf;
-
-       /* area will be created if it is not present. make sure the yang model
-        * is synced with FRR and call the appropriate NB cb.
-        */
 
-       if (!im) {
-               return CMD_SUCCESS;
-       }
-       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
-       if (!vrf_name) {
-               if (ifp) {
-                       if (ifp->vrf_id == VRF_DEFAULT)
-                               vrf_name = VRF_DEFAULT_NAME;
-                       else {
-                               vrf = vrf_lookup_by_id(ifp->vrf_id);
-                               if (vrf && !vrf_name)
-                                       vrf_name = vrf->name;
-                       }
-               } else
-                       vrf_name = VRF_DEFAULT_NAME;
+       if_dnode = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+       if (!if_dnode) {
+               vty_out(vty, "%% Failed to get iface dnode in candidate DB\n");
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
-       area = isis_area_lookup_by_vrf(tag, vrf_name);
-       if (!area) {
-               isis_global_instance_create(vrf_name);
-               snprintf(temp_xpath, XPATH_MAXLEN,
-                        "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']",
-                        tag, vrf_name);
-               nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
-               snprintf(
-                       temp_xpath, XPATH_MAXLEN,
-                       "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type",
-                       tag, vrf_name);
-               nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
-                                     listcount(im->isis) == 0 ? "level-1-2"
-                                                              : NULL);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
-                                     NULL);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
-                                     NB_OP_MODIFY, tag);
+       vrf_name = yang_dnode_get_string(if_dnode, "vrf");
 
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
-                                     vrf_name);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
-                                     NB_OP_MODIFY, "true");
-               nb_cli_enqueue_change(
-                       vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY,
-                       listcount(im->isis) == 0 ? "level-1-2" : "level-1");
-       } else {
-               /* area exists, circuit type defaults to its area's is_type */
-               switch (area->is_type) {
-               case IS_LEVEL_1:
-                       circ_type = "level-1";
-                       break;
-               case IS_LEVEL_2:
-                       circ_type = "level-2";
-                       break;
-               case IS_LEVEL_1_AND_2:
-                       circ_type = "level-1-2";
-                       break;
-               default:
-                       /* just to silence compiler warnings */
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
-                                     NULL);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
-                                     NB_OP_MODIFY, tag);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
-                                     vrf_name);
+       snprintf(inst_xpath, XPATH_MAXLEN,
+                "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
+                vrf_name);
 
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
-                                     NB_OP_MODIFY, "true");
+       /* if instance exists then inherit its type, create it otherwise */
+       inst_dnode = yang_dnode_get(vty->candidate_config->dnode, inst_xpath);
+       if (inst_dnode)
+               circ_type = yang_dnode_get_string(inst_dnode, "is-type");
+       else
+               nb_cli_enqueue_change(vty, inst_xpath, NB_OP_CREATE, NULL);
+
+       nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL);
+       nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", NB_OP_MODIFY,
+                             tag);
+       nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv4-routing",
+                             NB_OP_MODIFY, "true");
+       if (circ_type)
                nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
                                      NB_OP_MODIFY, circ_type);
-       }
 
        /* check if the interface is a loopback and if so set it as passive */
+       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
        if (ifp && if_is_loopback(ifp))
                nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
                                      NB_OP_MODIFY, "true");
@@ -246,95 +202,56 @@ DEFPY_YANG(ip_router_isis, ip_router_isis_cmd,
        return nb_cli_apply_changes(vty, NULL);
 }
 
+ALIAS_HIDDEN(ip_router_isis, ip_router_isis_vrf_cmd,
+            "ip router isis WORD$tag vrf NAME$vrf_name",
+            "Interface Internet Protocol config commands\n"
+            "IP router interface commands\n"
+            "IS-IS routing protocol\n"
+            "Routing process tag\n" VRF_CMD_HELP_STR)
+
 DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd,
-          "ipv6 router isis WORD$tag [vrf NAME$vrf_name]",
+          "ipv6 router isis WORD$tag",
           "Interface Internet Protocol config commands\n"
           "IP router interface commands\n"
           "IS-IS routing protocol\n"
-          "Routing process tag\n" VRF_CMD_HELP_STR)
+          "Routing process tag\n")
 {
-       char temp_xpath[XPATH_MAXLEN];
-       const char *circ_type;
+       char inst_xpath[XPATH_MAXLEN];
+       struct lyd_node *if_dnode, *inst_dnode;
+       const char *circ_type = NULL;
+       const char *vrf_name;
        struct interface *ifp;
-       struct isis_area *area;
-       struct vrf *vrf;
 
-       /* area will be created if it is not present. make sure the yang model
-        * is synced with FRR and call the appropriate NB cb.
-        */
-
-       if (!im)
-               return CMD_SUCCESS;
-
-       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
-       if (!vrf_name) {
-               if (ifp) {
-                       if (ifp->vrf_id == VRF_DEFAULT)
-                               vrf_name = VRF_DEFAULT_NAME;
-                       else {
-                               vrf = vrf_lookup_by_id(ifp->vrf_id);
-                               if (vrf && !vrf_name)
-                                       vrf_name = vrf->name;
-                       }
-               } else
-                       vrf_name = VRF_DEFAULT_NAME;
+       if_dnode = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+       if (!if_dnode) {
+               vty_out(vty, "%% Failed to get iface dnode in candidate DB\n");
+               return CMD_WARNING_CONFIG_FAILED;
        }
 
-       area = isis_area_lookup_by_vrf(tag, vrf_name);
-       if (!area) {
-               isis_global_instance_create(vrf_name);
-               snprintf(temp_xpath, XPATH_MAXLEN,
-                        "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']",
-                        tag, vrf_name);
-               nb_cli_enqueue_change(vty, temp_xpath, NB_OP_CREATE, tag);
-               snprintf(
-                       temp_xpath, XPATH_MAXLEN,
-                       "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']/is-type",
-                       tag, vrf_name);
-               nb_cli_enqueue_change(vty, temp_xpath, NB_OP_MODIFY,
-                                     listcount(im->isis) == 0 ? "level-1-2"
-                                                              : NULL);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
-                                     NULL);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
-                                     NB_OP_MODIFY, tag);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
-                                     vrf_name);
+       vrf_name = yang_dnode_get_string(if_dnode, "vrf");
 
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
-                                     NB_OP_MODIFY, "true");
-               nb_cli_enqueue_change(
-                       vty, "./frr-isisd:isis/circuit-type", NB_OP_MODIFY,
-                       listcount(im->isis) == 0 ? "level-1-2" : "level-1");
-       } else {
-               /* area exists, circuit type defaults to its area's is_type */
-               switch (area->is_type) {
-               case IS_LEVEL_1:
-                       circ_type = "level-1";
-                       break;
-               case IS_LEVEL_2:
-                       circ_type = "level-2";
-                       break;
-               case IS_LEVEL_1_AND_2:
-                       circ_type = "level-1-2";
-                       break;
-               default:
-                       /* just to silence compiler warnings */
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE,
-                                     NULL);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag",
-                                     NB_OP_MODIFY, tag);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/vrf", NB_OP_MODIFY,
-                                     vrf_name);
-               nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
-                                     NB_OP_MODIFY, "true");
+       snprintf(inst_xpath, XPATH_MAXLEN,
+                "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
+                vrf_name);
+
+       /* if instance exists then inherit its type, create it otherwise */
+       inst_dnode = yang_dnode_get(vty->candidate_config->dnode, inst_xpath);
+       if (inst_dnode)
+               circ_type = yang_dnode_get_string(inst_dnode, "is-type");
+       else
+               nb_cli_enqueue_change(vty, inst_xpath, NB_OP_CREATE, NULL);
+
+       nb_cli_enqueue_change(vty, "./frr-isisd:isis", NB_OP_CREATE, NULL);
+       nb_cli_enqueue_change(vty, "./frr-isisd:isis/area-tag", NB_OP_MODIFY,
+                             tag);
+       nb_cli_enqueue_change(vty, "./frr-isisd:isis/ipv6-routing",
+                             NB_OP_MODIFY, "true");
+       if (circ_type)
                nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
                                      NB_OP_MODIFY, circ_type);
-       }
 
        /* check if the interface is a loopback and if so set it as passive */
+       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
        if (ifp && if_is_loopback(ifp))
                nb_cli_enqueue_change(vty, "./frr-isisd:isis/passive",
                                      NB_OP_MODIFY, "true");
@@ -342,15 +259,21 @@ DEFPY_YANG(ip6_router_isis, ip6_router_isis_cmd,
        return nb_cli_apply_changes(vty, NULL);
 }
 
+ALIAS_HIDDEN(ip6_router_isis, ip6_router_isis_vrf_cmd,
+            "ipv6 router isis WORD$tag vrf NAME$vrf_name",
+            "Interface Internet Protocol config commands\n"
+            "IP router interface commands\n"
+            "IS-IS routing protocol\n"
+            "Routing process tag\n" VRF_CMD_HELP_STR)
+
 DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd,
-          "no <ip|ipv6>$ip router isis [WORD]$tag [vrf NAME$vrf_name]",
+          "no <ip|ipv6>$ip router isis [WORD]$tag",
           NO_STR
           "Interface Internet Protocol config commands\n"
           "IP router interface commands\n"
           "IP router interface commands\n"
           "IS-IS routing protocol\n"
-          "Routing process tag\n"
-          VRF_CMD_HELP_STR)
+          "Routing process tag\n")
 {
        const struct lyd_node *dnode;
 
@@ -383,36 +306,32 @@ DEFPY_YANG(no_ip_router_isis, no_ip_router_isis_cmd,
        return nb_cli_apply_changes(vty, NULL);
 }
 
+ALIAS_HIDDEN(no_ip_router_isis, no_ip_router_isis_vrf_cmd,
+            "no <ip|ipv6>$ip router isis WORD$tag vrf NAME$vrf_name",
+            NO_STR
+            "Interface Internet Protocol config commands\n"
+            "IP router interface commands\n"
+            "IP router interface commands\n"
+            "IS-IS routing protocol\n"
+            "Routing process tag\n"
+            VRF_CMD_HELP_STR)
+
 void cli_show_ip_isis_ipv4(struct vty *vty, struct lyd_node *dnode,
                           bool show_defaults)
 {
-       const char *vrf;
-
-       vrf = yang_dnode_get_string(dnode, "../vrf");
-
        if (!yang_dnode_get_bool(dnode, NULL))
                vty_out(vty, " no");
-       vty_out(vty, " ip router isis %s",
+       vty_out(vty, " ip router isis %s\n",
                yang_dnode_get_string(dnode, "../area-tag"));
-       if (!strmatch(vrf, VRF_DEFAULT_NAME))
-               vty_out(vty, " vrf %s", vrf);
-       vty_out(vty, "\n");
 }
 
 void cli_show_ip_isis_ipv6(struct vty *vty, struct lyd_node *dnode,
                           bool show_defaults)
 {
-       const char *vrf;
-
-       vrf = yang_dnode_get_string(dnode, "../vrf");
-
        if (!yang_dnode_get_bool(dnode, NULL))
                vty_out(vty, " no");
-       vty_out(vty, " ipv6 router isis %s",
+       vty_out(vty, " ipv6 router isis %s\n",
                yang_dnode_get_string(dnode, "../area-tag"));
-       if (!strmatch(vrf, VRF_DEFAULT_NAME))
-               vty_out(vty, " vrf %s", vrf);
-       vty_out(vty, "\n");
 }
 
 /*
@@ -2584,50 +2503,41 @@ DEFPY_YANG(no_isis_circuit_type, no_isis_circuit_type_cmd,
       "Level-1-2 adjacencies are formed\n"
       "Level-2 only adjacencies are formed\n")
 {
-       struct interface *ifp;
-       struct isis_circuit *circuit;
-       int is_type;
-       const char *circ_type;
+       char inst_xpath[XPATH_MAXLEN];
+       struct lyd_node *if_dnode, *inst_dnode;
+       const char *vrf_name;
+       const char *tag;
+       const char *circ_type = NULL;
 
        /*
         * Default value depends on whether the circuit is part of an area,
         * and the is-type of the area if there is one. So we need to do this
         * here.
         */
-       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
-       if (!ifp)
-               goto def_val;
+       if_dnode = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+       if (!if_dnode) {
+               vty_out(vty, "%% Failed to get iface dnode in candidate DB\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
-       circuit = circuit_scan_by_ifp(ifp);
-       if (!circuit)
-               goto def_val;
+       if (!yang_dnode_exists(if_dnode, "frr-isisd:isis/area-tag")) {
+               vty_out(vty, "%% ISIS is not configured on the interface\n");
+               return CMD_WARNING_CONFIG_FAILED;
+       }
 
-       if (circuit->state == C_STATE_UP)
-               is_type = circuit->area->is_type;
-       else
-               goto def_val;
+       vrf_name = yang_dnode_get_string(if_dnode, "vrf");
+       tag = yang_dnode_get_string(if_dnode, "frr-isisd:isis/area-tag");
 
-       switch (is_type) {
-       case IS_LEVEL_1:
-               circ_type = "level-1";
-               break;
-       case IS_LEVEL_2:
-               circ_type = "level-2";
-               break;
-       case IS_LEVEL_1_AND_2:
-               circ_type = "level-1-2";
-               break;
-       default:
-               return CMD_ERR_NO_MATCH;
-       }
-       nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
-                             NB_OP_MODIFY, circ_type);
+       snprintf(inst_xpath, XPATH_MAXLEN,
+                "/frr-isisd:isis/instance[area-tag='%s'][vrf='%s']", tag,
+                vrf_name);
 
-       return nb_cli_apply_changes(vty, NULL);
+       inst_dnode = yang_dnode_get(vty->candidate_config->dnode, inst_xpath);
+       if (inst_dnode)
+               circ_type = yang_dnode_get_string(inst_dnode, "is-type");
 
-def_val:
        nb_cli_enqueue_change(vty, "./frr-isisd:isis/circuit-type",
-                             NB_OP_MODIFY, NULL);
+                             NB_OP_MODIFY, circ_type);
 
        return nb_cli_apply_changes(vty, NULL);
 }
@@ -2737,6 +2647,7 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode,
 {
        bool l1_enabled, l2_enabled;
        bool l1_node_protection, l2_node_protection;
+       bool l1_link_fallback, l2_link_fallback;
 
        /* Classic LFA */
        l1_enabled = yang_dnode_get_bool(dnode, "./level-1/lfa/enable");
@@ -2782,13 +2693,21 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode,
                yang_dnode_get_bool(dnode, "./level-1/ti-lfa/node-protection");
        l2_node_protection =
                yang_dnode_get_bool(dnode, "./level-2/ti-lfa/node-protection");
+       l1_link_fallback =
+               yang_dnode_get_bool(dnode, "./level-1/ti-lfa/link-fallback");
+       l2_link_fallback =
+               yang_dnode_get_bool(dnode, "./level-2/ti-lfa/link-fallback");
+
 
        if (l1_enabled || l2_enabled) {
                if (l1_enabled == l2_enabled
-                   && l1_node_protection == l2_node_protection) {
+                   && l1_node_protection == l2_node_protection
+                   && l1_link_fallback == l2_link_fallback) {
                        vty_out(vty, " isis fast-reroute ti-lfa");
                        if (l1_node_protection)
                                vty_out(vty, " node-protection");
+                       if (l1_link_fallback)
+                               vty_out(vty, " link-fallback");
                        vty_out(vty, "\n");
                } else {
                        if (l1_enabled) {
@@ -2796,6 +2715,8 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode,
                                        " isis fast-reroute ti-lfa level-1");
                                if (l1_node_protection)
                                        vty_out(vty, " node-protection");
+                               if (l1_link_fallback)
+                                       vty_out(vty, " link-fallback");
                                vty_out(vty, "\n");
                        }
                        if (l2_enabled) {
@@ -2803,6 +2724,8 @@ void cli_show_ip_isis_frr(struct vty *vty, struct lyd_node *dnode,
                                        " isis fast-reroute ti-lfa level-2");
                                if (l2_node_protection)
                                        vty_out(vty, " node-protection");
+                               if (l2_link_fallback)
+                                       vty_out(vty, " link-fallback");
                                vty_out(vty, "\n");
                        }
                }
@@ -3007,14 +2930,15 @@ void cli_show_frr_remote_lfa_max_metric(struct vty *vty, struct lyd_node *dnode,
  * XPath: /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-{1,2}/ti-lfa/enable
  */
 DEFPY(isis_ti_lfa, isis_ti_lfa_cmd,
-      "[no] isis fast-reroute ti-lfa [level-1|level-2]$level [node-protection$node_protection]",
+      "[no] isis fast-reroute ti-lfa [level-1|level-2]$level [node-protection$node_protection [link-fallback$link_fallback]]",
       NO_STR
       "IS-IS routing protocol\n"
       "Interface IP Fast-reroute configuration\n"
       "Enable TI-LFA computation\n"
       "Enable TI-LFA computation for Level 1 only\n"
       "Enable TI-LFA computation for Level 2 only\n"
-      "Protect against node failures\n")
+      "Protect against node failures\n"
+      "Enable link-protection fallback\n")
 {
        if (!level || strmatch(level, "level-1")) {
                if (no) {
@@ -3026,6 +2950,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd,
                                vty,
                                "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/node-protection",
                                NB_OP_MODIFY, "false");
+                       nb_cli_enqueue_change(
+                               vty,
+                               "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback",
+                               NB_OP_MODIFY, "false");
                } else {
                        nb_cli_enqueue_change(
                                vty,
@@ -3036,6 +2964,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd,
                                "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/node-protection",
                                NB_OP_MODIFY,
                                node_protection ? "true" : "false");
+                       nb_cli_enqueue_change(
+                               vty,
+                               "./frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback",
+                               NB_OP_MODIFY, link_fallback ? "true" : "false");
                }
        }
        if (!level || strmatch(level, "level-2")) {
@@ -3048,6 +2980,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd,
                                vty,
                                "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/node-protection",
                                NB_OP_MODIFY, "false");
+                       nb_cli_enqueue_change(
+                               vty,
+                               "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback",
+                               NB_OP_MODIFY, "false");
                } else {
                        nb_cli_enqueue_change(
                                vty,
@@ -3058,6 +2994,10 @@ DEFPY(isis_ti_lfa, isis_ti_lfa_cmd,
                                "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/node-protection",
                                NB_OP_MODIFY,
                                node_protection ? "true" : "false");
+                       nb_cli_enqueue_change(
+                               vty,
+                               "./frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback",
+                               NB_OP_MODIFY, link_fallback ? "true" : "false");
                }
        }
 
@@ -3147,7 +3087,6 @@ DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd,
       NO_STR "IS-IS routing protocol\n" MPLS_STR MPLS_LDP_SYNC_STR)
 {
        const struct lyd_node *dnode;
-       struct interface *ifp;
 
        dnode = yang_dnode_get(vty->candidate_config->dnode,
                               "%s/frr-isisd:isis", VTY_CURR_XPATH);
@@ -3156,17 +3095,6 @@ DEFPY(isis_mpls_if_ldp_sync, isis_mpls_if_ldp_sync_cmd,
                return CMD_SUCCESS;
        }
 
-       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
-       if (if_is_loopback(ifp)) {
-               vty_out(vty, "ldp-sync does not run on loopback interface\n");
-               return CMD_SUCCESS;
-       }
-
-       if (ifp->vrf_id != VRF_DEFAULT) {
-               vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
-               return CMD_SUCCESS;
-       }
-
        nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/ldp-sync",
                              NB_OP_MODIFY, no ? "false" : "true");
 
@@ -3190,7 +3118,6 @@ DEFPY(isis_mpls_if_ldp_sync_holddown, isis_mpls_if_ldp_sync_holddown_cmd,
       "Time in seconds\n")
 {
        const struct lyd_node *dnode;
-       struct interface *ifp;
 
        dnode = yang_dnode_get(vty->candidate_config->dnode,
                               "%s/frr-isisd:isis", VTY_CURR_XPATH);
@@ -3199,17 +3126,6 @@ DEFPY(isis_mpls_if_ldp_sync_holddown, isis_mpls_if_ldp_sync_holddown_cmd,
                return CMD_SUCCESS;
        }
 
-       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
-       if (if_is_loopback(ifp)) {
-               vty_out(vty, "ldp-sync does not run on loopback interface\n");
-               return CMD_SUCCESS;
-       }
-
-       if (ifp->vrf_id != VRF_DEFAULT) {
-               vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
-               return CMD_SUCCESS;
-       }
-
        nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown",
                              NB_OP_MODIFY, holddown_str);
 
@@ -3222,7 +3138,6 @@ DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd,
              NO_MPLS_LDP_SYNC_HOLDDOWN_STR "Time in seconds\n")
 {
        const struct lyd_node *dnode;
-       struct interface *ifp;
 
        dnode = yang_dnode_get(vty->candidate_config->dnode,
                               "%s/frr-isisd:isis", VTY_CURR_XPATH);
@@ -3231,17 +3146,6 @@ DEFPY(no_isis_mpls_if_ldp_sync_holddown, no_isis_mpls_if_ldp_sync_holddown_cmd,
                return CMD_SUCCESS;
        }
 
-       ifp = nb_running_get_entry(NULL, VTY_CURR_XPATH, false);
-       if (if_is_loopback(ifp)) {
-               vty_out(vty, "ldp-sync does not run on loopback interface\n");
-               return CMD_SUCCESS;
-       }
-
-       if (ifp->vrf_id != VRF_DEFAULT) {
-               vty_out(vty, "ldp-sync only runs on DEFAULT VRF\n");
-               return CMD_SUCCESS;
-       }
-
        nb_cli_enqueue_change(vty, "./frr-isisd:isis/mpls/holddown",
                              NB_OP_DESTROY, NULL);
 
@@ -3262,8 +3166,11 @@ void isis_cli_init(void)
        install_element(CONFIG_NODE, &no_router_isis_cmd);
 
        install_element(INTERFACE_NODE, &ip_router_isis_cmd);
+       install_element(INTERFACE_NODE, &ip_router_isis_vrf_cmd);
        install_element(INTERFACE_NODE, &ip6_router_isis_cmd);
+       install_element(INTERFACE_NODE, &ip6_router_isis_vrf_cmd);
        install_element(INTERFACE_NODE, &no_ip_router_isis_cmd);
+       install_element(INTERFACE_NODE, &no_ip_router_isis_vrf_cmd);
        install_element(INTERFACE_NODE, &isis_bfd_cmd);
        install_element(INTERFACE_NODE, &isis_bfd_profile_cmd);
 
index 736d8d63f93c34efc0b58662740fb91d245bcffe..0a29dcd09a97f5f294de21436ca275c68002099f 100644 (file)
@@ -60,94 +60,93 @@ static const char *const csm_eventstr[] = {
 
 #define EVENT2STR(E) csm_eventstr[E]
 
-struct isis_circuit *
-isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg)
+struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event,
+                                          struct isis_circuit *circuit,
+                                          void *arg)
 {
-       int old_state;
-       struct isis *isis = NULL;
+       enum isis_circuit_state old_state;
        struct isis_area *area = NULL;
+       struct interface *ifp;
 
-       old_state = circuit ? circuit->state : C_STATE_NA;
+       assert(circuit);
+
+       old_state = circuit->state;
        if (IS_DEBUG_EVENTS)
-               zlog_debug("CSM_EVENT: %s", EVENT2STR(event));
+               zlog_debug("CSM_EVENT for %s: %s", circuit->interface->name,
+                          EVENT2STR(event));
 
        switch (old_state) {
        case C_STATE_NA:
-               if (circuit)
-                       zlog_warn("Non-null circuit while state C_STATE_NA");
-               assert(circuit == NULL);
                switch (event) {
                case ISIS_ENABLE:
                        area = arg;
 
-                       circuit = isis_circuit_new(area->isis);
                        isis_circuit_configure(circuit, area);
                        circuit->state = C_STATE_CONF;
                        break;
                case IF_UP_FROM_Z:
-                       isis = isis_lookup_by_vrfid(((struct interface *)arg)->vrf_id);
-                       if (isis == NULL) {
-                               zlog_warn(
-                                       " %s : ISIS routing instance not found",
-                                       __func__);
-                               break;
-                       }
-                       circuit = isis_circuit_new(isis);
-                       isis_circuit_if_add(circuit, (struct interface *)arg);
-                       listnode_add(isis->init_circ_list, circuit);
+                       ifp = arg;
+
+                       isis_circuit_if_add(circuit, ifp);
                        circuit->state = C_STATE_INIT;
                        break;
                case ISIS_DISABLE:
-                       zlog_warn("circuit already disabled");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s already disabled",
+                                          circuit->interface->name);
                        break;
                case IF_DOWN_FROM_Z:
-                       zlog_warn("circuit already disconnected");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s already disconnected",
+                                          circuit->interface->name);
                        break;
                }
                break;
        case C_STATE_INIT:
-               assert(circuit);
                switch (event) {
                case ISIS_ENABLE:
-                       isis_circuit_configure(circuit,
-                                              (struct isis_area *)arg);
+                       area = arg;
+
+                       isis_circuit_configure(circuit, area);
                        if (isis_circuit_up(circuit) != ISIS_OK) {
-                               isis_circuit_deconfigure(
-                                       circuit, (struct isis_area *)arg);
+                               isis_circuit_deconfigure(circuit, area);
                                break;
                        }
                        circuit->state = C_STATE_UP;
                        isis_event_circuit_state_change(circuit, circuit->area,
                                                        1);
-                       listnode_delete(circuit->isis->init_circ_list,
-                                       circuit);
                        break;
                case IF_UP_FROM_Z:
-                       assert(circuit);
-                       zlog_warn("circuit already connected");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s already connected",
+                                          circuit->interface->name);
                        break;
                case ISIS_DISABLE:
-                       zlog_warn("circuit already disabled");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s already disabled",
+                                          circuit->interface->name);
                        break;
                case IF_DOWN_FROM_Z:
-                       isis_circuit_if_del(circuit, (struct interface *)arg);
-                       listnode_delete(circuit->isis->init_circ_list,
-                                       circuit);
-                       isis_circuit_del(circuit);
-                       circuit = NULL;
+                       ifp = arg;
+
+                       isis_circuit_if_del(circuit, ifp);
+                       circuit->state = C_STATE_NA;
                        break;
                }
                break;
        case C_STATE_CONF:
-               assert(circuit);
                switch (event) {
                case ISIS_ENABLE:
-                       zlog_warn("circuit already enabled");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s is already enabled",
+                                          circuit->interface->name);
                        break;
                case IF_UP_FROM_Z:
-                       isis_circuit_if_add(circuit, (struct interface *)arg);
+                       ifp = arg;
+
+                       isis_circuit_if_add(circuit, ifp);
                        if (isis_circuit_up(circuit) != ISIS_OK) {
-                               isis_circuit_if_del(circuit, (struct interface *)arg);
+                               isis_circuit_if_del(circuit, ifp);
                                flog_err(
                                        EC_ISIS_CONFIG,
                                        "Could not bring up %s because of invalid config.",
@@ -159,53 +158,54 @@ isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg)
                                                        1);
                        break;
                case ISIS_DISABLE:
-                       isis_circuit_deconfigure(circuit,
-                                                (struct isis_area *)arg);
-                       isis_circuit_del(circuit);
-                       circuit = NULL;
+                       area = arg;
+
+                       isis_circuit_deconfigure(circuit, area);
+                       circuit->state = C_STATE_NA;
                        break;
                case IF_DOWN_FROM_Z:
-                       zlog_warn("circuit already disconnected");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s already disconnected",
+                                          circuit->interface->name);
                        break;
                }
                break;
        case C_STATE_UP:
-               assert(circuit);
                switch (event) {
                case ISIS_ENABLE:
-                       zlog_warn("circuit already configured");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s already enabled",
+                                          circuit->interface->name);
                        break;
                case IF_UP_FROM_Z:
-                       zlog_warn("circuit already connected");
+                       if (IS_DEBUG_EVENTS)
+                               zlog_debug("circuit %s already connected",
+                                          circuit->interface->name);
                        break;
                case ISIS_DISABLE:
-                       isis = circuit->isis;
+                       area = arg;
+
                        isis_circuit_down(circuit);
-                       isis_circuit_deconfigure(circuit,
-                                                (struct isis_area *)arg);
+                       isis_circuit_deconfigure(circuit, area);
                        circuit->state = C_STATE_INIT;
-                       isis_event_circuit_state_change(
-                               circuit, (struct isis_area *)arg, 0);
-                       listnode_add(isis->init_circ_list, circuit);
+                       isis_event_circuit_state_change(circuit, area, 0);
                        break;
                case IF_DOWN_FROM_Z:
+                       ifp = arg;
+
                        isis_circuit_down(circuit);
-                       isis_circuit_if_del(circuit, (struct interface *)arg);
+                       isis_circuit_if_del(circuit, ifp);
                        circuit->state = C_STATE_CONF;
                        isis_event_circuit_state_change(circuit, circuit->area,
                                                        0);
                        break;
                }
                break;
-
-       default:
-               zlog_warn("Invalid circuit state %d", old_state);
        }
 
        if (IS_DEBUG_EVENTS)
                zlog_debug("CSM_STATE_CHANGE: %s -> %s ", STATE2STR(old_state),
-                          circuit ? STATE2STR(circuit->state)
-                                  : STATE2STR(C_STATE_NA));
+                          STATE2STR(circuit->state));
 
        return circuit;
 }
index 53a5f9d5d09d1090a17234c96b455e8441b17a60..ad72ff5113fe04d4e74811b9f328f3a7151cb1a4 100644 (file)
 /*
  * Circuit states
  */
-#define C_STATE_NA   0
-#define C_STATE_INIT 1         /* Connected to interface */
-#define C_STATE_CONF 2         /* Configured for ISIS    */
-#define C_STATE_UP   3         /* CONN | CONF            */
+enum isis_circuit_state {
+       C_STATE_NA,
+       C_STATE_INIT, /* Connected to interface */
+       C_STATE_CONF, /* Configured for ISIS    */
+       C_STATE_UP,   /* CONN | CONF            */
+};
 
 /*
  * Circuit events
  */
-#define ISIS_ENABLE    1
-#define IF_UP_FROM_Z   2
-#define ISIS_DISABLE   3
-#define IF_DOWN_FROM_Z 4
+enum isis_circuit_event {
+       ISIS_ENABLE = 1,
+       IF_UP_FROM_Z,
+       ISIS_DISABLE,
+       IF_DOWN_FROM_Z,
+};
 
-struct isis_circuit *
-isis_csm_state_change(int event, struct isis_circuit *circuit, void *arg);
+struct isis_circuit *isis_csm_state_change(enum isis_circuit_event event,
+                                          struct isis_circuit *circuit,
+                                          void *arg);
 
 #endif /* _ZEBRA_ISIS_CSM_H */
index 585f76980650e3d4b83e5044a2491ae0efa92a34..62d8b8334ae85e7265c5e6712a39fcafe1e414e4 100644 (file)
@@ -65,28 +65,20 @@ int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state)
        struct interface *ifp;
        struct isis_circuit *circuit = NULL;
        struct isis_area *area;
-       struct listnode *node;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
-
-       /* if isis is not enabled or LDP-SYNC is not configured ignore */
-       if (!isis ||
-           !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
-               return 0;
 
        /* lookup circuit */
        ifp = if_lookup_by_index(state.ifindex, VRF_DEFAULT);
        if (ifp == NULL)
                return 0;
 
-       for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
-               circuit = circuit_lookup_by_ifp(ifp, area->circuit_list);
-               if (circuit != NULL)
-                       break;
-       }
+       circuit = ifp->info;
+       if (circuit == NULL)
+               return 0;
 
        /* if isis is not enabled or LDP-SYNC is not configured ignore */
-       if (circuit == NULL ||
-           !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+       area = circuit->area;
+       if (area == NULL
+           || !CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
                return 0;
 
        /* received ldp-sync interface state from LDP */
@@ -103,15 +95,12 @@ int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state)
 int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)
 {
        struct isis_area *area;
-       struct listnode *node;
-       struct vrf *vrf;
-       struct interface *ifp;
+       struct listnode *anode, *cnode;
        struct isis_circuit *circuit;
        struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
 
-       /* if isis is not enabled or LDP-SYNC is not configured ignore */
-       if (!isis ||
-           !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+       /* if isis is not enabled ignore */
+       if (!isis)
                return 0;
 
        if (announce.proto != ZEBRA_ROUTE_LDP)
@@ -123,15 +112,12 @@ int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)
         *  set cost to LSInfinity
         *  send request to LDP for LDP-SYNC state for each interface
         */
-       vrf = vrf_lookup_by_id(VRF_DEFAULT);
-       FOR_ALL_INTERFACES (vrf, ifp) {
-               for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
-                       circuit = circuit_lookup_by_ifp(ifp,
-                               area->circuit_list);
-                       if (circuit == NULL)
-                               continue;
+       for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
+               if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+                       continue;
+
+               for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
                        isis_ldp_sync_if_start(circuit, true);
-               }
        }
 
        return 0;
@@ -157,32 +143,6 @@ void isis_ldp_sync_state_req_msg(struct isis_circuit *circuit)
 /*
  * LDP-SYNC general interface routines
  */
-void isis_ldp_sync_if_init(struct isis_circuit *circuit, struct isis *isis)
-{
-       struct ldp_sync_info *ldp_sync_info;
-       struct interface *ifp = circuit->interface;
-
-       /* called when ISIS is configured on an interface
-        *  if LDP-IGP Sync is configured globally set state
-        *  and if ptop interface LDP LDP-SYNC is enabled
-        */
-       ils_debug("ldp_sync: init if %s ", ifp->name);
-       if (circuit->ldp_sync_info == NULL)
-               circuit->ldp_sync_info = ldp_sync_info_create();
-       ldp_sync_info = circuit->ldp_sync_info;
-
-       /* specifed on interface overrides global config. */
-       if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
-               ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown;
-
-       if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
-               ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
-
-       if ((circuit->circ_type == CIRCUIT_T_P2P || if_is_pointopoint(ifp)) &&
-           ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED)
-               ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
-}
-
 void isis_ldp_sync_if_start(struct isis_circuit *circuit,
        bool send_state_req)
 {
@@ -251,49 +211,17 @@ void isis_ldp_sync_ldp_fail(struct isis_circuit *circuit)
        }
 }
 
-void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove)
-{
-       struct ldp_sync_info *ldp_sync_info;
-
-       if (circuit->ldp_sync_info == NULL)
-               return;
-
-       ldp_sync_info = circuit->ldp_sync_info;
-
-       /* Stop LDP-SYNC on this interface:
-        *  if holddown timer is running stop it
-        *  delete ldp instance on interface
-        *  restore metric
-        */
-       ils_debug("ldp_sync: remove if %s", circuit->interface
-                 ? circuit->interface->name : "");
-
-       THREAD_OFF(ldp_sync_info->t_holddown);
-       ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
-       isis_ldp_sync_set_if_metric(circuit, true);
-       if (remove) {
-               /* ISIS instance being removed free ldp-sync info */
-               ldp_sync_info_free((struct ldp_sync_info **)&(ldp_sync_info));
-               circuit->ldp_sync_info = NULL;
-       }
-}
-
 static int isis_ldp_sync_adj_state_change(struct isis_adjacency *adj)
 {
        struct isis_circuit *circuit = adj->circuit;
-       struct ldp_sync_info *ldp_sync_info;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+       struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
+       struct isis_area *area = circuit->area;
 
-       if (!isis ||
-           !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) ||
-           circuit->interface->vrf_id != VRF_DEFAULT ||
-           if_is_loopback(circuit->interface))
+       if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)
+           || circuit->interface->vrf_id != VRF_DEFAULT
+           || if_is_loopback(circuit->interface))
                return 0;
 
-       if (circuit->ldp_sync_info == NULL)
-               isis_ldp_sync_if_init(circuit, isis);
-       ldp_sync_info = circuit->ldp_sync_info;
-
        if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
                return 0;
 
@@ -329,16 +257,15 @@ bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit, int level,
                                    int metric)
 {
        struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+       struct isis_area *area = circuit->area;
 
        /* configured interface metric has been changed:
         *   if LDP-IGP Sync is running and metric has been set to LSInfinity
         *   change saved value so when ldp-sync completes proper metric is
         *   restored
         */
-       if (isis &&
-           CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE) &&
-           ldp_sync_info != NULL) {
+       if (area && CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)
+           && ldp_sync_info != NULL) {
 
                if (CHECK_FLAG(ldp_sync_info->flags,
                               LDP_SYNC_FLAG_SET_METRIC)) {
@@ -471,15 +398,12 @@ void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit)
 void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
 {
        struct isis_area *area;
-       struct listnode *node;
+       struct listnode *anode, *cnode;
        struct isis_circuit *circuit;
-       struct interface *ifp;
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
        struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
 
-       /* if isis is not enabled or LDP-SYNC is not configured ignore */
-       if (!isis
-           || !CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+       /* if isis is not enabled ignore */
+       if (!isis)
                return;
 
        /* Check if the LDP main client session closed */
@@ -492,14 +416,12 @@ void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
         */
        zlog_err("ldp_sync: LDP down");
 
-       FOR_ALL_INTERFACES (vrf, ifp) {
-               for (ALL_LIST_ELEMENTS_RO(isis->area_list, node, area)) {
-                       circuit =
-                               circuit_lookup_by_ifp(ifp, area->circuit_list);
-                       if (circuit == NULL)
-                               continue;
+       for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
+               if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+                       continue;
+
+               for (ALL_LIST_ELEMENTS_RO(area->circuit_list, cnode, circuit))
                        isis_ldp_sync_ldp_fail(circuit);
-               }
        }
 }
 
@@ -507,110 +429,130 @@ void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
  * LDP-SYNC routes used by set commands.
  */
 
-void isis_if_set_ldp_sync_enable(struct isis_circuit *circuit)
+void isis_area_ldp_sync_enable(struct isis_area *area)
 {
-       struct ldp_sync_info *ldp_sync_info;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+       struct isis_circuit *circuit;
+       struct listnode *node;
+
+       if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
+               SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
+
+               for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
+                       isis_if_ldp_sync_enable(circuit);
+       }
+}
+
+void isis_area_ldp_sync_disable(struct isis_area *area)
+{
+       struct isis_circuit *circuit;
+       struct listnode *node;
+
+       if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
+               for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
+                       isis_if_ldp_sync_disable(circuit);
+
+               UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
+
+               UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
+               area->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
+       }
+}
+
+void isis_area_ldp_sync_set_holddown(struct isis_area *area, uint16_t holddown)
+{
+       struct isis_circuit *circuit;
+       struct listnode *node;
+
+       if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
+               UNSET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
+       else
+               SET_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
+
+       area->ldp_sync_cmd.holddown = holddown;
+
+       for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
+               isis_if_set_ldp_sync_holddown(circuit);
+}
+
+void isis_if_ldp_sync_enable(struct isis_circuit *circuit)
+{
+       struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
+       struct isis_area *area = circuit->area;
 
        /* called when setting LDP-SYNC at the global level:
         *  specifed on interface overrides global config
         *  if ptop link send msg to LDP indicating ldp-sync enabled
         */
-       if (!isis || if_is_loopback(circuit->interface))
+       if (if_is_loopback(circuit->interface))
                return;
 
-       if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
-               if (circuit->ldp_sync_info == NULL)
-                       isis_ldp_sync_if_init(circuit, isis);
-               ldp_sync_info = circuit->ldp_sync_info;
+       ils_debug("ldp_sync: enable if %s", circuit->interface->name);
 
-               /* config on interface, overrides global config. */
-               if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
-                       if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
-                           return;
+       if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+               return;
 
-               ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
-               ils_debug("ldp_sync: enable if %s", circuit->interface->name);
+       /* config on interface, overrides global config. */
+       if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG))
+               if (ldp_sync_info->enabled != LDP_IGP_SYNC_ENABLED)
+                       return;
 
-               /* send message to LDP if ptop link */
-               if (circuit->circ_type == CIRCUIT_T_P2P ||
-                   if_is_pointopoint(circuit->interface)) {
-                       ldp_sync_info->state =
-                               LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
-                       isis_ldp_sync_state_req_msg(circuit);
-               } else {
-                       ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
-                       zlog_debug("ldp_sync: Sync only runs on P2P links %s",
-                                  circuit->interface->name);
-               }
-       } else
-               /* delete LDP sync even if configured on an interface */
-               isis_ldp_sync_if_remove(circuit, false);
+       if (!CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
+               ldp_sync_info->holddown = area->ldp_sync_cmd.holddown;
+
+       if (circuit->circ_type == CIRCUIT_T_P2P
+           || if_is_pointopoint(circuit->interface)) {
+               ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
+               isis_ldp_sync_state_req_msg(circuit);
+       } else {
+               ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
+               ils_debug("ldp_sync: Sync only runs on P2P links %s",
+                         circuit->interface->name);
+       }
+}
+
+void isis_if_ldp_sync_disable(struct isis_circuit *circuit)
+{
+       struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
+       struct isis_area *area = circuit->area;
+
+       /* Stop LDP-SYNC on this interface:
+        *  if holddown timer is running stop it
+        *  delete ldp instance on interface
+        *  restore metric
+        */
+       if (if_is_loopback(circuit->interface))
+               return;
+
+       ils_debug("ldp_sync: remove if %s", circuit->interface->name);
+
+       if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
+               return;
+
+       THREAD_OFF(ldp_sync_info->t_holddown);
+       ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
+       isis_ldp_sync_set_if_metric(circuit, true);
 }
 
 void isis_if_set_ldp_sync_holddown(struct isis_circuit *circuit)
 {
-       struct ldp_sync_info *ldp_sync_info;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
+       struct ldp_sync_info *ldp_sync_info = circuit->ldp_sync_info;
+       struct isis_area *area = circuit->area;
 
        /* called when setting LDP-SYNC at the global level:
         *  specifed on interface overrides global config.
         */
-       if (!isis || if_is_loopback(circuit->interface))
+       if (if_is_loopback(circuit->interface))
                return;
 
-       if (circuit->ldp_sync_info == NULL)
-               isis_ldp_sync_if_init(circuit, isis);
-       ldp_sync_info = circuit->ldp_sync_info;
-
        /* config on interface, overrides global config. */
        if (CHECK_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN))
                return;
-       if (CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
-               ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown;
+       if (CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN))
+               ldp_sync_info->holddown = area->ldp_sync_cmd.holddown;
        else
                ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
 }
 
-void isis_ldp_sync_gbl_exit(bool remove)
-{
-       struct isis_area *area;
-       struct listnode *node;
-       struct isis_circuit *circuit;
-       struct interface *ifp;
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
-
-       /* if you delete LDP-SYNC at a gobal level is clears all LDP-SYNC
-        * configuration, even interface configuration
-        */
-       if (isis &&
-           CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
-               /* register with opaque client to recv LDP-IGP Sync msgs */
-               zclient_unregister_opaque(zclient,
-                                         LDP_IGP_SYNC_IF_STATE_UPDATE);
-               zclient_unregister_opaque(zclient,
-                                         LDP_IGP_SYNC_ANNOUNCE_UPDATE);
-
-               /* disable LDP-SYNC globally */
-               UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE);
-               UNSET_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_HOLDDOWN);
-               isis->ldp_sync_cmd.holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
-
-               /* remove LDP-SYNC on all ISIS interfaces */
-               FOR_ALL_INTERFACES (vrf, ifp) {
-                       for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
-                                                 area)) {
-                               circuit = circuit_lookup_by_ifp(ifp,
-                                       area->circuit_list);
-                               if (circuit == NULL)
-                                       continue;
-                               isis_ldp_sync_if_remove(circuit, remove);
-                       }
-               }
-       }
-}
-
 /*
  * LDP-SYNC routines used by show commands.
  */
@@ -693,11 +635,6 @@ DEFUN (show_isis_mpls_ldp_interface,
                return CMD_SUCCESS;
        }
 
-       if (!CHECK_FLAG(isis->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE)) {
-               vty_out(vty, "LDP-sync is disabled\n");
-               return CMD_SUCCESS;
-       }
-
        if (argv_find(argv, argc, "INTERFACE", &idx_intf))
                ifname = argv[idx_intf]->arg;
 
index 977c5ba0defd689ab3d2a3fd11f33ea029ca2d1a..69a180000775e99bd5b447a79daf27e7bc2c33c0 100644 (file)
                        zlog_debug(__VA_ARGS__);                               \
        } while (0)
 
-extern void isis_if_set_ldp_sync_enable(struct isis_circuit *circuit);
+extern void isis_area_ldp_sync_enable(struct isis_area *area);
+extern void isis_area_ldp_sync_disable(struct isis_area *area);
+extern void isis_area_ldp_sync_set_holddown(struct isis_area *area,
+                                           uint16_t holddown);
+extern void isis_if_ldp_sync_enable(struct isis_circuit *circuit);
+extern void isis_if_ldp_sync_disable(struct isis_circuit *circuit);
 extern void isis_if_set_ldp_sync_holddown(struct  isis_circuit *circuit);
-extern void isis_ldp_sync_if_init(struct isis_circuit *circuit,
-                                 struct isis *isis);
 extern void isis_ldp_sync_if_start(struct isis_circuit *circuit,
                                   bool send_state_req);
-extern void isis_ldp_sync_if_remove(struct isis_circuit *circuit, bool remove);
 extern void isis_ldp_sync_if_complete(struct isis_circuit *circuit);
 extern void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit);
 extern void
@@ -49,5 +51,4 @@ extern void isis_ldp_sync_set_if_metric(struct isis_circuit *circuit,
 extern bool isis_ldp_sync_if_metric_config(struct isis_circuit *circuit,
                                           int level, int metric);
 extern void isis_ldp_sync_init(void);
-extern void isis_ldp_sync_gbl_exit(bool remove);
 #endif /* _ZEBRA_ISIS_LDP_SYNC_H */
index 085177b94352ca1bfaaab884f7a1c28665360343..e033c28fefd345e86058c71b1f1eec4e6e8afc23 100644 (file)
@@ -1148,10 +1148,13 @@ static void lfa_calc_pq_spaces(struct isis_spftree *spftree_pc,
 
                        /*
                         * Compute the reverse SPF in the behalf of the node
-                        * adjacent to the failure.
+                        * adjacent to the failure, if we haven't done that
+                        * before
                         */
-                       adj_node->lfa.spftree_reverse =
-                               isis_spf_reverse_run(adj_node->lfa.spftree);
+                       if (!adj_node->lfa.spftree_reverse)
+                               adj_node->lfa.spftree_reverse =
+                                       isis_spf_reverse_run(
+                                               adj_node->lfa.spftree);
 
                        lfa_calc_reach_nodes(adj_node->lfa.spftree_reverse,
                                             spftree_reverse, adj_nodes, false,
@@ -2255,6 +2258,11 @@ static void isis_spf_run_tilfa(struct isis_area *area,
                spftree_pc_node = isis_tilfa_compute(area, spftree,
                                                     spftree_reverse, resource);
                isis_spftree_del(spftree_pc_node);
+
+               /* don't do link protection unless link-fallback is configured
+                */
+               if (!circuit->tilfa_link_fallback[spftree->level - 1])
+                       return;
        }
 
        /* Compute link protecting repair paths. */
index 227724934b52920954b26a704bb9eaaacf7f8d61..ecad16229c18b63c2b0aadc9638618fc6c6cc443 100644 (file)
@@ -685,13 +685,6 @@ const struct frr_yang_module_info frr_isisd_info = {
                                .modify = lib_interface_isis_area_tag_modify,
                        },
                },
-               {
-                       .xpath = "/frr-interface:lib/interface/frr-isisd:isis/vrf",
-                       .cbs = {
-                               .modify = lib_interface_isis_vrf_modify,
-                       },
-               },
-
                {
                        .xpath = "/frr-interface:lib/interface/frr-isisd:isis/circuit-type",
                        .cbs = {
@@ -984,6 +977,12 @@ const struct frr_yang_module_info frr_isisd_info = {
                                .modify = lib_interface_isis_fast_reroute_level_1_ti_lfa_node_protection_modify,
                        }
                },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback",
+                       .cbs = {
+                               .modify = lib_interface_isis_fast_reroute_level_1_ti_lfa_link_fallback_modify,
+                       }
+               },
                {
                        .xpath = "/frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/lfa/enable",
                        .cbs = {
@@ -1024,6 +1023,12 @@ const struct frr_yang_module_info frr_isisd_info = {
                                .modify = lib_interface_isis_fast_reroute_level_2_ti_lfa_node_protection_modify,
                        }
                },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback",
+                       .cbs = {
+                               .modify = lib_interface_isis_fast_reroute_level_2_ti_lfa_link_fallback_modify,
+                       }
+               },
                {
                        .xpath = "/frr-interface:lib/interface/state/frr-isisd:isis",
                        .cbs = {
index a6841b9fd4c6a3e857b92c4340ce0870c437f7ba..0c2f7b6b7e5acecace3d54c560be82429d6fb50c 100644 (file)
@@ -214,7 +214,6 @@ int isis_instance_mpls_te_router_address_destroy(
 int lib_interface_isis_create(struct nb_cb_create_args *args);
 int lib_interface_isis_destroy(struct nb_cb_destroy_args *args);
 int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args);
-int lib_interface_isis_vrf_modify(struct nb_cb_modify_args *args);
 int lib_interface_isis_ipv4_routing_modify(struct nb_cb_modify_args *args);
 int lib_interface_isis_ipv6_routing_modify(struct nb_cb_modify_args *args);
 int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args);
@@ -320,6 +319,8 @@ int lib_interface_isis_fast_reroute_level_1_ti_lfa_enable_modify(
        struct nb_cb_modify_args *args);
 int lib_interface_isis_fast_reroute_level_1_ti_lfa_node_protection_modify(
        struct nb_cb_modify_args *args);
+int lib_interface_isis_fast_reroute_level_1_ti_lfa_link_fallback_modify(
+       struct nb_cb_modify_args *args);
 int lib_interface_isis_fast_reroute_level_2_lfa_enable_modify(
        struct nb_cb_modify_args *args);
 int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_create(
@@ -336,6 +337,8 @@ int lib_interface_isis_fast_reroute_level_2_ti_lfa_enable_modify(
        struct nb_cb_modify_args *args);
 int lib_interface_isis_fast_reroute_level_2_ti_lfa_node_protection_modify(
        struct nb_cb_modify_args *args);
+int lib_interface_isis_fast_reroute_level_2_ti_lfa_link_fallback_modify(
+       struct nb_cb_modify_args *args);
 struct yang_data *
 lib_interface_state_isis_get_elem(struct nb_cb_get_elem_args *args);
 const void *lib_interface_state_isis_adjacencies_adjacency_get_next(
index c8ad816b585bd6196d8c18c1be172a2b66e6208a..5ca2329dd34e2e1adb08341f921d920b2a70fb14 100644 (file)
@@ -32,7 +32,6 @@
 #include "spf_backoff.h"
 #include "lib_errors.h"
 #include "vrf.h"
-#include "zclient.h"
 #include "ldp_sync.h"
 
 #include "isisd/isisd.h"
@@ -56,8 +55,6 @@
 DEFINE_MTYPE_STATIC(ISISD, ISIS_MPLS_TE,    "ISIS MPLS_TE parameters");
 DEFINE_MTYPE_STATIC(ISISD, ISIS_PLIST_NAME, "ISIS prefix-list name");
 
-extern struct zclient *zclient;
-
 /*
  * XPath: /frr-isisd:isis/instance
  */
@@ -87,16 +84,10 @@ int isis_instance_create(struct nb_cb_create_args *args)
 int isis_instance_destroy(struct nb_cb_destroy_args *args)
 {
        struct isis_area *area;
-       vrf_id_t vrf_id;
 
        if (args->event != NB_EV_APPLY)
                return NB_OK;
        area = nb_running_unset_entry(args->dnode);
-       vrf_id = area->isis->vrf_id;
-
-       /* remove ldp-sync config */
-       if (vrf_id == VRF_DEFAULT)
-               isis_ldp_sync_gbl_exit(true);
 
        isis_area_destroy(area);
        return NB_OK;
@@ -2369,11 +2360,6 @@ int isis_instance_segment_routing_prefix_sid_map_prefix_sid_n_flag_clear_modify(
 int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args)
 {
        struct isis_area *area;
-       struct listnode *node;
-       struct isis_circuit *circuit;
-       struct interface *ifp;
-       struct vrf *vrf;
-       struct isis *isis;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
@@ -2392,30 +2378,7 @@ int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args)
                break;
        case NB_EV_APPLY:
                area = nb_running_get_entry(args->dnode, NULL, true);
-               isis = area->isis;
-               vrf = vrf_lookup_by_id(isis->vrf_id);
-
-               /* register with opaque client to recv LDP-IGP Sync msgs */
-               zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
-               zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
-
-               if (!CHECK_FLAG(isis->ldp_sync_cmd.flags,
-                               LDP_SYNC_FLAG_ENABLE)) {
-                       SET_FLAG(isis->ldp_sync_cmd.flags,
-                                LDP_SYNC_FLAG_ENABLE);
-
-                       /* turn on LDP-IGP Sync on all ptop ISIS interfaces */
-                       FOR_ALL_INTERFACES (vrf, ifp) {
-                               for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
-                                                         area)) {
-                                       circuit = circuit_lookup_by_ifp(
-                                               ifp, area->circuit_list);
-                                       if (circuit == NULL)
-                                               continue;
-                                       isis_if_set_ldp_sync_enable(circuit);
-                               }
-                       }
-               }
+               isis_area_ldp_sync_enable(area);
                break;
        }
        return NB_OK;
@@ -2423,11 +2386,13 @@ int isis_instance_mpls_ldp_sync_create(struct nb_cb_create_args *args)
 
 int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args)
 {
+       struct isis_area *area;
+
        if (args->event != NB_EV_APPLY)
                return NB_OK;
 
-       /* remove ldp-sync config */
-       isis_ldp_sync_gbl_exit(false);
+       area = nb_running_get_entry(args->dnode, NULL, true);
+       isis_area_ldp_sync_disable(area);
 
        return NB_OK;
 }
@@ -2438,12 +2403,7 @@ int isis_instance_mpls_ldp_sync_destroy(struct nb_cb_destroy_args *args)
 int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args)
 {
        struct isis_area *area;
-       struct listnode *node;
-       struct isis_circuit *circuit;
-       struct interface *ifp;
-       struct vrf *vrf;
-       uint16_t holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
-       struct isis *isis;
+       uint16_t holddown;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
@@ -2462,29 +2422,8 @@ int isis_instance_mpls_ldp_sync_holddown_modify(struct nb_cb_modify_args *args)
                break;
        case NB_EV_APPLY:
                area = nb_running_get_entry(args->dnode, NULL, true);
-               isis = area->isis;
-               vrf = vrf_lookup_by_id(isis->vrf_id);
                holddown = yang_dnode_get_uint16(args->dnode, NULL);
-
-               if (holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
-                       UNSET_FLAG(isis->ldp_sync_cmd.flags,
-                                  LDP_SYNC_FLAG_HOLDDOWN);
-               else
-                       SET_FLAG(isis->ldp_sync_cmd.flags,
-                                LDP_SYNC_FLAG_HOLDDOWN);
-               isis->ldp_sync_cmd.holddown = holddown;
-
-               /* set holddown time on all ISIS interfaces */
-               FOR_ALL_INTERFACES (vrf, ifp) {
-                       for (ALL_LIST_ELEMENTS_RO(isis->area_list, node,
-                                                 area)) {
-                               circuit = circuit_lookup_by_ifp(ifp,
-                                                       area->circuit_list);
-                               if (circuit == NULL)
-                                       continue;
-                               isis_if_set_ldp_sync_holddown(circuit);
-                       }
-               }
+               isis_area_ldp_sync_set_holddown(area, holddown);
                break;
        }
        return NB_OK;
@@ -2498,9 +2437,7 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
        struct isis_area *area = NULL;
        struct interface *ifp;
        struct isis_circuit *circuit = NULL;
-       struct vrf *vrf;
        const char *area_tag = yang_dnode_get_string(args->dnode, "./area-tag");
-       const char *vrf_name = yang_dnode_get_string(args->dnode, "./vrf");
        uint32_t min_mtu, actual_mtu;
 
        switch (args->event) {
@@ -2515,14 +2452,6 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
                /* zebra might not know yet about the MTU - nothing we can do */
                if (!ifp || ifp->mtu == 0)
                        break;
-               vrf = vrf_lookup_by_id(ifp->vrf_id);
-               if (ifp->vrf_id != VRF_DEFAULT && vrf
-                   && strcmp(vrf->name, vrf_name) != 0) {
-                       snprintf(args->errmsg, args->errmsg_len,
-                                "interface %s not in vrf %s\n", ifp->name,
-                                vrf_name);
-                       return NB_ERR_VALIDATION;
-               }
                actual_mtu =
                        if_is_broadcast(ifp) ? ifp->mtu - LLC_LEN : ifp->mtu;
 
@@ -2544,24 +2473,8 @@ int lib_interface_isis_create(struct nb_cb_create_args *args)
                }
                break;
        case NB_EV_APPLY:
-               area = isis_area_lookup_by_vrf(area_tag, vrf_name);
-               /* The area should have already be created. We are
-                * setting the priority of the global isis area creation
-                * slightly lower, so it should be executed first, but I
-                * cannot rely on that so here I have to check.
-                */
-               if (!area) {
-                       flog_err(
-                               EC_LIB_NB_CB_CONFIG_APPLY,
-                               "%s: attempt to create circuit for area %s before the area has been created",
-                               __func__, area_tag);
-                       abort();
-               }
                ifp = nb_running_get_entry(args->dnode, NULL, true);
-               circuit = isis_circuit_create(area, ifp);
-               assert(circuit
-                      && (circuit->state == C_STATE_CONF
-                          || circuit->state == C_STATE_UP));
+               circuit = isis_circuit_new(ifp, area_tag);
                nb_running_set_entry(args->dnode, circuit);
                break;
        }
@@ -2577,18 +2490,9 @@ int lib_interface_isis_destroy(struct nb_cb_destroy_args *args)
                return NB_OK;
 
        circuit = nb_running_unset_entry(args->dnode);
-       if (!circuit)
-               return NB_ERR_INCONSISTENCY;
 
-       /* remove ldp-sync config */
-       isis_ldp_sync_if_remove(circuit, true);
+       isis_circuit_del(circuit);
 
-       /* disable both AFs for this circuit. this will also update the
-        * CSM state by sending an ISIS_DISABLED signal. If there is no
-        * area associated to the circuit there is nothing to do
-        */
-       if (circuit->area)
-               isis_circuit_af_set(circuit, false, false);
        return NB_OK;
 }
 
@@ -2630,44 +2534,6 @@ int lib_interface_isis_area_tag_modify(struct nb_cb_modify_args *args)
        return NB_OK;
 }
 
-/*
- * XPath: /frr-interface:lib/interface/frr-isisd:isis/vrf
- */
-int lib_interface_isis_vrf_modify(struct nb_cb_modify_args *args)
-{
-       struct interface *ifp;
-       struct vrf *vrf;
-       const char *ifname, *vrfname, *vrf_name;
-       struct isis_circuit *circuit;
-
-       if (args->event == NB_EV_VALIDATE) {
-               /* libyang doesn't like relative paths across module boundaries
-                */
-               ifname = yang_dnode_get_string(args->dnode->parent->parent,
-                                              "./name");
-               vrfname = yang_dnode_get_string(args->dnode->parent->parent,
-                                               "./vrf");
-               vrf = vrf_lookup_by_name(vrfname);
-               assert(vrf);
-               ifp = if_lookup_by_name(ifname, vrf->vrf_id);
-
-               if (!ifp)
-                       return NB_OK;
-
-               vrf_name = yang_dnode_get_string(args->dnode, NULL);
-               circuit = circuit_scan_by_ifp(ifp);
-               if (circuit && circuit->area && circuit->isis
-                   && strcmp(circuit->isis->name, vrf_name)) {
-                       snprintf(args->errmsg, args->errmsg_len,
-                                "ISIS circuit is already defined on vrf  %s",
-                                circuit->isis->name);
-                       return NB_ERR_VALIDATION;
-               }
-       }
-
-       return NB_OK;
-}
-
 /*
  * XPath: /frr-interface:lib/interface/frr-isisd:isis/circuit-type
  */
@@ -2678,7 +2544,6 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args)
        struct interface *ifp;
        struct vrf *vrf;
        const char *ifname, *vrfname;
-       struct isis *isis = NULL;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
@@ -2694,11 +2559,7 @@ int lib_interface_isis_circuit_type_modify(struct nb_cb_modify_args *args)
                if (!ifp)
                        break;
 
-               isis = isis_lookup_by_vrfid(ifp->vrf_id);
-               if (isis == NULL)
-                       return NB_ERR_VALIDATION;
-
-               circuit = circuit_lookup_by_ifp(ifp, isis->init_circ_list);
+               circuit = circuit_scan_by_ifp(ifp);
                if (circuit && circuit->state == C_STATE_UP
                    && circuit->area->is_type != IS_LEVEL_1_AND_2
                    && circuit->area->is_type != circ_type) {
@@ -3085,7 +2946,6 @@ int lib_interface_isis_network_type_modify(struct nb_cb_modify_args *args)
 int lib_interface_isis_passive_modify(struct nb_cb_modify_args *args)
 {
        struct isis_circuit *circuit;
-       struct isis_area *area;
        struct interface *ifp;
        bool passive = yang_dnode_get_bool(args->dnode, NULL);
 
@@ -3108,14 +2968,7 @@ int lib_interface_isis_passive_modify(struct nb_cb_modify_args *args)
                return NB_OK;
 
        circuit = nb_running_get_entry(args->dnode, NULL, true);
-       if (circuit->state != C_STATE_UP) {
-               circuit->is_passive = passive;
-       } else {
-               area = circuit->area;
-               isis_csm_state_change(ISIS_DISABLE, circuit, area);
-               circuit->is_passive = passive;
-               isis_csm_state_change(ISIS_ENABLE, circuit, area);
-       }
+       isis_circuit_passive_set(circuit, passive);
 
        return NB_OK;
 }
@@ -3318,13 +3171,23 @@ int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args)
        struct isis_circuit *circuit;
        struct ldp_sync_info *ldp_sync_info;
        bool ldp_sync_enable;
-       struct isis *isis;
+       struct interface *ifp;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
+               ifp = nb_running_get_entry(args->dnode->parent->parent->parent,
+                                          NULL, false);
+               if (ifp == NULL)
+                       return NB_ERR_VALIDATION;
+               if (if_is_loopback(ifp)) {
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "LDP-Sync does not run on loopback interface");
+                       return NB_ERR_VALIDATION;
+               }
+
                circuit = nb_running_get_entry(args->dnode, NULL, false);
                if (circuit == NULL || circuit->area == NULL)
-                       return NB_ERR_VALIDATION;
+                       break;
 
                if (circuit->isis->vrf_id != VRF_DEFAULT) {
                        snprintf(args->errmsg, args->errmsg_len,
@@ -3338,39 +3201,17 @@ int lib_interface_isis_mpls_ldp_sync_modify(struct nb_cb_modify_args *args)
        case NB_EV_APPLY:
                circuit = nb_running_get_entry(args->dnode, NULL, true);
                ldp_sync_enable = yang_dnode_get_bool(args->dnode, NULL);
-               isis = circuit->isis;
 
-               if (circuit->ldp_sync_info == NULL)
-                       isis_ldp_sync_if_init(circuit, isis);
-               assert(circuit->ldp_sync_info != NULL);
                ldp_sync_info = circuit->ldp_sync_info;
 
-               if (ldp_sync_enable) {
-                       /* enable LDP-SYNC on an interface
-                        *  if ptop interface send message to LDP to get state
-                        */
-                       SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
-                       ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
-                       if (circuit->circ_type == CIRCUIT_T_P2P) {
-                               ldp_sync_info->state =
-                                       LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
-                               isis_ldp_sync_state_req_msg(circuit);
-                       } else {
-                               zlog_debug("ldp_sync: only runs on P2P links %s",
-                                          circuit->interface->name);
-                               ldp_sync_info->state =
-                                       LDP_IGP_SYNC_STATE_NOT_REQUIRED;
-                       }
-               } else {
-                       /* disable LDP-SYNC on an interface
-                        *  stop holddown timer if running
-                        *  restore isis metric
-                        */
-                       SET_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;
-                       THREAD_OFF(ldp_sync_info->t_holddown);
-                       isis_ldp_sync_set_if_metric(circuit, true);
+               SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_IF_CONFIG);
+               ldp_sync_info->enabled = ldp_sync_enable;
+
+               if (circuit->area) {
+                       if (ldp_sync_enable)
+                               isis_if_ldp_sync_enable(circuit);
+                       else
+                               isis_if_ldp_sync_disable(circuit);
                }
                break;
        }
@@ -3385,13 +3226,23 @@ int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args)
        struct isis_circuit *circuit;
        struct ldp_sync_info *ldp_sync_info;
        uint16_t holddown;
-       struct isis *isis;
+       struct interface *ifp;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
+               ifp = nb_running_get_entry(args->dnode->parent->parent->parent,
+                                          NULL, false);
+               if (ifp == NULL)
+                       return NB_ERR_VALIDATION;
+               if (if_is_loopback(ifp)) {
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "LDP-Sync does not run on loopback interface");
+                       return NB_ERR_VALIDATION;
+               }
+
                circuit = nb_running_get_entry(args->dnode, NULL, false);
                if (circuit == NULL || circuit->area == NULL)
-                       return NB_ERR_VALIDATION;
+                       break;
 
                if (circuit->isis->vrf_id != VRF_DEFAULT) {
                        snprintf(args->errmsg, args->errmsg_len,
@@ -3405,11 +3256,7 @@ int lib_interface_isis_mpls_holddown_modify(struct nb_cb_modify_args *args)
        case NB_EV_APPLY:
                circuit = nb_running_get_entry(args->dnode, NULL, true);
                holddown = yang_dnode_get_uint16(args->dnode, NULL);
-               isis = circuit->isis;
 
-               if (circuit->ldp_sync_info == NULL)
-                       isis_ldp_sync_if_init(circuit, isis);
-               assert(circuit->ldp_sync_info != NULL);
                ldp_sync_info = circuit->ldp_sync_info;
 
                SET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
@@ -3423,14 +3270,23 @@ int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args)
 {
        struct isis_circuit *circuit;
        struct ldp_sync_info *ldp_sync_info;
-       struct isis *isis;
+       struct interface *ifp;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
-               circuit = nb_running_get_entry(args->dnode, NULL, false);
-               if (circuit == NULL || circuit->ldp_sync_info == NULL
-                   || circuit->area == NULL)
+               ifp = nb_running_get_entry(args->dnode->parent->parent->parent,
+                                          NULL, false);
+               if (ifp == NULL)
+                       return NB_ERR_VALIDATION;
+               if (if_is_loopback(ifp)) {
+                       snprintf(args->errmsg, args->errmsg_len,
+                                "LDP-Sync does not run on loopback interface");
                        return NB_ERR_VALIDATION;
+               }
+
+               circuit = nb_running_get_entry(args->dnode, NULL, false);
+               if (circuit == NULL || circuit->area == NULL)
+                       break;
 
                if (circuit->isis->vrf_id != VRF_DEFAULT) {
                        snprintf(args->errmsg, args->errmsg_len,
@@ -3443,15 +3299,12 @@ int lib_interface_isis_mpls_holddown_destroy(struct nb_cb_destroy_args *args)
                break;
        case NB_EV_APPLY:
                circuit = nb_running_get_entry(args->dnode, NULL, true);
-               isis = circuit->isis;
                ldp_sync_info = circuit->ldp_sync_info;
+
                UNSET_FLAG(ldp_sync_info->flags, LDP_SYNC_FLAG_HOLDDOWN);
 
-               if (CHECK_FLAG(isis->ldp_sync_cmd.flags,
-                              LDP_SYNC_FLAG_HOLDDOWN))
-                       ldp_sync_info->holddown = isis->ldp_sync_cmd.holddown;
-               else
-                       ldp_sync_info->holddown = LDP_IGP_SYNC_HOLDDOWN_DEFAULT;
+               if (circuit->area)
+                       isis_if_set_ldp_sync_holddown(circuit);
                break;
        }
 
@@ -3473,15 +3326,18 @@ int lib_interface_isis_fast_reroute_level_1_lfa_enable_modify(
 
        circuit = nb_running_get_entry(args->dnode, NULL, true);
        circuit->lfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL);
-       if (circuit->lfa_protection[0])
-               circuit->area->lfa_protected_links[0]++;
-       else {
-               assert(circuit->area->lfa_protected_links[0] > 0);
-               circuit->area->lfa_protected_links[0]--;
-       }
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area) {
+               if (circuit->lfa_protection[0])
+                       area->lfa_protected_links[0]++;
+               else {
+                       assert(area->lfa_protected_links[0] > 0);
+                       area->lfa_protected_links[0]--;
+               }
+
+               lsp_regenerate_schedule(area, area->is_type, 0);
+       }
 
        return NB_OK;
 }
@@ -3505,7 +3361,8 @@ int lib_interface_isis_fast_reroute_level_1_lfa_exclude_interface_create(
 
        isis_lfa_excluded_iface_add(circuit, ISIS_LEVEL1, exclude_ifname);
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3525,7 +3382,8 @@ int lib_interface_isis_fast_reroute_level_1_lfa_exclude_interface_destroy(
 
        isis_lfa_excluded_iface_delete(circuit, ISIS_LEVEL1, exclude_ifname);
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3545,15 +3403,18 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_enable_modify(
 
        circuit = nb_running_get_entry(args->dnode, NULL, true);
        circuit->rlfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL);
-       if (circuit->rlfa_protection[0])
-               circuit->area->rlfa_protected_links[0]++;
-       else {
-               assert(circuit->area->rlfa_protected_links[0] > 0);
-               circuit->area->rlfa_protected_links[0]--;
-       }
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area) {
+               if (circuit->rlfa_protection[0])
+                       area->rlfa_protected_links[0]++;
+               else {
+                       assert(area->rlfa_protected_links[0] > 0);
+                       area->rlfa_protected_links[0]--;
+               }
+
+               lsp_regenerate_schedule(area, area->is_type, 0);
+       }
 
        return NB_OK;
 }
@@ -3575,7 +3436,8 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_maximum_metric_modify(
        circuit->rlfa_max_metric[0] = yang_dnode_get_uint32(args->dnode, NULL);
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3593,7 +3455,8 @@ int lib_interface_isis_fast_reroute_level_1_remote_lfa_maximum_metric_destroy(
        circuit->rlfa_max_metric[0] = 0;
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3613,15 +3476,18 @@ int lib_interface_isis_fast_reroute_level_1_ti_lfa_enable_modify(
 
        circuit = nb_running_get_entry(args->dnode, NULL, true);
        circuit->tilfa_protection[0] = yang_dnode_get_bool(args->dnode, NULL);
-       if (circuit->tilfa_protection[0])
-               circuit->area->tilfa_protected_links[0]++;
-       else {
-               assert(circuit->area->tilfa_protected_links[0] > 0);
-               circuit->area->tilfa_protected_links[0]--;
-       }
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area) {
+               if (circuit->tilfa_protection[0])
+                       area->tilfa_protected_links[0]++;
+               else {
+                       assert(area->tilfa_protected_links[0] > 0);
+                       area->tilfa_protected_links[0]--;
+               }
+
+               lsp_regenerate_schedule(area, area->is_type, 0);
+       }
 
        return NB_OK;
 }
@@ -3644,7 +3510,32 @@ int lib_interface_isis_fast_reroute_level_1_ti_lfa_node_protection_modify(
                yang_dnode_get_bool(args->dnode, NULL);
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
+
+       return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-1/ti-lfa/link-fallback
+ */
+int lib_interface_isis_fast_reroute_level_1_ti_lfa_link_fallback_modify(
+       struct nb_cb_modify_args *args)
+{
+       struct isis_area *area;
+       struct isis_circuit *circuit;
+
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       circuit = nb_running_get_entry(args->dnode, NULL, true);
+       circuit->tilfa_link_fallback[0] =
+               yang_dnode_get_bool(args->dnode, NULL);
+
+       area = circuit->area;
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3664,15 +3555,18 @@ int lib_interface_isis_fast_reroute_level_2_lfa_enable_modify(
 
        circuit = nb_running_get_entry(args->dnode, NULL, true);
        circuit->lfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL);
-       if (circuit->lfa_protection[1])
-               circuit->area->lfa_protected_links[1]++;
-       else {
-               assert(circuit->area->lfa_protected_links[1] > 0);
-               circuit->area->lfa_protected_links[1]--;
-       }
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area) {
+               if (circuit->lfa_protection[1])
+                       area->lfa_protected_links[1]++;
+               else {
+                       assert(area->lfa_protected_links[1] > 0);
+                       area->lfa_protected_links[1]--;
+               }
+
+               lsp_regenerate_schedule(area, area->is_type, 0);
+       }
 
        return NB_OK;
 }
@@ -3696,7 +3590,8 @@ int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_create(
 
        isis_lfa_excluded_iface_add(circuit, ISIS_LEVEL2, exclude_ifname);
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3716,7 +3611,8 @@ int lib_interface_isis_fast_reroute_level_2_lfa_exclude_interface_destroy(
 
        isis_lfa_excluded_iface_delete(circuit, ISIS_LEVEL2, exclude_ifname);
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3736,15 +3632,18 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_enable_modify(
 
        circuit = nb_running_get_entry(args->dnode, NULL, true);
        circuit->rlfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL);
-       if (circuit->rlfa_protection[1])
-               circuit->area->rlfa_protected_links[1]++;
-       else {
-               assert(circuit->area->rlfa_protected_links[1] > 0);
-               circuit->area->rlfa_protected_links[1]--;
-       }
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area) {
+               if (circuit->rlfa_protection[1])
+                       area->rlfa_protected_links[1]++;
+               else {
+                       assert(area->rlfa_protected_links[1] > 0);
+                       area->rlfa_protected_links[1]--;
+               }
+
+               lsp_regenerate_schedule(area, area->is_type, 0);
+       }
 
        return NB_OK;
 }
@@ -3766,7 +3665,8 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_maximum_metric_modify(
        circuit->rlfa_max_metric[1] = yang_dnode_get_uint32(args->dnode, NULL);
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3784,7 +3684,8 @@ int lib_interface_isis_fast_reroute_level_2_remote_lfa_maximum_metric_destroy(
        circuit->rlfa_max_metric[1] = 0;
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
@@ -3804,15 +3705,18 @@ int lib_interface_isis_fast_reroute_level_2_ti_lfa_enable_modify(
 
        circuit = nb_running_get_entry(args->dnode, NULL, true);
        circuit->tilfa_protection[1] = yang_dnode_get_bool(args->dnode, NULL);
-       if (circuit->tilfa_protection[1])
-               circuit->area->tilfa_protected_links[1]++;
-       else {
-               assert(circuit->area->tilfa_protected_links[1] > 0);
-               circuit->area->tilfa_protected_links[1]--;
-       }
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area) {
+               if (circuit->tilfa_protection[1])
+                       area->tilfa_protected_links[1]++;
+               else {
+                       assert(area->tilfa_protected_links[1] > 0);
+                       area->tilfa_protected_links[1]--;
+               }
+
+               lsp_regenerate_schedule(area, area->is_type, 0);
+       }
 
        return NB_OK;
 }
@@ -3835,7 +3739,32 @@ int lib_interface_isis_fast_reroute_level_2_ti_lfa_node_protection_modify(
                yang_dnode_get_bool(args->dnode, NULL);
 
        area = circuit->area;
-       lsp_regenerate_schedule(area, area->is_type, 0);
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
+
+       return NB_OK;
+}
+
+/*
+ * XPath:
+ * /frr-interface:lib/interface/frr-isisd:isis/fast-reroute/level-2/ti-lfa/link-fallback
+ */
+int lib_interface_isis_fast_reroute_level_2_ti_lfa_link_fallback_modify(
+       struct nb_cb_modify_args *args)
+{
+       struct isis_area *area;
+       struct isis_circuit *circuit;
+
+       if (args->event != NB_EV_APPLY)
+               return NB_OK;
+
+       circuit = nb_running_get_entry(args->dnode, NULL, true);
+       circuit->tilfa_link_fallback[1] =
+               yang_dnode_get_bool(args->dnode, NULL);
+
+       area = circuit->area;
+       if (area)
+               lsp_regenerate_schedule(area, area->is_type, 0);
 
        return NB_OK;
 }
index fe6a2f405203643cd9d43d0f1e92b074435a3b3f..dfc865162fbbf1f71be4d445f1569406d24126fc 100644 (file)
@@ -36,7 +36,7 @@
 #include "memory.h"
 #include "smux.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #include "isisd/isis_constants.h"
 #include "isisd/isis_common.h"
@@ -629,6 +629,54 @@ static uint8_t isis_null_sysid[ISIS_SYS_ID_LEN];
 /* Protocols supported value */
 static uint8_t isis_snmp_protocols_supported = 0x7; /* All: iso, ipv4, ipv6 */
 
+#define SNMP_CIRCUITS_MAX (512)
+
+static struct isis_circuit *snmp_circuits[SNMP_CIRCUITS_MAX];
+static uint32_t snmp_circuit_id_last;
+
+static int isis_circuit_snmp_id_gen(struct isis_circuit *circuit)
+{
+       uint32_t id;
+       uint32_t i;
+
+       id = snmp_circuit_id_last;
+       id++;
+
+       /* find next unused entry */
+       for (i = 0; i < SNMP_CIRCUITS_MAX; i++) {
+               if (id >= SNMP_CIRCUITS_MAX) {
+                       id = 0;
+                       continue;
+               }
+
+               if (id == 0)
+                       continue;
+
+               if (snmp_circuits[id] == NULL)
+                       break;
+
+               id++;
+       }
+
+       if (i == SNMP_CIRCUITS_MAX) {
+               zlog_warn("Could not allocate a smmp-circuit-id");
+               return 0;
+       }
+
+       snmp_circuits[id] = circuit;
+       snmp_circuit_id_last = id;
+       circuit->snmp_id = id;
+
+       return 0;
+}
+
+static int isis_circuit_snmp_id_free(struct isis_circuit *circuit)
+{
+       snmp_circuits[circuit->snmp_id] = NULL;
+       circuit->snmp_id = 0;
+       return 0;
+}
+
 /*
  * Convenience function to move to the next circuit,
  */
@@ -636,10 +684,6 @@ static struct isis_circuit *isis_snmp_circuit_next(struct isis_circuit *circuit)
 {
        uint32_t start;
        uint32_t off;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
-
-       if (isis == NULL)
-               return NULL;
 
        start = 1;
 
@@ -647,7 +691,7 @@ static struct isis_circuit *isis_snmp_circuit_next(struct isis_circuit *circuit)
                start = circuit->snmp_id + 1;
 
        for (off = start; off < SNMP_CIRCUITS_MAX; off++) {
-               circuit = isis->snmp_circuits[off];
+               circuit = snmp_circuits[off];
 
                if (circuit != NULL)
                        return circuit;
@@ -912,16 +956,12 @@ static int isis_snmp_circuit_lookup_exact(oid *oid_idx, size_t oid_idx_len,
                                          struct isis_circuit **ret_circuit)
 {
        struct isis_circuit *circuit;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
-
-       if (isis == NULL)
-               return 0;
 
        if (oid_idx == NULL || oid_idx_len < 1
            || oid_idx[0] > SNMP_CIRCUITS_MAX)
                return 0;
 
-       circuit = isis->snmp_circuits[oid_idx[0]];
+       circuit = snmp_circuits[oid_idx[0]];
        if (circuit == NULL)
                return 0;
 
@@ -937,10 +977,6 @@ static int isis_snmp_circuit_lookup_next(oid *oid_idx, size_t oid_idx_len,
        oid off;
        oid start;
        struct isis_circuit *circuit;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
-
-       if (isis == NULL)
-               return 0;
 
        start = 0;
 
@@ -952,7 +988,7 @@ static int isis_snmp_circuit_lookup_next(oid *oid_idx, size_t oid_idx_len,
        }
 
        for (off = start; off < SNMP_CIRCUITS_MAX; ++off) {
-               circuit = isis->snmp_circuits[off];
+               circuit = snmp_circuits[off];
 
                if (circuit != NULL && off > start) {
                        if (ret_circuit != NULL)
@@ -1009,12 +1045,8 @@ static int isis_snmp_circuit_level_lookup_next(
 {
        oid off;
        oid start;
-       struct isis_circuit *circuit;
+       struct isis_circuit *circuit = NULL;
        int level;
-       struct isis *isis = isis_lookup_by_vrfid(VRF_DEFAULT);
-
-       if (isis == NULL)
-               return 0;
 
        start = 0;
 
@@ -1026,7 +1058,7 @@ static int isis_snmp_circuit_level_lookup_next(
        }
 
        for (off = start; off < SNMP_CIRCUITS_MAX; off++) {
-               circuit = isis->snmp_circuits[off];
+               circuit = snmp_circuits[off];
 
                if (circuit == NULL)
                        continue;
@@ -1919,8 +1951,6 @@ static uint8_t *isis_snmp_find_system_counter(struct variable *v, oid *name,
                /* If level does not match all counters are zeros */
                return SNMP_INTEGER(0);
 
-       val = 0;
-
        switch (v->magic) {
        case ISIS_SYSSTAT_CORRLSPS:
                val = 0;
@@ -2480,7 +2510,6 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
 
        switch (v->magic) {
        case ISIS_ISADJ_STATE:
-               val = ISIS_SNMP_ADJ_STATE_DOWN;
 
                switch (adj->adj_state) {
                case ISIS_ADJ_UNKNOWN:
@@ -2509,7 +2538,6 @@ static uint8_t *isis_snmp_find_isadj(struct variable *v, oid *name,
        }
 
        case ISIS_ISADJ_NEIGHSYSTYPE:
-               val = ISIS_SNMP_ADJ_NEIGHTYPE_UNKNOWN;
 
                switch (adj->sys_type) {
                case ISIS_SYSTYPE_UNKNOWN:
@@ -3449,6 +3477,8 @@ static int isis_snmp_module_init(void)
        hook_register(isis_hook_adj_state_change,
                      isis_snmp_adj_state_change_update);
        hook_register(isis_hook_lsp_error, isis_snmp_lsp_error_update);
+       hook_register(isis_circuit_new_hook, isis_circuit_snmp_id_gen);
+       hook_register(isis_circuit_del_hook, isis_circuit_snmp_id_free);
 
        hook_register(frr_late_init, isis_snmp_init);
        return 0;
index 60559841952e01e19988367770c275c15cb61f09..7020b6efeb7714b1dd555935ad4cb0ebd120797c 100644 (file)
@@ -229,10 +229,10 @@ DEFUN (ip_router_isis,
 
        area = isis_area_lookup(area_tag, VRF_DEFAULT);
        if (!area)
-               area = isis_area_create(area_tag, VRF_DEFAULT_NAME);
+               isis_area_create(area_tag, VRF_DEFAULT_NAME);
 
-       if (!circuit || !circuit->area) {
-               circuit = isis_circuit_create(area, ifp);
+       if (!circuit) {
+               circuit = isis_circuit_new(ifp, area_tag);
 
                if (circuit->state != C_STATE_CONF
                    && circuit->state != C_STATE_UP) {
@@ -288,7 +288,7 @@ DEFUN (no_ip_router_isis,
                return CMD_ERR_NO_MATCH;
        }
 
-       circuit = circuit_lookup_by_ifp(ifp, area->circuit_list);
+       circuit = circuit_scan_by_ifp(ifp);
        if (!circuit) {
                vty_out(vty, "ISIS is not enabled on circuit %s\n", ifp->name);
                return CMD_ERR_NO_MATCH;
@@ -301,6 +301,10 @@ DEFUN (no_ip_router_isis,
                ip = false;
 
        isis_circuit_af_set(circuit, ip, ipv6);
+
+       if (!ip && !ipv6)
+               isis_circuit_del(circuit);
+
        return CMD_SUCCESS;
 }
 
index cb4dd2569d14f869b5bbee50cde99277b856a708..90959eb98c0889e8f95da6b839e9bbfd6b650542 100644 (file)
@@ -728,6 +728,8 @@ static void isis_zebra_connected(struct zclient *zclient)
 {
        zclient_send_reg_requests(zclient, VRF_DEFAULT);
        zclient_register_opaque(zclient, LDP_RLFA_LABELS);
+       zclient_register_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
+       zclient_register_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
 }
 
 /*
@@ -818,6 +820,8 @@ void isis_zebra_init(struct thread_master *master, int instance)
 void isis_zebra_stop(void)
 {
        zclient_unregister_opaque(zclient, LDP_RLFA_LABELS);
+       zclient_unregister_opaque(zclient, LDP_IGP_SYNC_IF_STATE_UPDATE);
+       zclient_unregister_opaque(zclient, LDP_IGP_SYNC_ANNOUNCE_UPDATE);
        zclient_stop(zclient_sync);
        zclient_free(zclient_sync);
        zclient_stop(zclient);
index 714961c1776d1b3e6e9ac164727e28e7a2e77580..37416fc1a4e0b478bdbedaf72b54a23b1c8a5343 100644 (file)
@@ -114,16 +114,6 @@ int show_isis_neighbor_common(struct vty *, const char *id, char,
 int clear_isis_neighbor_common(struct vty *, const char *id, const char *vrf_name,
                               bool all_vrf);
 
-static void isis_add(struct isis *isis)
-{
-       listnode_add(im->isis, isis);
-}
-
-static void isis_delete(struct isis *isis)
-{
-       listnode_delete(im->isis, isis);
-}
-
 /* Link ISIS instance to VRF. */
 void isis_vrf_link(struct isis *isis, struct vrf *vrf)
 {
@@ -189,10 +179,8 @@ void isis_global_instance_create(const char *vrf_name)
        struct isis *isis;
 
        isis = isis_lookup_by_vrfname(vrf_name);
-       if (isis == NULL) {
-               isis = isis_new(vrf_name);
-               isis_add(isis);
-       }
+       if (isis == NULL)
+               isis_new(vrf_name);
 }
 
 struct isis *isis_new(const char *vrf_name)
@@ -201,16 +189,15 @@ struct isis *isis_new(const char *vrf_name)
        struct isis *isis;
 
        isis = XCALLOC(MTYPE_ISIS, sizeof(struct isis));
+
+       isis->name = XSTRDUP(MTYPE_ISIS_NAME, vrf_name);
+
        vrf = vrf_lookup_by_name(vrf_name);
 
-       if (vrf) {
-               isis->vrf_id = vrf->vrf_id;
+       if (vrf)
                isis_vrf_link(isis, vrf);
-               isis->name = XSTRDUP(MTYPE_ISIS_NAME, vrf->name);
-       } else {
+       else
                isis->vrf_id = VRF_UNKNOWN;
-               isis->name = XSTRDUP(MTYPE_ISIS_NAME, vrf_name);
-       }
 
        if (IS_DEBUG_EVENTS)
                zlog_debug(
@@ -224,43 +211,81 @@ struct isis *isis_new(const char *vrf_name)
        isis->process_id = getpid();
        isis->router_id = 0;
        isis->area_list = list_new();
-       isis->init_circ_list = list_new();
        isis->uptime = time(NULL);
        isis->snmp_notifications = 1;
        dyn_cache_init(isis);
 
+       listnode_add(im->isis, isis);
+
        return isis;
 }
 
+void isis_finish(struct isis *isis)
+{
+       struct vrf *vrf = NULL;
+
+       listnode_delete(im->isis, isis);
+
+       vrf = vrf_lookup_by_name(isis->name);
+       if (vrf)
+               isis_vrf_unlink(isis, vrf);
+       XFREE(MTYPE_ISIS_NAME, isis->name);
+
+       isis_redist_free(isis);
+       list_delete(&isis->area_list);
+       XFREE(MTYPE_ISIS, isis);
+}
+
+void isis_area_add_circuit(struct isis_area *area, struct isis_circuit *circuit)
+{
+       isis_csm_state_change(ISIS_ENABLE, circuit, area);
+
+       area->ip_circuits += circuit->ip_router;
+       area->ipv6_circuits += circuit->ipv6_router;
+
+       area->lfa_protected_links[0] += circuit->lfa_protection[0];
+       area->rlfa_protected_links[0] += circuit->rlfa_protection[0];
+       area->tilfa_protected_links[0] += circuit->tilfa_protection[0];
+
+       area->lfa_protected_links[1] += circuit->lfa_protection[1];
+       area->rlfa_protected_links[1] += circuit->rlfa_protection[1];
+       area->tilfa_protected_links[1] += circuit->tilfa_protection[1];
+}
+
+void isis_area_del_circuit(struct isis_area *area, struct isis_circuit *circuit)
+{
+       area->ip_circuits -= circuit->ip_router;
+       area->ipv6_circuits -= circuit->ipv6_router;
+
+       area->lfa_protected_links[0] -= circuit->lfa_protection[0];
+       area->rlfa_protected_links[0] -= circuit->rlfa_protection[0];
+       area->tilfa_protected_links[0] -= circuit->tilfa_protection[0];
+
+       area->lfa_protected_links[1] -= circuit->lfa_protection[1];
+       area->rlfa_protected_links[1] -= circuit->rlfa_protection[1];
+       area->tilfa_protected_links[1] -= circuit->tilfa_protection[1];
+
+       isis_csm_state_change(ISIS_DISABLE, circuit, area);
+}
+
 struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name)
 {
        struct isis_area *area;
        struct isis *isis = NULL;
        struct vrf *vrf = NULL;
+       struct interface *ifp;
+       struct isis_circuit *circuit;
+
        area = XCALLOC(MTYPE_ISIS_AREA, sizeof(struct isis_area));
 
-       if (vrf_name) {
-               vrf = vrf_lookup_by_name(vrf_name);
-               if (vrf) {
-                       isis = isis_lookup_by_vrfid(vrf->vrf_id);
-                       if (isis == NULL) {
-                               isis = isis_new(vrf_name);
-                               isis_add(isis);
-                       }
-               } else {
-                       isis = isis_lookup_by_vrfid(VRF_UNKNOWN);
-                       if (isis == NULL) {
-                               isis = isis_new(vrf_name);
-                               isis_add(isis);
-                       }
-               }
-       } else {
-               isis = isis_lookup_by_vrfid(VRF_DEFAULT);
-               if (isis == NULL) {
-                       isis = isis_new(VRF_DEFAULT_NAME);
-                       isis_add(isis);
-               }
-       }
+       if (!vrf_name)
+               vrf_name = VRF_DEFAULT_NAME;
+
+       vrf = vrf_lookup_by_name(vrf_name);
+       isis = isis_lookup_by_vrfname(vrf_name);
+
+       if (isis == NULL)
+               isis = isis_new(vrf_name);
 
        listnode_add(isis->area_list, area);
        area->isis = isis;
@@ -373,9 +398,19 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name)
        area->bfd_signalled_down = false;
        area->bfd_force_spf_refresh = false;
 
-
        QOBJ_REG(area, isis_area);
 
+       if (vrf) {
+               FOR_ALL_INTERFACES (vrf, ifp) {
+                       if (ifp->ifindex == IFINDEX_INTERNAL)
+                               continue;
+
+                       circuit = ifp->info;
+                       if (circuit)
+                               isis_area_add_circuit(area, circuit);
+               }
+       }
+
        return area;
 }
 
@@ -470,11 +505,9 @@ void isis_area_destroy(struct isis_area *area)
 
        if (area->circuit_list) {
                for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
-                                      circuit)) {
-                       circuit->ip_router = 0;
-                       circuit->ipv6_router = 0;
-                       isis_csm_state_change(ISIS_DISABLE, circuit, area);
-               }
+                                      circuit))
+                       isis_area_del_circuit(area, circuit);
+
                list_delete(&area->circuit_list);
        }
        list_delete(&area->adjacency_list);
@@ -572,10 +605,6 @@ static int isis_vrf_enable(struct vrf *vrf)
 
        isis = isis_lookup_by_vrfname(vrf->name);
        if (isis) {
-               if (isis->name && strmatch(vrf->name, VRF_DEFAULT_NAME)) {
-                       XFREE(MTYPE_ISIS_NAME, isis->name);
-                       isis->name = NULL;
-               }
                old_vrf_id = isis->vrf_id;
                /* We have instance configured, link to VRF and make it "up". */
                isis_vrf_link(isis, vrf);
@@ -630,28 +659,6 @@ void isis_vrf_init(void)
                 isis_vrf_delete, isis_vrf_enable);
 }
 
-void isis_finish(struct isis *isis)
-{
-       struct vrf *vrf = NULL;
-
-       isis_delete(isis);
-       if (isis->name) {
-               vrf = vrf_lookup_by_name(isis->name);
-               if (vrf)
-                       isis_vrf_unlink(isis, vrf);
-               XFREE(MTYPE_ISIS_NAME, isis->name);
-       } else {
-               vrf = vrf_lookup_by_id(VRF_DEFAULT);
-               if (vrf)
-                       isis_vrf_unlink(isis, vrf);
-       }
-
-       isis_redist_free(isis);
-       list_delete(&isis->area_list);
-       list_delete(&isis->init_circ_list);
-       XFREE(MTYPE_ISIS, isis);
-}
-
 void isis_terminate()
 {
        struct isis *isis;
@@ -1369,6 +1376,9 @@ DEFUN_NOSH (show_debugging,
                print_debug(vty, DEBUG_BFD, 1);
        if (IS_DEBUG_LDP_SYNC)
                print_debug(vty, DEBUG_LDP_SYNC, 1);
+       if (IS_DEBUG_LFA)
+               print_debug(vty, DEBUG_LFA, 1);
+
        return CMD_SUCCESS;
 }
 
index a2e821ad2ffab5d907f1627eb326b5f4b21a7d23..9d0b57e9f6834ba4040f02c6da4d3ce5bf0e7eea 100644 (file)
@@ -65,8 +65,6 @@ extern void isis_cli_init(void);
                all_vrf = strmatch(vrf_name, "all");                           \
        }
 
-#define SNMP_CIRCUITS_MAX (512)
-
 extern struct zebra_privs_t isisd_privs;
 
 /* uncomment if you are a developer in bug hunt */
@@ -91,18 +89,14 @@ struct isis {
        uint8_t sysid[ISIS_SYS_ID_LEN]; /* SystemID for this IS */
        uint32_t router_id;             /* Router ID from zebra */
        struct list *area_list; /* list of IS-IS areas */
-       struct list *init_circ_list;
        uint8_t max_area_addrs;           /* maximumAreaAdresses */
        struct area_addr *man_area_addrs; /* manualAreaAddresses */
        time_t uptime;                    /* when did we start */
        struct thread *t_dync_clean;      /* dynamic hostname cache cleanup thread */
        uint32_t circuit_ids_used[8];     /* 256 bits to track circuit ids 1 through 255 */
-       struct isis_circuit *snmp_circuits[SNMP_CIRCUITS_MAX];
-       uint32_t snmp_circuit_id_last;
        int snmp_notifications;
 
        struct route_table *ext_info[REDIST_PROTOCOL_COUNT];
-       struct ldp_sync_info_cmd ldp_sync_cmd;  /* MPLS LDP-IGP Sync */
 };
 
 extern struct isis_master *im;
@@ -214,6 +208,8 @@ struct isis_area {
        struct prefix_list *rlfa_plist[ISIS_LEVELS];
        size_t rlfa_protected_links[ISIS_LEVELS];
        size_t tilfa_protected_links[ISIS_LEVELS];
+       /* MPLS LDP-IGP Sync */
+       struct ldp_sync_info_cmd ldp_sync_cmd;
        /* Counters */
        uint32_t circuit_state_changes;
        struct isis_redist redist_settings[REDIST_PROTOCOL_COUNT]
@@ -248,7 +244,6 @@ DECLARE_MTYPE(ISIS_AREA_ADDR);      /* isis_area->area_addrs */
 DECLARE_HOOK(isis_area_overload_bit_update, (struct isis_area * area), (area));
 
 void isis_terminate(void);
-void isis_finish(struct isis *isis);
 void isis_master_init(struct thread_master *master);
 void isis_vrf_link(struct isis *isis, struct vrf *vrf);
 void isis_vrf_unlink(struct isis *isis, struct vrf *vrf);
@@ -261,6 +256,13 @@ void isis_init(void);
 void isis_vrf_init(void);
 
 struct isis *isis_new(const char *vrf_name);
+void isis_finish(struct isis *isis);
+
+void isis_area_add_circuit(struct isis_area *area,
+                          struct isis_circuit *circuit);
+void isis_area_del_circuit(struct isis_area *area,
+                          struct isis_circuit *circuit);
+
 struct isis_area *isis_area_create(const char *, const char *);
 struct isis_area *isis_area_lookup(const char *, vrf_id_t vrf_id);
 struct isis_area *isis_area_lookup_by_vrf(const char *area_tag,
index 11bae416577d3ddc33c8bb86db10c2460857ca04..4243bd60cf560246acae7e7bd55c8e09a33afac3 100644 (file)
@@ -138,7 +138,7 @@ nodist_isisd_isisd_SOURCES = \
        # end
 
 isisd_isisd_snmp_la_SOURCES = isisd/isis_snmp.c
-isisd_isisd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+isisd_isisd_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 isisd_isisd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 isisd_isisd_snmp_la_LIBADD = lib/libfrrsnmp.la
 
index 8fa74d1c3dd39464da87813447252d16755b6574..724e83adb29b4ae476034785b4e6f1fd448f4691 100644 (file)
@@ -134,6 +134,8 @@ lde(void)
        log_procname = log_procnames[PROC_LDE_ENGINE];
 
        master = frr_init();
+       /* no frr_config_fork() here, allow frr_pthread to create threads */
+       frr_is_after_fork = true;
 
        /* setup signal handler */
        signal_init(master, array_size(lde_signals), lde_signals);
@@ -1628,6 +1630,30 @@ lde_nbr_addr_update(struct lde_nbr *ln, struct lde_addr *lde_addr, int removed)
        }
 }
 
+void
+lde_allow_broken_lsp_update(int new_config)
+{
+       struct fec_node         *fn;
+       struct fec_nh           *fnh;
+       struct fec              *f;
+
+       RB_FOREACH(f, fec_tree, &ft) {
+               fn = (struct fec_node *)f;
+
+               LIST_FOREACH(fnh, &fn->nexthops, entry) {
+                       /* allow-broken-lsp config is changing so
+                        * we need to reprogram labeled routes to
+                        * have proper top-level label
+                        */
+                       if (!(new_config & F_LDPD_ALLOW_BROKEN_LSP))
+                               lde_send_delete_klabel(fn, fnh);
+
+                       if (fn->local_label != NO_LABEL)
+                               lde_send_change_klabel(fn, fnh);
+               }
+       }
+}
+
 static __inline int
 lde_map_compare(const struct lde_map *a, const struct lde_map *b)
 {
index e09be01ece58ac4ba9fe4d7b396a478a86b93f0d..dee6f3fcb9831e51e847844b1db89a8e70b15f23 100644 (file)
@@ -200,6 +200,7 @@ void                 lde_route_update_release(struct iface *, int);
 void            lde_route_update_release_all(int);
 struct lde_addr        *lde_address_find(struct lde_nbr *, int,
                    union ldpd_addr *);
+void            lde_allow_broken_lsp_update(int new_config);
 
 /* lde_lib.c */
 void            fec_init(struct fec_tree *);
index 9fb4e465159548b6903681ec6b77658a46af62c8..3932df48e027d610755e2970cb19f25214436765 100644 (file)
@@ -36,7 +36,7 @@
 #include "memory.h"
 #include "smux.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "ldpd.h"
 #include "ldpe.h"
 
index 882874f1be49179eff0a0f9a985a35857933c617..d788fa0687a28ee1c88951469d2ff78555503b31 100644 (file)
@@ -34,6 +34,7 @@ extern struct cmd_node ldp_debug_node;
 union ldpd_addr;
 int     ldp_get_address(const char *, int *, union ldpd_addr *);
 int     ldp_vty_mpls_ldp (struct vty *, const char *);
+int     ldp_vty_allow_broken_lsp(struct vty *, const char *);
 int     ldp_vty_address_family (struct vty *, const char *, const char *);
 int     ldp_vty_disc_holdtime(struct vty *, const char *, enum hello_type, long);
 int     ldp_vty_disc_interval(struct vty *, const char *, enum hello_type, long);
index 1f102f86fa89fb9594ec2b31ce576a6fab4bdf0e..b65ebf6f559e0a867930aefda8110bf376ff6d35 100644 (file)
@@ -241,6 +241,16 @@ DEFPY  (ldp_wait_for_sync,
 
 }
 
+DEFPY  (ldp_allow_broken_lsps,
+       ldp_allow_broken_lsps_cmd,
+       "[no] install allow-broken-lsps",
+       NO_STR
+       "install lsps\n"
+       "if no remote-label install with imp-null")
+{
+       return (ldp_vty_allow_broken_lsp(vty, no));
+}
+
 DEFPY  (ldp_discovery_targeted_hello_accept,
        ldp_discovery_targeted_hello_accept_cmd,
        "[no] discovery targeted-hello accept [from <(1-199)|(1300-2699)|WORD>$from_acl]",
@@ -844,6 +854,7 @@ ldp_vty_init (void)
        install_element(LDP_NODE, &ldp_router_id_cmd);
        install_element(LDP_NODE, &ldp_ordered_control_cmd);
        install_element(LDP_NODE, &ldp_wait_for_sync_cmd);
+       install_element(LDP_NODE, &ldp_allow_broken_lsps_cmd);
 
        install_element(LDP_IPV4_NODE, &ldp_discovery_link_holdtime_cmd);
        install_element(LDP_IPV4_NODE, &ldp_discovery_targeted_holdtime_cmd);
index d21e3c0409970bc1335b24690ef7586e208237d7..b35d3dfa00793e6d5e2b9bafa0a8049d3d892417 100644 (file)
@@ -290,6 +290,9 @@ ldp_config_write(struct vty *vty)
                vty_out (vty, " wait-for-sync %u\n",
                    ldpd_conf->wait_for_sync_interval);
 
+       if (ldpd_conf->flags & F_LDPD_ALLOW_BROKEN_LSP)
+               vty_out(vty, " install allow-broken-lsp\n");
+
        RB_FOREACH(nbrp, nbrp_head, &ldpd_conf->nbrp_tree) {
                if (nbrp->flags & F_NBRP_KEEPALIVE)
                        vty_out (vty, " neighbor %pI4 session holdtime %u\n",
@@ -429,6 +432,9 @@ ldp_vty_mpls_ldp(struct vty *vty, const char *negate)
                vty_conf->flags |= F_LDPD_ENABLED;
        }
 
+       /* register / de-register to recv info from zebra */
+       ldp_zebra_regdereg_zebra_info(!negate);
+
        ldp_config_apply(vty, vty_conf);
 
        return (CMD_SUCCESS);
@@ -1036,6 +1042,19 @@ int ldp_vty_wait_for_sync_interval(struct vty *vty, const char *negate,
        return (CMD_SUCCESS);
 }
 
+int
+ldp_vty_allow_broken_lsp(struct vty *vty, const char *negate)
+{
+       if (negate)
+               vty_conf->flags &= ~F_LDPD_ALLOW_BROKEN_LSP;
+       else
+               vty_conf->flags |= F_LDPD_ALLOW_BROKEN_LSP;
+
+       ldp_config_apply(vty, vty_conf);
+
+       return (CMD_SUCCESS);
+}
+
 int
 ldp_vty_ds_cisco_interop(struct vty *vty, const char * negate)
 {
index ea86c2dc039c40fbc474718066d7689e6dc7b8c8..2d90412d173418e931fcf0969dedfe82b060369d 100644 (file)
@@ -54,6 +54,7 @@ static int    ldp_zebra_opaque_msg_handler(ZAPI_CALLBACK_ARGS);
 static void    ldp_sync_zebra_init(void);
 
 static struct zclient  *zclient;
+static bool zebra_registered = false;
 
 static void
 ifp2kif(struct interface *ifp, struct kif *kif)
@@ -245,12 +246,17 @@ ldp_zebra_send_mpls_labels(int cmd, struct kroute *kr)
                zl.route.instance = kr->route_instance;
        }
 
-       /*
-        * For broken LSPs, instruct the forwarding plane to pop the top-level
+       /* If allow-broken-lsps is enabled then if an lsp is received with
+        * no remote label, instruct the forwarding plane to pop the top-level
         * label and forward packets normally. This is a best-effort attempt
         * to deliver labeled IP packets to their final destination (instead of
         * dropping them).
         */
+       if (kr->remote_label == NO_LABEL
+           && !(ldpd_conf->flags & F_LDPD_ALLOW_BROKEN_LSP)
+           && cmd == ZEBRA_MPLS_LABELS_ADD)
+               return 0;
+
        if (kr->remote_label == NO_LABEL)
                kr->remote_label = MPLS_LABEL_IMPLICIT_NULL;
 
@@ -629,14 +635,42 @@ ldp_zebra_read_pw_status_update(ZAPI_CALLBACK_ARGS)
        return (0);
 }
 
+void ldp_zebra_regdereg_zebra_info(bool want_register)
+{
+       if (zebra_registered == want_register)
+               return;
+
+       log_debug("%s to receive default VRF information",
+                 want_register ? "Register" : "De-register");
+
+       if (want_register) {
+               zclient_send_reg_requests(zclient, VRF_DEFAULT);
+               zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
+                                       ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
+               zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient,
+                                       AFI_IP6, ZEBRA_ROUTE_ALL, 0,
+                                       VRF_DEFAULT);
+       } else {
+               zclient_send_dereg_requests(zclient, VRF_DEFAULT);
+               zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
+                                       AFI_IP, ZEBRA_ROUTE_ALL, 0,
+                                       VRF_DEFAULT);
+               zebra_redistribute_send(ZEBRA_REDISTRIBUTE_DELETE, zclient,
+                                       AFI_IP6, ZEBRA_ROUTE_ALL, 0,
+                                       VRF_DEFAULT);
+       }
+       zebra_registered = want_register;
+}
+
 static void
 ldp_zebra_connected(struct zclient *zclient)
 {
-       zclient_send_reg_requests(zclient, VRF_DEFAULT);
-       zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP,
-           ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
-       zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP6,
-           ZEBRA_ROUTE_ALL, 0, VRF_DEFAULT);
+       zebra_registered = false;
+
+       /* if MPLS was already enabled and we are re-connecting, register again
+        */
+       if (vty_conf->flags & F_LDPD_ENABLED)
+               ldp_zebra_regdereg_zebra_info(true);
 
        ldp_zebra_opaque_register();
 
@@ -650,9 +684,8 @@ ldp_zebra_filter_update(struct access_list *access)
 
        if (access && access->name[0] != '\0') {
                strlcpy(laccess.name, access->name, sizeof(laccess.name));
-               laccess.type = access->type;
-               debug_evt("%s ACL update filter name %s type %d", __func__,
-                   access->name, access->type);
+               debug_evt("%s ACL update filter name %s", __func__,
+                         access->name);
 
                main_imsg_compose_both(IMSG_FILTER_UPDATE, &laccess,
                        sizeof(laccess));
index d69a4dcd3c5ade83093b3241c41584a17abb9aa8..800b954d65253769e009a5bb5873443eb405f46f 100644 (file)
@@ -1365,6 +1365,16 @@ merge_global(struct ldpd_conf *conf, struct ldpd_conf *xconf)
                        ldpe_reset_ds_nbrs();
        }
 
+       /*
+        * Configuration of allow-broken-lsp requires reprograming all
+        * labeled routes
+        */
+       if ((conf->flags & F_LDPD_ALLOW_BROKEN_LSP) !=
+           (xconf->flags & F_LDPD_ALLOW_BROKEN_LSP)) {
+               if (ldpd_process == PROC_LDE_ENGINE)
+                       lde_allow_broken_lsp_update(xconf->flags);
+       }
+
        if (ldpd_process == PROC_LDP_ENGINE)
                ldpe_set_config_change_time();
 
index 8fdc16fc7b97b60a366147109df48c5510a332fc..616c390e50b0e6e1c14dd4ffdc46c0269f73eba0 100644 (file)
@@ -174,7 +174,6 @@ struct ldpd_init {
 
 struct ldp_access {
        char                     name[ACL_NAMSIZ];
-       enum access_type         type;
 };
 
 union ldpd_addr {
@@ -591,7 +590,7 @@ DECLARE_QOBJ_TYPE(ldpd_conf);
 #define        F_LDPD_DS_CISCO_INTEROP 0x0002
 #define        F_LDPD_ENABLED          0x0004
 #define        F_LDPD_ORDERED_CONTROL  0x0008
-
+#define        F_LDPD_ALLOW_BROKEN_LSP 0x0010
 
 struct ldpd_af_global {
        struct thread           *disc_ev;
@@ -906,6 +905,8 @@ int          ldp_sync_zebra_send_state_update(struct ldp_igp_sync_if_state *);
 int             ldp_zebra_send_rlfa_labels(struct zapi_rlfa_response *
                    rlfa_labels);
 
+void ldp_zebra_regdereg_zebra_info(bool want_register);
+
 /* compatibility */
 #ifndef __OpenBSD__
 #define __IPV6_ADDR_MC_SCOPE(a)                ((a)->s6_addr[1] & 0x0f)
index d09eb2fa33e84c00320467e93bb08bce4f88aa2e..428d2ab7b49a7fc4d766df6834fd9268311328fe 100644 (file)
@@ -111,6 +111,8 @@ ldpe(void)
        log_procname = log_procnames[ldpd_process];
 
        master = frr_init();
+       /* no frr_config_fork() here, allow frr_pthread to create threads */
+       frr_is_after_fork = true;
 
        /* setup signal handler */
        signal_init(master, array_size(ldpe_signals), ldpe_signals);
index 5fc3847c6d8cf53de2680c372b59fc389beea6c7..b7e2ab72d6b33fbd74bfdb10c4a73d04bec3c518 100644 (file)
@@ -64,6 +64,6 @@ ldpd_ldpd_SOURCES = ldpd/ldpd.c
 ldpd_ldpd_LDADD = ldpd/libldp.a lib/libfrr.la $(LIBCAP)
 
 ldpd_ldpd_snmp_la_SOURCES = ldpd/ldp_snmp.c
-ldpd_ldpd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+ldpd_ldpd_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 ldpd_ldpd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 ldpd_ldpd_snmp_la_LIBADD = lib/libfrrsnmp.la
index b5a035ee2be81e31ad558fb4c8760022691ae096..6d4e68d651105501a09cfbc9e99aa35fe3573c5a 100644 (file)
@@ -30,7 +30,7 @@
 #include "smux.h"
 #include "memory.h"
 #include "linklist.h"
-#include "version.h"
+#include "lib/version.h"
 #include "lib_errors.h"
 #include "xref.h"
 
diff --git a/lib/assert/assert.h b/lib/assert/assert.h
new file mode 100644 (file)
index 0000000..fbdbd52
--- /dev/null
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2021  David Lamparter, for NetDEF, Inc.
+ *
+ * Permission to use, copy, modify, and 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+/* WARNING: this file is "special" in that it overrides the system-provided
+ * assert.h by being on the include path before it.  That means it should
+ * provide the functional equivalent.
+ *
+ * This is intentional because FRR extends assert() to write to the log and
+ * add backtraces.  Overriding the entire file is the simplest and most
+ * reliable way to get this to work;  there were problems previously with the
+ * system assert.h getting included afterwards and redefining assert() back to
+ * the system variant.
+ */
+
+#ifndef _FRR_ASSERT_H
+#define _FRR_ASSERT_H
+
+#include "xref.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __cplusplus
+/* C++ has this built-in, but C provides it in assert.h for >=C11.  Since we
+ * replace assert.h entirely, we need to provide it here too.
+ */
+#define static_assert _Static_assert
+#endif
+
+struct xref_assert {
+       struct xref xref;
+
+       const char *expr;
+       const char *extra, *args;
+};
+
+extern void _zlog_assert_failed(const struct xref_assert *xref,
+                               const char *extra, ...) PRINTFRR(2, 3)
+       __attribute__((noreturn));
+
+/* the "do { } while (expr_)" is there to get a warning for assignments inside
+ * the assert expression aka "assert(x = 1)".  The (necessary) braces around
+ * expr_ in the if () statement would suppress these warnings.  Since
+ * _zlog_assert_failed() is noreturn, the while condition will never be
+ * checked.
+ */
+#define assert(expr_)                                                          \
+       ({                                                                     \
+               static const struct xref_assert _xref __attribute__(           \
+                       (used)) = {                                            \
+                       .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__),       \
+                       .expr = #expr_,                                        \
+               };                                                             \
+               XREF_LINK(_xref.xref);                                         \
+               if (__builtin_expect((expr_) ? 0 : 1, 0))                      \
+                       do {                                                   \
+                               _zlog_assert_failed(&_xref, NULL);             \
+                       } while (expr_);                                       \
+       })
+
+#define assertf(expr_, extra_, ...)                                            \
+       ({                                                                     \
+               static const struct xref_assert _xref __attribute__(           \
+                       (used)) = {                                            \
+                       .xref = XREF_INIT(XREFT_ASSERT, NULL, __func__),       \
+                       .expr = #expr_,                                        \
+                       .extra = extra_,                                       \
+                       .args = #__VA_ARGS__,                                  \
+               };                                                             \
+               XREF_LINK(_xref.xref);                                         \
+               if (__builtin_expect((expr_) ? 0 : 1, 0))                      \
+                       do {                                                   \
+                               _zlog_assert_failed(&_xref, extra_,            \
+                                                   ##__VA_ARGS__);            \
+                       } while (expr_);                                       \
+       })
+
+#define zassert assert
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _FRR_ASSERT_H */
index 276d6c685e64c0cd1eebca1e7c07a487dfbcb1ad..0974c268096d4bd1fe9896d169d901312125b1e1 100644 (file)
--- a/lib/bfd.c
+++ b/lib/bfd.c
@@ -237,7 +237,7 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
        memset(sp, 0, sizeof(*sp));
 
        /* Get interface index. */
-       ifindex = stream_getl(s);
+       STREAM_GETL(s, ifindex);
 
        /* Lookup index. */
        if (ifindex != 0) {
@@ -252,25 +252,28 @@ struct interface *bfd_get_peer_info(struct stream *s, struct prefix *dp,
        }
 
        /* Fetch destination address. */
-       dp->family = stream_getc(s);
+       STREAM_GETC(s, dp->family);
 
        plen = prefix_blen(dp);
-       stream_get(&dp->u.prefix, s, plen);
-       dp->prefixlen = stream_getc(s);
+       STREAM_GET(&dp->u.prefix, s, plen);
+       STREAM_GETC(s, dp->prefixlen);
 
        /* Get BFD status. */
-       *status = stream_getl(s);
+       STREAM_GETL(s, (*status));
 
-       sp->family = stream_getc(s);
+       STREAM_GETC(s, sp->family);
 
        plen = prefix_blen(sp);
-       stream_get(&sp->u.prefix, s, plen);
-       sp->prefixlen = stream_getc(s);
+       STREAM_GET(&sp->u.prefix, s, plen);
+       STREAM_GETC(s, sp->prefixlen);
 
-       local_remote_cbit = stream_getc(s);
+       STREAM_GETC(s, local_remote_cbit);
        if (remote_cbit)
                *remote_cbit = local_remote_cbit;
        return ifp;
+
+stream_failure:
+       return NULL;
 }
 
 /*
@@ -616,8 +619,6 @@ struct bfd_session_params {
 
        /** BFD session installation state. */
        bool installed;
-       /** BFD session enabled. */
-       bool enabled;
 
        /** Global BFD paramaters list. */
        TAILQ_ENTRY(bfd_session_params) entry;
@@ -745,6 +746,21 @@ static int _bfd_sess_send(struct thread *t)
                        bsp->installed = false;
                else if (bsp->args.command == ZEBRA_BFD_DEST_REGISTER)
                        bsp->installed = true;
+       } else {
+               struct ipaddr src, dst;
+
+               src.ipa_type = bsp->args.family;
+               src.ipaddr_v6 = bsp->args.src;
+               dst.ipa_type = bsp->args.family;
+               dst.ipaddr_v6 = bsp->args.dst;
+
+               zlog_err(
+                       "%s: BFD session %pIA -> %pIA interface %s VRF %s(%u) was not %s",
+                       __func__, &src, &dst,
+                       bsp->args.ifnamelen ? bsp->args.ifname : "*",
+                       vrf_id_to_name(bsp->args.vrf_id), bsp->args.vrf_id,
+                       bsp->lastev == BSE_INSTALL ? "installed"
+                                                  : "uninstalled");
        }
 
        return 0;
@@ -779,18 +795,33 @@ void bfd_sess_free(struct bfd_session_params **bsp)
        XFREE(MTYPE_BFD_INFO, (*bsp));
 }
 
-void bfd_sess_enable(struct bfd_session_params *bsp, bool enable)
+static bool bfd_sess_address_changed(const struct bfd_session_params *bsp,
+                                    uint32_t family,
+                                    const struct in6_addr *src,
+                                    const struct in6_addr *dst)
 {
-       /* Remove the session when disabling. */
-       if (!enable)
-               _bfd_sess_remove(bsp);
+       size_t addrlen;
 
-       bsp->enabled = enable;
+       if (bsp->args.family != family)
+               return true;
+
+       addrlen = (family == AF_INET) ? sizeof(struct in_addr)
+                                     : sizeof(struct in6_addr);
+       if ((src == NULL && memcmp(&bsp->args.src, &i6a_zero, addrlen))
+           || (src && memcmp(src, &bsp->args.src, addrlen))
+           || memcmp(dst, &bsp->args.dst, addrlen))
+               return true;
+
+       return false;
 }
 
 void bfd_sess_set_ipv4_addrs(struct bfd_session_params *bsp,
                             struct in_addr *src, struct in_addr *dst)
 {
+       if (!bfd_sess_address_changed(bsp, AF_INET, (struct in6_addr *)src,
+                                     (struct in6_addr *)dst))
+               return;
+
        /* If already installed, remove the old setting. */
        _bfd_sess_remove(bsp);
 
@@ -811,6 +842,10 @@ void bfd_sess_set_ipv4_addrs(struct bfd_session_params *bsp,
 void bfd_sess_set_ipv6_addrs(struct bfd_session_params *bsp,
                             struct in6_addr *src, struct in6_addr *dst)
 {
+       if (!bfd_sess_address_changed(bsp, AF_INET, (struct in6_addr *)src,
+                                     (struct in6_addr *)dst))
+               return;
+
        /* If already installed, remove the old setting. */
        _bfd_sess_remove(bsp);
 
@@ -828,6 +863,10 @@ void bfd_sess_set_ipv6_addrs(struct bfd_session_params *bsp,
 
 void bfd_sess_set_interface(struct bfd_session_params *bsp, const char *ifname)
 {
+       if ((ifname == NULL && bsp->args.ifnamelen == 0)
+           || (ifname && strcmp(bsp->args.ifname, ifname) == 0))
+               return;
+
        /* If already installed, remove the old setting. */
        _bfd_sess_remove(bsp);
 
@@ -861,6 +900,9 @@ void bfd_sess_set_profile(struct bfd_session_params *bsp, const char *profile)
 
 void bfd_sess_set_vrf(struct bfd_session_params *bsp, vrf_id_t vrf_id)
 {
+       if (bsp->args.vrf_id == vrf_id)
+               return;
+
        /* If already installed, remove the old setting. */
        _bfd_sess_remove(bsp);
 
@@ -871,6 +913,9 @@ void bfd_sess_set_mininum_ttl(struct bfd_session_params *bsp, uint8_t min_ttl)
 {
        assert(min_ttl != 0);
 
+       if (bsp->args.ttl == ((BFD_SINGLE_HOP_TTL + 1) - min_ttl))
+               return;
+
        /* If already installed, remove the old setting. */
        _bfd_sess_remove(bsp);
 
@@ -882,6 +927,9 @@ void bfd_sess_set_mininum_ttl(struct bfd_session_params *bsp, uint8_t min_ttl)
 
 void bfd_sess_set_hop_count(struct bfd_session_params *bsp, uint8_t min_ttl)
 {
+       if (bsp->args.ttl == min_ttl)
+               return;
+
        /* If already installed, remove the old setting. */
        _bfd_sess_remove(bsp);
 
@@ -906,10 +954,6 @@ void bfd_sess_set_timers(struct bfd_session_params *bsp,
 
 void bfd_sess_install(struct bfd_session_params *bsp)
 {
-       /* Don't attempt to install/update when disabled. */
-       if (!bsp->enabled)
-               return;
-
        bsp->lastev = BSE_INSTALL;
        thread_add_event(bsglobal.tm, _bfd_sess_send, bsp, 0, &bsp->installev);
 }
@@ -1057,8 +1101,8 @@ static int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS)
 
        /* Replay all activated peers. */
        TAILQ_FOREACH (bsp, &bsglobal.bsplist, entry) {
-               /* Skip disabled sessions. */
-               if (!bsp->enabled)
+               /* Skip not installed sessions. */
+               if (!bsp->installed)
                        continue;
 
                /* We are reconnecting, so we must send installation. */
@@ -1077,7 +1121,7 @@ static int zclient_bfd_session_reply(ZAPI_CALLBACK_ARGS)
 
 static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
 {
-       struct bfd_session_params *bsp;
+       struct bfd_session_params *bsp, *bspn;
        size_t sessions_updated = 0;
        struct interface *ifp;
        int remote_cbit = false;
@@ -1094,6 +1138,13 @@ static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
 
        ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &state, &remote_cbit,
                                vrf_id);
+       /*
+        * When interface lookup fails or an invalid stream is read, we must
+        * not proceed otherwise it will trigger an assertion while checking
+        * family type below.
+        */
+       if (dp.family == 0 || sp.family == 0)
+               return 0;
 
        if (bsglobal.debugging) {
                ifstr[0] = 0;
@@ -1127,9 +1178,9 @@ static int zclient_bfd_session_update(ZAPI_CALLBACK_ARGS)
        now = monotime(NULL);
 
        /* Notify all matching sessions about update. */
-       TAILQ_FOREACH (bsp, &bsglobal.bsplist, entry) {
-               /* Skip disabled or not installed entries. */
-               if (!bsp->enabled || !bsp->installed)
+       TAILQ_FOREACH_SAFE (bsp, &bsglobal.bsplist, entry, bspn) {
+               /* Skip not installed entries. */
+               if (!bsp->installed)
                        continue;
                /* Skip different VRFs. */
                if (bsp->args.vrf_id != vrf_id)
index 1325f86a303a928bff1fb821376b1370b305ceae..113f167d3b0bed0892c873fd543d8ca0854cfc1e 100644 (file)
--- a/lib/bfd.h
+++ b/lib/bfd.h
@@ -169,7 +169,7 @@ typedef void (*bsp_status_update)(struct bfd_session_params *bsp,
 /**
  * Allocates and initializes the session parameters.
  *
- * \param updatedb status update notification callback.
+ * \param updatecb status update notification callback.
  * \param args application independent data.
  *
  * \returns pointer to configuration storage.
@@ -184,17 +184,13 @@ struct bfd_session_params *bfd_sess_new(bsp_status_update updatecb, void *args);
  */
 void bfd_sess_free(struct bfd_session_params **bsp);
 
-/**
- * Enable/disable session installation.
- *
- * \param bsp session parameters.
- * \param enable knob variable.
- */
-void bfd_sess_enable(struct bfd_session_params *bsp, bool enable);
-
 /**
  * Set the local and peer address of the BFD session.
  *
+ * NOTE:
+ * If the address changed the session is removed and must be installed again
+ * with `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param src local address (optional, can be `NULL`).
  * \param dst remote address (mandatory).
@@ -205,6 +201,10 @@ void bfd_sess_set_ipv4_addrs(struct bfd_session_params *bsp,
 /**
  * Set the local and peer address of the BFD session.
  *
+ * NOTE:
+ * If the address changed the session is removed and must be installed again
+ * with `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param src local address (optional, can be `NULL`).
  * \param dst remote address (mandatory).
@@ -215,6 +215,10 @@ void bfd_sess_set_ipv6_addrs(struct bfd_session_params *bsp,
 /**
  * Configure the BFD session interface.
  *
+ * NOTE:
+ * If the interface changed the session is removed and must be installed again
+ * with `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param ifname interface name (or `NULL` to remove it).
  */
@@ -223,6 +227,9 @@ void bfd_sess_set_interface(struct bfd_session_params *bsp, const char *ifname);
 /**
  * Configure the BFD session profile name.
  *
+ * NOTE:
+ * Session profile will only change after a `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param profile profile name (or `NULL` to remove it).
  */
@@ -231,6 +238,10 @@ void bfd_sess_set_profile(struct bfd_session_params *bsp, const char *profile);
 /**
  * Configure the BFD session VRF.
  *
+ * NOTE:
+ * If the VRF changed the session is removed and must be installed again
+ * with `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param vrf_id the VRF identification number.
  */
@@ -239,6 +250,10 @@ void bfd_sess_set_vrf(struct bfd_session_params *bsp, vrf_id_t vrf_id);
 /**
  * Configure the BFD session single/multi hop setting.
  *
+ * NOTE:
+ * If the TTL changed the session is removed and must be installed again
+ * with `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param min_ttl minimum TTL value expected (255 for single hop, 254 for
  *                multi hop with single hop, 253 for multi hop with two hops
@@ -260,6 +275,10 @@ void bfd_sess_set_mininum_ttl(struct bfd_session_params *bsp, uint8_t min_ttl);
  * Instead of receiving the minimum expected TTL, it receives the amount of
  * hops the protocol will jump.
  *
+ * NOTE:
+ * If the TTL changed the session is removed and must be installed again
+ * with `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param min_ttl minimum amount of hops expected (1 for single hop, 2 or
  *                more for multi hop).
@@ -269,6 +288,9 @@ void bfd_sess_set_hop_count(struct bfd_session_params *bsp, uint8_t min_ttl);
 /**
  * Configure the BFD session to set the Control Plane Independent bit.
  *
+ * NOTE:
+ * Session CPI bit will only change after a `bfd_sess_install`.
+ *
  * \param bsp BFD session parameters.
  * \param enable BFD Control Plane Independent state.
  */
@@ -280,6 +302,11 @@ void bfd_sess_set_cbit(struct bfd_session_params *bsp, bool enable);
  * Configures the BFD session timers to use. This is specially useful with
  * `ptm-bfd` which does not support timers.
  *
+ * NOTE:
+ * Session timers will only apply if the session has not been created yet.
+ * If the session is already installed you must uninstall and install again
+ * to take effect.
+ *
  * \param bsp BFD session parameters.
  * \param detection_multiplier the detection multiplier value.
  * \param min_rx minimum required receive period.
@@ -292,6 +319,10 @@ void bfd_sess_set_timers(struct bfd_session_params *bsp,
 /**
  * Installs or updates the BFD session based on the saved session arguments.
  *
+ * NOTE:
+ * This function has a delayed effect: it will only install/update after
+ * all northbound/CLI command batch finishes.
+ *
  * \param bsp session parameters.
  */
 void bfd_sess_install(struct bfd_session_params *bsp);
@@ -299,6 +330,10 @@ void bfd_sess_install(struct bfd_session_params *bsp);
 /**
  * Uninstall the BFD session based on the saved session arguments.
  *
+ * NOTE:
+ * This function uninstalls the session immediately (if installed) and cancels
+ * any previous `bfd_sess_install` calls.
+ *
  * \param bsp session parameters.
  */
 void bfd_sess_uninstall(struct bfd_session_params *bsp);
index 6223697ae98589db84fe2723c1d5bb7f1e7e86f9..7ca99c9a940191c45597c12dc3081abe71d96ac1 100644 (file)
@@ -106,12 +106,7 @@ int main(int argc, char **argv)
 /* and now for the ugly part... provide simplified logging functions so we
  * don't need to link libzebra (which would be a circular build dep) */
 
-#ifdef __ASSERT_FUNCTION
-#undef __ASSERT_FUNCTION
-#endif
-
 #include "log.h"
-#include "zassert.h"
 
 void vzlogx(const struct xref_logmsg *xref, int prio,
            const char *format, va_list args)
@@ -120,15 +115,6 @@ void vzlogx(const struct xref_logmsg *xref, int prio,
        fputs("\n", stderr);
 }
 
-void _zlog_assert_failed(const char *assertion, const char *file,
-                        unsigned int line, const char *function)
-{
-       fprintf(stderr,
-               "Assertion `%s' failed in file %s, line %u, function %s",
-               assertion, file, line, (function ? function : "?"));
-       abort();
-}
-
 void memory_oom(size_t size, const char *name)
 {
        abort();
index d2798b500227de6cc7cad288d106d1d71e3808fc..7fb405bdfbb417086dd2802e56acd00e3ff2d588 100644 (file)
@@ -900,13 +900,31 @@ enum node_type node_parent(enum node_type node)
 /* Execute command by argument vline vector. */
 static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
                                    struct vty *vty,
-                                   const struct cmd_element **cmd)
+                                   const struct cmd_element **cmd,
+                                   unsigned int up_level)
 {
        struct list *argv_list;
        enum matcher_rv status;
        const struct cmd_element *matched_element = NULL;
+       unsigned int i;
+       int xpath_index = vty->xpath_index;
+       int node = vty->node;
 
-       struct graph *cmdgraph = cmd_node_graph(cmdvec, vty->node);
+       /* only happens for legacy split config file load;  need to check for
+        * a match before calling node_exit handlers below
+        */
+       for (i = 0; i < up_level; i++) {
+               if (node <= CONFIG_NODE)
+                       return CMD_NO_LEVEL_UP;
+
+               node = node_parent(node);
+
+               if (xpath_index > 0
+                   && vty_check_node_for_xpath_decrement(node, vty->node))
+                       xpath_index--;
+       }
+
+       struct graph *cmdgraph = cmd_node_graph(cmdvec, node);
        status = command_match(cmdgraph, vline, &argv_list, &matched_element);
 
        if (cmd)
@@ -926,12 +944,16 @@ static int cmd_execute_command_real(vector vline, enum cmd_filter_type filter,
                }
        }
 
+       for (i = 0; i < up_level; i++)
+               cmd_exit(vty);
+
        // build argv array from argv list
        struct cmd_token **argv = XMALLOC(
                MTYPE_TMP, argv_list->count * sizeof(struct cmd_token *));
        struct listnode *ln;
        struct cmd_token *token;
-       unsigned int i = 0;
+
+       i = 0;
        for (ALL_LIST_ELEMENTS_RO(argv_list, ln, token))
                argv[i++] = token;
 
@@ -1012,7 +1034,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
                                         vector_lookup(vline, index));
 
                ret = cmd_execute_command_real(shifted_vline, FILTER_RELAXED,
-                                              vty, cmd);
+                                              vty, cmd, 0);
 
                vector_free(shifted_vline);
                vty->node = onode;
@@ -1021,7 +1043,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
        }
 
        saved_ret = ret =
-               cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd);
+               cmd_execute_command_real(vline, FILTER_RELAXED, vty, cmd, 0);
 
        if (vtysh)
                return saved_ret;
@@ -1038,7 +1060,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
                                                                  onode))
                                vty->xpath_index--;
                        ret = cmd_execute_command_real(vline, FILTER_RELAXED,
-                                                      vty, cmd);
+                                                      vty, cmd, 0);
                        if (ret == CMD_SUCCESS || ret == CMD_WARNING
                            || ret == CMD_NOT_MY_INSTANCE
                            || ret == CMD_WARNING_CONFIG_FAILED)
@@ -1069,7 +1091,7 @@ int cmd_execute_command(vector vline, struct vty *vty,
 int cmd_execute_command_strict(vector vline, struct vty *vty,
                               const struct cmd_element **cmd)
 {
-       return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd);
+       return cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd, 0);
 }
 
 /*
@@ -1220,6 +1242,7 @@ int command_config_read_one_line(struct vty *vty,
 {
        vector vline;
        int ret;
+       unsigned up_level = 0;
 
        vline = cmd_make_strvec(vty->buf);
 
@@ -1230,36 +1253,20 @@ int command_config_read_one_line(struct vty *vty,
        /* Execute configuration command : this is strict match */
        ret = cmd_execute_command_strict(vline, vty, cmd);
 
-       // Climb the tree and try the command again at each node
-       if (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
-           && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
-           && ret != CMD_SUCCESS && ret != CMD_WARNING
-           && ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
-           && vty->node != CONFIG_NODE) {
-               int saved_node = vty->node;
-               int saved_xpath_index = vty->xpath_index;
-
-               while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
-                      && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
-                      && ret != CMD_SUCCESS && ret != CMD_WARNING
-                      && vty->node > CONFIG_NODE) {
-                       vty->node = node_parent(vty->node);
-                       if (vty->xpath_index > 0
-                           && vty_check_node_for_xpath_decrement(vty->node,
-                                                                 saved_node))
-                               vty->xpath_index--;
-                       ret = cmd_execute_command_strict(vline, vty, cmd);
-               }
-
-               // If climbing the tree did not work then ignore the command and
-               // stay at the same node
-               if (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
-                   && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
-                   && ret != CMD_SUCCESS && ret != CMD_WARNING) {
-                       vty->node = saved_node;
-                       vty->xpath_index = saved_xpath_index;
-               }
-       }
+       /* The logic for trying parent nodes is in cmd_execute_command_real()
+        * since calling ->node_exit() correctly is a bit involved.  This is
+        * also the only reason CMD_NO_LEVEL_UP exists.
+        */
+       while (!(use_daemon && ret == CMD_SUCCESS_DAEMON)
+              && !(!use_daemon && ret == CMD_ERR_NOTHING_TODO)
+              && ret != CMD_SUCCESS && ret != CMD_WARNING
+              && ret != CMD_NOT_MY_INSTANCE && ret != CMD_WARNING_CONFIG_FAILED
+              && ret != CMD_NO_LEVEL_UP)
+               ret = cmd_execute_command_real(vline, FILTER_STRICT, vty, cmd,
+                                              ++up_level);
+
+       if (ret == CMD_NO_LEVEL_UP)
+               ret = CMD_ERR_NO_MATCH;
 
        if (ret != CMD_SUCCESS &&
            ret != CMD_WARNING &&
index 14e51486eab8fb1c949f54ed81b386e264830f2d..51da4c52e63a18dde2832e99c73e73193405c796 100644 (file)
@@ -137,6 +137,7 @@ enum node_type {
        PREFIX_IPV6_NODE,       /* Prefix list node. */
        AS_LIST_NODE,            /* AS list node. */
        COMMUNITY_LIST_NODE,     /* Community list node. */
+       COMMUNITY_ALIAS_NODE, /* Community alias node. */
        RMAP_NODE,               /* Route map node. */
        PBRMAP_NODE,             /* PBR map node. */
        SMUX_NODE,               /* SNMP configuration node. */
@@ -223,6 +224,7 @@ struct cmd_node {
 #define CMD_SUSPEND             12
 #define CMD_WARNING_CONFIG_FAILED 13
 #define CMD_NOT_MY_INSTANCE    14
+#define CMD_NO_LEVEL_UP 15
 
 /* Argc max counts. */
 #define CMD_ARGC_MAX   256
index 0556605d637cd5d731b1a692db1b2e1ae99c1e01..9c096995f513770f1b838380fc697e972804df4e 100644 (file)
@@ -35,7 +35,7 @@
 #pragma GCC diagnostic ignored "-Wsign-compare"
 #pragma GCC diagnostic ignored "-Wmissing-prototypes"
 
-#include "command_parse.h"
+#include "lib/command_parse.h"
 
 #define YY_USER_ACTION yylloc->last_column += yyleng;
 #define LOC_STEP do { if (yylloc) { \
index 5ebc19b2789b97dade616233a3c38075cf1cf5cd..f5e42cc304898afa6a187e09afd59cf83a83e897 100644 (file)
@@ -75,7 +75,7 @@
 
 %code provides {
   #ifndef FLEX_SCANNER
-  #include "command_lex.h"
+  #include "lib/command_lex.h"
   #endif
 
   extern void set_lexer_string (yyscan_t *scn, const char *string);
index b7a142bdee5ac5aa3129262929d31d8f0239993d..86cf347e01543ce53cfa8bccb453a43edd981040 100644 (file)
@@ -373,6 +373,10 @@ CPP_NOTICE("time to remove this CONFDATE block")
 #else /* !_FRR_ATTRIBUTE_PRINTFRR */
 #define PRINTFRR(a, b) __attribute__((format(printf, a, b)))
 
+/* frr-format plugin is C-only for now, so no point in doing these shenanigans
+ * for C++...  (also they can break some C++ stuff...)
+ */
+#ifndef __cplusplus
 /* these should be typedefs, but might also be #define */
 #ifdef uint64_t
 #undef uint64_t
@@ -400,6 +404,8 @@ _Static_assert(sizeof(_uint64_t) == 8 && sizeof(_int64_t) == 8,
 #define PRIu64 "llu"
 #define PRId64 "lld"
 #define PRIx64 "llx"
+
+#endif /* !__cplusplus */
 #endif /* !_FRR_ATTRIBUTE_PRINTFRR */
 
 #ifdef __cplusplus
index 7466aad5b15462afb55c4adffcb410f6b1f17cb5..fe099b6469e87e6fd5d3c69631afc1066f171f8a 100644 (file)
@@ -18,7 +18,7 @@
 #include <zebra.h>
 
 #include "defaults.h"
-#include "version.h"
+#include "lib/version.h"
 
 static char df_version[128] = FRR_VER_SHORT, df_profile[128] = DFLT_NAME;
 static struct frr_default *dflt_first = NULL, **dflt_next = &dflt_first;
index 60bd0a47bb0c00f2f7f01da7b004a5834ff35c2e..0f503d2ab98e767041674e262eed4a6e6d7d731f 100644 (file)
@@ -240,150 +240,59 @@ static int distribute_list_prefix_unset(struct distribute_ctx *ctx,
        return 1;
 }
 
-DEFUN (distribute_list,
-       distribute_list_cmd,
-       "distribute-list [prefix] WORD <in|out> [WORD]",
-       "Filter networks in routing updates\n"
-       "Specify a prefix\n"
-       "Access-list name\n"
-       "Filter incoming routing updates\n"
-       "Filter outgoing routing updates\n"
-       "Interface name\n")
+static enum distribute_type distribute_direction(const char *dir, bool v4)
 {
-       int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
-       /* Check of distribute list type. */
-       enum distribute_type type = argv[2 + prefix]->arg[0] == 'i'
-                                           ? DISTRIBUTE_V4_IN
-                                           : DISTRIBUTE_V4_OUT;
-
-       /* Set appropriate function call */
-       void (*distfn)(struct distribute_ctx *, const char *,
-                      enum distribute_type, const char *) =
-               prefix ? &distribute_list_prefix_set : &distribute_list_set;
-       struct distribute_ctx *ctx =
-               (struct distribute_ctx *)listnode_head(dist_ctx_list);
-
-       /* if interface is present, get name */
-       const char *ifname = NULL;
-       if (argv[argc - 1]->type == VARIABLE_TKN)
-               ifname = argv[argc - 1]->arg;
+       if (dir[0] == 'i') {
+               if (v4)
+                       return DISTRIBUTE_V4_IN;
+               else
+                       return DISTRIBUTE_V6_IN;
+       } else if (dir[0] == 'o') {
+               if (v4)
+                       return DISTRIBUTE_V4_OUT;
+               else
+                       return DISTRIBUTE_V6_OUT;
+       }
 
-       /* Get interface name corresponding distribute list. */
-       distfn(ctx, ifname, type, argv[1 + prefix]->arg);
+       assert(!"Expecting in or out only, fix your code");
 
-       return CMD_SUCCESS;
+       __builtin_unreachable();
 }
 
-DEFUN (ipv6_distribute_list,
-       ipv6_distribute_list_cmd,
-       "ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
-       "IPv6\n"
-       "Filter networks in routing updates\n"
-       "Specify a prefix\n"
-       "Access-list name\n"
-       "Filter incoming routing updates\n"
-       "Filter outgoing routing updates\n"
-       "Interface name\n")
+int distribute_list_parser(bool prefix, bool v4, const char *dir,
+                          const char *list, const char *ifname)
 {
-       int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
-       /* Check of distribute list type. */
-       enum distribute_type type = argv[3 + prefix]->arg[0] == 'i'
-                                           ? DISTRIBUTE_V6_IN
-                                           : DISTRIBUTE_V6_OUT;
+       enum distribute_type type = distribute_direction(dir, v4);
+       struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
 
-       /* Set appropriate function call */
        void (*distfn)(struct distribute_ctx *, const char *,
                       enum distribute_type, const char *) =
                prefix ? &distribute_list_prefix_set : &distribute_list_set;
-       struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
 
-       /* if interface is present, get name */
-       const char *ifname = NULL;
-       if (argv[argc - 1]->type == VARIABLE_TKN)
-               ifname = argv[argc - 1]->arg;
-
-       /* Get interface name corresponding distribute list. */
-       distfn(ctx, ifname, type, argv[2 + prefix]->arg);
+       distfn(ctx, ifname, type, list);
 
        return CMD_SUCCESS;
 }
 
-DEFUN (no_distribute_list,
-       no_distribute_list_cmd,
-       "no distribute-list [prefix] WORD <in|out> [WORD]",
-       NO_STR
-       "Filter networks in routing updates\n"
-       "Specify a prefix\n"
-       "Access-list name\n"
-       "Filter incoming routing updates\n"
-       "Filter outgoing routing updates\n"
-       "Interface name\n")
+int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4,
+                             const char *dir, const char *list,
+                             const char *ifname)
 {
-       int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
-       int idx_alname = 2 + prefix;
-       int idx_disttype = idx_alname + 1;
-       enum distribute_type type =
-               argv[idx_disttype]->arg[0] == 'i' ?
-               DISTRIBUTE_V4_IN : DISTRIBUTE_V4_OUT;
-
-       /* Set appropriate function call */
-       int (*distfn)(struct distribute_ctx *, const char *,
-                      enum distribute_type, const char *) =
-               prefix ? &distribute_list_prefix_unset : &distribute_list_unset;
+       enum distribute_type type = distribute_direction(dir, v4);
        struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
+       int ret;
 
-       /* if interface is present, get name */
-       const char *ifname = NULL;
-       if (argv[argc - 1]->type == VARIABLE_TKN)
-               ifname = argv[argc - 1]->arg;
-       /* Get interface name corresponding distribute list. */
-       int ret = distfn(ctx, ifname, type, argv[2 + prefix]->arg);
-
-       if (!ret) {
-               vty_out(vty, "distribute list doesn't exist\n");
-               return CMD_WARNING_CONFIG_FAILED;
-       }
-       return CMD_SUCCESS;
-}
-
-DEFUN (no_ipv6_distribute_list,
-       no_ipv6_distribute_list_cmd,
-       "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
-       NO_STR
-       "IPv6\n"
-       "Filter networks in routing updates\n"
-       "Specify a prefix\n"
-       "Access-list name\n"
-       "Filter incoming routing updates\n"
-       "Filter outgoing routing updates\n"
-       "Interface name\n")
-{
-       int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
-       int idx_alname = 3 + prefix;
-       int idx_disttype = idx_alname + 1;
-
-       enum distribute_type type =
-               argv[idx_disttype]->arg[0] == 'i' ?
-               DISTRIBUTE_V6_IN : DISTRIBUTE_V6_OUT;
-       struct distribute_ctx *ctx = listnode_head(dist_ctx_list);
-
-       /* Set appropriate function call */
        int (*distfn)(struct distribute_ctx *, const char *,
-                      enum distribute_type, const char *) =
+                     enum distribute_type, const char *) =
                prefix ? &distribute_list_prefix_unset : &distribute_list_unset;
 
-       /* if interface is present, get name */
-       const char *ifname = NULL;
-
-       if (argv[argc - 1]->type == VARIABLE_TKN)
-               ifname = argv[argc - 1]->arg;
-       /* Get interface name corresponding distribute list. */
-       int ret = distfn(ctx, ifname, type, argv[3 + prefix]->arg);
 
+       ret = distfn(ctx, ifname, type, list);
        if (!ret) {
                vty_out(vty, "distribute list doesn't exist\n");
                return CMD_WARNING_CONFIG_FAILED;
        }
+
        return CMD_SUCCESS;
 }
 
@@ -577,32 +486,3 @@ struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf)
        listnode_add(dist_ctx_list, ctx);
        return ctx;
 }
-
-/* Initialize distribute list vty commands */
-void distribute_list_init(int node)
-{
-       /* vtysh command-extraction doesn't grok install_element(node, ) */
-       if (node == RIP_NODE) {
-               install_element(RIP_NODE, &distribute_list_cmd);
-               install_element(RIP_NODE, &no_distribute_list_cmd);
-       } else if (node == RIPNG_NODE) {
-               install_element(RIPNG_NODE, &distribute_list_cmd);
-               install_element(RIPNG_NODE, &no_distribute_list_cmd);
-               /* install v6 */
-               install_element(RIPNG_NODE, &ipv6_distribute_list_cmd);
-               install_element(RIPNG_NODE, &no_ipv6_distribute_list_cmd);
-       }
-
-       /* TODO: install v4 syntax command for v6 only protocols. */
-       /* if (node == RIPNG_NODE) {
-        *   install_element (node, &ipv6_as_v4_distribute_list_all_cmd);
-        *   install_element (node, &no_ipv6_as_v4_distribute_list_all_cmd);
-        *   install_element (node, &ipv6_as_v4_distribute_list_cmd);
-        *   install_element (node, &no_ipv6_as_v4_distribute_list_cmd);
-        *   install_element (node, &ipv6_as_v4_distribute_list_prefix_all_cmd);
-        *   install_element (node,
-        &no_ipv6_as_v4_distribute_list_prefix_all_cmd);
-        *   install_element (node, &ipv6_as_v4_distribute_list_prefix_cmd);
-        *   install_element (node, &no_ipv6_as_v4_distribute_list_prefix_cmd);
-          }*/
-}
index 4016d3b1331642119852bbb7531b61505b7cb155..83682dea6ad4fb822e67a89e643738f7c16bc0ea 100644 (file)
@@ -64,7 +64,6 @@ struct distribute_ctx {
 };
 
 /* Prototypes for distribute-list. */
-extern void distribute_list_init(int node);
 extern struct distribute_ctx *distribute_list_ctx_create(struct vrf *vrf);
 extern void distribute_list_delete(struct distribute_ctx **ctx);
 extern void distribute_list_add_hook(struct distribute_ctx *ctx,
@@ -85,6 +84,11 @@ extern enum filter_type distribute_apply_in(struct interface *,
 extern enum filter_type distribute_apply_out(struct interface *,
                                             struct prefix *);
 
+extern int distribute_list_parser(bool prefix, bool v4, const char *dir,
+                                 const char *list, const char *ifname);
+extern int distribute_list_no_parser(struct vty *vty, bool prefix, bool v4,
+                                    const char *dir, const char *list,
+                                    const char *ifname);
 #ifdef __cplusplus
 }
 #endif
index 83423ba321922255865e7613a147a3d865488d88..b7a935d0768dbbd576b77f6343e1ec796aace32b 100644 (file)
@@ -37,7 +37,6 @@ DEFINE_MTYPE_STATIC(LIB, ACCESS_FILTER, "Access Filter");
 
 /* Static structure for mac access_list's master. */
 static struct access_master access_master_mac = {
-       {NULL, NULL},
        {NULL, NULL},
        NULL,
        NULL,
@@ -45,7 +44,6 @@ static struct access_master access_master_mac = {
 
 /* Static structure for IPv4 access_list's master. */
 static struct access_master access_master_ipv4 = {
-       {NULL, NULL},
        {NULL, NULL},
        NULL,
        NULL,
@@ -53,7 +51,6 @@ static struct access_master access_master_ipv4 = {
 
 /* Static structure for IPv6 access_list's master. */
 static struct access_master access_master_ipv6 = {
-       {NULL, NULL},
        {NULL, NULL},
        NULL,
        NULL,
@@ -166,10 +163,7 @@ void access_list_delete(struct access_list *access)
 
        master = access->master;
 
-       if (access->type == ACCESS_TYPE_NUMBER)
-               list = &master->num;
-       else
-               list = &master->str;
+       list = &master->str;
 
        if (access->next)
                access->next->prev = access->prev;
@@ -181,6 +175,11 @@ void access_list_delete(struct access_list *access)
        else
                list->head = access->next;
 
+       route_map_notify_dependencies(access->name, RMAP_EVENT_FILTER_DELETED);
+
+       if (master->delete_hook)
+               master->delete_hook(access);
+
        XFREE(MTYPE_ACCESS_LIST_STR, access->name);
 
        XFREE(MTYPE_TMP, access->remark);
@@ -192,8 +191,6 @@ void access_list_delete(struct access_list *access)
    is sorted by the name. */
 static struct access_list *access_list_insert(afi_t afi, const char *name)
 {
-       unsigned int i;
-       long number;
        struct access_list *access;
        struct access_list *point;
        struct access_list_list *alist;
@@ -208,36 +205,13 @@ static struct access_list *access_list_insert(afi_t afi, const char *name)
        access->name = XSTRDUP(MTYPE_ACCESS_LIST_STR, name);
        access->master = master;
 
-       /* If name is made by all digit character.  We treat it as
-          number. */
-       for (number = 0, i = 0; i < strlen(name); i++) {
-               if (isdigit((unsigned char)name[i]))
-                       number = (number * 10) + (name[i] - '0');
-               else
-                       break;
-       }
+       /* Set access_list to string list. */
+       alist = &master->str;
 
-       /* In case of name is all digit character */
-       if (i == strlen(name)) {
-               access->type = ACCESS_TYPE_NUMBER;
-
-               /* Set access_list to number list. */
-               alist = &master->num;
-
-               for (point = alist->head; point; point = point->next)
-                       if (atol(point->name) >= number)
-                               break;
-       } else {
-               access->type = ACCESS_TYPE_STRING;
-
-               /* Set access_list to string list. */
-               alist = &master->str;
-
-               /* Set point to insertion point. */
-               for (point = alist->head; point; point = point->next)
-                       if (strcmp(point->name, name) >= 0)
-                               break;
-       }
+       /* Set point to insertion point. */
+       for (point = alist->head; point; point = point->next)
+               if (strcmp(point->name, name) >= 0)
+                       break;
 
        /* In case of this is the first element of master. */
        if (alist->head == NULL) {
@@ -285,10 +259,6 @@ struct access_list *access_list_lookup(afi_t afi, const char *name)
        if (master == NULL)
                return NULL;
 
-       for (access = master->num.head; access; access = access->next)
-               if (strcmp(access->name, name) == 0)
-                       return access;
-
        for (access = master->str.head; access; access = access->next)
                if (strcmp(access->name, name) == 0)
                        return access;
@@ -469,59 +439,6 @@ void access_list_filter_add(struct access_list *access,
   host                 A single host address
 */
 
-struct filter *filter_lookup_cisco(struct access_list *access,
-                                  struct filter *mnew)
-{
-       struct filter *mfilter;
-       struct filter_cisco *filter;
-       struct filter_cisco *new;
-
-       new = &mnew->u.cfilter;
-
-       for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
-               filter = &mfilter->u.cfilter;
-
-               if (filter->extended) {
-                       if (mfilter->type == mnew->type
-                           && filter->addr.s_addr == new->addr.s_addr
-                           && filter->addr_mask.s_addr == new->addr_mask.s_addr
-                           && filter->mask.s_addr == new->mask.s_addr
-                           && filter->mask_mask.s_addr
-                                      == new->mask_mask.s_addr)
-                               return mfilter;
-               } else {
-                       if (mfilter->type == mnew->type
-                           && filter->addr.s_addr == new->addr.s_addr
-                           && filter->addr_mask.s_addr
-                                      == new->addr_mask.s_addr)
-                               return mfilter;
-               }
-       }
-
-       return NULL;
-}
-
-struct filter *filter_lookup_zebra(struct access_list *access,
-                                  struct filter *mnew)
-{
-       struct filter *mfilter;
-       struct filter_zebra *filter;
-       struct filter_zebra *new;
-
-       new = &mnew->u.zfilter;
-
-       for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
-               filter = &mfilter->u.zfilter;
-
-               if (filter->exact == new->exact
-                   && mfilter->type == mnew->type) {
-                       if (prefix_same(&filter->prefix, &new->prefix))
-                               return mfilter;
-               }
-       }
-       return NULL;
-}
-
 static void config_write_access_zebra(struct vty *, struct filter *);
 static void config_write_access_cisco(struct vty *, struct filter *);
 
@@ -541,53 +458,6 @@ static int filter_show(struct vty *vty, const char *name, afi_t afi)
        /* Print the name of the protocol */
        vty_out(vty, "%s:\n", frr_protoname);
 
-       for (access = master->num.head; access; access = access->next) {
-               if (name && strcmp(access->name, name) != 0)
-                       continue;
-
-               write = 1;
-
-               for (mfilter = access->head; mfilter; mfilter = mfilter->next) {
-                       filter = &mfilter->u.cfilter;
-
-                       if (write) {
-                               vty_out(vty, "%s %s access list %s\n",
-                                       mfilter->cisco ? (filter->extended
-                                                                 ? "Extended"
-                                                                 : "Standard")
-                                                      : "Zebra",
-                                       (afi == AFI_IP)
-                                               ? ("IP")
-                                               : ((afi == AFI_IP6) ? ("IPv6 ")
-                                                                   : ("MAC ")),
-                                       access->name);
-                               write = 0;
-                       }
-
-                       vty_out(vty, "    seq %" PRId64, mfilter->seq);
-                       vty_out(vty, " %s%s", filter_type_str(mfilter),
-                               mfilter->type == FILTER_DENY ? "  " : "");
-
-                       if (!mfilter->cisco)
-                               config_write_access_zebra(vty, mfilter);
-                       else if (filter->extended)
-                               config_write_access_cisco(vty, mfilter);
-                       else {
-                               if (filter->addr_mask.s_addr == 0xffffffff)
-                                       vty_out(vty, " any\n");
-                               else {
-                                       vty_out(vty, " %pI4", &filter->addr);
-                                       if (filter->addr_mask.s_addr
-                                           != INADDR_ANY)
-                                               vty_out(vty,
-                                                       ", wildcard bits %pI4",
-                                                       &filter->addr_mask);
-                                       vty_out(vty, "\n");
-                               }
-                       }
-               }
-       }
-
        for (access = master->str.head; access; access = access->next) {
                if (name && strcmp(access->name, name) != 0)
                        continue;
@@ -787,18 +657,11 @@ static void access_list_reset_mac(void)
        if (master == NULL)
                return;
 
-       for (access = master->num.head; access; access = next) {
-               next = access->next;
-               access_list_delete(access);
-       }
        for (access = master->str.head; access; access = next) {
                next = access->next;
                access_list_delete(access);
        }
 
-       assert(master->num.head == NULL);
-       assert(master->num.tail == NULL);
-
        assert(master->str.head == NULL);
        assert(master->str.tail == NULL);
 }
@@ -845,18 +708,11 @@ static void access_list_reset_ipv4(void)
        if (master == NULL)
                return;
 
-       for (access = master->num.head; access; access = next) {
-               next = access->next;
-               access_list_delete(access);
-       }
        for (access = master->str.head; access; access = next) {
                next = access->next;
                access_list_delete(access);
        }
 
-       assert(master->num.head == NULL);
-       assert(master->num.tail == NULL);
-
        assert(master->str.head == NULL);
        assert(master->str.tail == NULL);
 }
@@ -886,18 +742,11 @@ static void access_list_reset_ipv6(void)
        if (master == NULL)
                return;
 
-       for (access = master->num.head; access; access = next) {
-               next = access->next;
-               access_list_delete(access);
-       }
        for (access = master->str.head; access; access = next) {
                next = access->next;
                access_list_delete(access);
        }
 
-       assert(master->num.head == NULL);
-       assert(master->num.tail == NULL);
-
        assert(master->str.head == NULL);
        assert(master->str.tail == NULL);
 }
index 28f52020221b25fb5fd832c1cbe4c044a3861f75..941fabd38b8a7d77b311ac17032804a3bed0c6e0 100644 (file)
@@ -50,8 +50,6 @@ extern "C" {
 /* Filter type is made by `permit', `deny' and `dynamic'. */
 enum filter_type { FILTER_DENY, FILTER_PERMIT, FILTER_DYNAMIC };
 
-enum access_type { ACCESS_TYPE_STRING, ACCESS_TYPE_NUMBER };
-
 struct filter_cisco {
        /* Cisco access-list */
        int extended;
@@ -103,8 +101,6 @@ struct access_list {
 
        struct access_master *master;
 
-       enum access_type type;
-
        struct access_list *next;
        struct access_list *prev;
 
@@ -120,9 +116,6 @@ struct access_list_list {
 
 /* Master structure of access_list. */
 struct access_master {
-       /* List of access_list which name is number. */
-       struct access_list_list num;
-
        /* List of access_list which name is string. */
        struct access_list_list str;
 
@@ -151,10 +144,6 @@ void access_list_filter_add(struct access_list *access,
 void access_list_filter_delete(struct access_list *access,
                               struct filter *filter);
 int64_t filter_new_seq_get(struct access_list *access);
-struct filter *filter_lookup_cisco(struct access_list *access,
-                                  struct filter *mnew);
-struct filter *filter_lookup_zebra(struct access_list *access,
-                                  struct filter *mnew);
 
 extern const struct frr_yang_module_info frr_filter_info;
 
@@ -194,6 +183,9 @@ struct acl_dup_args {
        /** Duplicated entry found in list? */
        bool ada_found;
 
+       /** Sequence number of the found entry */
+       int64_t ada_seq;
+
        /** (Optional) Already existing `dnode`. */
        const struct lyd_node *ada_entry_dnode;
 };
@@ -224,6 +216,9 @@ struct plist_dup_args {
        /** Duplicated entry found in list? */
        bool pda_found;
 
+       /** Sequence number of the found entry */
+       int64_t pda_seq;
+
        /** (Optional) Already existing `dnode`. */
        const struct lyd_node *pda_entry_dnode;
 };
index 96444ac970f916db284b81e477adbc5ee0390735..f030ce1b335a6433a0b2922c59e0c9e0f4ef0a9f 100644 (file)
 
 #define PREFIX_LIST_NAME_STR "Prefix list entry name\n"
 
-/*
- * Helper function to locate filter data structures for Cisco-style ACLs.
- */
-static int64_t acl_cisco_get_seq(struct access_list *acl, const char *action,
-                                const char *src, const char *src_mask,
-                                const char *dst, const char *dst_mask)
-{
-       struct filter_cisco *fc;
-       struct filter f, *fn;
-
-       memset(&f, 0, sizeof(f));
-       f.cisco = 1;
-       if (strcmp(action, "permit") == 0)
-               f.type = FILTER_PERMIT;
-       else
-               f.type = FILTER_DENY;
-
-       fc = &f.u.cfilter;
-       inet_pton(AF_INET, src, &fc->addr);
-       inet_pton(AF_INET, src_mask, &fc->addr_mask);
-       fc->addr.s_addr &= ~fc->addr_mask.s_addr;
-       if (dst != NULL) {
-               fc->extended = 1;
-               inet_pton(AF_INET, dst, &fc->mask);
-               inet_pton(AF_INET, dst_mask, &fc->mask_mask);
-               fc->mask.s_addr &= ~fc->mask_mask.s_addr;
-       }
-
-       fn = filter_lookup_cisco(acl, &f);
-       if (fn == NULL)
-               return -1;
-
-       return fn->seq;
-}
-
-/*
- * Helper function to locate filter data structures for zebra-style ACLs.
- */
-static int64_t acl_zebra_get_seq(struct access_list *acl, const char *action,
-                                const struct prefix *p, bool exact)
-{
-       struct filter_zebra *fz;
-       struct filter f, *fn;
-
-       memset(&f, 0, sizeof(f));
-       memset(&fz, 0, sizeof(fz));
-       if (strcmp(action, "permit") == 0)
-               f.type = FILTER_PERMIT;
-       else
-               f.type = FILTER_DENY;
-
-       fz = &f.u.zfilter;
-       if (p->family)
-               prefix_copy(&fz->prefix, p);
-       fz->exact = exact;
-
-       fn = filter_lookup_zebra(acl, &f);
-       if (fn == NULL)
-               return -1;
-
-       return fn->seq;
-}
-
 /*
  * Helper function to generate a sequence number for legacy commands.
  */
@@ -146,6 +83,53 @@ static long acl_get_seq(struct vty *vty, const char *xpath)
        return seq + 5;
 }
 
+static int acl_remove_if_empty(struct vty *vty, const char *iptype,
+                              const char *name)
+{
+       char xpath[XPATH_MAXLEN];
+
+       snprintf(xpath, sizeof(xpath),
+                "/frr-filter:lib/access-list[type='%s'][name='%s']/remark",
+                iptype, name);
+       /* List is not empty if there is a remark, check that: */
+       if (yang_dnode_exists(vty->candidate_config->dnode, xpath))
+               return CMD_SUCCESS;
+
+       /* Check if we have any entries: */
+       snprintf(xpath, sizeof(xpath),
+                "/frr-filter:lib/access-list[type='%s'][name='%s']", iptype,
+                name);
+       /*
+        * NOTE: if the list is empty it will return the first sequence
+        * number: 5.
+        */
+       if (acl_get_seq(vty, xpath) != 5)
+               return CMD_SUCCESS;
+
+       /* Nobody is using this list, lets remove it. */
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+       return nb_cli_apply_changes(vty, NULL);
+}
+
+static int acl_remove(struct vty *vty, const char *iptype, const char *name,
+                     int64_t sseq)
+{
+       char xpath[XPATH_MAXLEN];
+       int rv;
+
+       snprintfrr(
+               xpath, sizeof(xpath),
+               "/frr-filter:lib/access-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']",
+               iptype, name, sseq);
+       nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
+
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, iptype, name);
+
+       return rv;
+}
+
 /*
  * Cisco (legacy) access lists.
  */
@@ -184,7 +168,7 @@ DEFPY_YANG(
                        ada.ada_value[1] = mask_str;
                } else {
                        ada.ada_xpath[0] = "./source-any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -238,44 +222,36 @@ DEFPY_YANG(
        "Address to match\n"
        "Wildcard bits\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv4", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv4";
+       ada.ada_name = name;
+       ada.ada_action = action;
+       if (host_str && mask_str == NULL) {
+               ada.ada_xpath[0] = "./host";
+               ada.ada_value[0] = host_str;
+       } else if (host_str && mask_str) {
+               ada.ada_xpath[0] = "./network/address";
+               ada.ada_value[0] = host_str;
+               ada.ada_xpath[1] = "./network/mask";
+               ada.ada_value[1] = mask_str;
+       } else {
+               ada.ada_xpath[0] = "./source-any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       sseq = acl_cisco_get_seq(acl, action, host_str,
-                                mask_str ? mask_str : CISCO_HOST_WILDCARD_MASK,
-                                NULL, NULL);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv4", name, sseq);
 }
 
 DEFPY_YANG(
@@ -324,7 +300,7 @@ DEFPY_YANG(
                        idx++;
                } else {
                        ada.ada_xpath[idx] = "./source-any";
-                       ada.ada_value[idx] = "true";
+                       ada.ada_value[idx] = "";
                        idx++;
                }
 
@@ -341,7 +317,7 @@ DEFPY_YANG(
                        idx++;
                } else {
                        ada.ada_xpath[idx] = "./destination-any";
-                       ada.ada_value[idx] = "true";
+                       ada.ada_value[idx] = "";
                        idx++;
                }
 
@@ -416,68 +392,58 @@ DEFPY_YANG(
        "Destination address to match\n"
        "Any destination host\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
+       int idx = 0;
        int64_t sseq;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintfrr(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv4", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv4";
+       ada.ada_name = name;
+       ada.ada_action = action;
+       if (src_str && src_mask_str == NULL) {
+               ada.ada_xpath[idx] = "./host";
+               ada.ada_value[idx] = src_str;
+               idx++;
+       } else if (src_str && src_mask_str) {
+               ada.ada_xpath[idx] = "./network/address";
+               ada.ada_value[idx] = src_str;
+               idx++;
+               ada.ada_xpath[idx] = "./network/mask";
+               ada.ada_value[idx] = src_mask_str;
+               idx++;
+       } else {
+               ada.ada_xpath[idx] = "./source-any";
+               ada.ada_value[idx] = "";
+               idx++;
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (src_str != NULL) {
-               if (dst_str != NULL)
-                       sseq = acl_cisco_get_seq(
-                               acl, action, src_str,
-                               src_mask_str ? src_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK,
-                               dst_str,
-                               dst_mask_str ? dst_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK);
-               else
-                       sseq = acl_cisco_get_seq(
-                               acl, action, src_str,
-                               src_mask_str ? src_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK,
-                               "0.0.0.0", CISCO_ANY_WILDCARD_MASK);
+       if (dst_str && dst_mask_str == NULL) {
+               ada.ada_xpath[idx] = "./destination-host";
+               ada.ada_value[idx] = dst_str;
+               idx++;
+       } else if (dst_str && dst_mask_str) {
+               ada.ada_xpath[idx] = "./destination-network/address";
+               ada.ada_value[idx] = dst_str;
+               idx++;
+               ada.ada_xpath[idx] = "./destination-network/mask";
+               ada.ada_value[idx] = dst_mask_str;
+               idx++;
        } else {
-               if (dst_str != NULL)
-                       sseq = acl_cisco_get_seq(
-                               acl, action, "0.0.0.0", CISCO_ANY_WILDCARD_MASK,
-                               dst_str,
-                               dst_mask_str ? dst_mask_str
-                                            : CISCO_HOST_WILDCARD_MASK);
-               else
-                       sseq = acl_cisco_get_seq(
-                               acl, action, "0.0.0.0", CISCO_ANY_WILDCARD_MASK,
-                               "0.0.0.0", CISCO_ANY_WILDCARD_MASK);
+               ada.ada_xpath[idx] = "./destination-any";
+               ada.ada_value[idx] = "";
+               idx++;
        }
-       if (sseq == -1)
-               return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
+               return CMD_WARNING_CONFIG_FAILED;
 
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv4", name, sseq);
 }
 
 /*
@@ -517,7 +483,7 @@ DEFPY_YANG(
                        }
                } else {
                        ada.ada_xpath[0] = "./any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -568,49 +534,36 @@ DEFPY_YANG(
        "Exact match of the prefixes\n"
        "Match any IPv4\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       struct prefix pany;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv4'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv4", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv4'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv4";
+       ada.ada_name = name;
+       ada.ada_action = action;
+
+       if (prefix_str) {
+               ada.ada_xpath[0] = "./ipv4-prefix";
+               ada.ada_value[0] = prefix_str;
+               if (exact) {
+                       ada.ada_xpath[1] = "./ipv4-exact-match";
+                       ada.ada_value[1] = "true";
+               }
+       } else {
+               ada.ada_xpath[0] = "./any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (prefix_str == NULL) {
-               memset(&pany, 0, sizeof(pany));
-               pany.family = AF_INET;
-               sseq = acl_zebra_get_seq(acl, action, &pany, exact);
-       } else
-               sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
-                                        exact);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv4", name, sseq);
 }
 
 DEFPY_YANG(
@@ -662,13 +615,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/access-list[type='ipv4'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, "ipv4", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -715,7 +673,7 @@ DEFPY_YANG(
                        }
                } else {
                        ada.ada_xpath[0] = "./any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -767,49 +725,36 @@ DEFPY_YANG(
        "Exact match of the prefixes\n"
        "Match any IPv6\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       struct prefix pany;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='ipv6'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "ipv6", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='ipv6'][name='%s']", name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       ada.ada_type = "ipv6";
+       ada.ada_name = name;
+       ada.ada_action = action;
+
+       if (prefix_str) {
+               ada.ada_xpath[0] = "./ipv6-prefix";
+               ada.ada_value[0] = prefix_str;
+               if (exact) {
+                       ada.ada_xpath[1] = "./ipv6-exact-match";
+                       ada.ada_value[1] = "true";
+               }
+       } else {
+               ada.ada_xpath[0] = "./any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (prefix == NULL) {
-               memset(&pany, 0, sizeof(pany));
-               pany.family = AF_INET6;
-               sseq = acl_zebra_get_seq(acl, action, &pany, exact);
-       } else
-               sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
-                                        exact);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "ipv6", name, sseq);
 }
 
 DEFPY_YANG(
@@ -864,13 +809,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/access-list[type='ipv6'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, "ipv6", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -913,7 +863,7 @@ DEFPY_YANG(
                        ada.ada_value[0] = mac_str;
                } else {
                        ada.ada_xpath[0] = "./any";
-                       ada.ada_value[0] = "true";
+                       ada.ada_value[0] = "";
                }
 
                /* Duplicated entry without sequence, just quit. */
@@ -951,7 +901,7 @@ DEFPY_YANG(
 
 DEFPY_YANG(
        no_mac_access_list, no_mac_access_list_cmd,
-       "no mac access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X:X:X:X:X$prefix|any>",
+       "no mac access-list WORD$name [seq (1-4294967295)$seq] <deny|permit>$action <X:X:X:X:X:X$mac|any>",
        NO_STR
        MAC_STR
        ACCESS_LIST_STR
@@ -961,49 +911,32 @@ DEFPY_YANG(
        "MAC address\n"
        "Match any MAC address\n")
 {
-       struct access_list *acl;
-       struct lyd_node *dnode;
        int64_t sseq;
-       struct prefix pany;
-       char xpath[XPATH_MAXLEN];
-       char xpath_entry[XPATH_MAXLEN + 32];
+       struct acl_dup_args ada = {};
 
        /* If the user provided sequence number, then just go for it. */
-       if (seq_str != NULL) {
-               snprintf(
-                       xpath, sizeof(xpath),
-                       "/frr-filter:lib/access-list[type='mac'][name='%s']/entry[sequence='%s']",
-                       name, seq_str);
-               nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
-               return nb_cli_apply_changes(vty, NULL);
-       }
+       if (seq_str != NULL)
+               return acl_remove(vty, "mac", name, seq);
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/access-list[type='mac'][name='%s']", name);
+       ada.ada_type = "mac";
+       ada.ada_name = name;
+       ada.ada_action = action;
 
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       if (mac_str) {
+               ada.ada_xpath[0] = "./mac";
+               ada.ada_value[0] = mac_str;
+       } else {
+               ada.ada_xpath[0] = "./any";
+               ada.ada_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       acl = nb_running_get_entry(dnode, NULL, true);
-       if (prefix == NULL) {
-               memset(&pany, 0, sizeof(pany));
-               pany.family = AF_ETHERNET;
-               sseq = acl_zebra_get_seq(acl, action, &pany, false);
-       } else
-               sseq = acl_zebra_get_seq(acl, action, (struct prefix *)prefix,
-                                        false);
-       if (sseq == -1)
+       if (acl_is_dup(vty->candidate_config->dnode, &ada))
+               sseq = ada.ada_seq;
+       else
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, sseq);
-       nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
-
-       return nb_cli_apply_changes(vty, NULL);
+       return acl_remove(vty, "mac", name, sseq);
 }
 
 DEFPY_YANG(
@@ -1058,13 +991,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/access-list[type='mac'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return acl_remove_if_empty(vty, "mac", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -1257,13 +1195,13 @@ static int plist_remove_if_empty(struct vty *vty, const char *iptype,
 }
 
 static int plist_remove(struct vty *vty, const char *iptype, const char *name,
-                       const char *seq, const char *action, struct prefix *p,
-                       long ge, long le)
+                       const char *seq, const char *action,
+                       const char *prefix_str, const char *ge_str,
+                       const char *le_str)
 {
-       struct prefix_list_entry *pentry;
-       enum prefix_list_type plt;
-       struct prefix_list *pl;
-       struct lyd_node *dnode;
+       int64_t sseq;
+       int arg_idx = 0;
+       struct plist_dup_args pda = {};
        char xpath[XPATH_MAXLEN];
        char xpath_entry[XPATH_MAXLEN + 32];
        int rv;
@@ -1284,29 +1222,57 @@ static int plist_remove(struct vty *vty, const char *iptype, const char *name,
        }
 
        /* Otherwise, to keep compatibility, we need to figure it out. */
-       snprintf(xpath, sizeof(xpath),
-                "/frr-filter:lib/prefix-list[type='%s'][name='%s']", iptype,
-                name);
-
-       /* Access-list must exist before entries. */
-       if (yang_dnode_exists(running_config->dnode, xpath) == false)
-               return CMD_WARNING_CONFIG_FAILED;
+       pda.pda_type = iptype;
+       pda.pda_name = name;
+       pda.pda_action = action;
+       if (prefix_str) {
+               if (strmatch(iptype, "ipv4")) {
+                       pda.pda_xpath[arg_idx] = "./ipv4-prefix";
+                       pda.pda_value[arg_idx] = prefix_str;
+                       arg_idx++;
+                       if (ge_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv4-prefix-length-greater-or-equal";
+                               pda.pda_value[arg_idx] = ge_str;
+                               arg_idx++;
+                       }
+                       if (le_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv4-prefix-length-lesser-or-equal";
+                               pda.pda_value[arg_idx] = le_str;
+                               arg_idx++;
+                       }
+               } else {
+                       pda.pda_xpath[arg_idx] = "./ipv6-prefix";
+                       pda.pda_value[arg_idx] = prefix_str;
+                       arg_idx++;
+                       if (ge_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv6-prefix-length-greater-or-equal";
+                               pda.pda_value[arg_idx] = ge_str;
+                               arg_idx++;
+                       }
+                       if (le_str) {
+                               pda.pda_xpath[arg_idx] =
+                                       "./ipv6-prefix-length-lesser-or-equal";
+                               pda.pda_value[arg_idx] = le_str;
+                               arg_idx++;
+                       }
+               }
+       } else {
+               pda.pda_xpath[0] = "./any";
+               pda.pda_value[0] = "";
+       }
 
-       /* Use access-list data structure to fetch sequence. */
-       assert(action != NULL);
-       if (strcmp(action, "permit") == 0)
-               plt = PREFIX_PERMIT;
+       if (plist_is_dup(vty->candidate_config->dnode, &pda))
+               sseq = pda.pda_seq;
        else
-               plt = PREFIX_DENY;
-
-       dnode = yang_dnode_get(running_config->dnode, xpath);
-       pl = nb_running_get_entry(dnode, NULL, true);
-       pentry = prefix_list_entry_lookup(pl, p, plt, -1, le, ge);
-       if (pentry == NULL)
                return CMD_WARNING_CONFIG_FAILED;
 
-       snprintfrr(xpath_entry, sizeof(xpath_entry),
-                  "%s/entry[sequence='%" PRId64 "']", xpath, pentry->seq);
+       snprintfrr(
+               xpath_entry, sizeof(xpath_entry),
+               "/frr-filter:lib/prefix-list[type='%s'][name='%s']/entry[sequence='%" PRId64 "']",
+               iptype, name, sseq);
        nb_cli_enqueue_change(vty, xpath_entry, NB_OP_DESTROY, NULL);
 
        rv = nb_cli_apply_changes(vty, NULL);
@@ -1394,14 +1360,31 @@ DEFPY_YANG(
                nb_cli_enqueue_change(vty, "./ipv4-prefix", NB_OP_MODIFY,
                                      prefix_str);
 
-               if (ge_str)
+               if (ge_str) {
                        nb_cli_enqueue_change(
                                vty, "./ipv4-prefix-length-greater-or-equal",
                                NB_OP_MODIFY, ge_str);
-               if (le_str)
+               } else {
+                       /*
+                        * Remove old ge if not being modified
+                        */
+                       nb_cli_enqueue_change(
+                               vty, "./ipv4-prefix-length-greater-or-equal",
+                               NB_OP_DESTROY, NULL);
+               }
+
+               if (le_str) {
                        nb_cli_enqueue_change(
                                vty, "./ipv4-prefix-length-lesser-or-equal",
                                NB_OP_MODIFY, le_str);
+               } else {
+                       /*
+                        * Remove old le if not being modified
+                        */
+                       nb_cli_enqueue_change(
+                               vty, "./ipv4-prefix-length-lesser-or-equal",
+                               NB_OP_DESTROY, NULL);
+               }
        } else {
                nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL);
        }
@@ -1425,8 +1408,8 @@ DEFPY_YANG(
        "Maximum prefix length to be matched\n"
        "Maximum prefix length\n")
 {
-       return plist_remove(vty, "ipv4", name, seq_str, action,
-                           (struct prefix *)prefix, ge, le);
+       return plist_remove(vty, "ipv4", name, seq_str, action, prefix_str,
+                           ge_str, le_str);
 }
 
 DEFPY_YANG(
@@ -1438,7 +1421,7 @@ DEFPY_YANG(
        PREFIX_LIST_NAME_STR
        ACCESS_LIST_SEQ_STR)
 {
-       return plist_remove(vty, "ipv4", name, seq_str, NULL, NULL, 0, 0);
+       return plist_remove(vty, "ipv4", name, seq_str, NULL, NULL, NULL, NULL);
 }
 
 DEFPY_YANG(
@@ -1493,13 +1476,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/prefix-list[type='ipv4'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return plist_remove_if_empty(vty, "ipv4", name);
+
+       return rv;
 }
 
 ALIAS(
@@ -1590,14 +1578,31 @@ DEFPY_YANG(
                nb_cli_enqueue_change(vty, "./ipv6-prefix", NB_OP_MODIFY,
                                      prefix_str);
 
-               if (ge_str)
+               if (ge_str) {
                        nb_cli_enqueue_change(
                                vty, "./ipv6-prefix-length-greater-or-equal",
                                NB_OP_MODIFY, ge_str);
-               if (le_str)
+               } else {
+                       /*
+                        * Remove old ge if not being modified
+                        */
+                       nb_cli_enqueue_change(
+                               vty, "./ipv6-prefix-length-greater-or-equal",
+                               NB_OP_DESTROY, NULL);
+               }
+
+               if (le_str) {
                        nb_cli_enqueue_change(
                                vty, "./ipv6-prefix-length-lesser-or-equal",
                                NB_OP_MODIFY, le_str);
+               } else {
+                       /*
+                        * Remove old le if not being modified
+                        */
+                       nb_cli_enqueue_change(
+                               vty, "./ipv6-prefix-length-lesser-or-equal",
+                               NB_OP_DESTROY, NULL);
+               }
        } else {
                nb_cli_enqueue_change(vty, "./any", NB_OP_CREATE, NULL);
        }
@@ -1621,8 +1626,8 @@ DEFPY_YANG(
        "Minimum prefix length to be matched\n"
        "Minimum prefix length\n")
 {
-       return plist_remove(vty, "ipv6", name, seq_str, action,
-                           (struct prefix *)prefix, ge, le);
+       return plist_remove(vty, "ipv6", name, seq_str, action, prefix_str,
+                           ge_str, le_str);
 }
 
 DEFPY_YANG(
@@ -1634,7 +1639,7 @@ DEFPY_YANG(
        PREFIX_LIST_NAME_STR
        ACCESS_LIST_SEQ_STR)
 {
-       return plist_remove(vty, "ipv6", name, seq_str, NULL, NULL, 0, 0);
+       return plist_remove(vty, "ipv6", name, seq_str, NULL, NULL, NULL, NULL);
 }
 
 DEFPY_YANG(
@@ -1689,13 +1694,18 @@ DEFPY_YANG(
        ACCESS_LIST_REMARK_STR)
 {
        char xpath[XPATH_MAXLEN];
+       int rv;
 
        snprintf(xpath, sizeof(xpath),
                 "/frr-filter:lib/prefix-list[type='ipv6'][name='%s']/remark",
                 name);
        nb_cli_enqueue_change(vty, xpath, NB_OP_DESTROY, NULL);
 
-       return nb_cli_apply_changes(vty, NULL);
+       rv = nb_cli_apply_changes(vty, NULL);
+       if (rv == CMD_SUCCESS)
+               return plist_remove_if_empty(vty, "ipv6", name);
+
+       return rv;
 }
 
 ALIAS(
index 3aa362ad63060b897b50b93175b3ab57148ddf31..85805ffa47c190436e9e39b633e2d9a5e6baa3b6 100644 (file)
@@ -279,6 +279,7 @@ static int _acl_is_dup(const struct lyd_node *dnode, void *arg)
        }
 
        ada->ada_found = true;
+       ada->ada_seq = yang_dnode_get_uint32(dnode, "sequence");
 
        return YANG_ITER_STOP;
 }
@@ -416,6 +417,7 @@ static int _plist_is_dup(const struct lyd_node *dnode, void *arg)
        }
 
        pda->pda_found = true;
+       pda->pda_seq = yang_dnode_get_uint32(dnode, "sequence");
 
        return YANG_ITER_STOP;
 }
@@ -506,17 +508,12 @@ static int lib_access_list_create(struct nb_cb_create_args *args)
 
 static int lib_access_list_destroy(struct nb_cb_destroy_args *args)
 {
-       struct access_master *am;
        struct access_list *acl;
 
        if (args->event != NB_EV_APPLY)
                return NB_OK;
 
        acl = nb_running_unset_entry(args->dnode);
-       am = acl->master;
-       if (am->delete_hook)
-               am->delete_hook(acl);
-
        access_list_delete(acl);
 
        return NB_OK;
index 03359f4d18ea1e1913feeff80bb08a969468be1a..898fe98aada9f712e25dcb3df7b917779f2883ac 100644 (file)
@@ -28,6 +28,7 @@
 #include "memory.h"
 #include "linklist.h"
 #include "zlog.h"
+#include "libfrr.h"
 #include "libfrr_trace.h"
 
 DEFINE_MTYPE_STATIC(LIB, FRR_PTHREAD, "FRR POSIX Thread");
@@ -162,6 +163,8 @@ int frr_pthread_run(struct frr_pthread *fpt, const pthread_attr_t *attr)
        int ret;
        sigset_t oldsigs, blocksigs;
 
+       assert(frr_is_after_fork || !"trying to start thread before fork()");
+
        /* Ensure we never handle signals on a background thread by blocking
         * everything here (new thread inherits signal mask)
         */
index 6e5088142a10c3985d09c4048d9671ff2afc959e..17695e6607c8049d150f054957df8cbb9de30dfd 100644 (file)
@@ -45,9 +45,15 @@ static struct log_ref ferr_lib_warn[] = {
                .suggestion = "Gather log data and open an Issue. restart FRR",
        },
        {
-               .code = EC_LIB_SLOW_THREAD,
-               .title = "The Event subsystem has detected a slow process",
-               .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner.  This can be either a misconfiguration, bug, or some combination therof.",
+               .code = EC_LIB_SLOW_THREAD_CPU,
+               .title = "The Event subsystem has detected a slow cpu time process",
+               .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner.  This can be either a misconfiguration, bug, or some combination therof.  In this case total CPU time was over 5 seconds.  Which indicates that FRR is very busy doing some work and should be addressed",
+               .suggestion = "Gather log data and open an Issue",
+       },
+       {
+               .code = EC_LIB_SLOW_THREAD_WALL,
+               .title = "The Event subsystem has detected a slow wall time process",
+               .description = "The Event subsystem has detected a slow process, this typically indicates that FRR is having trouble completing work in a timely manner.  This can be either a misconfiguration, bug or some combination therof.  In this case total WALL time was over 5 seconds.  Which indicates that FRR might be having trouble being scheduled or some system call is delaying",
                .suggestion = "Gather log data and open an Issue",
        },
        {
index 4730b6aa330721ee5c4fc469c097e72d855d9c92..9f0f58d20b1842a11fc83edc27952c99922cfd3e 100644 (file)
@@ -44,7 +44,8 @@ enum lib_log_refs {
        EC_LIB_SNMP,
        EC_LIB_STREAM,
        EC_LIB_LINUX_NS,
-       EC_LIB_SLOW_THREAD,
+       EC_LIB_SLOW_THREAD_CPU,
+       EC_LIB_SLOW_THREAD_WALL,
        EC_LIB_NO_THREAD,
        EC_LIB_RMAP_RECURSION_LIMIT,
        EC_LIB_BACKUP_CONFIG,
index 5b0a523fb51e76091b035d5cbc78178cfc51bae0..970e82c0649c050abaf44c6b7cac61a6e0ae8584 100644 (file)
@@ -29,7 +29,7 @@
 #include "privs.h"
 #include "vty.h"
 #include "command.h"
-#include "version.h"
+#include "lib/version.h"
 #include "lib_vty.h"
 #include "log_vty.h"
 #include "zclient.h"
@@ -46,7 +46,8 @@
 #include "frrscript.h"
 
 DEFINE_HOOK(frr_late_init, (struct thread_master * tm), (tm));
-DEFINE_HOOK(frr_very_late_init, (struct thread_master * tm), (tm));
+DEFINE_HOOK(frr_config_pre, (struct thread_master * tm), (tm));
+DEFINE_HOOK(frr_config_post, (struct thread_master * tm), (tm));
 DEFINE_KOOH(frr_early_fini, (), ());
 DEFINE_KOOH(frr_fini, (), ());
 
@@ -69,6 +70,8 @@ static char dbfile_default[512];
 #endif
 static char vtypath_default[512];
 
+/* cleared in frr_preinit(), then re-set after daemonizing */
+bool frr_is_after_fork = true;
 bool debug_memstats_at_exit = false;
 static bool nodetach_term, nodetach_daemon;
 static uint64_t startup_fds;
@@ -307,6 +310,7 @@ void frr_init_vtydir(void)
 void frr_preinit(struct frr_daemon_info *daemon, int argc, char **argv)
 {
        di = daemon;
+       frr_is_after_fork = false;
 
        /* basename(), opencoded. */
        char *p = strrchr(argv[0], '/');
@@ -931,6 +935,8 @@ static void frr_daemonize(void)
  */
 static int frr_config_read_in(struct thread *t)
 {
+       hook_call(frr_config_pre, master);
+
        if (!vty_read_config(vty_shared_candidate_config, di->config_file,
                             config_default)
            && di->backup_config_file) {
@@ -964,7 +970,7 @@ static int frr_config_read_in(struct thread *t)
                                __func__, nb_err_name(ret), errmsg);
        }
 
-       hook_call(frr_very_late_init, master);
+       hook_call(frr_config_post, master);
 
        return 0;
 }
@@ -987,6 +993,8 @@ void frr_config_fork(void)
        if (di->daemon_mode || di->terminal)
                frr_daemonize();
 
+       frr_is_after_fork = true;
+
        if (!di->pid_file)
                di->pid_file = pidfile_default;
        pid_output(di->pid_file);
index db0f36498668c9d7ea8061539fcc3cfd5b312480..3dc5d7af81db4c30fb4c04bfc53c4757cadfa3b6 100644 (file)
@@ -141,8 +141,12 @@ extern enum frr_cli_mode frr_get_cli_mode(void);
 extern uint32_t frr_get_fd_limit(void);
 extern bool frr_is_startup_fd(int fd);
 
+/* call order of these hooks is as ordered here */
 DECLARE_HOOK(frr_late_init, (struct thread_master * tm), (tm));
-DECLARE_HOOK(frr_very_late_init, (struct thread_master * tm), (tm));
+/* fork() happens between late_init and config_pre */
+DECLARE_HOOK(frr_config_pre, (struct thread_master * tm), (tm));
+DECLARE_HOOK(frr_config_post, (struct thread_master * tm), (tm));
+
 extern void frr_config_fork(void);
 
 extern void frr_run(struct thread_master *master);
@@ -168,6 +172,8 @@ extern const char frr_scriptdir[];
 
 extern char frr_protoname[];
 extern char frr_protonameinst[];
+/* always set in the spot where we *would* fork even if we don't do so */
+extern bool frr_is_after_fork;
 
 extern bool debug_memstats_at_exit;
 
index 2f300e6ee1ef94adc8c906a920c753bcb155cb51..59320322ca459fabe3a3db89af649839976e4177 100644 (file)
@@ -1,4 +1,6 @@
 #define TRACEPOINT_CREATE_PROBES
 #define TRACEPOINT_DEFINE
 
+#include <zebra.h>
+
 #include "libfrr_trace.h"
index 8606f8eb09424bb52da511ff0ab1c2ca25d7bbe7..afeb89c5922ab9a00578b224c4f2eb88a48a9d0e 100644 (file)
@@ -22,6 +22,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "if.h"
 #include "linklist.h"
 #include "log.h"
index 5de6c8a81729bddf8df27f64999a09ac2d944750..8137b68d845daf4d75f8f25fb04f7020b073bd8b 100644 (file)
@@ -320,23 +320,6 @@ void list_delete_all_node(struct list *list)
        list->count = 0;
 }
 
-void list_filter_out_nodes(struct list *list, bool (*cond)(void *data))
-{
-       struct listnode *node;
-       struct listnode *next;
-       void *data;
-
-       assert(list);
-
-       for (ALL_LIST_ELEMENTS(list, node, next, data)) {
-               if ((cond && cond(data)) || (!cond)) {
-                       if (*list->del)
-                               (*list->del)(data);
-                       list_delete_node(list, node);
-               }
-       }
-}
-
 void list_delete(struct list **list)
 {
        assert(*list);
index d8820c924d9170977e8d313b070fec2603b8dd67..1452145218064457ae3cb32ae1b90c15291167d0 100644 (file)
@@ -294,19 +294,6 @@ extern void list_delete_all_node(struct list *list);
  */
 extern void list_delete_node(struct list *list, struct listnode *node);
 
-/*
- * Delete all nodes which satisfy a condition from a list.
- * Deletes the node if cond function returns true for the node.
- * If function ptr passed is NULL, it deletes all nodes
- *
- * list
- *    list to operate on
- * cond
- *    function pointer which takes node data as input and return true or false
- */
-
-extern void list_filter_out_nodes(struct list *list, bool (*cond)(void *data));
-
 /*
  * Insert a new element into a list with insertion sort if there is no
  * duplicate element present in the list. This assumes the input list is
index ca2f50168602638a34cb600eb32be1f4db72bb41..936422104f95f7500025c674fa02410e52320ed0 100644 (file)
--- a/lib/log.c
+++ b/lib/log.c
@@ -311,17 +311,6 @@ void zlog_thread_info(int log_level)
                zlog(log_level, "Current thread not known/applicable");
 }
 
-void _zlog_assert_failed(const char *assertion, const char *file,
-                        unsigned int line, const char *function)
-{
-       zlog(LOG_CRIT, "Assertion `%s' failed in file %s, line %u, function %s",
-            assertion, file, line, (function ? function : "?"));
-       zlog_backtrace(LOG_CRIT);
-       zlog_thread_info(LOG_CRIT);
-       log_memstats(stderr, "log");
-       abort();
-}
-
 void memory_oom(size_t size, const char *name)
 {
        zlog(LOG_CRIT,
@@ -472,7 +461,10 @@ static const struct zebra_desc_table command_types[] = {
        DESC_ENTRY(ZEBRA_NHRP_NEIGH_UNREGISTER),
        DESC_ENTRY(ZEBRA_NEIGH_IP_ADD),
        DESC_ENTRY(ZEBRA_NEIGH_IP_DEL),
-       DESC_ENTRY(ZEBRA_CONFIGURE_ARP)};
+       DESC_ENTRY(ZEBRA_CONFIGURE_ARP),
+       DESC_ENTRY(ZEBRA_GRE_GET),
+       DESC_ENTRY(ZEBRA_GRE_UPDATE),
+       DESC_ENTRY(ZEBRA_GRE_SOURCE_SET)};
 #undef DESC_ENTRY
 
 static const struct zebra_desc_table unknown = {0, "unknown", '?'};
index 714725364451770b50f05984c76ab5d57c5f5e35..59f1742d01e16acaa79277a19f8c58b276dd503a 100644 (file)
--- a/lib/log.h
+++ b/lib/log.h
@@ -22,8 +22,6 @@
 #ifndef _ZEBRA_LOG_H
 #define _ZEBRA_LOG_H
 
-#include "zassert.h"
-
 #include <syslog.h>
 #include <stdint.h>
 #include <stdbool.h>
index c26621ae99d1e3e1aac6e98ed6e8ff574160dce4..9dbf216d31521bae8db4f4d7079b16d56f1686d1 100644 (file)
@@ -146,11 +146,11 @@ void log_show_syslog(struct vty *vty)
                        zlog_progname);
 }
 
-DEFUN (show_logging,
-       show_logging_cmd,
-       "show logging",
-       SHOW_STR
-       "Show current logging configuration\n")
+DEFUN_NOSH (show_logging,
+           show_logging_cmd,
+           "show logging",
+           SHOW_STR
+           "Show current logging configuration\n")
 {
        log_show_syslog(vty);
 
@@ -647,6 +647,18 @@ DEFPY (show_log_filter,
        return CMD_SUCCESS;
 }
 
+/* Enable/disable 'immediate' mode, with no output buffering */
+DEFPY (log_immediate_mode,
+       log_immediate_mode_cmd,
+       "[no] log immediate-mode",
+       NO_STR
+       "Logging control"
+       "Output immediately, without buffering")
+{
+       zlog_set_immediate(!no);
+       return CMD_SUCCESS;
+}
+
 void log_config_write(struct vty *vty)
 {
        bool show_cmdline_hint = false;
@@ -775,4 +787,5 @@ void log_cmd_init(void)
        install_element(CONFIG_NODE, &log_filter_clear_cmd);
        install_element(CONFIG_NODE, &config_log_filterfile_cmd);
        install_element(CONFIG_NODE, &no_config_log_filterfile_cmd);
+       install_element(CONFIG_NODE, &log_immediate_mode_cmd);
 }
index d2491a34797cd86c8aab91f0e084834557976e4c..1d51a6396d97efebc105db389aafdb89023f095a 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "module.h"
 #include "memory.h"
-#include "version.h"
+#include "lib/version.h"
 
 DEFINE_MTYPE_STATIC(LIB, MODULE_LOADNAME, "Module loading name");
 DEFINE_MTYPE_STATIC(LIB, MODULE_LOADARGS, "Module loading arguments");
index 84393981497894a27dd8647b50c2f7116f29937d..0ac6c0ae1b0eec87cb5989b05337f4cf9029cabe 100644 (file)
@@ -62,7 +62,8 @@ static int _nexthop_labels_cmp(const struct nexthop *nh1,
        if (nhl1->num_labels < nhl2->num_labels)
                return -1;
 
-       return memcmp(nhl1->label, nhl2->label, nhl1->num_labels);
+       return memcmp(nhl1->label, nhl2->label,
+                     (nhl1->num_labels * sizeof(mpls_label_t)));
 }
 
 int nexthop_g_addr_cmp(enum nexthop_types_t type, const union g_addr *addr1,
@@ -202,6 +203,105 @@ int nexthop_cmp(const struct nexthop *next1, const struct nexthop *next2)
        return ret;
 }
 
+/*
+ * More-limited comparison function used to detect duplicate
+ * nexthops. This is used in places where we don't need the full
+ * comparison of 'nexthop_cmp()'.
+ */
+int nexthop_cmp_basic(const struct nexthop *nh1,
+                     const struct nexthop *nh2)
+{
+       int ret = 0;
+       const struct mpls_label_stack *nhl1 = NULL;
+       const struct mpls_label_stack *nhl2 = NULL;
+
+       if (nh1 == NULL && nh2 == NULL)
+               return 0;
+
+       if (nh1 && !nh2)
+               return 1;
+
+       if (!nh1 && nh2)
+               return -1;
+
+       if (nh1->vrf_id < nh2->vrf_id)
+               return -1;
+
+       if (nh1->vrf_id > nh2->vrf_id)
+               return 1;
+
+       if (nh1->type < nh2->type)
+               return -1;
+
+       if (nh1->type > nh2->type)
+               return 1;
+
+       if (nh1->weight < nh2->weight)
+               return -1;
+
+       if (nh1->weight > nh2->weight)
+               return 1;
+
+       switch (nh1->type) {
+       case NEXTHOP_TYPE_IPV4:
+       case NEXTHOP_TYPE_IPV6:
+               ret = nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate);
+               if (ret != 0)
+                       return ret;
+               break;
+       case NEXTHOP_TYPE_IPV4_IFINDEX:
+       case NEXTHOP_TYPE_IPV6_IFINDEX:
+               ret = nexthop_g_addr_cmp(nh1->type, &nh1->gate, &nh2->gate);
+               if (ret != 0)
+                       return ret;
+               /* Intentional Fall-Through */
+       case NEXTHOP_TYPE_IFINDEX:
+               if (nh1->ifindex < nh2->ifindex)
+                       return -1;
+
+               if (nh1->ifindex > nh2->ifindex)
+                       return 1;
+               break;
+       case NEXTHOP_TYPE_BLACKHOLE:
+               if (nh1->bh_type < nh2->bh_type)
+                       return -1;
+
+               if (nh1->bh_type > nh2->bh_type)
+                       return 1;
+               break;
+       }
+
+       /* Compare source addr */
+       ret = nexthop_g_addr_cmp(nh1->type, &nh1->src, &nh2->src);
+       if (ret != 0)
+               goto done;
+
+       nhl1 = nh1->nh_label;
+       nhl2 = nh2->nh_label;
+
+       /* No labels is a match */
+       if (!nhl1 && !nhl2)
+               return 0;
+
+       if (nhl1 && !nhl2)
+               return 1;
+
+       if (nhl2 && !nhl1)
+               return -1;
+
+       if (nhl1->num_labels > nhl2->num_labels)
+               return 1;
+
+       if (nhl1->num_labels < nhl2->num_labels)
+               return -1;
+
+       ret = memcmp(nhl1->label, nhl2->label,
+                    (nhl1->num_labels * sizeof(mpls_label_t)));
+
+done:
+       return ret;
+}
+
 /*
  * nexthop_type_to_str
  */
index f1ad195cf4cfbe67b9efe5553d2aa1fe500cab3b..d6ea83cf0614db530f8fc0f8be486a1569510311 100644 (file)
@@ -207,6 +207,11 @@ extern int nexthop_g_addr_cmp(enum nexthop_types_t type,
                              const union g_addr *addr1,
                              const union g_addr *addr2);
 
+/* More-limited comparison function used to detect duplicate nexthops.
+ * Returns -1, 0, 1
+ */
+int nexthop_cmp_basic(const struct nexthop *nh1, const struct nexthop *nh2);
+
 extern const char *nexthop_type_to_str(enum nexthop_types_t nh_type);
 extern bool nexthop_labels_match(const struct nexthop *nh1,
                                 const struct nexthop *nh2);
index f88c2161daabed92f2e0c6cd7b340466ff6698c0..81e30bce49419393e823f68021ac6235ac5911d7 100644 (file)
@@ -20,7 +20,7 @@
 #include <zebra.h>
 
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "defaults.h"
 #include "log.h"
 #include "lib_errors.h"
index 3d8771ffbce0b6f62bd994d7db90aa75c2efd77d..403537e0432de9938976204e8c983377be3c88d5 100644 (file)
@@ -24,7 +24,7 @@
 #include "command.h"
 #include "debug.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "northbound.h"
 
 #include <confd_lib.h>
index d042e15dad302ffe64ab8c620654e4615bbf2398..58f4e42516431138dc3c90f637e2db5dd18138f5 100644 (file)
@@ -23,7 +23,7 @@
 
 #include "log.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "command.h"
 #include "lib_errors.h"
 #include "northbound.h"
index 9fc640ceea2dee016de070bb8e81804e91fb2681..63fd40f8d3a63763561f71136908d570f2368a22 100644 (file)
@@ -25,7 +25,7 @@
 #include "debug.h"
 #include "memory.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "northbound.h"
 
 #include <sysrepo.h>
@@ -736,7 +736,7 @@ static int frr_sr_finish(void)
        return 0;
 }
 
-static int frr_sr_module_very_late_init(struct thread_master *tm)
+static int frr_sr_module_config_loaded(struct thread_master *tm)
 {
        master = tm;
 
@@ -761,7 +761,7 @@ static int frr_sr_module_late_init(struct thread_master *tm)
 static int frr_sr_module_init(void)
 {
        hook_register(frr_late_init, frr_sr_module_late_init);
-       hook_register(frr_very_late_init, frr_sr_module_very_late_init);
+       hook_register(frr_config_post, frr_sr_module_config_loaded);
 
        return 0;
 }
index bd1d89a94cf296a8beb260ed5a4b4362abe9ac13..b82dde82585d9ed813679ca5fbe62548d30fd1f1 100644 (file)
@@ -22,7 +22,7 @@
 #include <zebra.h>
 #include <fcntl.h>
 #include <log.h>
-#include "version.h"
+#include "lib/version.h"
 #include "network.h"
 #include "lib_errors.h"
 
index 92c8b8ee557115cce21f88a5d895389644a6f23d..0ee02f8a0b5f09bb00a82feddd095c5ce6ef76ee 100644 (file)
@@ -66,15 +66,9 @@ struct prefix_list_list {
 
 /* Master structure of prefix_list. */
 struct prefix_master {
-       /* List of prefix_list which name is number. */
-       struct prefix_list_list num;
-
        /* List of prefix_list which name is string. */
        struct prefix_list_list str;
 
-       /* Whether sequential number is used. */
-       bool seqnum;
-
        /* The latest update. */
        struct prefix_list *recent;
 
@@ -90,22 +84,22 @@ struct prefix_master {
 
 /* Static structure of IPv4 prefix_list's master. */
 static struct prefix_master prefix_master_ipv4 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
+       {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4,
 };
 
 /* Static structure of IPv6 prefix-list's master. */
 static struct prefix_master prefix_master_ipv6 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
+       {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6,
 };
 
 /* Static structure of BGP ORF prefix_list's master. */
 static struct prefix_master prefix_master_orf_v4 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV4,
+       {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV4,
 };
 
 /* Static structure of BGP ORF prefix_list's master. */
 static struct prefix_master prefix_master_orf_v6 = {
-       {NULL, NULL}, {NULL, NULL}, 1, NULL, NULL, NULL, PLC_MAXLEVELV6,
+       {NULL, NULL}, NULL, NULL, NULL, PLC_MAXLEVELV6,
 };
 
 static struct prefix_master *prefix_master_get(afi_t afi, int orf)
@@ -144,10 +138,6 @@ static struct prefix_list *prefix_list_lookup_do(afi_t afi, int orf,
        if (master == NULL)
                return NULL;
 
-       for (plist = master->num.head; plist; plist = plist->next)
-               if (strcmp(plist->name, name) == 0)
-                       return plist;
-
        for (plist = master->str.head; plist; plist = plist->next)
                if (strcmp(plist->name, name) == 0)
                        return plist;
@@ -197,8 +187,6 @@ void prefix_list_entry_free(struct prefix_list_entry *pentry)
 static struct prefix_list *prefix_list_insert(afi_t afi, int orf,
                                              const char *name)
 {
-       unsigned int i;
-       long number;
        struct prefix_list *plist;
        struct prefix_list *point;
        struct prefix_list_list *list;
@@ -215,36 +203,13 @@ static struct prefix_list *prefix_list_insert(afi_t afi, int orf,
        plist->trie =
                XCALLOC(MTYPE_PREFIX_LIST_TRIE, sizeof(struct pltrie_table));
 
-       /* If name is made by all digit character.  We treat it as
-          number. */
-       for (number = 0, i = 0; i < strlen(name); i++) {
-               if (isdigit((unsigned char)name[i]))
-                       number = (number * 10) + (name[i] - '0');
-               else
-                       break;
-       }
-
-       /* In case of name is all digit character */
-       if (i == strlen(name)) {
-               plist->type = PREFIX_TYPE_NUMBER;
+       /* Set prefix_list to string list. */
+       list = &master->str;
 
-               /* Set prefix_list to number list. */
-               list = &master->num;
-
-               for (point = list->head; point; point = point->next)
-                       if (atol(point->name) >= number)
-                               break;
-       } else {
-               plist->type = PREFIX_TYPE_STRING;
-
-               /* Set prefix_list to string list. */
-               list = &master->str;
-
-               /* Set point to insertion point. */
-               for (point = list->head; point; point = point->next)
-                       if (strcmp(point->name, name) >= 0)
-                               break;
-       }
+       /* Set point to insertion point. */
+       for (point = list->head; point; point = point->next)
+               if (strcmp(point->name, name) >= 0)
+                       break;
 
        /* In case of this is the first element of master. */
        if (list->head == NULL) {
@@ -313,10 +278,7 @@ void prefix_list_delete(struct prefix_list *plist)
 
        master = plist->master;
 
-       if (plist->type == PREFIX_TYPE_NUMBER)
-               list = &master->num;
-       else
-               list = &master->str;
+       list = &master->str;
 
        if (plist->next)
                plist->next->prev = plist->prev;
@@ -1003,8 +965,7 @@ static void vty_show_prefix_entry(struct vty *vty, afi_t afi,
 
                        vty_out(vty, "   ");
 
-                       if (master->seqnum)
-                               vty_out(vty, "seq %" PRId64 " ", pentry->seq);
+                       vty_out(vty, "seq %" PRId64 " ", pentry->seq);
 
                        vty_out(vty, "%s ", prefix_list_type_str(pentry));
 
@@ -1060,10 +1021,6 @@ static int vty_show_prefix_list(struct vty *vty, afi_t afi, const char *name,
                                        master->recent->name);
                }
 
-               for (plist = master->num.head; plist; plist = plist->next)
-                       vty_show_prefix_entry(vty, afi, plist, master, dtype,
-                                             seqnum);
-
                for (plist = master->str.head; plist; plist = plist->next)
                        vty_show_prefix_entry(vty, afi, plist, master, dtype,
                                              seqnum);
@@ -1152,11 +1109,6 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
                return CMD_WARNING;
 
        if (name == NULL && prefix == NULL) {
-               for (plist = master->num.head; plist; plist = plist->next)
-                       for (pentry = plist->head; pentry;
-                            pentry = pentry->next)
-                               pentry->hitcnt = 0;
-
                for (plist = master->str.head; plist; plist = plist->next)
                        for (pentry = plist->head; pentry;
                             pentry = pentry->next)
@@ -1192,19 +1144,6 @@ static int vty_clear_prefix_list(struct vty *vty, afi_t afi, const char *name,
 #include "lib/plist_clippy.c"
 #endif
 
-DEFPY (ip_prefix_list_sequence_number,
-       ip_prefix_list_sequence_number_cmd,
-       "[no] ip prefix-list sequence-number",
-       NO_STR
-       IP_STR
-       PREFIX_LIST_STR
-       "Include/exclude sequence numbers in NVGEN\n")
-{
-       prefix_master_ipv4.seqnum = no ? false : true;
-       return CMD_SUCCESS;
-}
-
-
 DEFPY (show_ip_prefix_list,
        show_ip_prefix_list_cmd,
        "show ip prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
@@ -1281,18 +1220,6 @@ DEFPY (clear_ip_prefix_list,
        return vty_clear_prefix_list(vty, AFI_IP, prefix_list, prefix_str);
 }
 
-DEFPY (ipv6_prefix_list_sequence_number,
-       ipv6_prefix_list_sequence_number_cmd,
-       "[no] ipv6 prefix-list sequence-number",
-       NO_STR
-       IPV6_STR
-       PREFIX_LIST_STR
-       "Include/exclude sequence numbers in NVGEN\n")
-{
-       prefix_master_ipv6.seqnum = no ? false : true;
-       return CMD_SUCCESS;
-}
-
 DEFPY (show_ipv6_prefix_list,
        show_ipv6_prefix_list_cmd,
        "show ipv6 prefix-list [WORD [seq$dseq (1-4294967295)$arg]]",
@@ -1538,22 +1465,14 @@ static void prefix_list_reset_afi(afi_t afi, int orf)
        if (master == NULL)
                return;
 
-       for (plist = master->num.head; plist; plist = next) {
-               next = plist->next;
-               prefix_list_delete(plist);
-       }
        for (plist = master->str.head; plist; plist = next) {
                next = plist->next;
                prefix_list_delete(plist);
        }
 
-       assert(master->num.head == NULL);
-       assert(master->num.tail == NULL);
-
        assert(master->str.head == NULL);
        assert(master->str.tail == NULL);
 
-       master->seqnum = true;
        master->recent = NULL;
 }
 
@@ -1576,8 +1495,6 @@ static void plist_autocomplete_afi(afi_t afi, vector comps,
 
        for (plist = master->str.head; plist; plist = plist->next)
                vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name));
-       for (plist = master->num.head; plist; plist = plist->next)
-               vector_set(comps, XSTRDUP(MTYPE_COMPLETION, plist->name));
 }
 
 static void plist_autocomplete(vector comps, struct cmd_token *token)
@@ -1597,8 +1514,6 @@ static void prefix_list_init_ipv4(void)
 {
        install_node(&prefix_node);
 
-       install_element(CONFIG_NODE, &ip_prefix_list_sequence_number_cmd);
-
        install_element(VIEW_NODE, &show_ip_prefix_list_cmd);
        install_element(VIEW_NODE, &show_ip_prefix_list_prefix_cmd);
        install_element(VIEW_NODE, &show_ip_prefix_list_summary_cmd);
@@ -1618,8 +1533,6 @@ static void prefix_list_init_ipv6(void)
 {
        install_node(&prefix_ipv6_node);
 
-       install_element(CONFIG_NODE, &ipv6_prefix_list_sequence_number_cmd);
-
        install_element(VIEW_NODE, &show_ipv6_prefix_list_cmd);
        install_element(VIEW_NODE, &show_ipv6_prefix_list_prefix_cmd);
        install_element(VIEW_NODE, &show_ipv6_prefix_list_summary_cmd);
index 5e0beabbc690b39929664eb06d90cabcdbcadd7a..571978a517ee1fc9bd85c8f84421a3f0a6ef9b79 100644 (file)
@@ -26,8 +26,6 @@
 extern "C" {
 #endif
 
-enum prefix_name_type { PREFIX_TYPE_STRING, PREFIX_TYPE_NUMBER };
-
 struct pltrie_table;
 
 struct prefix_list {
@@ -36,8 +34,6 @@ struct prefix_list {
 
        struct prefix_master *master;
 
-       enum prefix_name_type type;
-
        int count;
        int rangecount;
 
index 4338ac3a2fa365e741a5b338f79df25a307f3eb6..37f1f9c8cd1f92e1fd6ba6b723c3039e0521bf76 100644 (file)
@@ -305,8 +305,8 @@ struct va_format {
 
 #define FMT_NSTD(expr)                                                         \
        ({                                                                     \
-               typeof(expr) _v;                                               \
                FMT_NSTD_BEGIN                                                 \
+               typeof(expr) _v;                                               \
                _v = expr;                                                     \
                FMT_NSTD_END                                                   \
                _v;                                                            \
index 49221e7cb356783aae4ebfeeb48a06c13d453667..6efa8077c25feecd525c1a4d4e12361111a54127 100644 (file)
@@ -131,38 +131,3 @@ void ringbuf_wipe(struct ringbuf *buf)
        memset(buf->data, 0x00, buf->size);
        ringbuf_reset(buf);
 }
-
-ssize_t ringbuf_read(struct ringbuf *buf, int sock)
-{
-       size_t to_read = ringbuf_space(buf);
-       size_t bytes_to_end = buf->size - buf->end;
-       ssize_t bytes_read;
-       struct iovec iov[2] = {};
-
-       /* Calculate amount of read blocks. */
-       if (to_read > bytes_to_end) {
-               iov[0].iov_base = buf->data + buf->end;
-               iov[0].iov_len = bytes_to_end;
-               iov[1].iov_base = buf->data;
-               iov[1].iov_len = to_read - bytes_to_end;
-       } else {
-               iov[0].iov_base = buf->data + buf->end;
-               iov[0].iov_len = to_read;
-       }
-
-       /* Do the system call. */
-       bytes_read = readv(sock, iov, 2);
-       if (bytes_read <= 0)
-               return bytes_read;
-
-       /* Calculate the new end. */
-       if ((size_t)bytes_read > bytes_to_end)
-               buf->end = bytes_read - bytes_to_end;
-       else
-               buf->end += bytes_read;
-
-       /* Set emptiness state. */
-       buf->empty = (buf->start == buf->end) && (buf->empty && !bytes_read);
-
-       return bytes_read;
-}
index 209687512bed8f2bd71bb15be7d27ae30981acca..b8f4d9798dc97f2391c6358271111bf30758328e 100644 (file)
@@ -126,17 +126,6 @@ void ringbuf_reset(struct ringbuf *buf);
  */
 void ringbuf_wipe(struct ringbuf *buf);
 
-/**
- * Perform a socket/file `read()` in to the ring buffer.
- *
- * \param buf the ring buffer pointer.
- * \param sock the file descriptor.
- * \returns the number of bytes read, `0` on connection close or `-1` with
- *          `errno` pointing the error (see `readv()` man page for more
- *          information.)
- */
-ssize_t ringbuf_read(struct ringbuf *buf, int sock);
-
 #ifdef __cplusplus
 }
 #endif
index db06e9caac75653dc80b1810ff808f1d09da408e..3473ca2aea8cf12f6043d91fc5f739784aa199af 100644 (file)
@@ -271,6 +271,7 @@ lib_route_map_entry_description_destroy(struct nb_cb_destroy_args *args)
 static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args)
 {
        struct route_map_index *rmi;
+       struct route_map *map;
 
        switch (args->event) {
        case NB_EV_VALIDATE:
@@ -281,7 +282,15 @@ static int lib_route_map_entry_action_modify(struct nb_cb_modify_args *args)
        case NB_EV_APPLY:
                rmi = nb_running_get_entry(args->dnode, NULL, true);
                rmi->type = yang_dnode_get_enum(args->dnode, NULL);
-               /* TODO: notify? */
+               map = rmi->map;
+
+               /* Execute event hook. */
+               if (route_map_master.event_hook) {
+                       (*route_map_master.event_hook)(map->name);
+                       route_map_notify_dependencies(map->name,
+                                                     RMAP_EVENT_CALL_ADDED);
+               }
+
                break;
        }
 
index 0160354a7e07e63913890cae7fa4e46e4f8300f3..6238fb055d5e96c96b25252347420c947938faf3 100644 (file)
@@ -16,6 +16,8 @@
  * 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 "northbound.h"
 #include "libfrr.h"
 #include "routing_nb.h"
index f66f32015dc141ffc7c25d8a1bee5115e64b0a38..594ad6c9e816069274d70cc0f78f93bf91653282 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "northbound.h"
 #include "libfrr.h"
 #include "vrf.h"
index 37ced5b402de5ccb8e15dd11c25bfb267eab5f6c..a9b7a4aefc279928e4f0c308a809e7b5c9ed6996 100644 (file)
@@ -35,8 +35,6 @@ static inline uint32_t be32dec(const void *pp)
        return ((uint32_t)(p[3]) + ((uint32_t)(p[2]) << 8)
                + ((uint32_t)(p[1]) << 16) + ((uint32_t)(p[0]) << 24));
 }
-#else
-#include <sys/endian.h>
 #endif
 
 #if !HAVE_DECL_BE32ENC
@@ -49,8 +47,6 @@ static inline void be32enc(void *pp, uint32_t x)
        p[1] = (x >> 16) & 0xff;
        p[0] = (x >> 24) & 0xff;
 }
-#else
-#include <sys/endian.h>
 #endif
 
 /*
index 64cec1385de54513f069433f89f4c35d9d504a81..be7297f26441d57d3f13b7fdab2b1dcb0614ab4f 100644 (file)
@@ -237,9 +237,12 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
        /* make sure we don't hang in here.  default for SIGALRM is terminate.
         * - if we're in backtrace for more than a second, abort. */
        struct sigaction sa_default = {.sa_handler = SIG_DFL};
+
        sigaction(SIGALRM, &sa_default, NULL);
+       sigaction(signo, &sa_default, NULL);
 
        sigset_t sigset;
+
        sigemptyset(&sigset);
        sigaddset(&sigset, SIGALRM);
        sigprocmask(SIG_UNBLOCK, &sigset, NULL);
@@ -252,7 +255,16 @@ core_handler(int signo, siginfo_t *siginfo, void *context)
        log_memstats(stderr, "core_handler");
 
        zlog_tls_buffer_fini();
-       abort();
+
+       /* give the kernel a chance to generate a coredump */
+       sigaddset(&sigset, signo);
+       sigprocmask(SIG_UNBLOCK, &sigset, NULL);
+       raise(signo);
+
+       /* only chance to end up here is if the default action for signo is
+        * something other than kill or coredump the process
+        */
+       _exit(128 + signo);
 }
 
 static void trap_default_signals(void)
index ed21b72df78bdb76c0fe031cc4e1791cd3ffb899..98bfda507964931393d5b30e410892bd16672e93 100644 (file)
 #include "sockunion.h"
 #include "lib_errors.h"
 
+#if (defined(__FreeBSD__)                                                      \
+     && ((__FreeBSD_version >= 500022 && __FreeBSD_version < 700000)           \
+        || (__FreeBSD_version < 500000 && __FreeBSD_version >= 440000)))      \
+       || (defined(__NetBSD__) && defined(__NetBSD_Version__)                 \
+           && __NetBSD_Version__ >= 106010000)                                \
+       || defined(__OpenBSD__) || defined(__APPLE__)                          \
+       || defined(__DragonFly__) || defined(__sun)
+#define HAVE_BSD_STRUCT_IP_MREQ_HACK
+#endif
+
 void setsockopt_so_recvbuf(int sock, int size)
 {
        int orig_req = size;
@@ -657,3 +667,39 @@ int sockopt_tcp_signature(int sock, union sockunion *su, const char *password)
 {
        return sockopt_tcp_signature_ext(sock, su, 0, password);
 }
+
+/* set TCP mss value to socket */
+int sockopt_tcp_mss_set(int sock, int tcp_maxseg)
+{
+       int ret = 0;
+       socklen_t tcp_maxseg_len = sizeof(tcp_maxseg);
+
+       ret = setsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &tcp_maxseg,
+                        tcp_maxseg_len);
+       if (ret != 0) {
+               flog_err_sys(EC_LIB_SYSTEM_CALL,
+                            "%s failed: setsockopt(%d): %s", __func__, sock,
+                            safe_strerror(errno));
+       }
+
+       return ret;
+}
+
+/* get TCP mss value synced by socket */
+int sockopt_tcp_mss_get(int sock)
+{
+       int ret = 0;
+       int tcp_maxseg = 0;
+       socklen_t tcp_maxseg_len = sizeof(tcp_maxseg);
+
+       ret = getsockopt(sock, IPPROTO_TCP, TCP_MAXSEG, &tcp_maxseg,
+                        &tcp_maxseg_len);
+       if (ret != 0) {
+               flog_err_sys(EC_LIB_SYSTEM_CALL,
+                            "%s failed: getsockopt(%d): %s", __func__, sock,
+                            safe_strerror(errno));
+               return 0;
+       }
+
+       return tcp_maxseg;
+}
index 545abe631fcfedb7935224948805dec77524eec6..6c80841e3c2b904ec20a8b1766bae21ef11e01e9 100644 (file)
@@ -133,6 +133,26 @@ extern int sockopt_tcp_signature(int sock, union sockunion *su,
 extern int sockopt_tcp_signature_ext(int sock, union sockunion *su,
                                     uint16_t prefixlen, const char *password);
 
+/*
+ * set TCP max segment size. This option allows user to configure
+ * max segment size for TCP session
+ *
+ * sock
+ *    Socket to enable option on.
+ *
+ * tcp_maxseg
+ *    value used for TCP segment size negotiation during SYN
+ */
+extern int sockopt_tcp_mss_set(int sock, int tcp_maxseg);
+
+/*
+ * get TCP max segment size. This option allows user to get
+ * the segment size for TCP session
+ *
+ * sock
+ *    Socket to get max segement size.
+ */
+extern int sockopt_tcp_mss_get(int sock);
 #ifdef __cplusplus
 }
 #endif
index 0853d4bb2bb01705a24c3108376d281bf9333a32..480c2938d0d4a93b3668f2bd0a01e8dc43daec4f 100644 (file)
@@ -141,10 +141,14 @@ vtysh_scan += \
        lib/if_rmap.c \
        lib/keychain.c \
        lib/lib_vty.c \
+       lib/log_vty.c \
        lib/nexthop_group.c \
        lib/plist.c \
+       lib/resolver.c \
        lib/routemap.c \
        lib/routemap_cli.c \
+       lib/spf_backoff.c \
+       lib/thread.c \
        lib/vrf.c \
        lib/vty.c \
        # end
@@ -274,13 +278,14 @@ pkginclude_HEADERS += \
        lib/yang.h \
        lib/yang_translator.h \
        lib/yang_wrappers.h \
-       lib/zassert.h \
        lib/zclient.h \
        lib/zebra.h \
        lib/zlog.h \
        lib/zlog_targets.h \
        lib/pbr.h \
        lib/routing_nb.h \
+       \
+       lib/assert/assert.h \
        # end
 
 
@@ -314,7 +319,7 @@ if SNMP
 lib_LTLIBRARIES += lib/libfrrsnmp.la
 endif
 
-lib_libfrrsnmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+lib_libfrrsnmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 lib_libfrrsnmp_la_LDFLAGS = -version-info 0:0:0
 lib_libfrrsnmp_la_LIBADD = $(SNMP_LIBS)
 lib_libfrrsnmp_la_SOURCES = \
@@ -330,7 +335,7 @@ lib_LTLIBRARIES += lib/libfrrcares.la
 pkginclude_HEADERS += lib/resolver.h
 endif
 
-lib_libfrrcares_la_CFLAGS = $(WERROR) $(CARES_CFLAGS)
+lib_libfrrcares_la_CFLAGS = $(AM_CFLAGS) $(CARES_CFLAGS)
 lib_libfrrcares_la_LDFLAGS = -version-info 0:0:0
 lib_libfrrcares_la_LIBADD = $(CARES_LIBS)
 lib_libfrrcares_la_SOURCES = \
@@ -345,7 +350,7 @@ lib_LTLIBRARIES += lib/libfrrzmq.la
 pkginclude_HEADERS += lib/frr_zmq.h
 endif
 
-lib_libfrrzmq_la_CFLAGS = $(WERROR) $(ZEROMQ_CFLAGS)
+lib_libfrrzmq_la_CFLAGS = $(AM_CFLAGS) $(ZEROMQ_CFLAGS)
 lib_libfrrzmq_la_LDFLAGS = -version-info 0:0:0
 lib_libfrrzmq_la_LIBADD = $(ZEROMQ_LIBS)
 lib_libfrrzmq_la_SOURCES = \
@@ -359,7 +364,7 @@ if CONFD
 module_LTLIBRARIES += lib/confd.la
 endif
 
-lib_confd_la_CFLAGS = $(WERROR) $(CONFD_CFLAGS)
+lib_confd_la_CFLAGS = $(AM_CFLAGS) $(CONFD_CFLAGS)
 lib_confd_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 lib_confd_la_LIBADD = lib/libfrr.la $(CONFD_LIBS)
 lib_confd_la_SOURCES = lib/northbound_confd.c
@@ -371,7 +376,7 @@ if SYSREPO
 module_LTLIBRARIES += lib/sysrepo.la
 endif
 
-lib_sysrepo_la_CFLAGS = $(WERROR) $(SYSREPO_CFLAGS)
+lib_sysrepo_la_CFLAGS = $(AM_CFLAGS) $(SYSREPO_CFLAGS)
 lib_sysrepo_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 lib_sysrepo_la_LIBADD = lib/libfrr.la $(SYSREPO_LIBS)
 lib_sysrepo_la_SOURCES = lib/northbound_sysrepo.c
@@ -409,8 +414,8 @@ lib_grammar_sandbox_SOURCES = \
 lib_grammar_sandbox_LDADD = \
        lib/libfrr.la
 
-lib_clippy_CPPFLAGS = $(AM_CPPFLAGS) -D_GNU_SOURCE -DBUILDING_CLIPPY
-lib_clippy_CFLAGS = $(PYTHON_CFLAGS)
+lib_clippy_CPPFLAGS = $(CPPFLAGS_BASE) -D_GNU_SOURCE -DBUILDING_CLIPPY
+lib_clippy_CFLAGS = $(AC_CFLAGS) $(PYTHON_CFLAGS)
 lib_clippy_LDADD = $(PYTHON_LIBS) $(UST_LIBS) -lelf
 lib_clippy_LDFLAGS = -export-dynamic
 lib_clippy_SOURCES = \
index 866090341e29071456631174e995424bbe5e82b4..3af89fad5aea740e24a6428937a6162c8c76e000 100644 (file)
@@ -124,11 +124,12 @@ static void cpu_record_hash_free(void *a)
 static void vty_out_cpu_thread_history(struct vty *vty,
                                       struct cpu_thread_history *a)
 {
-       vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu",
+       vty_out(vty, "%5zu %10zu.%03zu %9zu %8zu %9zu %8zu %9zu %9zu %9zu",
                a->total_active, a->cpu.total / 1000, a->cpu.total % 1000,
-               a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max,
-               (a->real.total / a->total_calls), a->real.max);
-       vty_out(vty, " %c%c%c%c%c  %s\n",
+               a->total_calls, (a->cpu.total / a->total_calls), a->cpu.max,
+               (a->real.total / a->total_calls), a->real.max,
+               a->total_cpu_warn, a->total_wall_warn);
+       vty_out(vty, "  %c%c%c%c%c  %s\n",
                a->types & (1 << THREAD_READ) ? 'R' : ' ',
                a->types & (1 << THREAD_WRITE) ? 'W' : ' ',
                a->types & (1 << THREAD_TIMER) ? 'T' : ' ',
@@ -149,6 +150,10 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
                atomic_load_explicit(&a->total_active, memory_order_seq_cst);
        copy.total_calls =
                atomic_load_explicit(&a->total_calls, memory_order_seq_cst);
+       copy.total_cpu_warn =
+               atomic_load_explicit(&a->total_cpu_warn, memory_order_seq_cst);
+       copy.total_wall_warn =
+               atomic_load_explicit(&a->total_wall_warn, memory_order_seq_cst);
        copy.cpu.total =
                atomic_load_explicit(&a->cpu.total, memory_order_seq_cst);
        copy.cpu.max = atomic_load_explicit(&a->cpu.max, memory_order_seq_cst);
@@ -165,6 +170,8 @@ static void cpu_record_hash_print(struct hash_bucket *bucket, void *args[])
        vty_out_cpu_thread_history(vty, &copy);
        totals->total_active += copy.total_active;
        totals->total_calls += copy.total_calls;
+       totals->total_cpu_warn += copy.total_cpu_warn;
+       totals->total_wall_warn += copy.total_wall_warn;
        totals->real.total += copy.real.total;
        if (totals->real.max < copy.real.max)
                totals->real.max = copy.real.max;
@@ -202,7 +209,7 @@ static void cpu_record_print(struct vty *vty, uint8_t filter)
                        vty_out(vty,
                                "Active   Runtime(ms)   Invoked Avg uSec Max uSecs");
                        vty_out(vty, " Avg uSec Max uSecs");
-                       vty_out(vty, "  Type  Thread\n");
+                       vty_out(vty, "  CPU_Warn Wall_Warn  Type   Thread\n");
 
                        if (m->cpu_record->count)
                                hash_iterate(
@@ -223,7 +230,7 @@ static void cpu_record_print(struct vty *vty, uint8_t filter)
        vty_out(vty, "%30s %18s %18s\n", "",
                "CPU (user+system):", "Real (wall-clock):");
        vty_out(vty, "Active   Runtime(ms)   Invoked Avg uSec Max uSecs");
-       vty_out(vty, " Avg uSec Max uSecs");
+       vty_out(vty, " Avg uSec Max uSecs  CPU_Warn Wall_Warn");
        vty_out(vty, "  Type  Thread\n");
 
        if (tmp.total_calls > 0)
@@ -300,13 +307,13 @@ static uint8_t parse_filter(const char *filterstr)
 }
 
 #ifndef EXCLUDE_CPU_TIME
-DEFUN (show_thread_cpu,
-       show_thread_cpu_cmd,
-       "show thread cpu [FILTER]",
-       SHOW_STR
-       "Thread information\n"
-       "Thread CPU usage\n"
-       "Display filter (rwtex)\n")
+DEFUN_NOSH (show_thread_cpu,
+           show_thread_cpu_cmd,
+           "show thread cpu [FILTER]",
+           SHOW_STR
+           "Thread information\n"
+           "Thread CPU usage\n"
+           "Display filter (rwtex)\n")
 {
        uint8_t filter = (uint8_t)-1U;
        int idx = 0;
@@ -367,12 +374,12 @@ static void show_thread_poll_helper(struct vty *vty, struct thread_master *m)
        }
 }
 
-DEFUN (show_thread_poll,
-       show_thread_poll_cmd,
-       "show thread poll",
-       SHOW_STR
-       "Thread information\n"
-       "Show poll FD's and information\n")
+DEFUN_NOSH (show_thread_poll,
+           show_thread_poll_cmd,
+           "show thread poll",
+           SHOW_STR
+           "Thread information\n"
+           "Show poll FD's and information\n")
 {
        struct listnode *node;
        struct thread_master *m;
@@ -657,7 +664,7 @@ static int time_hhmmss(char *buf, int buf_size, long sec)
        long mm;
        int wr;
 
-       zassert(buf_size >= 8);
+       assert(buf_size >= 8);
 
        hh = sec / 3600;
        sec %= 3600;
@@ -855,7 +862,10 @@ struct thread *_thread_add_read_write(const struct xref_threadsched *xref,
                         xref->funcname, xref->xref.file, xref->xref.line,
                         t_ptr, fd, 0, arg, 0);
 
-       assert(fd >= 0 && fd < m->fd_limit);
+       assert(fd >= 0);
+       if (fd >= m->fd_limit)
+               assert(!"Number of FD's open is greater than FRR currently configured to handle, aborting");
+
        frr_with_mutex(&m->mtx) {
                if (t_ptr && *t_ptr)
                        // thread is already scheduled; don't reschedule
@@ -1850,15 +1860,33 @@ void thread_call(struct thread *thread)
                                 memory_order_seq_cst);
 
 #ifdef CONSUMED_TIME_CHECK
-       if (realtime > CONSUMED_TIME_CHECK) {
+       if (cputime > CONSUMED_TIME_CHECK) {
                /*
-                * We have a CPU Hog on our hands.
+                * We have a CPU Hog on our hands.  The time FRR
+                * has spent doing actual work ( not sleeping )
+                * is greater than 5 seconds.
                 * Whinge about it now, so we're aware this is yet another task
                 * to fix.
                 */
+               atomic_fetch_add_explicit(&thread->hist->total_cpu_warn,
+                                         1, memory_order_seq_cst);
+               flog_warn(
+                       EC_LIB_SLOW_THREAD_CPU,
+                       "CPU HOG: task %s (%lx) ran for %lums (cpu time %lums)",
+                       thread->xref->funcname, (unsigned long)thread->func,
+                       realtime / 1000, cputime / 1000);
+       } else if (realtime > CONSUMED_TIME_CHECK) {
+               /*
+                * The runtime for a task is greater than 5 seconds, but
+                * the cpu time is under 5 seconds.  Let's whine
+                * about this because this could imply some sort of
+                * scheduling issue.
+                */
+               atomic_fetch_add_explicit(&thread->hist->total_wall_warn,
+                                         1, memory_order_seq_cst);
                flog_warn(
-                       EC_LIB_SLOW_THREAD,
-                       "SLOW THREAD: task %s (%lx) ran for %lums (cpu time %lums)",
+                       EC_LIB_SLOW_THREAD_WALL,
+                       "STARVATION: task %s (%lx) ran for %lums (cpu time %lums)",
                        thread->xref->funcname, (unsigned long)thread->func,
                        realtime / 1000, cputime / 1000);
        }
index af6833113100b15442234585f886a9650eeba2e0..fee728dbf9416478cdf857620d2edc480b38fb8f 100644 (file)
@@ -119,6 +119,8 @@ struct thread {
 
 struct cpu_thread_history {
        int (*func)(struct thread *);
+       atomic_size_t total_cpu_warn;
+       atomic_size_t total_wall_warn;
        atomic_size_t total_calls;
        atomic_size_t total_active;
        struct time_stats {
index 60e6d0901677f54a786ceec470759bdc0aa09b8c..cbed8d489375f989de6ed079bbfff10ce6a4d10b 100644 (file)
@@ -117,6 +117,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h)                     \
        typed_rb_remove(&h->rr, re);                                           \
        return container_of(re, type, field.re);                               \
 }                                                                              \
+TYPESAFE_SWAP_ALL_SIMPLE(prefix)                                               \
 macro_pure const type *prefix ## _const_first(const struct prefix##_head *h)   \
 {                                                                              \
        const struct typed_rb_entry *re;                                       \
index 27e7be1286a2d4684ae34fd7d9b34c04e3bcc986..ecac1a4381c9b86794db65fc1b93f94cffaa0fc9 100644 (file)
@@ -78,6 +78,19 @@ macro_inline type *prefix ## _find_gteq(struct prefix##_head *h,               \
 }                                                                              \
 /* ... */
 
+/* SWAP_ALL_SIMPLE = for containers where the items don't point back to the
+ * head *AND* the head doesn'T points to itself (= everything except LIST,
+ * DLIST and SKIPLIST), just switch out the entire head
+ */
+#define TYPESAFE_SWAP_ALL_SIMPLE(prefix)                                       \
+macro_inline void prefix ## _swap_all(struct prefix##_head *a,                 \
+                                     struct prefix##_head *b)                 \
+{                                                                              \
+       struct prefix##_head tmp = *a;                                         \
+       *a = *b;                                                               \
+       *b = tmp;                                                              \
+}                                                                              \
+/* ... */
 
 /* single-linked list, unsorted/arbitrary.
  * can be used as queue with add_tail / pop
@@ -169,6 +182,17 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h)                     \
                h->sh.last_next = &h->sh.first;                                \
        return container_of(sitem, type, field.si);                            \
 }                                                                              \
+macro_inline void prefix ## _swap_all(struct prefix##_head *a,                 \
+                                     struct prefix##_head *b)                 \
+{                                                                              \
+       struct prefix##_head tmp = *a;                                         \
+       *a = *b;                                                               \
+       *b = tmp;                                                              \
+       if (a->sh.last_next == &b->sh.first)                                   \
+               a->sh.last_next = &a->sh.first;                                \
+       if (b->sh.last_next == &a->sh.first)                                   \
+               b->sh.last_next = &b->sh.first;                                \
+}                                                                              \
 macro_pure const type *prefix ## _const_first(const struct prefix##_head *h)   \
 {                                                                              \
        return container_of_null(h->sh.first, type, field.si);                 \
@@ -215,6 +239,34 @@ static inline void typesafe_dlist_add(struct dlist_head *head,
        head->count++;
 }
 
+static inline void typesafe_dlist_swap_all(struct dlist_head *a,
+                                          struct dlist_head *b)
+{
+       struct dlist_head tmp = *a;
+
+       a->count = b->count;
+       if (a->count) {
+               a->hitem.next = b->hitem.next;
+               a->hitem.prev = b->hitem.prev;
+               a->hitem.next->prev = &a->hitem;
+               a->hitem.prev->next = &a->hitem;
+       } else {
+               a->hitem.next = &a->hitem;
+               a->hitem.prev = &a->hitem;
+       }
+
+       b->count = tmp.count;
+       if (b->count) {
+               b->hitem.next = tmp.hitem.next;
+               b->hitem.prev = tmp.hitem.prev;
+               b->hitem.next->prev = &b->hitem;
+               b->hitem.prev->next = &b->hitem;
+       } else {
+               b->hitem.next = &b->hitem;
+               b->hitem.prev = &b->hitem;
+       }
+}
+
 /* double-linked list, for fast item deletion
  */
 #define PREDECL_DLIST(prefix)                                                  \
@@ -271,6 +323,11 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h)                     \
        h->dh.count--;                                                         \
        return container_of(ditem, type, field.di);                            \
 }                                                                              \
+macro_inline void prefix ## _swap_all(struct prefix##_head *a,                 \
+                                     struct prefix##_head *b)                 \
+{                                                                              \
+       typesafe_dlist_swap_all(&a->dh, &b->dh);                               \
+}                                                                              \
 macro_pure const type *prefix ## _const_first(const struct prefix##_head *h)   \
 {                                                                              \
        const struct dlist_item *ditem = h->dh.hitem.next;                     \
@@ -380,6 +437,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h)                     \
                typesafe_heap_resize(&h->hh, false);                           \
        return container_of(hitem, type, field.hi);                            \
 }                                                                              \
+TYPESAFE_SWAP_ALL_SIMPLE(prefix)                                               \
 macro_pure const type *prefix ## _const_first(const struct prefix##_head *h)   \
 {                                                                              \
        if (h->hh.count == 0)                                                  \
@@ -518,6 +576,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h)                     \
        h->sh.first = sitem->next;                                             \
        return container_of(sitem, type, field.si);                            \
 }                                                                              \
+TYPESAFE_SWAP_ALL_SIMPLE(prefix)                                               \
 macro_pure const type *prefix ## _const_first(const struct prefix##_head *h)   \
 {                                                                              \
        return container_of_null(h->sh.first, type, field.si);                 \
@@ -708,6 +767,7 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h)                     \
                }                                                              \
        return NULL;                                                           \
 }                                                                              \
+TYPESAFE_SWAP_ALL_SIMPLE(prefix)                                               \
 macro_pure const type *prefix ## _const_first(const struct prefix##_head *h)   \
 {                                                                              \
        uint32_t i;                                                            \
@@ -824,6 +884,17 @@ macro_inline type *prefix ## _pop(struct prefix##_head *h)                     \
        struct sskip_item *sitem = typesafe_skiplist_pop(&h->sh);              \
        return container_of_null(sitem, type, field.si);                       \
 }                                                                              \
+macro_inline void prefix ## _swap_all(struct prefix##_head *a,                 \
+                                     struct prefix##_head *b)                 \
+{                                                                              \
+       struct prefix##_head tmp = *a;                                         \
+       *a = *b;                                                               \
+       *b = tmp;                                                              \
+       a->sh.hitem.next[SKIPLIST_OVERFLOW] = (struct sskip_item *)            \
+               ((uintptr_t)a->sh.overflow | 1);                               \
+       b->sh.hitem.next[SKIPLIST_OVERFLOW] = (struct sskip_item *)            \
+               ((uintptr_t)b->sh.overflow | 1);                               \
+}                                                                              \
 macro_pure const type *prefix ## _const_first(const struct prefix##_head *h)   \
 {                                                                              \
        const struct sskip_item *first = h->sh.hitem.next[0];                  \
index d535d131c812bbabef68886bf72ea7df00823bdd..5078f3ad6ef9ad90b8e736473ca587a468d59bb2 100644 (file)
@@ -25,7 +25,7 @@
 #define _ZEBRA_VERSION_H
 
 #ifdef GIT_VERSION
-#include "gitversion.h"
+#include "lib/gitversion.h"
 #endif
 
 #ifdef __cplusplus
index 96cfef1c0af46bb583e135ca206c8e346ad7672b..f92c912084e51bc3d9dc9f57daa2202c3344ba17 100644 (file)
--- a/lib/vty.c
+++ b/lib/vty.c
@@ -515,13 +515,19 @@ static int vty_command(struct vty *vty, char *buf)
 
 #ifdef CONSUMED_TIME_CHECK
                GETRUSAGE(&after);
-               if ((realtime = thread_consumed_time(&after, &before, &cputime))
-                   > CONSUMED_TIME_CHECK)
+               realtime = thread_consumed_time(&after, &before, &cputime);
+               if (cputime > CONSUMED_TIME_CHECK) {
                        /* Warn about CPU hog that must be fixed. */
                        flog_warn(
-                               EC_LIB_SLOW_THREAD,
-                               "SLOW COMMAND: command took %lums (cpu time %lums): %s",
+                               EC_LIB_SLOW_THREAD_CPU,
+                               "CPU HOG: command took %lums (cpu time %lums): %s",
                                realtime / 1000, cputime / 1000, buf);
+               } else if (realtime > CONSUMED_TIME_CHECK) {
+                       flog_warn(
+                               EC_LIB_SLOW_THREAD_WALL,
+                               "STARVATION: command took %lums (cpu time %lums): %s",
+                               realtime / 1000, cputime / 1000, buf);
+               }
        }
 #endif /* CONSUMED_TIME_CHECK */
 
index b1cb172b410d3e260a535a70ce9b03c43b7b0549..949458b313a334ef26d9e791a63aaec244a47871 100644 (file)
@@ -33,6 +33,7 @@ enum xref_type {
        XREFT_THREADSCHED = 0x100,
 
        XREFT_LOGMSG = 0x200,
+       XREFT_ASSERT = 0x280,
 
        XREFT_DEFUN = 0x300,
        XREFT_INSTALL_ELEMENT = 0x301,
@@ -137,6 +138,19 @@ extern void xref_gcc_workaround(const struct xref *xref);
 extern const struct xref * const __start_xref_array[1] DSO_LOCAL;
 extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
 
+#if defined(__has_feature)
+#if __has_feature(address_sanitizer)
+/* no redzone around each of the xref_p please, we're building an array out
+ * of variables here.  kinda breaks things if there's redzones between each
+ * array item.
+ */
+#define xref_array_attr used, section("xref_array"), no_sanitize("address")
+#endif
+#endif
+#ifndef xref_array_attr
+#define xref_array_attr used, section("xref_array")
+#endif
+
 /* this macro is invoked once for each standalone DSO through
  *   FRR_MODULE_SETUP  \
  *                      }-> FRR_COREMOD_SETUP -> XREF_SETUP
@@ -151,8 +165,7 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
                        /* .func = */ "dummy",                                 \
        };                                                                     \
        static const struct xref * const _dummy_xref_p                         \
-                       __attribute__((used, section("xref_array")))           \
-                       = &_dummy_xref;                                        \
+                       __attribute__((xref_array_attr)) = &_dummy_xref;       \
        static void __attribute__((used, _CONSTRUCTOR(1100)))                  \
                        _xref_init(void) {                                     \
                static struct xref_block _xref_block = {                       \
@@ -225,7 +238,7 @@ extern const struct xref * const __stop_xref_array[1] DSO_LOCAL;
 #if defined(__clang__) || !defined(__cplusplus)
 #define XREF_LINK(dst)                                                         \
        static const struct xref * const NAMECTR(xref_p_)                      \
-                       __attribute__((used, section("xref_array")))           \
+                       __attribute__((xref_array_attr))                       \
                = &(dst)                                                       \
        /* end */
 
diff --git a/lib/zassert.h b/lib/zassert.h
deleted file mode 100644 (file)
index 527282c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * This file is part of Quagga.
- *
- * Quagga 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, or (at your option) any
- * later version.
- *
- * Quagga 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
- */
-
-#ifndef _QUAGGA_ASSERT_H
-#define _QUAGGA_ASSERT_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-extern void _zlog_assert_failed(const char *assertion, const char *file,
-                               unsigned int line, const char *function)
-       __attribute__((noreturn));
-
-#undef __ASSERT_FUNCTION
-#define __ASSERT_FUNCTION    __func__
-
-#define zassert(EX)                                                            \
-       ((void)((EX) ? 0 : (_zlog_assert_failed(#EX, __FILE__, __LINE__,       \
-                                               __ASSERT_FUNCTION),            \
-                           0)))
-
-#undef assert
-#define assert(EX) zassert(EX)
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* _QUAGGA_ASSERT_H */
index d613906d829d1de5ff345cbaa3a87f3e44e5f135..3ea1789441b857d150578e657ee9c7cfd6ca0d1b 100644 (file)
@@ -587,7 +587,7 @@ zclient_send_router_id_update(struct zclient *zclient,
 enum zclient_send_status
 zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
                                struct interface *ifp, int enable,
-                               int ra_interval)
+                               uint32_t ra_interval)
 {
        struct stream *s;
 
@@ -3931,6 +3931,11 @@ static int zclient_read(struct thread *thread)
                        (*zclient->neighbor_get)(command, zclient, length,
                                                 vrf_id);
                break;
+       case ZEBRA_GRE_UPDATE:
+               if (zclient->gre_update)
+                       (*zclient->gre_update)(command, zclient,
+                                              length, vrf_id);
+               break;
        default:
                break;
        }
@@ -4252,3 +4257,23 @@ int zclient_neigh_ip_decode(struct stream *s, struct zapi_neigh_ip *api)
  stream_failure:
        return -1;
 }
+
+int zclient_send_zebra_gre_request(struct zclient *client,
+                                  struct interface *ifp)
+{
+       struct stream *s;
+
+       if (!client || client->sock < 0) {
+               zlog_err("%s : zclient not ready", __func__);
+               return -1;
+       }
+       s = client->obuf;
+       stream_reset(s);
+       zclient_create_header(s,
+                             ZEBRA_GRE_GET,
+                             ifp->vrf_id);
+       stream_putl(s, ifp->ifindex);
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zclient_send_message(client);
+       return 0;
+}
index 90240e40b2f78eccf305fb5184c7d1623633435e..8c279165425246212dc6c3996d8a47639372bd82 100644 (file)
@@ -232,6 +232,9 @@ typedef enum {
        ZEBRA_NEIGH_IP_ADD,
        ZEBRA_NEIGH_IP_DEL,
        ZEBRA_CONFIGURE_ARP,
+       ZEBRA_GRE_GET,
+       ZEBRA_GRE_UPDATE,
+       ZEBRA_GRE_SOURCE_SET,
 } zebra_message_types_t;
 
 enum zebra_error_types {
@@ -393,6 +396,7 @@ struct zclient {
        void (*neighbor_added)(ZAPI_CALLBACK_ARGS);
        void (*neighbor_removed)(ZAPI_CALLBACK_ARGS);
        void (*neighbor_get)(ZAPI_CALLBACK_ARGS);
+       void (*gre_update)(ZAPI_CALLBACK_ARGS);
 };
 
 /* Zebra API message flag. */
@@ -753,6 +757,29 @@ enum zclient_send_status {
        ZCLIENT_SEND_BUFFERED = 1
 };
 
+static inline const char *
+zapi_nhg_notify_owner2str(enum zapi_nhg_notify_owner note)
+{
+       const char *ret = "UNKNOWN";
+
+       switch (note) {
+       case ZAPI_NHG_FAIL_INSTALL:
+               ret = "ZAPI_NHG_FAIL_INSTALL";
+               break;
+       case ZAPI_NHG_INSTALLED:
+               ret = "ZAPI_NHG_INSTALLED";
+               break;
+       case ZAPI_NHG_REMOVE_FAIL:
+               ret = "ZAPI_NHG_REMOVE_FAIL";
+               break;
+       case ZAPI_NHG_REMOVED:
+               ret = "ZAPI_NHG_REMOVED";
+               break;
+       }
+
+       return ret;
+}
+
 static inline const char *
 zapi_rule_notify_owner2str(enum zapi_rule_notify_owner note)
 {
@@ -888,7 +915,7 @@ zclient_send_router_id_update(struct zclient *zclient,
 extern enum zclient_send_status
 zclient_send_interface_radv_req(struct zclient *zclient, vrf_id_t vrf_id,
                                struct interface *ifp, int enable,
-                               int ra_interval);
+                               uint32_t ra_interval);
 extern enum zclient_send_status
 zclient_send_interface_protodown(struct zclient *zclient, vrf_id_t vrf_id,
                                 struct interface *ifp, bool down);
@@ -1205,6 +1232,8 @@ struct zapi_client_close_info {
 extern int zapi_client_close_notify_decode(struct stream *s,
                                           struct zapi_client_close_info *info);
 
+extern int zclient_send_zebra_gre_request(struct zclient *client,
+                                         struct interface *ifp);
 #ifdef __cplusplus
 }
 #endif
index 5c3d91ba74bca34aefb5871f3863e4583294e19b..3b624117de769cbd45ae0c3a3e96389e30bc3485 100644 (file)
 #include <limits.h>
 #include <inttypes.h>
 #include <stdbool.h>
+#ifdef HAVE_SYS_ENDIAN_H
+#include <sys/endian.h>
+#endif
+#ifdef HAVE_ENDIAN_H
+#include <endian.h>
+#endif
 
 /* machine dependent includes */
 #ifdef HAVE_LINUX_VERSION_H
 #define __attribute__(x)
 #endif /* !__GNUC__ || VTYSH_EXTRACT_PL */
 
-#include "zassert.h"
+#include <assert.h>
 
 /*
  * Add explicit static cast only when using a C++ compiler.
@@ -280,22 +286,10 @@ struct in_pktinfo {
 #define HAVE_IP_HDRINCL_BSD_ORDER
 #endif
 
-/* Define BYTE_ORDER, if not defined. Useful for compiler conditional
- * code, rather than preprocessor conditional.
- * Not all the world has this BSD define.
- */
+/* autoconf macros for this are deprecated, just find endian.h */
 #ifndef BYTE_ORDER
-#define BIG_ENDIAN     4321    /* least-significant byte first (vax, pc) */
-#define LITTLE_ENDIAN  1234    /* most-significant byte first (IBM, net) */
-#define PDP_ENDIAN     3412    /* LSB first in word, MSW first in long (pdp) */
-
-#if defined(WORDS_BIGENDIAN)
-#define BYTE_ORDER     BIG_ENDIAN
-#else  /* !WORDS_BIGENDIAN */
-#define BYTE_ORDER     LITTLE_ENDIAN
-#endif /* WORDS_BIGENDIAN */
-
-#endif /* ndef BYTE_ORDER */
+#error please locate an endian.h file appropriate to your platform
+#endif
 
 /* For old definition. */
 #ifndef IN6_ARE_ADDR_EQUAL
@@ -312,7 +306,7 @@ struct in_pktinfo {
 #include "compiler.h"
 
 /* Zebra route's types are defined in route_types.h */
-#include "route_types.h"
+#include "lib/route_types.h"
 
 #define strmatch(a,b) (!strcmp((a), (b)))
 
index f54670932830b8f90202e1a7b06ae532051bc205..89ab9265d1c3bc2df0d370a8b51f97409fe4592c 100644 (file)
@@ -81,6 +81,11 @@ static gid_t zlog_gid = -1;
 DECLARE_ATOMLIST(zlog_targets, struct zlog_target, head);
 static struct zlog_targets_head zlog_targets;
 
+/* Global setting for buffered vs immediate output. The default is
+ * per-pthread buffering.
+ */
+static bool default_immediate;
+
 /* cf. zlog.h for additional comments on this struct.
  *
  * Note: you MUST NOT pass the format string + va_list to non-FRR format
@@ -142,6 +147,7 @@ struct zlog_msg {
 struct zlog_tls {
        char *mmbuf;
        size_t bufpos;
+       bool do_unlink;
 
        size_t nmsgs;
        struct zlog_msg msgs[TLS_LOG_MAXMSG];
@@ -266,13 +272,14 @@ void zlog_tls_buffer_init(void)
                         mmpath, strerror(errno));
                goto out_anon_unlink;
        }
+       zlog_tls->do_unlink = true;
 
        close(mmfd);
        zlog_tls_set(zlog_tls);
        return;
 
 out_anon_unlink:
-       unlink(mmpath);
+       unlinkat(zlog_tmpdirfd, mmpath, 0);
        close(mmfd);
 out_anon:
 
@@ -296,14 +303,16 @@ out_anon:
 void zlog_tls_buffer_fini(void)
 {
        char mmpath[MAXPATHLEN];
+       struct zlog_tls *zlog_tls = zlog_tls_get();
+       bool do_unlink = zlog_tls ? zlog_tls->do_unlink : false;
 
        zlog_tls_buffer_flush();
 
-       zlog_tls_free(zlog_tls_get());
+       zlog_tls_free(zlog_tls);
        zlog_tls_set(NULL);
 
        snprintfrr(mmpath, sizeof(mmpath), "logbuf.%ld", zlog_gettid());
-       if (unlinkat(zlog_tmpdirfd, mmpath, 0))
+       if (do_unlink && unlinkat(zlog_tmpdirfd, mmpath, 0))
                zlog_err("unlink logbuf: %s (%d)", strerror(errno), errno);
 }
 
@@ -391,7 +400,7 @@ static void vzlog_tls(struct zlog_tls *zlog_tls, const struct xref_logmsg *xref,
        struct zlog_msg *msg;
        char *buf;
        bool ignoremsg = true;
-       bool immediate = false;
+       bool immediate = default_immediate;
 
        /* avoid further processing cost if no target wants this message */
        rcu_read_lock();
@@ -517,6 +526,36 @@ void zlog_sigsafe(const char *text, size_t len)
        }
 }
 
+void _zlog_assert_failed(const struct xref_assert *xref, const char *extra, ...)
+{
+       va_list ap;
+       static bool assert_in_assert; /* "global-ish" variable, init to 0 */
+
+       if (assert_in_assert)
+               abort();
+       assert_in_assert = true;
+
+       if (extra) {
+               struct va_format vaf;
+
+               va_start(ap, extra);
+               vaf.fmt = extra;
+               vaf.va = &ap;
+
+               zlog(LOG_CRIT,
+                    "%s:%d: %s(): assertion (%s) failed, extra info: %pVA",
+                    xref->xref.file, xref->xref.line, xref->xref.func,
+                    xref->expr, &vaf);
+
+               va_end(ap);
+       } else
+               zlog(LOG_CRIT, "%s:%d: %s(): assertion (%s) failed",
+                    xref->xref.file, xref->xref.line, xref->xref.func,
+                    xref->expr);
+
+       /* abort() prints backtrace & memstats in SIGABRT handler */
+       abort();
+}
 
 int zlog_msg_prio(struct zlog_msg *msg)
 {
@@ -710,6 +749,14 @@ struct zlog_target *zlog_target_replace(struct zlog_target *oldzt,
        return oldzt;
 }
 
+/*
+ * Enable or disable 'immediate' output - default is to buffer
+ * each pthread's messages.
+ */
+void zlog_set_immediate(bool set_p)
+{
+       default_immediate = set_p;
+}
 
 /* common init */
 
index 66d8f1e5d73f2eb22e22a3f54aed125fd6efb91e..c421c16f38835dfe63a0b12a8bb3d06c146f82b4 100644 (file)
@@ -25,6 +25,8 @@
 #include <unistd.h>
 #include <sys/uio.h>
 
+#include <assert.h>
+
 #include "atomlist.h"
 #include "frrcu.h"
 #include "memory.h"
@@ -249,6 +251,9 @@ extern void zlog_tls_buffer_init(void);
 extern void zlog_tls_buffer_flush(void);
 extern void zlog_tls_buffer_fini(void);
 
+/* Enable or disable 'immediate' output - default is to buffer messages. */
+extern void zlog_set_immediate(bool set_p);
+
 #ifdef __cplusplus
 }
 #endif
index f258a8fbbddacf8b2eedb8c8b5bfbb83eca62f2d..7799fbfda75015d81a3309cf69525dcb52fd102a 100644 (file)
@@ -78,40 +78,48 @@ void zlog_fd(struct zlog_target *zt, struct zlog_msg *msgs[], size_t nmsgs)
                struct zlog_msg *msg = msgs[i];
                int prio = zlog_msg_prio(msg);
 
-               if (prio > zt->prio_min)
-                       continue;
-
-               iov[iovpos].iov_base = ts_pos;
-               if (iovpos > 0)
-                       *ts_pos++ = '\n';
-               ts_pos += zlog_msg_ts(msg, ts_pos, sizeof(ts_buf) - 1
-                                     - (ts_pos - ts_buf),
-                                     ZLOG_TS_LEGACY | zte->ts_subsec);
-               *ts_pos++ = ' ';
-               iov[iovpos].iov_len = ts_pos - (char *)iov[iovpos].iov_base;
+               if (prio <= zt->prio_min) {
+                       iov[iovpos].iov_base = ts_pos;
+                       if (iovpos > 0)
+                               *ts_pos++ = '\n';
+                       ts_pos += zlog_msg_ts(msg, ts_pos,
+                                             sizeof(ts_buf) - 1
+                                                     - (ts_pos - ts_buf),
+                                             ZLOG_TS_LEGACY | zte->ts_subsec);
+                       *ts_pos++ = ' ';
+                       iov[iovpos].iov_len =
+                               ts_pos - (char *)iov[iovpos].iov_base;
 
-               iovpos++;
+                       iovpos++;
 
-               if (zte->record_priority) {
-                       iov[iovpos].iov_base = (char *)prionames[prio];
-                       iov[iovpos].iov_len = strlen(iov[iovpos].iov_base);
+                       if (zte->record_priority) {
+                               iov[iovpos].iov_base = (char *)prionames[prio];
+                               iov[iovpos].iov_len =
+                                       strlen(iov[iovpos].iov_base);
 
-                       iovpos++;
-               }
+                               iovpos++;
+                       }
 
-               iov[iovpos].iov_base = zlog_prefix;
-               iov[iovpos].iov_len = zlog_prefixsz;
+                       iov[iovpos].iov_base = zlog_prefix;
+                       iov[iovpos].iov_len = zlog_prefixsz;
 
-               iovpos++;
+                       iovpos++;
 
-               iov[iovpos].iov_base = (char *)zlog_msg_text(msg, &textlen);
-               iov[iovpos].iov_len = textlen;
+                       iov[iovpos].iov_base =
+                               (char *)zlog_msg_text(msg, &textlen);
+                       iov[iovpos].iov_len = textlen;
 
-               iovpos++;
+                       iovpos++;
+               }
 
-               if (ts_buf + sizeof(ts_buf) - ts_pos < TS_LEN
-                   || i + 1 == nmsgs
-                   || array_size(iov) - iovpos < 5) {
+               /* conditions that trigger writing:
+                *  - out of space for more timestamps/headers
+                *  - this being the last message in the batch
+                *  - not enough remaining iov entries
+                */
+               if (iovpos > 0 && (ts_buf + sizeof(ts_buf) - ts_pos < TS_LEN
+                                  || i + 1 == nmsgs
+                                  || array_size(iov) - iovpos < 5)) {
                        iov[iovpos].iov_base = (char *)"\n";
                        iov[iovpos].iov_len = 1;
 
index cc778b9e99a1d3ce544508fba0663cd20e950ee0..d444101103259b6e198402df7b20d36928dadffe 100644 (file)
@@ -8,3 +8,5 @@
 !ax_sys_weak_alias.m4
 !ax_sys_weak_alias.m4
 !pkg.m4
+
+/ac
index 9feb352255bd9ac4879ca515dbde60097bd49d0f..dde24eaf89a94ee0bf047d8cc06a577961d2a686 100644 (file)
@@ -514,47 +514,24 @@ AC_DEFUN([AX_LUA_HEADERS],
     ])
 
   AS_IF([test "x$ac_cv_header_lua_h" = 'xyes'],
-    [ dnl Make a program to print LUA_VERSION defined in the header.
-      dnl TODO It would be really nice if we could do this without compiling a
-      dnl program, then it would work when cross compiling. But I'm not sure how
-      dnl to do this reliably. For now, assume versions match when cross compiling.
-
-      AS_IF([test "x$cross_compiling" != 'xyes'],
-        [ AC_CACHE_CHECK([for Lua header version],
-            [ax_cv_lua_header_version],
-            [ _ax_lua_saved_cppflags=$CPPFLAGS
-              CPPFLAGS="$CPPFLAGS $LUA_INCLUDE"
-              AC_RUN_IFELSE(
-                [ AC_LANG_SOURCE([[
-#include <lua.h>
-#include <stdlib.h>
-#include <stdio.h>
-int main(int argc, char ** argv)
-{
-  if(argc > 1) printf("%s", LUA_VERSION);
-  exit(EXIT_SUCCESS);
-}
-]])
-                ],
-                [ ax_cv_lua_header_version=`./conftest$EXEEXT p | \
+    [ AC_CACHE_CHECK([for Lua header version],
+        [ax_cv_lua_header_version],
+        [
+          ax_cv_lua_header_version=`echo LUA_VERSION | \
+            $CC -P -E $LUA_INCLUDE -imacros lua.h - | \
+                $SED -e 's%"\s*"%%g' -e 's%^\s*%%' | \
+                tr -d '"\n' | \
                     $SED -n "s|^Lua \(@<:@0-9@:>@\{1,\}\.@<:@0-9@:>@\{1,\}\).\{0,\}|\1|p"`
-                ],
-                [ax_cv_lua_header_version='unknown'])
-              CPPFLAGS=$_ax_lua_saved_cppflags
-            ])
-
-          dnl Compare this to the previously found LUA_VERSION.
-          AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
-          AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
-            [ AC_MSG_RESULT([yes])
-              ax_header_version_match='yes'
-            ],
-            [ AC_MSG_RESULT([no])
-              ax_header_version_match='no'
-            ])
-        ],
-        [ AC_MSG_WARN([cross compiling so assuming header version number matches])
+        ])
+
+      dnl Compare this to the previously found LUA_VERSION.
+      AC_MSG_CHECKING([if Lua header version matches $LUA_VERSION])
+      AS_IF([test "x$ax_cv_lua_header_version" = "x$LUA_VERSION"],
+        [ AC_MSG_RESULT([yes])
           ax_header_version_match='yes'
+        ],
+        [ AC_MSG_RESULT([no])
+          ax_header_version_match='no'
         ])
     ])
 
index 9cabdbf0652940ffb9731541aca6559478f15fa5..4986bfb99c647ea87e71fa082f753e6bc5f68786 100644 (file)
@@ -7,29 +7,17 @@
  * (at your option) any later version.
  */
 
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <string.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <asm/types.h>
-#include <arpa/inet.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/ip.h>
-#include <linux/if_arp.h>
-#include <linux/if_tunnel.h>
-#include <linux/limits.h>
+#include <errno.h>
+#include "zebra.h"
+#include <linux/if_packet.h>
 
 #include "nhrp_protocol.h"
 #include "os.h"
-#include "netlink.h"
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *__restrict dest,
+              const char *__restrict src, size_t destsize);
+#endif
 
 static int nhrp_socket_fd = -1;
 
@@ -42,7 +30,7 @@ int os_socket(void)
 }
 
 int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
-              size_t addrlen)
+              size_t addrlen, uint16_t protocol)
 {
        struct sockaddr_ll lladdr;
        struct iovec iov = {
@@ -54,23 +42,27 @@ int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
                .msg_iov = &iov,
                .msg_iovlen = 1,
        };
-       int status;
+       int status, fd;
 
        if (addrlen > sizeof(lladdr.sll_addr))
                return -1;
 
        memset(&lladdr, 0, sizeof(lladdr));
        lladdr.sll_family = AF_PACKET;
-       lladdr.sll_protocol = htons(ETH_P_NHRP);
+       lladdr.sll_protocol = htons(protocol);
        lladdr.sll_ifindex = ifindex;
        lladdr.sll_halen = addrlen;
        memcpy(lladdr.sll_addr, addr, addrlen);
 
-       status = sendmsg(nhrp_socket_fd, &msg, 0);
-       if (status < 0)
+       fd = os_socket();
+       if (fd < 0)
                return -1;
 
-       return 0;
+       status = sendmsg(fd, &msg, 0);
+       if (status < 0)
+               return -errno;
+
+       return status;
 }
 
 int os_recvmsg(uint8_t *buf, size_t *len, int *ifindex, uint8_t *addr,
@@ -111,7 +103,7 @@ static int linux_configure_arp(const char *iface, int on)
 {
        struct ifreq ifr;
 
-       strncpy(ifr.ifr_name, iface, IFNAMSIZ - 1);
+       strlcpy(ifr.ifr_name, iface, IFNAMSIZ);
        if (ioctl(nhrp_socket_fd, SIOCGIFFLAGS, &ifr))
                return -1;
 
index 74cb81daaa644a0bc5f82e8ea11f85ac4422fa97..f1143a2b5ebbddbb71d74dcebf299f1241b0ea4e 100644 (file)
@@ -7,20 +7,16 @@
  * (at your option) any later version.
  */
 
-#include <stdint.h>
+#include <zebra.h>
+#include <vrf.h>
+#include <if.h>
 
-union sockunion;
-struct interface;
 
 extern int netlink_nflog_group;
-extern int netlink_req_fd;
+extern int netlink_mcast_nflog_group;
 
-void netlink_init(void);
 int netlink_configure_arp(unsigned int ifindex, int pf);
 void netlink_update_binding(struct interface *ifp, union sockunion *proto,
                            union sockunion *nbma);
 void netlink_set_nflog_group(int nlgroup);
 
-void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key,
-                         unsigned int *link_index, struct in_addr *saddr);
-void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index);
index ecea0a9ec57bedcda1a7f3c30bbd6de27fe6648b..5fcb31188896fa63dec343e748d67b813c0b53fb 100644 (file)
@@ -25,7 +25,6 @@
 #include "netlink.h"
 #include "znl.h"
 
-int netlink_req_fd = -1;
 int netlink_nflog_group;
 static int netlink_log_fd = -1;
 static struct thread *netlink_log_thread;
@@ -203,10 +202,3 @@ void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS)
                nhrp_cache_set_used(c, state == ZEBRA_NEIGH_STATE_REACHABLE);
        }
 }
-
-void netlink_init(void)
-{
-       netlink_req_fd = znl_open(NETLINK_ROUTE, 0);
-       if (netlink_req_fd < 0)
-               return;
-}
diff --git a/nhrpd/netlink_gre.c b/nhrpd/netlink_gre.c
deleted file mode 100644 (file)
index 3fdfa9c..0000000
+++ /dev/null
@@ -1,152 +0,0 @@
-/* NHRP netlink/GRE tunnel configuration code
- * Copyright (c) 2014-2016 Timo Teräs
- *
- * This file is free software: you may copy, redistribute 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.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <sys/socket.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/in.h>
-#include <linux/if.h>
-#include <linux/ip.h>
-#include <linux/ipv6.h>
-#include <linux/if_tunnel.h>
-
-#include "debug.h"
-#include "netlink.h"
-#include "znl.h"
-
-static int __netlink_gre_get_data(struct zbuf *zb, struct zbuf *data,
-                                 int ifindex)
-{
-       struct nlmsghdr *n;
-       struct ifinfomsg *ifi;
-       struct zbuf payload, rtapayload;
-       struct rtattr *rta;
-
-       debugf(NHRP_DEBUG_KERNEL, "netlink-link-gre: get-info %u", ifindex);
-
-       n = znl_nlmsg_push(zb, RTM_GETLINK, NLM_F_REQUEST);
-       ifi = znl_push(zb, sizeof(*ifi));
-       *ifi = (struct ifinfomsg){
-               .ifi_index = ifindex,
-       };
-       znl_nlmsg_complete(zb, n);
-
-       if (zbuf_send(zb, netlink_req_fd) < 0
-           || zbuf_recv(zb, netlink_req_fd) < 0)
-               return -1;
-
-       n = znl_nlmsg_pull(zb, &payload);
-       if (!n)
-               return -1;
-
-       if (n->nlmsg_type != RTM_NEWLINK)
-               return -1;
-
-       ifi = znl_pull(&payload, sizeof(struct ifinfomsg));
-       if (!ifi)
-               return -1;
-
-       debugf(NHRP_DEBUG_KERNEL,
-              "netlink-link-gre: ifindex %u, receive msg_type %u, msg_flags %u",
-              ifi->ifi_index, n->nlmsg_type, n->nlmsg_flags);
-
-       if (ifi->ifi_index != ifindex)
-               return -1;
-
-       while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
-               if (rta->rta_type == IFLA_LINKINFO)
-                       break;
-       if (!rta)
-               return -1;
-
-       payload = rtapayload;
-       while ((rta = znl_rta_pull(&payload, &rtapayload)) != NULL)
-               if (rta->rta_type == IFLA_INFO_DATA)
-                       break;
-       if (!rta)
-               return -1;
-
-       *data = rtapayload;
-       return 0;
-}
-
-void netlink_gre_get_info(unsigned int ifindex, uint32_t *gre_key,
-                         unsigned int *link_index, struct in_addr *saddr)
-{
-       struct zbuf *zb = zbuf_alloc(8192), data, rtapl;
-       struct rtattr *rta;
-
-       *link_index = 0;
-       *gre_key = 0;
-       saddr->s_addr = 0;
-
-       if (__netlink_gre_get_data(zb, &data, ifindex) < 0)
-               goto err;
-
-       while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
-               switch (rta->rta_type) {
-               case IFLA_GRE_LINK:
-                       *link_index = zbuf_get32(&rtapl);
-                       break;
-               case IFLA_GRE_IKEY:
-               case IFLA_GRE_OKEY:
-                       *gre_key = zbuf_get32(&rtapl);
-                       break;
-               case IFLA_GRE_LOCAL:
-                       saddr->s_addr = zbuf_get32(&rtapl);
-                       break;
-               }
-       }
-err:
-       zbuf_free(zb);
-}
-
-void netlink_gre_set_link(unsigned int ifindex, unsigned int link_index)
-{
-       struct nlmsghdr *n;
-       struct ifinfomsg *ifi;
-       struct rtattr *rta_info, *rta_data, *rta;
-       struct zbuf *zr = zbuf_alloc(8192), data, rtapl;
-       struct zbuf *zb = zbuf_alloc(8192);
-       size_t len;
-
-       if (__netlink_gre_get_data(zr, &data, ifindex) < 0)
-               goto err;
-
-       n = znl_nlmsg_push(zb, RTM_NEWLINK, NLM_F_REQUEST);
-       ifi = znl_push(zb, sizeof(*ifi));
-       *ifi = (struct ifinfomsg){
-               .ifi_index = ifindex,
-       };
-       rta_info = znl_rta_nested_push(zb, IFLA_LINKINFO);
-       znl_rta_push(zb, IFLA_INFO_KIND, "gre", 3);
-       rta_data = znl_rta_nested_push(zb, IFLA_INFO_DATA);
-
-       znl_rta_push_u32(zb, IFLA_GRE_LINK, link_index);
-       while ((rta = znl_rta_pull(&data, &rtapl)) != NULL) {
-               if (rta->rta_type == IFLA_GRE_LINK)
-                       continue;
-               len = zbuf_used(&rtapl);
-               znl_rta_push(zb, rta->rta_type, zbuf_pulln(&rtapl, len), len);
-       }
-
-       znl_rta_nested_complete(zb, rta_data);
-       znl_rta_nested_complete(zb, rta_info);
-
-       znl_nlmsg_complete(zb, n);
-       zbuf_send(zb, netlink_req_fd);
-       zbuf_recv(zb, netlink_req_fd);
-err:
-       zbuf_free(zb);
-       zbuf_free(zr);
-}
index bcf0e2168c9275683ac14a4e3f3bc9fe11283213..c358baecb27c3fb1c7f51d5594bd7e1554960629 100644 (file)
@@ -72,7 +72,7 @@ static void nhrp_cache_free(struct nhrp_cache *c)
        debugf(NHRP_DEBUG_COMMON, "Deleting cache entry");
        nhrp_cache_counts[c->cur.type]--;
        notifier_call(&c->notifier_list, NOTIFY_CACHE_DELETE);
-       zassert(!notifier_active(&c->notifier_list));
+       assert(!notifier_active(&c->notifier_list));
        hash_release(nifp->cache_hash, c);
        THREAD_OFF(c->t_timeout);
        THREAD_OFF(c->t_auth);
index f6d89b141a2038857b555e783921c777a8ff57d4..2db8997bad4e918c639fcee2053c267c33a0dc0a 100644 (file)
 
 #include "nhrpd.h"
 #include "os.h"
-#include "netlink.h"
+#include "hash.h"
 
 DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF, "NHRP interface");
+DEFINE_MTYPE_STATIC(NHRPD, NHRP_IF_GRE, "NHRP GRE interface");
+
+struct hash *nhrp_gre_list;
 
 static void nhrp_interface_update_cache_config(struct interface *ifp,
                                               bool available,
                                               uint8_t family);
 
+static unsigned int nhrp_gre_info_key(const void *data)
+{
+       const struct nhrp_gre_info *r = data;
+
+       return r->ifindex;
+}
+
+static bool nhrp_gre_info_cmp(const void *data, const void *key)
+{
+       const struct nhrp_gre_info *a = data, *b = key;
+
+       if (a->ifindex == b->ifindex)
+               return true;
+       return false;
+}
+
+static void *nhrp_interface_gre_alloc(void *data)
+{
+       struct nhrp_gre_info *a;
+       struct nhrp_gre_info *b = data;
+
+       a = XMALLOC(MTYPE_NHRP_IF_GRE, sizeof(struct nhrp_gre_info));
+       memcpy(a, b, sizeof(struct nhrp_gre_info));
+       return a;
+}
+
+struct nhrp_gre_info *nhrp_gre_info_alloc(struct nhrp_gre_info *p)
+{
+       struct nhrp_gre_info *a;
+
+       a = (struct nhrp_gre_info *)hash_get(nhrp_gre_list, p,
+                                            nhrp_interface_gre_alloc);
+       return a;
+}
+
 static int nhrp_if_new_hook(struct interface *ifp)
 {
        struct nhrp_interface *nifp;
@@ -42,6 +80,7 @@ static int nhrp_if_new_hook(struct interface *ifp)
                struct nhrp_afi_data *ad = &nifp->afi[afi];
                ad->holdtime = NHRPD_DEFAULT_HOLDTIME;
                list_init(&ad->nhslist_head);
+               list_init(&ad->mcastlist_head);
        }
 
        return 0;
@@ -55,6 +94,7 @@ static int nhrp_if_delete_hook(struct interface *ifp)
 
        nhrp_cache_interface_del(ifp);
        nhrp_nhs_interface_del(ifp);
+       nhrp_multicast_interface_del(ifp);
        nhrp_peer_interface_del(ifp);
 
        if (nifp->ipsec_profile)
@@ -72,6 +112,9 @@ void nhrp_interface_init(void)
 {
        hook_register_prio(if_add, 0, nhrp_if_new_hook);
        hook_register_prio(if_del, 0, nhrp_if_delete_hook);
+
+       nhrp_gre_list = hash_create(nhrp_gre_info_key, nhrp_gre_info_cmp,
+                                   "NHRP GRE list Hash");
 }
 
 void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi)
@@ -100,14 +143,16 @@ static void nhrp_interface_update_source(struct interface *ifp)
 {
        struct nhrp_interface *nifp = ifp->info;
 
-       if (!nifp->source || !nifp->nbmaifp
-           || (ifindex_t)nifp->linkidx == nifp->nbmaifp->ifindex)
+       if (!nifp->source || !nifp->nbmaifp ||
+           ((ifindex_t)nifp->link_idx == nifp->nbmaifp->ifindex &&
+            (nifp->link_vrf_id == nifp->nbmaifp->vrf_id)))
                return;
 
-       nifp->linkidx = nifp->nbmaifp->ifindex;
-       debugf(NHRP_DEBUG_IF, "%s: bound device index changed to %d", ifp->name,
-              nifp->linkidx);
-       netlink_gre_set_link(ifp->ifindex, nifp->linkidx);
+       nifp->link_idx = nifp->nbmaifp->ifindex;
+       nifp->link_vrf_id = nifp->nbmaifp->vrf_id;
+       debugf(NHRP_DEBUG_IF, "%s: bound device index changed to %d, vr %u",
+              ifp->name, nifp->link_idx, nifp->link_vrf_id);
+       nhrp_send_zebra_gre_source_set(ifp, nifp->link_idx, nifp->link_vrf_id);
 }
 
 static void nhrp_interface_interface_notifier(struct notifier_block *n,
@@ -134,7 +179,8 @@ static void nhrp_interface_interface_notifier(struct notifier_block *n,
        }
 }
 
-static void nhrp_interface_update_nbma(struct interface *ifp)
+void nhrp_interface_update_nbma(struct interface *ifp,
+                               struct nhrp_gre_info *gre_info)
 {
        struct nhrp_interface *nifp = ifp->info, *nbmanifp = NULL;
        struct interface *nbmaifp = NULL;
@@ -143,21 +189,32 @@ static void nhrp_interface_update_nbma(struct interface *ifp)
        sockunion_family(&nbma) = AF_UNSPEC;
 
        if (nifp->source)
-               nbmaifp = if_lookup_by_name(nifp->source, VRF_DEFAULT);
+               nbmaifp = if_lookup_by_name(nifp->source, nifp->link_vrf_id);
 
        switch (ifp->ll_type) {
        case ZEBRA_LLT_IPGRE: {
                struct in_addr saddr = {0};
-               netlink_gre_get_info(ifp->ifindex, &nifp->grekey,
-                                    &nifp->linkidx, &saddr);
+
+               if (!gre_info) {
+                       nhrp_send_zebra_gre_request(ifp);
+                       return;
+               }
+               nifp->i_grekey = gre_info->ikey;
+               nifp->o_grekey = gre_info->okey;
+               nifp->link_idx = gre_info->ifindex_link;
+               nifp->link_vrf_id = gre_info->vrfid_link;
+               saddr.s_addr = gre_info->vtep_ip.s_addr;
+
                debugf(NHRP_DEBUG_IF, "%s: GRE: %x %x %x", ifp->name,
-                      nifp->grekey, nifp->linkidx, saddr.s_addr);
-               if (saddr.s_addr != INADDR_ANY)
-                       sockunion_set(&nbma, AF_INET, (uint8_t *)&saddr.s_addr,
+                      nifp->i_grekey, nifp->link_idx, saddr.s_addr);
+               if (saddr.s_addr)
+                       sockunion_set(&nbma, AF_INET,
+                                     (uint8_t *)&saddr.s_addr,
                                      sizeof(saddr.s_addr));
-               else if (!nbmaifp && nifp->linkidx != IFINDEX_INTERNAL)
+               else if (!nbmaifp && nifp->link_idx != IFINDEX_INTERNAL)
                        nbmaifp =
-                               if_lookup_by_index(nifp->linkidx, VRF_DEFAULT);
+                               if_lookup_by_index(nifp->link_idx,
+                                                  nifp->link_vrf_id);
        } break;
        default:
                break;
@@ -320,7 +377,7 @@ int nhrp_ifp_create(struct interface *ifp)
               ifp->name, ifp->ifindex, ifp->ll_type,
               if_link_type_str(ifp->ll_type));
 
-       nhrp_interface_update_nbma(ifp);
+       nhrp_interface_update_nbma(ifp, NULL);
 
        return 0;
 }
@@ -400,7 +457,7 @@ static void nhrp_interface_update_cache_config(struct interface *ifp, bool avail
 int nhrp_ifp_up(struct interface *ifp)
 {
        debugf(NHRP_DEBUG_IF, "if-up: %s", ifp->name);
-       nhrp_interface_update_nbma(ifp);
+       nhrp_interface_update_nbma(ifp, NULL);
 
        return 0;
 }
@@ -491,5 +548,5 @@ void nhrp_interface_set_source(struct interface *ifp, const char *ifname)
                free(nifp->source);
        nifp->source = ifname ? strdup(ifname) : NULL;
 
-       nhrp_interface_update_nbma(ifp);
+       nhrp_interface_update_nbma(ifp, NULL);
 }
index 5c819017f499911ee2edd247ae17b6ece80ccbd5..c2111a7706ff2cf61804bf33144c9b821d843ad9 100644 (file)
@@ -18,7 +18,7 @@
 #include "getopt.h"
 #include "thread.h"
 #include "sigevent.h"
-#include "version.h"
+#include "lib/version.h"
 #include "log.h"
 #include "memory.h"
 #include "command.h"
@@ -26,7 +26,6 @@
 #include "filter.h"
 
 #include "nhrpd.h"
-#include "netlink.h"
 #include "nhrp_errors.h"
 
 DEFINE_MGROUP(NHRPD, "NHRP");
@@ -154,7 +153,6 @@ int main(int argc, char **argv)
        assert(nhrpd_privs.change);
        nhrpd_privs.change(ZPRIVS_RAISE);
 
-       netlink_init();
        evmgr_init();
        nhrp_vc_init();
        nhrp_packet_init();
diff --git a/nhrpd/nhrp_multicast.c b/nhrpd/nhrp_multicast.c
new file mode 100644 (file)
index 0000000..b78afda
--- /dev/null
@@ -0,0 +1,305 @@
+/* NHRP Multicast Support
+ * Copyright (c) 2020-2021 4RF Limited
+ *
+ * This file is free software: you may copy, redistribute 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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <net/if.h>
+#include <net/ethernet.h>
+#include <netinet/if_ether.h>
+#include <linux/netlink.h>
+#include <linux/neighbour.h>
+#include <linux/netfilter/nfnetlink_log.h>
+#include <linux/if_packet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include "thread.h"
+#include "nhrpd.h"
+#include "netlink.h"
+#include "znl.h"
+#include "os.h"
+
+DEFINE_MTYPE_STATIC(NHRPD, NHRP_MULTICAST, "NHRP Multicast");
+
+int netlink_mcast_nflog_group;
+static int netlink_mcast_log_fd = -1;
+static struct thread *netlink_mcast_log_thread;
+
+struct mcast_ctx {
+       struct interface *ifp;
+       struct zbuf *pkt;
+};
+
+static void nhrp_multicast_send(struct nhrp_peer *p, struct zbuf *zb)
+{
+       size_t addrlen;
+       int ret;
+
+       addrlen = sockunion_get_addrlen(&p->vc->remote.nbma);
+       ret = os_sendmsg(zb->head, zbuf_used(zb), p->ifp->ifindex,
+                        sockunion_get_addr(&p->vc->remote.nbma), addrlen,
+                        addrlen == 4 ? ETH_P_IP : ETH_P_IPV6);
+
+       debugf(NHRP_DEBUG_COMMON,
+              "Multicast Packet: %pSU -> %pSU, ret = %d, size = %zu, addrlen = %zu",
+              &p->vc->local.nbma, &p->vc->remote.nbma, ret, zbuf_used(zb),
+              addrlen);
+}
+
+static void nhrp_multicast_forward_nbma(union sockunion *nbma_addr,
+                                       struct interface *ifp, struct zbuf *pkt)
+{
+       struct nhrp_peer *p = nhrp_peer_get(ifp, nbma_addr);
+
+       if (p && p->online) {
+               /* Send packet */
+               nhrp_multicast_send(p, pkt);
+       }
+       nhrp_peer_unref(p);
+}
+
+static void nhrp_multicast_forward_cache(struct nhrp_cache *c, void *pctx)
+{
+       struct mcast_ctx *ctx = (struct mcast_ctx *)pctx;
+
+       if (c->cur.type == NHRP_CACHE_DYNAMIC && c->cur.peer)
+               nhrp_multicast_forward_nbma(&c->cur.peer->vc->remote.nbma,
+                                           ctx->ifp, ctx->pkt);
+}
+
+static void nhrp_multicast_forward(struct nhrp_multicast *mcast, void *pctx)
+{
+       struct mcast_ctx *ctx = (struct mcast_ctx *)pctx;
+       struct nhrp_interface *nifp = ctx->ifp->info;
+
+       if (!nifp->enabled)
+               return;
+
+       /* dynamic */
+       if (sockunion_family(&mcast->nbma_addr) == AF_UNSPEC) {
+               nhrp_cache_foreach(ctx->ifp, nhrp_multicast_forward_cache,
+                                  pctx);
+               return;
+       }
+
+       /* Fixed IP Address */
+       nhrp_multicast_forward_nbma(&mcast->nbma_addr, ctx->ifp, ctx->pkt);
+}
+
+static void netlink_mcast_log_handler(struct nlmsghdr *msg, struct zbuf *zb)
+{
+       struct nfgenmsg *nf;
+       struct rtattr *rta;
+       struct zbuf rtapl;
+       uint32_t *out_ndx = NULL;
+       afi_t afi;
+       struct mcast_ctx ctx;
+
+       nf = znl_pull(zb, sizeof(*nf));
+       if (!nf)
+               return;
+
+       ctx.pkt = NULL;
+       while ((rta = znl_rta_pull(zb, &rtapl)) != NULL) {
+               switch (rta->rta_type) {
+               case NFULA_IFINDEX_OUTDEV:
+                       out_ndx = znl_pull(&rtapl, sizeof(*out_ndx));
+                       break;
+               case NFULA_PAYLOAD:
+                       ctx.pkt = &rtapl;
+                       break;
+                       /* NFULA_HWHDR exists and is supposed to contain source
+                        * hardware address. However, for ip_gre it seems to be
+                        * the nexthop destination address if the packet matches
+                        * route.
+                        */
+               }
+       }
+
+       if (!out_ndx || !ctx.pkt)
+               return;
+
+       ctx.ifp = if_lookup_by_index(htonl(*out_ndx), VRF_DEFAULT);
+       if (!ctx.ifp)
+               return;
+
+       debugf(NHRP_DEBUG_COMMON,
+              "Intercepted multicast packet leaving %s len %zu",
+              ctx.ifp->name, zbuf_used(ctx.pkt));
+
+       for (afi = 0; afi < AFI_MAX; afi++) {
+               nhrp_multicast_foreach(ctx.ifp, afi, nhrp_multicast_forward,
+                                      (void *)&ctx);
+       }
+}
+
+static int netlink_mcast_log_recv(struct thread *t)
+{
+       uint8_t buf[65535]; /* Max OSPF Packet size */
+       int fd = THREAD_FD(t);
+       struct zbuf payload, zb;
+       struct nlmsghdr *n;
+
+       netlink_mcast_log_thread = NULL;
+
+       zbuf_init(&zb, buf, sizeof(buf), 0);
+       while (zbuf_recv(&zb, fd) > 0) {
+               while ((n = znl_nlmsg_pull(&zb, &payload)) != NULL) {
+                       debugf(NHRP_DEBUG_COMMON,
+                              "Netlink-mcast-log: Received msg_type %u, msg_flags %u",
+                              n->nlmsg_type, n->nlmsg_flags);
+                       switch (n->nlmsg_type) {
+                       case (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_PACKET:
+                               netlink_mcast_log_handler(n, &payload);
+                               break;
+                       }
+               }
+       }
+
+       thread_add_read(master, netlink_mcast_log_recv, 0, netlink_mcast_log_fd,
+                       &netlink_mcast_log_thread);
+
+       return 0;
+}
+
+static void netlink_mcast_log_register(int fd, int group)
+{
+       struct nlmsghdr *n;
+       struct nfgenmsg *nf;
+       struct nfulnl_msg_config_cmd cmd;
+       struct zbuf *zb = zbuf_alloc(512);
+
+       n = znl_nlmsg_push(zb, (NFNL_SUBSYS_ULOG << 8) | NFULNL_MSG_CONFIG,
+                          NLM_F_REQUEST | NLM_F_ACK);
+       nf = znl_push(zb, sizeof(*nf));
+       *nf = (struct nfgenmsg){
+               .nfgen_family = AF_UNSPEC,
+               .version = NFNETLINK_V0,
+               .res_id = htons(group),
+       };
+       cmd.command = NFULNL_CFG_CMD_BIND;
+       znl_rta_push(zb, NFULA_CFG_CMD, &cmd, sizeof(cmd));
+       znl_nlmsg_complete(zb, n);
+
+       zbuf_send(zb, fd);
+       zbuf_free(zb);
+}
+
+void netlink_mcast_set_nflog_group(int nlgroup)
+{
+       if (netlink_mcast_log_fd >= 0) {
+               THREAD_OFF(netlink_mcast_log_thread);
+               close(netlink_mcast_log_fd);
+               netlink_mcast_log_fd = -1;
+               debugf(NHRP_DEBUG_COMMON, "De-register nflog group");
+       }
+       netlink_mcast_nflog_group = nlgroup;
+       if (nlgroup) {
+               netlink_mcast_log_fd = znl_open(NETLINK_NETFILTER, 0);
+               if (netlink_mcast_log_fd < 0)
+                       return;
+
+               netlink_mcast_log_register(netlink_mcast_log_fd, nlgroup);
+               thread_add_read(master, netlink_mcast_log_recv, 0,
+                               netlink_mcast_log_fd,
+                               &netlink_mcast_log_thread);
+               debugf(NHRP_DEBUG_COMMON, "Register nflog group: %d",
+                      netlink_mcast_nflog_group);
+       }
+}
+
+static int nhrp_multicast_free(struct interface *ifp,
+                              struct nhrp_multicast *mcast)
+{
+       list_del(&mcast->list_entry);
+       XFREE(MTYPE_NHRP_MULTICAST, mcast);
+       return 0;
+}
+
+int nhrp_multicast_add(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast;
+
+       list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
+       {
+               if (sockunion_same(&mcast->nbma_addr, nbma_addr))
+                       return NHRP_ERR_ENTRY_EXISTS;
+       }
+
+       mcast = XMALLOC(MTYPE_NHRP_MULTICAST, sizeof(struct nhrp_multicast));
+
+       *mcast = (struct nhrp_multicast){
+               .afi = afi, .ifp = ifp, .nbma_addr = *nbma_addr,
+       };
+       list_add_tail(&mcast->list_entry, &nifp->afi[afi].mcastlist_head);
+
+       debugf(NHRP_DEBUG_COMMON, "Adding multicast entry (%pSU)", nbma_addr);
+
+       return NHRP_OK;
+}
+
+int nhrp_multicast_del(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast, *tmp;
+
+       list_for_each_entry_safe(mcast, tmp, &nifp->afi[afi].mcastlist_head,
+                                list_entry)
+       {
+               if (!sockunion_same(&mcast->nbma_addr, nbma_addr))
+                       continue;
+
+               debugf(NHRP_DEBUG_COMMON, "Deleting multicast entry (%pSU)",
+                      nbma_addr);
+
+               nhrp_multicast_free(ifp, mcast);
+
+               return NHRP_OK;
+       }
+
+       return NHRP_ERR_ENTRY_NOT_FOUND;
+}
+
+void nhrp_multicast_interface_del(struct interface *ifp)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast, *tmp;
+       afi_t afi;
+
+       for (afi = 0; afi < AFI_MAX; afi++) {
+               debugf(NHRP_DEBUG_COMMON,
+                      "Cleaning up multicast entries (%d)",
+                      !list_empty(&nifp->afi[afi].mcastlist_head));
+
+               list_for_each_entry_safe(
+                       mcast, tmp, &nifp->afi[afi].mcastlist_head, list_entry)
+               {
+                       nhrp_multicast_free(ifp, mcast);
+               }
+       }
+}
+
+void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
+                           void (*cb)(struct nhrp_multicast *, void *),
+                           void *ctx)
+{
+       struct nhrp_interface *nifp = ifp->info;
+       struct nhrp_multicast *mcast;
+
+       list_for_each_entry(mcast, &nifp->afi[afi].mcastlist_head, list_entry)
+       {
+               cb(mcast, ctx);
+       }
+}
index a44190d29253bfedf33c758231cb19b1183e18f4..5a7da703acc7c629fe37621c35ae56bb8401794c 100644 (file)
@@ -376,7 +376,7 @@ void nhrp_peer_send(struct nhrp_peer *p, struct zbuf *zb)
 
        os_sendmsg(zb->head, zbuf_used(zb), p->ifp->ifindex,
                   sockunion_get_addr(&p->vc->remote.nbma),
-                  sockunion_get_addrlen(&p->vc->remote.nbma));
+                  sockunion_get_addrlen(&p->vc->remote.nbma), ETH_P_NHRP);
        zbuf_reset(zb);
 }
 
index 23fa0771eff84f6b553f810236a237933b86214d..ee8db277d9a9a69b24966831af3b53ebf6da5605 100644 (file)
@@ -380,6 +380,7 @@ void nhrp_zebra_init(void)
        zclient->neighbor_added = nhrp_neighbor_operation;
        zclient->neighbor_removed = nhrp_neighbor_operation;
        zclient->neighbor_get = nhrp_neighbor_operation;
+       zclient->gre_update = nhrp_gre_update;
        zclient_init(zclient, ZEBRA_ROUTE_NHRP, 0, &nhrpd_privs);
 }
 
@@ -412,6 +413,33 @@ void nhrp_send_zebra_configure_arp(struct interface *ifp, int family)
        zclient_send_message(zclient);
 }
 
+void nhrp_send_zebra_gre_source_set(struct interface *ifp,
+                                   unsigned int link_idx,
+                                   vrf_id_t link_vrf_id)
+{
+       struct stream *s;
+
+       if (!zclient || zclient->sock < 0) {
+               zlog_err("%s : zclient not ready", __func__);
+               return;
+       }
+       if (link_idx == IFINDEX_INTERNAL || link_vrf_id == VRF_UNKNOWN) {
+               /* silently ignore */
+               return;
+       }
+       s = zclient->obuf;
+       stream_reset(s);
+       zclient_create_header(s,
+                             ZEBRA_GRE_SOURCE_SET,
+                             ifp->vrf_id);
+       stream_putl(s, ifp->ifindex);
+       stream_putl(s, link_idx);
+       stream_putl(s, link_vrf_id);
+       stream_putl(s, 0); /* mtu provisioning */
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zclient_send_message(zclient);
+}
+
 void nhrp_send_zebra_nbr(union sockunion *in,
                         union sockunion *out,
                         struct interface *ifp)
@@ -429,6 +457,11 @@ void nhrp_send_zebra_nbr(union sockunion *in,
        zclient_send_message(zclient);
 }
 
+int nhrp_send_zebra_gre_request(struct interface *ifp)
+{
+       return zclient_send_zebra_gre_request(zclient, ifp);
+}
+
 void nhrp_zebra_terminate(void)
 {
        nhrp_zebra_register_neigh(VRF_DEFAULT, AFI_IP, false);
@@ -441,3 +474,48 @@ void nhrp_zebra_terminate(void)
        route_table_finish(zebra_rib[AFI_IP]);
        route_table_finish(zebra_rib[AFI_IP6]);
 }
+
+void nhrp_gre_update(ZAPI_CALLBACK_ARGS)
+{
+       struct stream *s;
+       struct nhrp_gre_info gre_info, *val;
+       struct interface *ifp;
+
+       /* result */
+       s = zclient->ibuf;
+       if (vrf_id != VRF_DEFAULT)
+               return;
+
+       /* read GRE information */
+       STREAM_GETL(s, gre_info.ifindex);
+       STREAM_GETL(s, gre_info.ikey);
+       STREAM_GETL(s, gre_info.okey);
+       STREAM_GETL(s, gre_info.ifindex_link);
+       STREAM_GETL(s, gre_info.vrfid_link);
+       STREAM_GETL(s, gre_info.vtep_ip.s_addr);
+       STREAM_GETL(s, gre_info.vtep_ip_remote.s_addr);
+       if (gre_info.ifindex == IFINDEX_INTERNAL)
+               val = NULL;
+       else
+               val = hash_lookup(nhrp_gre_list, &gre_info);
+       if (val) {
+               if (gre_info.vtep_ip.s_addr != val->vtep_ip.s_addr ||
+                   gre_info.vrfid_link != val->vrfid_link ||
+                   gre_info.ifindex_link != val->ifindex_link ||
+                   gre_info.ikey != val->ikey ||
+                   gre_info.okey != val->okey) {
+                       /* update */
+                       memcpy(val, &gre_info, sizeof(struct nhrp_gre_info));
+               }
+       } else {
+               val = nhrp_gre_info_alloc(&gre_info);
+       }
+       ifp = if_lookup_by_index(gre_info.ifindex, vrf_id);
+       debugf(NHRP_DEBUG_EVENT, "%s: gre interface %d vr %d obtained from system",
+              ifp ? ifp->name : "<none>", gre_info.ifindex, vrf_id);
+       if (ifp)
+               nhrp_interface_update_nbma(ifp, val);
+       return;
+stream_failure:
+       zlog_err("%s(): error reading response ..", __func__);
+}
index 4358605e2b03b14511ec00a34d140ec109e84a90..420ea12ec1e23c9771370a11aaee54af9d216ed0 100644 (file)
@@ -187,6 +187,9 @@ static int nhrp_config_write(struct vty *vty)
        if (netlink_nflog_group) {
                vty_out(vty, "nhrp nflog-group %d\n", netlink_nflog_group);
        }
+       if (netlink_mcast_nflog_group)
+               vty_out(vty, "nhrp multicast-nflog-group %d\n",
+                       netlink_mcast_nflog_group);
 
        return 0;
 }
@@ -257,6 +260,31 @@ DEFUN(no_nhrp_nflog_group, no_nhrp_nflog_group_cmd,
        return CMD_SUCCESS;
 }
 
+DEFUN(nhrp_multicast_nflog_group, nhrp_multicast_nflog_group_cmd,
+       "nhrp multicast-nflog-group (1-65535)",
+       NHRP_STR
+       "Specify NFLOG group number for Multicast Packets\n"
+       "NFLOG group number\n")
+{
+       uint32_t nfgroup;
+
+       nfgroup = strtoul(argv[2]->arg, NULL, 10);
+       netlink_mcast_set_nflog_group(nfgroup);
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(no_nhrp_multicast_nflog_group, no_nhrp_multicast_nflog_group_cmd,
+       "no nhrp multicast-nflog-group [(1-65535)]",
+       NO_STR
+       NHRP_STR
+       "Specify NFLOG group number\n"
+       "NFLOG group number\n")
+{
+       netlink_mcast_set_nflog_group(0);
+       return CMD_SUCCESS;
+}
+
 DEFUN(tunnel_protection, tunnel_protection_cmd,
        "tunnel protection vici profile PROFILE [fallback-profile FALLBACK]",
        "NHRP/GRE integration\n"
@@ -570,6 +598,53 @@ DEFUN(if_no_nhrp_map, if_no_nhrp_map_cmd,
        return CMD_SUCCESS;
 }
 
+DEFUN(if_nhrp_map_multicast, if_nhrp_map_multicast_cmd,
+       AFI_CMD " nhrp map multicast <A.B.C.D|X:X::X:X|dynamic>",
+       AFI_STR
+       NHRP_STR
+       "Multicast NBMA Configuration\n"
+       "Use this NBMA mapping for multicasts\n"
+       "IPv4 NBMA address\n"
+       "IPv6 NBMA address\n"
+       "Dynamically learn destinations from client registrations on hub\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       afi_t afi = cmd_to_afi(argv[0]);
+       union sockunion nbma_addr;
+       int ret;
+
+       if (str2sockunion(argv[4]->arg, &nbma_addr) < 0)
+               sockunion_family(&nbma_addr) = AF_UNSPEC;
+
+       ret = nhrp_multicast_add(ifp, afi, &nbma_addr);
+
+       return nhrp_vty_return(vty, ret);
+}
+
+DEFUN(if_no_nhrp_map_multicast, if_no_nhrp_map_multicast_cmd,
+       "no " AFI_CMD " nhrp map multicast <A.B.C.D|X:X::X:X|dynamic>",
+       NO_STR
+       AFI_STR
+       NHRP_STR
+       "Multicast NBMA Configuration\n"
+       "Use this NBMA mapping for multicasts\n"
+       "IPv4 NBMA address\n"
+       "IPv6 NBMA address\n"
+       "Dynamically learn destinations from client registrations on hub\n")
+{
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       afi_t afi = cmd_to_afi(argv[1]);
+       union sockunion nbma_addr;
+       int ret;
+
+       if (str2sockunion(argv[5]->arg, &nbma_addr) < 0)
+               sockunion_family(&nbma_addr) = AF_UNSPEC;
+
+       ret = nhrp_multicast_del(ifp, afi, &nbma_addr);
+
+       return nhrp_vty_return(vty, ret);
+}
+
 DEFUN(if_nhrp_nhs, if_nhrp_nhs_cmd,
        AFI_CMD " nhrp nhs <A.B.C.D|X:X::X:X|dynamic> nbma <A.B.C.D|FQDN>",
        AFI_STR
@@ -732,8 +807,8 @@ static void show_ip_nhrp_nhs(struct nhrp_nhs *n, struct nhrp_registration *reg,
        ctx->count++;
 
        if (reg && reg->peer)
-               sockunion2str(&reg->peer->vc->remote.nbma,
-                             buf[0], sizeof(buf[0]));
+               sockunion2str(&reg->peer->vc->remote.nbma, buf[0],
+                             sizeof(buf[0]));
        else
                snprintf(buf[0], sizeof(buf[0]), "-");
        sockunion2str(reg ? &reg->proto_addr : &n->proto_addr, buf[1],
@@ -1047,19 +1122,20 @@ struct write_map_ctx {
        const char *aficmd;
 };
 
-static void interface_config_write_nhrp_map(struct nhrp_cache_config *c, void *data)
+static void interface_config_write_nhrp_map(struct nhrp_cache_config *c,
+                                           void *data)
 {
        struct write_map_ctx *ctx = data;
        struct vty *vty = ctx->vty;
-       char buf[2][SU_ADDRSTRLEN];
 
        if (sockunion_family(&c->remote_addr) != ctx->family)
                return;
 
-       vty_out(vty, " %s nhrp map %s %s\n", ctx->aficmd,
-               sockunion2str(&c->remote_addr, buf[0], sizeof(buf[0])),
-               c->type == NHRP_CACHE_LOCAL
-               ? "local" : sockunion2str(&c->nbma, buf[1], sizeof(buf[1])));
+       vty_out(vty, " %s nhrp map %pSU ", ctx->aficmd, &c->remote_addr);
+       if (c->type == NHRP_CACHE_LOCAL)
+               vty_out(vty, "local\n");
+       else
+               vty_out(vty, "%pSU\n", &c->nbma);
 }
 
 static int interface_config_write(struct vty *vty)
@@ -1069,9 +1145,9 @@ static int interface_config_write(struct vty *vty)
        struct interface *ifp;
        struct nhrp_interface *nifp;
        struct nhrp_nhs *nhs;
+       struct nhrp_multicast *mcast;
        const char *aficmd;
        afi_t afi;
-       char buf[SU_ADDRSTRLEN];
        int i;
 
        FOR_ALL_INTERFACES (vrf, ifp) {
@@ -1122,21 +1198,31 @@ static int interface_config_write(struct vty *vty)
                                .family = afi2family(afi),
                                .aficmd = aficmd,
                        };
-                       nhrp_cache_config_foreach(ifp, interface_config_write_nhrp_map,
-                                                 &mapctx);
+                       nhrp_cache_config_foreach(
+                               ifp, interface_config_write_nhrp_map, &mapctx);
 
                        list_for_each_entry(nhs, &ad->nhslist_head,
                                            nhslist_entry)
                        {
-                               vty_out(vty, " %s nhrp nhs %s nbma %s\n",
-                                       aficmd,
-                                       sockunion_family(&nhs->proto_addr)
-                                                       == AF_UNSPEC
-                                               ? "dynamic"
-                                               : sockunion2str(
-                                                         &nhs->proto_addr, buf,
-                                                         sizeof(buf)),
-                                       nhs->nbma_fqdn);
+                               vty_out(vty, " %s nhrp nhs ", aficmd);
+                               if (sockunion_family(&nhs->proto_addr)
+                                  == AF_UNSPEC)
+                                       vty_out(vty, "dynamic");
+                               else
+                                       vty_out(vty, "%pSU", &nhs->proto_addr);
+                               vty_out(vty, "nbma %s\n", nhs->nbma_fqdn);
+                       }
+
+                       list_for_each_entry(mcast, &ad->mcastlist_head,
+                                           list_entry)
+                       {
+                               vty_out(vty, " %s nhrp map multicast ", aficmd);
+                               if (sockunion_family(&mcast->nbma_addr)
+                                  == AF_UNSPEC)
+                                       vty_out(vty, "dynamic\n");
+                               else
+                                       vty_out(vty, "%pSU\n",
+                                               &mcast->nbma_addr);
                        }
                }
 
@@ -1171,6 +1257,8 @@ void nhrp_config_init(void)
        install_element(CONFIG_NODE, &no_nhrp_event_socket_cmd);
        install_element(CONFIG_NODE, &nhrp_nflog_group_cmd);
        install_element(CONFIG_NODE, &no_nhrp_nflog_group_cmd);
+       install_element(CONFIG_NODE, &nhrp_multicast_nflog_group_cmd);
+       install_element(CONFIG_NODE, &no_nhrp_multicast_nflog_group_cmd);
 
        /* interface specific commands */
        install_node(&nhrp_interface_node);
@@ -1192,6 +1280,8 @@ void nhrp_config_init(void)
        install_element(INTERFACE_NODE, &if_no_nhrp_reg_flags_cmd);
        install_element(INTERFACE_NODE, &if_nhrp_map_cmd);
        install_element(INTERFACE_NODE, &if_no_nhrp_map_cmd);
+       install_element(INTERFACE_NODE, &if_nhrp_map_multicast_cmd);
+       install_element(INTERFACE_NODE, &if_no_nhrp_map_multicast_cmd);
        install_element(INTERFACE_NODE, &if_nhrp_nhs_cmd);
        install_element(INTERFACE_NODE, &if_no_nhrp_nhs_cmd);
 }
index 136f855dfcc934f04abd65bfaea2f5fb7bf9f1d1..17abb04762aa021dcf8d362968b04aba99b3a4c7 100644 (file)
@@ -86,14 +86,22 @@ static inline int notifier_active(struct notifier_list *l)
        return !list_empty(&l->notifier_head);
 }
 
+extern struct hash *nhrp_gre_list;
+
 void nhrp_zebra_init(void);
 void nhrp_zebra_terminate(void);
 void nhrp_send_zebra_configure_arp(struct interface *ifp, int family);
 void nhrp_send_zebra_nbr(union sockunion *in,
                         union sockunion *out,
                         struct interface *ifp);
-void nhrp_send_zebra_configure_arp(struct interface *ifp,
-                                  int family);
+
+void nhrp_send_zebra_gre_source_set(struct interface *ifp,
+                                   unsigned int link_idx,
+                                   vrf_id_t link_vrf_id);
+
+extern int nhrp_send_zebra_gre_request(struct interface *ifp);
+extern struct nhrp_gre_info *nhrp_gre_info_alloc(struct nhrp_gre_info *p);
+
 struct zbuf;
 struct nhrp_vc;
 struct nhrp_cache;
@@ -269,6 +277,13 @@ struct nhrp_nhs {
        struct list_head reglist_head;
 };
 
+struct nhrp_multicast {
+       struct interface *ifp;
+       struct list_head list_entry;
+       afi_t afi;
+       union sockunion nbma_addr; /* IP-address */
+};
+
 struct nhrp_registration {
        struct list_head reglist_entry;
        struct thread *t_register;
@@ -293,8 +308,10 @@ struct nhrp_interface {
        char *ipsec_profile, *ipsec_fallback_profile, *source;
        union sockunion nbma;
        union sockunion nat_nbma;
-       unsigned int linkidx;
-       uint32_t grekey;
+       unsigned int link_idx;
+       unsigned int link_vrf_id;
+       uint32_t i_grekey;
+       uint32_t o_grekey;
 
        struct hash *peer_hash;
        struct hash *cache_config_hash;
@@ -314,9 +331,22 @@ struct nhrp_interface {
                unsigned short mtu;
                unsigned int holdtime;
                struct list_head nhslist_head;
+               struct list_head mcastlist_head;
        } afi[AFI_MAX];
 };
 
+struct nhrp_gre_info {
+       ifindex_t ifindex;
+       struct in_addr vtep_ip; /* IFLA_GRE_LOCAL */
+       struct in_addr vtep_ip_remote; /* IFLA_GRE_REMOTE */
+       uint32_t ikey;
+       uint32_t okey;
+       ifindex_t ifindex_link; /* Interface index of interface
+                                * linked with GRE
+                                */
+       vrf_id_t vrfid_link;
+};
+
 extern struct zebra_privs_t nhrpd_privs;
 
 int sock_open_unix(const char *path);
@@ -324,6 +354,8 @@ int sock_open_unix(const char *path);
 void nhrp_interface_init(void);
 void nhrp_interface_update(struct interface *ifp);
 void nhrp_interface_update_mtu(struct interface *ifp, afi_t afi);
+void nhrp_interface_update_nbma(struct interface *ifp,
+                               struct nhrp_gre_info *gre_info);
 
 int nhrp_interface_add(ZAPI_CALLBACK_ARGS);
 int nhrp_interface_delete(ZAPI_CALLBACK_ARGS);
@@ -332,6 +364,7 @@ int nhrp_interface_down(ZAPI_CALLBACK_ARGS);
 int nhrp_interface_address_add(ZAPI_CALLBACK_ARGS);
 int nhrp_interface_address_delete(ZAPI_CALLBACK_ARGS);
 void nhrp_neighbor_operation(ZAPI_CALLBACK_ARGS);
+void nhrp_gre_update(ZAPI_CALLBACK_ARGS);
 
 void nhrp_interface_notify_add(struct interface *ifp, struct notifier_block *n,
                               notifier_fn_t fn);
@@ -356,6 +389,16 @@ void nhrp_nhs_foreach(struct interface *ifp, afi_t afi,
                      void *ctx);
 void nhrp_nhs_interface_del(struct interface *ifp);
 
+int nhrp_multicast_add(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr);
+int nhrp_multicast_del(struct interface *ifp, afi_t afi,
+                      union sockunion *nbma_addr);
+void nhrp_multicast_interface_del(struct interface *ifp);
+void nhrp_multicast_foreach(struct interface *ifp, afi_t afi,
+                           void (*cb)(struct nhrp_multicast *, void *),
+                           void *ctx);
+void netlink_mcast_set_nflog_group(int nlgroup);
+
 void nhrp_route_update_nhrp(const struct prefix *p, struct interface *ifp);
 void nhrp_route_announce(int add, enum nhrp_cache_type type,
                         const struct prefix *p, struct interface *ifp,
index dd65d3cbe104e8746bfc88e97846a32cbca368c8..2b9e07fa6ef5655b32939f0881ee45ddcd961f4d 100644 (file)
@@ -1,7 +1,7 @@
 
 int os_socket(void);
 int os_sendmsg(const uint8_t *buf, size_t len, int ifindex, const uint8_t *addr,
-              size_t addrlen);
+              size_t addrlen, uint16_t protocol);
 int os_recvmsg(uint8_t *buf, size_t *len, int *ifindex, uint8_t *addr,
               size_t *addrlen);
 int os_configure_dmvpn(unsigned int ifindex, const char *ifname, int af);
index 61b1fe31b2f203ba4293ec8d5b942bf29eb774ab..9a186d6ed840b9c4f98bc5ac97a12d86faf1edfc 100644 (file)
@@ -13,7 +13,6 @@ nhrpd_nhrpd_LDADD = lib/libfrr.la lib/libfrrcares.la $(LIBCAP)
 nhrpd_nhrpd_SOURCES = \
        nhrpd/linux.c \
        nhrpd/netlink_arp.c \
-       nhrpd/netlink_gre.c \
        nhrpd/nhrp_cache.c \
        nhrpd/nhrp_errors.c \
        nhrpd/nhrp_event.c \
@@ -22,6 +21,7 @@ nhrpd_nhrpd_SOURCES = \
        nhrpd/nhrp_nhs.c \
        nhrpd/nhrp_packet.c \
        nhrpd/nhrp_peer.c \
+       nhrpd/nhrp_multicast.c \
        nhrpd/nhrp_route.c \
        nhrpd/nhrp_shortcut.c \
        nhrpd/nhrp_vc.c \
index 43ce974817986c52656bdff848e943264f98a6e6..e191a90f2d8c0bd2cdf1643f09c5d3b7753a3660 100644 (file)
@@ -14,7 +14,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <errno.h>
-#include "zassert.h"
+#include <assert.h>
 #include "zbuf.h"
 #include "memory.h"
 #include "nhrpd.h"
@@ -59,7 +59,7 @@ void zbuf_reset(struct zbuf *zb)
 
 void zbuf_reset_head(struct zbuf *zb, void *ptr)
 {
-       zassert((void *)zb->buf <= ptr && ptr <= (void *)zb->tail);
+       assert((void *)zb->buf <= ptr && ptr <= (void *)zb->tail);
        zb->head = ptr;
 }
 
index d4a7c15a95a07a49fb2a26c23a6f0589946cee77..2741860bfd6d8dfdd73a8fea8ca307104c3cb4f6 100644 (file)
@@ -15,7 +15,6 @@
 #include <endian.h>
 #include <sys/types.h>
 
-#include "zassert.h"
 #include "list.h"
 
 struct zbuf {
index 27d4f0755ef656129a0359b0a4acff330a6cb1d5..286e6427817b175010008bb2f147467526929e3e 100644 (file)
@@ -389,6 +389,8 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
                                        zlog_debug(
                                                "prefix %pFX was denied by export list",
                                                &route->prefix);
+                               ospf6_abr_delete_route(route, summary,
+                                                      summary_table, old);
                                return 0;
                        }
        }
@@ -401,6 +403,9 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
                                zlog_debug(
                                        "prefix %pFX was denied by filter-list out",
                                        &route->prefix);
+                       ospf6_abr_delete_route(route, summary, summary_table,
+                                              old);
+
                        return 0;
                }
 
@@ -1075,7 +1080,8 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
                            == FILTER_DENY) {
                                if (is_debug)
                                        zlog_debug(
-                                               "Prefix was denied by import-list");
+                                               "Prefix %pFX was denied by import-list",
+                                               &prefix);
                                if (old)
                                        ospf6_route_remove(old, table);
                                return;
@@ -1087,7 +1093,9 @@ void ospf6_abr_examin_summary(struct ospf6_lsa *lsa, struct ospf6_area *oa)
                if (prefix_list_apply(PREFIX_LIST_IN(oa), &prefix)
                    != PREFIX_PERMIT) {
                        if (is_debug)
-                               zlog_debug("Prefix was denied by prefix-list");
+                               zlog_debug(
+                                       "Prefix %pFX was denied by prefix-list in",
+                                       &prefix);
                        if (old)
                                ospf6_route_remove(old, table);
                        return;
@@ -1287,6 +1295,21 @@ void ospf6_abr_reimport(struct ospf6_area *oa)
                ospf6_abr_examin_summary(lsa, oa);
 }
 
+/* export filter removed so determine if we should reoriginate summary LSAs */
+void ospf6_abr_reexport(struct ospf6_area *oa)
+{
+       struct ospf6_route *route;
+
+       /* if not a ABR return success */
+       if (!ospf6_is_router_abr(oa->ospf6))
+               return;
+
+       /* Redo summaries if required */
+       for (route = ospf6_route_head(oa->ospf6->route_table); route;
+            route = ospf6_route_next(route))
+               ospf6_abr_originate_summary_to_area(route, oa);
+}
+
 void ospf6_abr_prefix_resummarize(struct ospf6 *o)
 {
        struct ospf6_route *route;
index 25a73f9203943953d4f5f2bedd4e62962d0c87f6..6a912ac63055e4781b9fed5456d44bcaa7629705 100644 (file)
@@ -73,6 +73,7 @@ extern void ospf6_abr_examin_brouter(uint32_t router_id,
                                     struct ospf6_route *route,
                                     struct ospf6 *ospf6);
 extern void ospf6_abr_reimport(struct ospf6_area *oa);
+extern void ospf6_abr_reexport(struct ospf6_area *oa);
 extern void ospf6_abr_range_reset_cost(struct ospf6 *ospf6);
 extern void ospf6_abr_prefix_resummarize(struct ospf6 *ospf6);
 
@@ -86,5 +87,6 @@ extern void ospf6_abr_old_path_update(struct ospf6_route *old_route,
                                      struct ospf6_route *route,
                                      struct ospf6_route_table *table);
 extern void ospf6_abr_init(void);
+extern void ospf6_abr_reexport(struct ospf6_area *oa);
 
 #endif /*OSPF6_ABR_H*/
index 6bf61b4804b0981c43311331c4757d7c32d7e55f..d65e40279dc57c0cf6818ae82b3071f1266b1e3b 100644 (file)
@@ -661,7 +661,9 @@ DEFUN (area_filter_list,
                XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
                PREFIX_NAME_OUT(area) =
                        XSTRDUP(MTYPE_OSPF6_PLISTNAME, plistname);
-               ospf6_abr_enable_area(area);
+
+               /* Redo summaries if required */
+               ospf6_abr_reexport(area);
        }
 
        return CMD_SUCCESS;
@@ -703,12 +705,32 @@ DEFUN (no_area_filter_list,
                                return CMD_SUCCESS;
 
                XFREE(MTYPE_OSPF6_PLISTNAME, PREFIX_NAME_OUT(area));
-               ospf6_abr_enable_area(area);
+               PREFIX_LIST_OUT(area) = NULL;
+               ospf6_abr_reexport(area);
        }
 
        return CMD_SUCCESS;
 }
 
+void ospf6_filter_update(struct access_list *access)
+{
+       struct ospf6_area *oa;
+       struct listnode *n, *node, *nnode;
+       struct ospf6 *ospf6;
+
+       for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
+               for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
+                       if (IMPORT_NAME(oa)
+                           && strcmp(IMPORT_NAME(oa), access->name) == 0)
+                               ospf6_abr_reimport(oa);
+
+                       if (EXPORT_NAME(oa)
+                           && strcmp(EXPORT_NAME(oa), access->name) == 0)
+                               ospf6_abr_reexport(oa);
+               }
+       }
+}
+
 void ospf6_area_plist_update(struct prefix_list *plist, int add)
 {
        struct listnode *node, *nnode;
@@ -724,11 +746,15 @@ void ospf6_area_plist_update(struct prefix_list *plist, int add)
        for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
                for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, n, oa)) {
                        if (PREFIX_NAME_IN(oa)
-                           && !strcmp(PREFIX_NAME_IN(oa), name))
+                           && !strcmp(PREFIX_NAME_IN(oa), name)) {
                                PREFIX_LIST_IN(oa) = add ? plist : NULL;
+                               ospf6_abr_reexport(oa);
+                       }
                        if (PREFIX_NAME_OUT(oa)
-                           && !strcmp(PREFIX_NAME_OUT(oa), name))
+                           && !strcmp(PREFIX_NAME_OUT(oa), name)) {
                                PREFIX_LIST_OUT(oa) = add ? plist : NULL;
+                               ospf6_abr_reexport(oa);
+                       }
                }
        }
 }
@@ -818,7 +844,9 @@ DEFUN (area_export_list,
                free(EXPORT_NAME(area));
 
        EXPORT_NAME(area) = strdup(argv[idx_name]->arg);
-       ospf6_abr_enable_area(area);
+
+       /* Redo summaries if required */
+       ospf6_abr_reexport(area);
 
        return CMD_SUCCESS;
 }
@@ -846,39 +874,26 @@ DEFUN (no_area_export_list,
                free(EXPORT_NAME(area));
 
        EXPORT_NAME(area) = NULL;
-       ospf6_abr_enable_area(area);
+       ospf6_abr_reexport(area);
 
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_spf_tree,
-       show_ipv6_ospf6_spf_tree_cmd,
-       "show ipv6 ospf6 spf tree [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Shortest Path First calculation\n"
-       "Show SPF tree\n"
-        JSON_STR)
+static int ipv6_ospf6_spf_tree_common(struct vty *vty, struct ospf6 *ospf6,
+                                     bool uj)
 {
        struct listnode *node;
        struct ospf6_area *oa;
+       struct prefix prefix;
        struct ospf6_vertex *root;
        struct ospf6_route *route;
-       struct prefix prefix;
-       struct ospf6 *ospf6;
        json_object *json = NULL;
        json_object *json_area = NULL;
        json_object *json_head = NULL;
-       bool uj = use_json(argc, argv);
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
 
        if (uj)
                json = json_object_new_object();
        ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
-
        for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
                if (uj) {
                        json_area = json_object_new_object();
@@ -918,35 +933,47 @@ DEFUN (show_ipv6_ospf6_spf_tree,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_area_spf_tree,
-       show_ipv6_ospf6_area_spf_tree_cmd,
-       "show ipv6 ospf6 area A.B.C.D spf tree",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       OSPF6_AREA_STR
-       OSPF6_AREA_ID_STR
-       "Shortest Path First calculation\n"
-       "Show SPF tree\n")
+DEFUN(show_ipv6_ospf6_spf_tree, show_ipv6_ospf6_spf_tree_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] spf tree [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Shortest Path First calculation\n"
+      "Show SPF tree\n" JSON_STR)
 {
-       int idx_ipv4 = 4;
-       uint32_t area_id;
-       struct ospf6_area *oa;
-       struct ospf6_vertex *root;
-       struct ospf6_route *route;
-       struct prefix prefix;
+       struct listnode *node;
        struct ospf6 *ospf6;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+       bool uj = use_json(argc, argv);
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ipv6_ospf6_spf_tree_common(vty, ospf6, uj);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
+       return CMD_SUCCESS;
+}
+
+static int show_ospf6_area_spf_tree_common(struct vty *vty,
+                                          struct cmd_token **argv,
+                                          struct ospf6 *ospf6,
+                                          uint32_t area_id, int idx_ipv4)
+{
 
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       struct ospf6_area *oa;
+       struct prefix prefix;
+       struct ospf6_vertex *root;
+       struct ospf6_route *route;
 
        ospf6_linkstate_prefix(ospf6->router_id, htonl(0), &prefix);
 
-       if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
-               vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
-               return CMD_SUCCESS;
-       }
        oa = ospf6_area_lookup(area_id, ospf6);
        if (oa == NULL) {
                vty_out(vty, "No such Area: %s\n", argv[idx_ipv4]->arg);
@@ -965,41 +992,55 @@ DEFUN (show_ipv6_ospf6_area_spf_tree,
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
-       show_ipv6_ospf6_simulate_spf_tree_root_cmd,
-       "show ipv6 ospf6 simulate spf-tree A.B.C.D area A.B.C.D",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Shortest Path First calculation\n"
-       "Show SPF tree\n"
-       "Specify root's router-id to calculate another router's SPF tree\n"
-       "OSPF6 area parameters\n"
-       OSPF6_AREA_ID_STR)
+DEFUN(show_ipv6_ospf6_area_spf_tree, show_ipv6_ospf6_area_spf_tree_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] area A.B.C.D spf tree",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" OSPF6_AREA_STR OSPF6_AREA_ID_STR
+      "Shortest Path First calculation\n"
+      "Show SPF tree\n")
 {
-       int idx_ipv4 = 5;
-       int idx_ipv4_2 = 7;
+       int idx_ipv4 = 4;
        uint32_t area_id;
+       struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_ipv4 += 2;
+
+       if (inet_pton(AF_INET, argv[idx_ipv4]->arg, &area_id) != 1) {
+               vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4]->arg);
+               return CMD_SUCCESS;
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       show_ospf6_area_spf_tree_common(vty, argv, ospf6,
+                                                       area_id, idx_ipv4);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
+       return CMD_SUCCESS;
+}
+
+static int
+show_ospf6_simulate_spf_tree_commen(struct vty *vty, struct cmd_token **argv,
+                                   struct ospf6 *ospf6, uint32_t router_id,
+                                   uint32_t area_id, struct prefix prefix,
+                                   int idx_ipv4, int idx_ipv4_2)
+{
        struct ospf6_area *oa;
        struct ospf6_vertex *root;
        struct ospf6_route *route;
-       struct prefix prefix;
-       uint32_t router_id;
        struct ospf6_route_table *spf_table;
        unsigned char tmp_debug_ospf6_spf = 0;
-       struct ospf6 *ospf6;
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
 
-       inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
-       ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
-
-       if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
-               vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
-               return CMD_SUCCESS;
-       }
        oa = ospf6_area_lookup(area_id, ospf6);
        if (oa == NULL) {
                vty_out(vty, "No such Area: %s\n", argv[idx_ipv4_2]->arg);
@@ -1029,6 +1070,54 @@ DEFUN (show_ipv6_ospf6_simulate_spf_tree_root,
        return CMD_SUCCESS;
 }
 
+DEFUN(show_ipv6_ospf6_simulate_spf_tree_root,
+      show_ipv6_ospf6_simulate_spf_tree_root_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] simulate spf-tree A.B.C.D area A.B.C.D",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Shortest Path First calculation\n"
+      "Show SPF tree\n"
+      "Specify root's router-id to calculate another router's SPF tree\n"
+      "OSPF6 area parameters\n" OSPF6_AREA_ID_STR)
+{
+       int idx_ipv4 = 5;
+       int idx_ipv4_2 = 7;
+       uint32_t area_id;
+       struct prefix prefix;
+       uint32_t router_id;
+       struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_ipv4 += 2;
+               idx_ipv4_2 += 2;
+       }
+       inet_pton(AF_INET, argv[idx_ipv4]->arg, &router_id);
+       ospf6_linkstate_prefix(router_id, htonl(0), &prefix);
+
+       if (inet_pton(AF_INET, argv[idx_ipv4_2]->arg, &area_id) != 1) {
+               vty_out(vty, "Malformed Area-ID: %s\n", argv[idx_ipv4_2]->arg);
+               return CMD_SUCCESS;
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       show_ospf6_simulate_spf_tree_commen(
+                               vty, argv, ospf6, router_id, area_id, prefix,
+                               idx_ipv4, idx_ipv4_2);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
+       return CMD_SUCCESS;
+}
+
 DEFUN (ospf6_area_stub,
        ospf6_area_stub_cmd,
        "area <A.B.C.D|(0-4294967295)> stub",
@@ -1158,8 +1247,9 @@ void ospf6_area_interface_delete(struct ospf6_interface *oi)
 
        if (!om6->ospf6)
                return;
-       for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6))
+       for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
                for (ALL_LIST_ELEMENTS(ospf6->area_list, node, nnode, oa))
                        if (listnode_lookup(oa->if_list, oi))
                                listnode_delete(oa->if_list, oi);
+       }
 }
index 8a58b2a50ed571da8dc46e6f8dc7e4e75b4d2107..761fe75f73a5b1dc6d78a754c6258c7e1cbd9b96 100644 (file)
@@ -148,6 +148,7 @@ extern void ospf6_area_show(struct vty *, struct ospf6_area *,
                            json_object *json_areas, bool use_json);
 
 extern void ospf6_area_plist_update(struct prefix_list *plist, int add);
+extern void ospf6_filter_update(struct access_list *access);
 extern void ospf6_area_config_write(struct vty *vty, struct ospf6 *ospf6);
 extern void ospf6_area_init(void);
 struct ospf6_interface;
index ffd6dc22c373084ed152e958e76d2bea5490c01c..c37d89bcb8a8be8400ef0ef4b576e404ac37feaa 100644 (file)
@@ -41,6 +41,7 @@
 #include "ospf6_spf.h"
 
 #include "ospf6_top.h"
+#include "ospf6d.h"
 #include "ospf6_area.h"
 #include "ospf6_interface.h"
 #include "ospf6_neighbor.h"
@@ -1397,7 +1398,7 @@ DEFUN (ospf6_redistribute,
        struct ospf6_redist *red;
 
        VTY_DECLVAR_CONTEXT(ospf6, ospf6);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+
        char *proto = argv[argc - 1]->text;
        type = proto_redistnum(AFI_IP6, proto);
        if (type < 0)
@@ -1427,7 +1428,6 @@ DEFUN (ospf6_redistribute_routemap,
        struct ospf6_redist *red;
 
        VTY_DECLVAR_CONTEXT(ospf6, ospf6);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
 
        char *proto = argv[idx_protocol]->text;
        type = proto_redistnum(AFI_IP6, proto);
@@ -1460,8 +1460,6 @@ DEFUN (no_ospf6_redistribute,
 
        VTY_DECLVAR_CONTEXT(ospf6, ospf6);
 
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
-
        char *proto = argv[idx_protocol]->text;
        type = proto_redistnum(AFI_IP6, proto);
        if (type < 0)
@@ -1639,8 +1637,6 @@ DEFPY (ospf6_default_route_originate,
 
        int cur_originate = ospf6->default_originate;
 
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
-
        red = ospf6_redist_add(ospf6, DEFAULT_ROUTE, 0);
 
        if (always != NULL)
@@ -1696,8 +1692,6 @@ DEFPY (no_ospf6_default_information_originate,
 
        VTY_DECLVAR_CONTEXT(ospf6, ospf6);
 
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
-
        red = ospf6_redist_lookup(ospf6, DEFAULT_ROUTE, 0);
        if (!red)
                return CMD_SUCCESS;
@@ -2215,46 +2209,61 @@ static void ospf6_asbr_external_route_show(struct vty *vty,
                        forwarding);
 }
 
-DEFUN (show_ipv6_ospf6_redistribute,
-       show_ipv6_ospf6_redistribute_cmd,
-       "show ipv6 ospf6 redistribute [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "redistributing External information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_redistribute, show_ipv6_ospf6_redistribute_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] redistribute [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "redistributing External information\n" JSON_STR)
 {
        struct ospf6_route *route;
        struct ospf6 *ospf6 = NULL;
        json_object *json = NULL;
        bool uj = use_json(argc, argv);
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
        json_object *json_array_routes = NULL;
        json_object *json_array_redistribute = NULL;
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
 
        if (uj) {
                json = json_object_new_object();
                json_array_routes = json_object_new_array();
                json_array_redistribute = json_object_new_array();
        }
-       ospf6_redistribute_show_config(vty, ospf6, json_array_redistribute,
-                                      json, uj);
 
-       for (route = ospf6_route_head(ospf6->external_table); route;
-            route = ospf6_route_next(route)) {
-               ospf6_asbr_external_route_show(vty, route, json_array_routes,
-                                              uj);
-       }
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf
+                   || ((ospf6->name == NULL && vrf_name == NULL)
+                       || (ospf6->name && vrf_name
+                           && strcmp(ospf6->name, vrf_name) == 0))) {
+                       ospf6_redistribute_show_config(
+                               vty, ospf6, json_array_redistribute, json, uj);
+
+                       for (route = ospf6_route_head(ospf6->external_table);
+                            route; route = ospf6_route_next(route)) {
+                               ospf6_asbr_external_route_show(
+                                       vty, route, json_array_routes, uj);
+                       }
 
-       if (uj) {
-               json_object_object_add(json, "routes", json_array_routes);
-               vty_out(vty, "%s\n",
-                       json_object_to_json_string_ext(
-                               json, JSON_C_TO_STRING_PRETTY));
-               json_object_free(json);
+                       if (uj) {
+                               json_object_object_add(json, "routes",
+                                                      json_array_routes);
+                               vty_out(vty, "%s\n",
+                                       json_object_to_json_string_ext(
+                                               json, JSON_C_TO_STRING_PRETTY));
+                               json_object_free(json);
+                       }
+
+                       if (!all_vrf)
+                               break;
+               }
        }
+
        return CMD_SUCCESS;
 }
 
index a701583621fe2d1378523185d0d33f06b3ffafef..ba8c398dee4a1dd14fa74cfceface3eb16c8f9b9 100644 (file)
 
 extern struct zclient *zclient;
 
-/*
- * ospf6_bfd_info_free - Free BFD info structure
- */
-void ospf6_bfd_info_free(void **bfd_info)
-{
-       bfd_info_free((struct bfd_info **)bfd_info);
-}
-
-/*
- * ospf6_bfd_show_info - Show BFD info structure
- */
-void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only,
-                        json_object *json_obj, bool use_json)
-{
-       if (param_only)
-               bfd_show_param(vty, bfd_info, 1, 0, use_json, json_obj);
-       else
-               bfd_show_info(vty, bfd_info, 0, 1, use_json, json_obj);
-}
-
-/*
- * ospf6_bfd_reg_dereg_nbr - Register/Deregister a neighbor with BFD through
- *                           zebra for starting/stopping the monitoring of
- *                           the neighbor rechahability.
- */
-void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command)
-{
-       struct ospf6_interface *oi = on->ospf6_if;
-       struct interface *ifp = oi->interface;
-       struct bfd_info *bfd_info;
-       char src[64];
-       int cbit;
-
-       if (!oi->bfd_info || !on->bfd_info)
-               return;
-       bfd_info = (struct bfd_info *)oi->bfd_info;
-
-       if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
-               inet_ntop(AF_INET6, &on->linklocal_addr, src, sizeof(src));
-               zlog_debug("%s nbr (%s) with BFD",
-                          bfd_get_command_dbg_str(command), src);
-       }
-
-       cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
-
-       bfd_peer_sendmsg(zclient, bfd_info, AF_INET6, &on->linklocal_addr,
-                        on->ospf6_if->linklocal_addr, ifp->name, 0, 0, cbit,
-                        command, 0, ifp->vrf_id);
-
-       if (command == ZEBRA_BFD_DEST_DEREGISTER)
-               bfd_info_free((struct bfd_info **)&on->bfd_info);
-}
-
 /*
  * ospf6_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
  *                           neighbor state is changed to/from 2way.
@@ -104,12 +51,33 @@ void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command)
 void ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state,
                             int state)
 {
-       if ((old_state < OSPF6_NEIGHBOR_TWOWAY)
-           && (state >= OSPF6_NEIGHBOR_TWOWAY))
-               ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_REGISTER);
-       else if ((old_state >= OSPF6_NEIGHBOR_TWOWAY)
-                && (state < OSPF6_NEIGHBOR_TWOWAY))
-               ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER);
+       int family;
+       struct in6_addr src, dst;
+
+       /* Skip sessions without BFD. */
+       if (on->bfd_session == NULL)
+               return;
+
+       if (old_state < OSPF6_NEIGHBOR_TWOWAY
+           && state >= OSPF6_NEIGHBOR_TWOWAY) {
+               /*
+                * Check if neighbor address changed.
+                *
+                * When the neighbor is configured BFD before having an existing
+                * connection, then the destination address will be set to `::`
+                * which will cause session installation failure. This piece of
+                * code updates the address in that case.
+                */
+               bfd_sess_addresses(on->bfd_session, &family, &src, &dst);
+               if (memcmp(&on->linklocal_addr, &dst, sizeof(dst))) {
+                       bfd_sess_set_ipv6_addrs(on->bfd_session, &src,
+                                               &on->linklocal_addr);
+               }
+
+               bfd_sess_install(on->bfd_session);
+       } else if (old_state >= OSPF6_NEIGHBOR_TWOWAY
+                  && state < OSPF6_NEIGHBOR_TWOWAY)
+               bfd_sess_uninstall(on->bfd_session);
 }
 
 /*
@@ -118,134 +86,43 @@ void ospf6_bfd_trigger_event(struct ospf6_neighbor *on, int old_state,
  *                               zebra for starting/stopping the monitoring of
  *                               the neighbor rechahability.
  */
-static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface *oi, int command)
+static void ospf6_bfd_reg_dereg_all_nbr(struct ospf6_interface *oi,
+                                       bool install)
 {
        struct ospf6_neighbor *on;
        struct listnode *node;
 
        for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
-               if (command == ZEBRA_BFD_DEST_REGISTER)
-                       ospf6_bfd_info_nbr_create(oi, on);
-
-               if (on->state < OSPF6_NEIGHBOR_TWOWAY) {
-                       if (command == ZEBRA_BFD_DEST_DEREGISTER)
-                               bfd_info_free(
-                                       (struct bfd_info **)&on->bfd_info);
+               /* Remove all sessions. */
+               if (!install) {
+                       bfd_sess_free(&on->bfd_session);
                        continue;
                }
 
-               ospf6_bfd_reg_dereg_nbr(on, command);
-       }
-}
+               /* Always allocate session data even if not enabled. */
+               ospf6_bfd_info_nbr_create(oi, on);
 
-/*
- * ospf6_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
- *                        to zebra
- */
-static int ospf6_bfd_nbr_replay(ZAPI_CALLBACK_ARGS)
-{
-       struct vrf *vrf = vrf_lookup_by_id(vrf_id);
-       struct listnode *node;
-       struct interface *ifp;
-       struct ospf6_interface *oi;
-       struct ospf6_neighbor *on;
-       char dst[64];
-
-       if (IS_OSPF6_DEBUG_ZEBRA(RECV))
-               zlog_debug("Zebra: BFD Dest replay request");
-
-       /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
-
-       /* Replay the neighbor, if BFD is enabled on the interface*/
-       FOR_ALL_INTERFACES (vrf, ifp) {
-               oi = (struct ospf6_interface *)ifp->info;
-
-               if (!oi || !oi->bfd_info)
+               /*
+                * If not connected yet, don't create any session but defer it
+                * for later. See function `ospf6_bfd_trigger_event`.
+                */
+               if (on->state < OSPF6_NEIGHBOR_TWOWAY)
                        continue;
 
-               for (ALL_LIST_ELEMENTS_RO(oi->neighbor_list, node, on)) {
-                       if (on->state < OSPF6_NEIGHBOR_TWOWAY)
-                               continue;
-
-                       if (IS_OSPF6_DEBUG_ZEBRA(SEND)) {
-                               inet_ntop(AF_INET6, &on->linklocal_addr, dst,
-                                         sizeof(dst));
-                               zlog_debug("Replaying nbr (%s) to BFD", dst);
-                       }
-
-                       ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_UPDATE);
-               }
+               bfd_sess_install(on->bfd_session);
        }
-       return 0;
 }
 
-/*
- * ospf6_bfd_interface_dest_update - Find the neighbor for which the BFD status
- *                                   has changed and bring down the neighbor
- *                                   connectivity if BFD down is received.
- */
-static int ospf6_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
+static void ospf6_bfd_callback(struct bfd_session_params *bsp,
+                              const struct bfd_session_status *bss, void *arg)
 {
-       struct interface *ifp;
-       struct ospf6_interface *oi;
-       struct ospf6_neighbor *on;
-       struct prefix dp;
-       struct prefix sp;
-       struct listnode *node, *nnode;
-       char dst[64];
-       int status;
-       int old_status;
-       struct bfd_info *bfd_info;
-       struct timeval tv;
-
-       ifp = bfd_get_peer_info(zclient->ibuf, &dp, &sp, &status,
-                               NULL, vrf_id);
-
-       if ((ifp == NULL) || (dp.family != AF_INET6))
-               return 0;
-
-       if (IS_OSPF6_DEBUG_ZEBRA(RECV))
-               zlog_debug("Zebra: interface %s bfd destination %pFX %s",
-                          ifp->name, &dp, bfd_get_status_str(status));
-
-
-       oi = (struct ospf6_interface *)ifp->info;
-       if (!oi || !oi->bfd_info)
-               return 0;
-
-       for (ALL_LIST_ELEMENTS(oi->neighbor_list, node, nnode, on)) {
-               if (memcmp(&(on->linklocal_addr), &dp.u.prefix6,
-                          sizeof(struct in6_addr)))
-                       continue;
-
-               if (IS_OSPF6_DEBUG_NEIGHBOR(EVENT)) {
-                       inet_ntop(AF_INET6, &on->linklocal_addr, dst,
-                                 sizeof(dst));
-                       zlog_debug("[%s:%s]: BFD %s", ifp->name, dst,
-                                  bfd_get_status_str(status));
-               }
-
-               if (!on->bfd_info)
-                       continue;
-
-               bfd_info = (struct bfd_info *)on->bfd_info;
-               if (bfd_info->status == status)
-                       continue;
+       struct ospf6_neighbor *on = arg;
 
-               old_status = bfd_info->status;
-               BFD_SET_CLIENT_STATUS(bfd_info->status, status);
-               monotime(&tv);
-               bfd_info->last_update = tv.tv_sec;
-
-               if ((status == BFD_STATUS_DOWN)
-                   && (old_status == BFD_STATUS_UP)) {
-                       THREAD_OFF(on->inactivity_timer);
-                       thread_add_event(master, inactivity_timer, on, 0, NULL);
-               }
+       if (bss->state == BFD_STATUS_DOWN
+           && bss->previous_state == BFD_STATUS_UP) {
+               THREAD_OFF(on->inactivity_timer);
+               thread_add_event(master, inactivity_timer, on, 0, NULL);
        }
-
-       return 0;
 }
 
 /*
@@ -254,21 +131,19 @@ static int ospf6_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
 void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi,
                               struct ospf6_neighbor *on)
 {
-       struct bfd_info *oi_bfd_info;
-       struct bfd_info *on_bfd_info;
-
-       if (!oi->bfd_info)
+       if (!oi->bfd_config.enabled)
                return;
 
-       oi_bfd_info = (struct bfd_info *)oi->bfd_info;
-
-       if (!on->bfd_info)
-               on->bfd_info = bfd_info_create();
+       if (on->bfd_session == NULL)
+               on->bfd_session = bfd_sess_new(ospf6_bfd_callback, on);
 
-       on_bfd_info = (struct bfd_info *)on->bfd_info;
-       on_bfd_info->detect_mult = oi_bfd_info->detect_mult;
-       on_bfd_info->desired_min_tx = oi_bfd_info->desired_min_tx;
-       on_bfd_info->required_min_rx = oi_bfd_info->required_min_rx;
+       bfd_sess_set_timers(on->bfd_session,
+                           oi->bfd_config.detection_multiplier,
+                           oi->bfd_config.min_rx, oi->bfd_config.min_tx);
+       bfd_sess_set_ipv6_addrs(on->bfd_session, on->ospf6_if->linklocal_addr,
+                               &on->linklocal_addr);
+       bfd_sess_set_interface(on->bfd_session, oi->interface->name);
+       bfd_sess_set_profile(on->bfd_session, oi->bfd_config.profile);
 }
 
 /*
@@ -276,48 +151,63 @@ void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi,
  */
 void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi)
 {
-#if HAVE_BFDD == 0
-       struct bfd_info *bfd_info;
-#endif /* ! HAVE_BFDD */
-
-       if (!oi->bfd_info)
+       if (!oi->bfd_config.enabled)
                return;
 
 #if HAVE_BFDD == 0
-       bfd_info = (struct bfd_info *)oi->bfd_info;
-
-       if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
+       if (oi->bfd_config.detection_multiplier != BFD_DEF_DETECT_MULT
+           || oi->bfd_config.min_rx != BFD_DEF_MIN_RX
+           || oi->bfd_config.min_tx != BFD_DEF_MIN_TX)
                vty_out(vty, " ipv6 ospf6 bfd %d %d %d\n",
-                       bfd_info->detect_mult, bfd_info->required_min_rx,
-                       bfd_info->desired_min_tx);
+                       oi->bfd_config.detection_multiplier,
+                       oi->bfd_config.min_rx, oi->bfd_config.min_tx);
        else
 #endif /* ! HAVE_BFDD */
                vty_out(vty, " ipv6 ospf6 bfd\n");
+
+       if (oi->bfd_config.profile)
+               vty_out(vty, " ipv6 ospf6 bfd profile %s\n",
+                       oi->bfd_config.profile);
 }
 
-/*
- * ospf6_bfd_if_param_set - Set the configured BFD paramter values for
- *                            interface.
- */
-static void ospf6_bfd_if_param_set(struct ospf6_interface *oi, uint32_t min_rx,
-                                  uint32_t min_tx, uint8_t detect_mult,
-                                  int defaults)
+DEFUN(ipv6_ospf6_bfd, ipv6_ospf6_bfd_cmd,
+      "ipv6 ospf6 bfd [profile BFDPROF]",
+      IP6_STR OSPF6_STR
+      "Enables BFD support\n"
+      "BFD Profile selection\n"
+      "BFD Profile name\n")
 {
-       int command = 0;
+       VTY_DECLVAR_CONTEXT(interface, ifp);
+       struct ospf6_interface *oi;
+       int prof_idx = 4;
+       assert(ifp);
 
-       bfd_set_param((struct bfd_info **)&(oi->bfd_info), min_rx, min_tx,
-                     detect_mult, NULL, defaults, &command);
-       if (command)
-               ospf6_bfd_reg_dereg_all_nbr(oi, command);
+       oi = (struct ospf6_interface *)ifp->info;
+       if (oi == NULL)
+               oi = ospf6_interface_create(ifp);
+       assert(oi);
+
+       oi->bfd_config.detection_multiplier = BFD_DEF_DETECT_MULT;
+       oi->bfd_config.min_rx = BFD_DEF_MIN_RX;
+       oi->bfd_config.min_tx = BFD_DEF_MIN_TX;
+       oi->bfd_config.enabled = true;
+       if (argc > prof_idx) {
+               XFREE(MTYPE_TMP, oi->bfd_config.profile);
+               oi->bfd_config.profile =
+                       XSTRDUP(MTYPE_TMP, argv[prof_idx]->arg);
+       }
+
+       ospf6_bfd_reg_dereg_all_nbr(oi, true);
+
+       return CMD_SUCCESS;
 }
 
-DEFUN (ipv6_ospf6_bfd,
-       ipv6_ospf6_bfd_cmd,
-       "ipv6 ospf6 bfd",
-       IP6_STR
-       OSPF6_STR
-       "Enables BFD support\n"
-       )
+DEFUN(no_ipv6_ospf6_bfd_profile, no_ipv6_ospf6_bfd_profile_cmd,
+      "no ipv6 ospf6 bfd profile [BFDPROF]",
+      NO_STR IP6_STR OSPF6_STR
+      "BFD support\n"
+      "BFD Profile selection\n"
+      "BFD Profile name\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        struct ospf6_interface *oi;
@@ -328,8 +218,14 @@ DEFUN (ipv6_ospf6_bfd,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       ospf6_bfd_if_param_set(oi, BFD_DEF_MIN_RX, BFD_DEF_MIN_TX,
-                              BFD_DEF_DETECT_MULT, 1);
+       /* BFD not enabled, nothing to do. */
+       if (!oi->bfd_config.enabled)
+               return CMD_SUCCESS;
+
+       /* Remove profile and apply new configuration. */
+       XFREE(MTYPE_TMP, oi->bfd_config.profile);
+       ospf6_bfd_reg_dereg_all_nbr(oi, true);
+
        return CMD_SUCCESS;
 }
 
@@ -353,10 +249,6 @@ DEFUN(
        int idx_number_2 = 4;
        int idx_number_3 = 5;
        struct ospf6_interface *oi;
-       uint32_t rx_val;
-       uint32_t tx_val;
-       uint8_t dm_val;
-       int ret;
 
        assert(ifp);
 
@@ -365,13 +257,13 @@ DEFUN(
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       if ((ret = bfd_validate_param(
-                    vty, argv[idx_number]->arg, argv[idx_number_2]->arg,
-                    argv[idx_number_3]->arg, &dm_val, &rx_val, &tx_val))
-           != CMD_SUCCESS)
-               return ret;
+       oi->bfd_config.detection_multiplier =
+               strtoul(argv[idx_number]->arg, NULL, 10);
+       oi->bfd_config.min_rx = strtoul(argv[idx_number_2]->arg, NULL, 10);
+       oi->bfd_config.min_tx = strtoul(argv[idx_number_3]->arg, NULL, 10);
+       oi->bfd_config.enabled = true;
 
-       ospf6_bfd_if_param_set(oi, rx_val, tx_val, dm_val, 0);
+       ospf6_bfd_reg_dereg_all_nbr(oi, true);
 
        return CMD_SUCCESS;
 }
@@ -394,24 +286,19 @@ DEFUN (no_ipv6_ospf6_bfd,
                oi = ospf6_interface_create(ifp);
        assert(oi);
 
-       if (oi->bfd_info) {
-               ospf6_bfd_reg_dereg_all_nbr(oi, ZEBRA_BFD_DEST_DEREGISTER);
-               bfd_info_free((struct bfd_info **)&(oi->bfd_info));
-       }
+       oi->bfd_config.enabled = false;
+       ospf6_bfd_reg_dereg_all_nbr(oi, false);
 
        return CMD_SUCCESS;
 }
 
 void ospf6_bfd_init(void)
 {
-       bfd_gbl_init();
-
-       /* Initialize BFD client functions */
-       zclient->interface_bfd_dest_update = ospf6_bfd_interface_dest_update;
-       zclient->bfd_dest_replay = ospf6_bfd_nbr_replay;
+       bfd_protocol_integration_init(zclient, master);
 
        /* Install BFD command */
        install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_cmd);
        install_element(INTERFACE_NODE, &ipv6_ospf6_bfd_param_cmd);
+       install_element(INTERFACE_NODE, &no_ipv6_ospf6_bfd_profile_cmd);
        install_element(INTERFACE_NODE, &no_ipv6_ospf6_bfd_cmd);
 }
index ddf624efceb42e41d6898e50b7c7e16bcf9c3db5..651ce2a6e3ae45b95701590e55a41a2d9547b3ce 100644 (file)
@@ -24,6 +24,9 @@
 #define OSPF6_BFD_H
 #include "lib/json.h"
 
+/**
+ * Initialize BFD integration.
+ */
 extern void ospf6_bfd_init(void);
 
 extern void ospf6_bfd_trigger_event(struct ospf6_neighbor *nbr, int old_state,
@@ -34,10 +37,4 @@ extern void ospf6_bfd_write_config(struct vty *vty, struct ospf6_interface *oi);
 extern void ospf6_bfd_info_nbr_create(struct ospf6_interface *oi,
                                      struct ospf6_neighbor *on);
 
-extern void ospf6_bfd_info_free(void **bfd_info);
-
-extern void ospf6_bfd_show_info(struct vty *vty, void *bfd_info, int param_only,
-                               json_object *json_obj, bool use_json);
-
-extern void ospf6_bfd_reg_dereg_nbr(struct ospf6_neighbor *on, int command);
 #endif /* OSPF6_BFD_H */
index 5f4815fec1ddd8533e4edb0d864a691487e21c24..0fa6f8c7791de5181360513ed987abcb8bb0ffb1 100644 (file)
@@ -381,7 +381,8 @@ void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
                } else {
                        /* (d) add retrans-list, schedule retransmission */
                        if (is_debug)
-                               zlog_debug("Add retrans-list of this neighbor");
+                               zlog_debug("Add retrans-list of neighbor %s ",
+                                          on->name);
                        ospf6_increment_retrans_count(lsa);
                        ospf6_lsdb_add(ospf6_lsa_copy(lsa), on->retrans_list);
                        thread_add_timer(master, ospf6_lsupdate_send_neighbor,
@@ -395,7 +396,8 @@ void ospf6_flood_interface(struct ospf6_neighbor *from, struct ospf6_lsa *lsa,
        if (retrans_added == 0) {
                if (is_debug)
                        zlog_debug(
-                               "No retransmission scheduled, next interface");
+                               "No retransmission scheduled, next interface %s",
+                               oi->interface->name);
                return;
        }
 
index 158b8dc483d017c7438a90efe35b0fdad280a405..11bdd1e3553ad3bb3edb5d76882f51fcfbfeecbc 100644 (file)
@@ -272,11 +272,12 @@ void ospf6_interface_delete(struct ospf6_interface *oi)
        if (oi->plist_name)
                XFREE(MTYPE_CFG_PLIST_NAME, oi->plist_name);
 
-       ospf6_bfd_info_free(&(oi->bfd_info));
-
        /* disable from area list if possible */
        ospf6_area_interface_delete(oi);
 
+       /* Free BFD allocated data. */
+       XFREE(MTYPE_TMP, oi->bfd_config.profile);
+
        XFREE(MTYPE_OSPF6_IF, oi);
 }
 
@@ -473,8 +474,8 @@ void ospf6_interface_connected_route_update(struct interface *ifp)
        OSPF6_INTRA_PREFIX_LSA_SCHEDULE_STUB(oi->area);
 }
 
-static void ospf6_interface_state_change(uint8_t next_state,
-                                        struct ospf6_interface *oi)
+static int ospf6_interface_state_change(uint8_t next_state,
+                                       struct ospf6_interface *oi)
 {
        uint8_t prev_state;
        struct ospf6 *ospf6;
@@ -483,7 +484,7 @@ static void ospf6_interface_state_change(uint8_t next_state,
        oi->state = next_state;
 
        if (prev_state == next_state)
-               return;
+               return -1;
 
        /* log */
        if (IS_OSPF6_DEBUG_INTERFACE) {
@@ -524,6 +525,8 @@ static void ospf6_interface_state_change(uint8_t next_state,
        }
 
        hook_call(ospf6_interface_change, oi, next_state, prev_state);
+
+       return 0;
 }
 
 
@@ -1148,23 +1151,39 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
                for (ALL_LSDB(oi->lsack_list, lsa, lsanext))
                        vty_out(vty, "      %s\n", lsa->name);
        }
-       ospf6_bfd_show_info(vty, oi->bfd_info, 1, json_obj, use_json);
+
+       /* BFD specific. */
+       if (oi->bfd_config.enabled) {
+               if (use_json) {
+                       struct json_object *json_bfd = json_object_new_object();
+
+                       json_object_int_add(
+                               json_bfd, "detectMultiplier",
+                               oi->bfd_config.detection_multiplier);
+                       json_object_int_add(json_bfd, "rxMinInterval",
+                                           oi->bfd_config.min_rx);
+                       json_object_int_add(json_bfd, "txMinInterval",
+                                           oi->bfd_config.min_tx);
+                       json_object_object_add(json_obj, "peerBfdInfo",
+                                              json_bfd);
+               } else {
+                       vty_out(vty,
+                               "  BFD: Detect Multiplier: %d, Min Rx interval: %d, Min Tx interval: %d\n",
+                               oi->bfd_config.detection_multiplier,
+                               oi->bfd_config.min_rx, oi->bfd_config.min_tx);
+               }
+       }
+
        return 0;
 }
 
-/* show interface */
-DEFUN(show_ipv6_ospf6_interface,
-      show_ipv6_ospf6_interface_ifname_cmd,
-      "show ipv6 ospf6 interface [IFNAME] [json]",
-      SHOW_STR
-      IP6_STR
-      OSPF6_STR
-      INTERFACE_STR
-      IFNAME_STR
-      JSON_STR)
+static int show_ospf6_interface_common(struct vty *vty, vrf_id_t vrf_id,
+                                      int argc, struct cmd_token **argv,
+                                      int idx_ifname, int intf_idx,
+                                      int json_idx)
 {
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
-       int idx_ifname = 4;
+
+       struct vrf *vrf = vrf_lookup_by_id(vrf_id);
        struct interface *ifp;
        json_object *json;
        json_object *json_int;
@@ -1172,9 +1191,8 @@ DEFUN(show_ipv6_ospf6_interface,
 
        if (uj) {
                json = json_object_new_object();
-               if (argc == 6) {
-                       ifp = if_lookup_by_name(argv[idx_ifname]->arg,
-                                               VRF_DEFAULT);
+               if (argc == json_idx) {
+                       ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
                        json_int = json_object_new_object();
                        if (ifp == NULL) {
                                json_object_string_add(json, "noSuchInterface",
@@ -1201,9 +1219,8 @@ DEFUN(show_ipv6_ospf6_interface,
                                json, JSON_C_TO_STRING_PRETTY));
                json_object_free(json);
        } else {
-               if (argc == 5) {
-                       ifp = if_lookup_by_name(argv[idx_ifname]->arg,
-                                               VRF_DEFAULT);
+               if (argc == intf_idx) {
+                       ifp = if_lookup_by_name(argv[idx_ifname]->arg, vrf_id);
                        if (ifp == NULL) {
                                vty_out(vty, "No such Interface: %s\n",
                                        argv[idx_ifname]->arg);
@@ -1215,6 +1232,42 @@ DEFUN(show_ipv6_ospf6_interface,
                                ospf6_interface_show(vty, ifp, NULL, uj);
                }
        }
+       return CMD_SUCCESS;
+}
+
+/* show interface */
+DEFUN(show_ipv6_ospf6_interface, show_ipv6_ospf6_interface_ifname_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] interface [IFNAME] [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" INTERFACE_STR IFNAME_STR JSON_STR)
+{
+       int idx_ifname = 4;
+       int intf_idx = 5;
+       int json_idx = 6;
+       struct listnode *node;
+       struct ospf6 *ospf6;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_ifname += 2;
+               intf_idx += 2;
+               json_idx += 2;
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       show_ospf6_interface_common(vty, ospf6->vrf_id, argc,
+                                                   argv, idx_ifname, intf_idx,
+                                                   json_idx);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
        return CMD_SUCCESS;
 }
@@ -1222,7 +1275,7 @@ DEFUN(show_ipv6_ospf6_interface,
 static int ospf6_interface_show_traffic(struct vty *vty,
                                        struct interface *intf_ifp,
                                        int display_once, json_object *json,
-                                       bool use_json)
+                                       bool use_json, vrf_id_t vrf_id)
 {
        struct interface *ifp;
        struct vrf *vrf = NULL;
@@ -1232,7 +1285,7 @@ static int ospf6_interface_show_traffic(struct vty *vty,
        if (intf_ifp)
                vrf = vrf_lookup_by_id(intf_ifp->vrf_id);
        else
-               vrf = vrf_lookup_by_id(VRF_DEFAULT);
+               vrf = vrf_lookup_by_id(vrf_id);
 
        if (!display_once && !use_json) {
                vty_out(vty, "\n");
@@ -1333,17 +1386,9 @@ static int ospf6_interface_show_traffic(struct vty *vty,
        return CMD_SUCCESS;
 }
 
-/* show interface */
-DEFUN(show_ipv6_ospf6_interface_traffic,
-      show_ipv6_ospf6_interface_traffic_cmd,
-      "show ipv6 ospf6 interface traffic [IFNAME] [json]",
-      SHOW_STR
-      IP6_STR
-      OSPF6_STR
-      INTERFACE_STR
-      "Protocol Packet counters\n"
-      IFNAME_STR
-      JSON_STR)
+static int ospf6_interface_show_traffic_common(struct vty *vty, int argc,
+                                              struct cmd_token **argv,
+                                              vrf_id_t vrf_id)
 {
        int idx_ifname = 0;
        int display_once = 0;
@@ -1357,7 +1402,7 @@ DEFUN(show_ipv6_ospf6_interface_traffic,
 
        if (argv_find(argv, argc, "IFNAME", &idx_ifname)) {
                intf_name = argv[idx_ifname]->arg;
-               ifp = if_lookup_by_name(intf_name, VRF_DEFAULT);
+               ifp = if_lookup_by_name(intf_name, vrf_id);
                if (uj) {
                        if (ifp == NULL) {
                                json_object_string_add(json, "status",
@@ -1397,7 +1442,7 @@ DEFUN(show_ipv6_ospf6_interface_traffic,
                }
        }
 
-       ospf6_interface_show_traffic(vty, ifp, display_once, json, uj);
+       ospf6_interface_show_traffic(vty, ifp, display_once, json, uj, vrf_id);
 
        if (uj) {
                vty_out(vty, "%s\n",
@@ -1406,94 +1451,148 @@ DEFUN(show_ipv6_ospf6_interface_traffic,
                json_object_free(json);
        }
 
+       return CMD_SUCCESS;
+}
+
+/* show interface */
+DEFUN(show_ipv6_ospf6_interface_traffic, show_ipv6_ospf6_interface_traffic_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] interface traffic [IFNAME] [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" INTERFACE_STR
+      "Protocol Packet counters\n" IFNAME_STR JSON_STR)
+{
+       struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_interface_show_traffic_common(vty, argc, argv,
+                                                           ospf6->vrf_id);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
        return CMD_SUCCESS;
 }
 
 
-DEFUN (show_ipv6_ospf6_interface_ifname_prefix,
-       show_ipv6_ospf6_interface_ifname_prefix_cmd,
-       "show ipv6 ospf6 interface IFNAME prefix\
+DEFUN(show_ipv6_ospf6_interface_ifname_prefix,
+      show_ipv6_ospf6_interface_ifname_prefix_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] interface IFNAME prefix\
           [<\
            detail\
            |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
          >] [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       INTERFACE_STR
-       IFNAME_STR
-       "Display connected prefixes to advertise\n"
-       "Display details of the prefixes\n"
-       OSPF6_ROUTE_ADDRESS_STR
-       OSPF6_ROUTE_PREFIX_STR
-       OSPF6_ROUTE_MATCH_STR
-       "Display details of the prefixes\n"
-       JSON_STR)
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" INTERFACE_STR IFNAME_STR
+      "Display connected prefixes to advertise\n"
+      "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
+             OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
+      "Display details of the prefixes\n" JSON_STR)
 {
        int idx_ifname = 4;
        int idx_prefix = 6;
-       struct interface *ifp;
        struct ospf6_interface *oi;
        bool uj = use_json(argc, argv);
 
-       ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT);
-       if (ifp == NULL) {
-               vty_out(vty, "No such Interface: %s\n", argv[idx_ifname]->arg);
-               return CMD_WARNING;
+       struct ospf6 *ospf6;
+       struct listnode *node;
+       struct interface *ifp;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_ifname += 2;
+               idx_prefix += 2;
        }
 
-       oi = ifp->info;
-       if (oi == NULL) {
-               vty_out(vty, "OSPFv3 is not enabled on %s\n",
-                       argv[idx_ifname]->arg);
-               return CMD_WARNING;
-       }
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ifp = if_lookup_by_name(argv[idx_ifname]->arg,
+                                               ospf6->vrf_id);
+                       if (ifp == NULL) {
+                               vty_out(vty, "No such Interface: %s\n",
+                                       argv[idx_ifname]->arg);
+                               return CMD_WARNING;
+                       }
 
-       if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
-               vty_out(vty, "Interface %s not attached to area\n",
-                       argv[idx_ifname]->arg);
-               return CMD_WARNING;
-       }
+                       oi = ifp->info;
+                       if (oi == NULL
+                           || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
+                               vty_out(vty,
+                                       "Interface %s not attached to area\n",
+                                       argv[idx_ifname]->arg);
+                               return CMD_WARNING;
+                       }
+
+                       ospf6_route_table_show(vty, idx_prefix, argc, argv,
+                                              oi->route_connected, uj);
 
-       ospf6_route_table_show(vty, idx_prefix, argc, argv, oi->route_connected,
-                              uj);
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_interface_prefix,
-       show_ipv6_ospf6_interface_prefix_cmd,
-       "show ipv6 ospf6 interface prefix\
+DEFUN(show_ipv6_ospf6_interface_prefix, show_ipv6_ospf6_interface_prefix_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] interface prefix\
           [<\
            detail\
            |<X:X::X:X|X:X::X:X/M> [<match|detail>]\
          >] [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       INTERFACE_STR
-       "Display connected prefixes to advertise\n"
-       "Display details of the prefixes\n"
-       OSPF6_ROUTE_ADDRESS_STR
-       OSPF6_ROUTE_PREFIX_STR
-       OSPF6_ROUTE_MATCH_STR
-       "Display details of the prefixes\n"
-       JSON_STR)
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" INTERFACE_STR
+      "Display connected prefixes to advertise\n"
+      "Display details of the prefixes\n" OSPF6_ROUTE_ADDRESS_STR
+             OSPF6_ROUTE_PREFIX_STR OSPF6_ROUTE_MATCH_STR
+      "Display details of the prefixes\n" JSON_STR)
 {
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
+       struct vrf *vrf = NULL;
        int idx_prefix = 5;
        struct ospf6_interface *oi;
        struct interface *ifp;
        bool uj = use_json(argc, argv);
-
-       FOR_ALL_INTERFACES (vrf, ifp) {
-               oi = (struct ospf6_interface *)ifp->info;
-               if (oi == NULL || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE))
-                       continue;
-
-               ospf6_route_table_show(vty, idx_prefix, argc, argv,
-                                      oi->route_connected, uj);
+       struct listnode *node;
+       struct ospf6 *ospf6;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_prefix += 2;
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       vrf = vrf_lookup_by_id(ospf6->vrf_id);
+                       FOR_ALL_INTERFACES (vrf, ifp) {
+                               oi = (struct ospf6_interface *)ifp->info;
+                               if (oi == NULL
+                                   || CHECK_FLAG(oi->flag,
+                                                 OSPF6_INTERFACE_DISABLE))
+                                       continue;
+
+                               ospf6_route_table_show(vty, idx_prefix, argc,
+                                                      argv,
+                                                      oi->route_connected, uj);
+                       }
+                       if (!all_vrf)
+                               break;
+               }
        }
 
        return CMD_SUCCESS;
@@ -1879,10 +1978,13 @@ DEFUN (ipv6_ospf6_priority,
                               ? OSPF6_INTERFACE_PRIORITY
                               : strtoul(argv[idx_number]->arg, NULL, 10);
 
-       if (oi->area && (oi->state == OSPF6_INTERFACE_DROTHER
-                        || oi->state == OSPF6_INTERFACE_BDR
-                        || oi->state == OSPF6_INTERFACE_DR))
-               ospf6_interface_state_change(dr_election(oi), oi);
+       if (oi->area
+           && (oi->state == OSPF6_INTERFACE_DROTHER
+               || oi->state == OSPF6_INTERFACE_BDR
+               || oi->state == OSPF6_INTERFACE_DR)) {
+               if (ospf6_interface_state_change(dr_election(oi), oi) == -1)
+                       OSPF6_LINK_LSA_SCHEDULE(oi);
+       }
 
        return CMD_SUCCESS;
 }
@@ -2188,9 +2290,8 @@ DEFUN (no_ipv6_ospf6_network,
        return CMD_SUCCESS;
 }
 
-static int config_write_ospf6_interface(struct vty *vty)
+static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf)
 {
-       struct vrf *vrf = vrf_lookup_by_id(VRF_DEFAULT);
        struct ospf6_interface *oi;
        struct interface *ifp;
 
@@ -2199,7 +2300,11 @@ static int config_write_ospf6_interface(struct vty *vty)
                if (oi == NULL)
                        continue;
 
-               vty_frame(vty, "interface %s\n", oi->interface->name);
+               if (vrf->vrf_id == VRF_DEFAULT)
+                       vty_frame(vty, "interface %s\n", oi->interface->name);
+               else
+                       vty_frame(vty, "interface %s vrf %s\n",
+                                 oi->interface->name, vrf->name);
 
                if (ifp->desc)
                        vty_out(vty, " description %s\n", ifp->desc);
@@ -2254,13 +2359,27 @@ static int config_write_ospf6_interface(struct vty *vty)
        return 0;
 }
 
-static int config_write_ospf6_interface(struct vty *vty);
+/* Configuration write function for ospfd. */
+static int config_write_interface(struct vty *vty)
+{
+       int write = 0;
+       struct vrf *vrf = NULL;
+
+       /* Display all VRF aware OSPF interface configuration */
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               write += config_write_ospf6_interface(vty, vrf);
+       }
+
+       return write;
+}
+
+static int config_write_ospf6_interface(struct vty *vty, struct vrf *vrf);
 static struct cmd_node interface_node = {
        .name = "interface",
        .node = INTERFACE_NODE,
        .parent_node = CONFIG_NODE,
        .prompt = "%s(config-if)# ",
-       .config_write = config_write_ospf6_interface,
+       .config_write = config_write_interface,
 };
 
 static int ospf6_ifp_create(struct interface *ifp)
index 2a5a9ba4a2da1981b03f29fc55c2ede2a49ec7b6..a45a841406da4e4a6b6b1ab0ee47c4ef4c3c756a 100644 (file)
@@ -119,7 +119,13 @@ struct ospf6_interface {
        char *plist_name;
 
        /* BFD information */
-       void *bfd_info;
+       struct {
+               bool enabled;
+               uint8_t detection_multiplier;
+               uint32_t min_rx;
+               uint32_t min_tx;
+               char *profile;
+       } bfd_config;
 
        /* Statistics Fields */
        uint32_t hello_in;
index adff76ec4114f15a75dff061b146d4a16d668d4e..61a438b04a123432d1e41463e18a75014a7afefc 100644 (file)
@@ -1672,7 +1672,7 @@ void ospf6_intra_prefix_route_ecmp_path(struct ospf6_area *oa,
 
                        if (IS_OSPF6_DEBUG_EXAMIN(INTRA_PREFIX))
                                zlog_debug(
-                                       "%s: route %pFX %p with final effective paths %u nh%u",
+                                       "%s: route %pFX %p with final effective paths %u nh %u",
                                        __func__, &route->prefix,
                                        (void *)old_route,
                                        old_route->paths
index cf61ca7a62dd16c20e5052292534505e046813b4..5ffcf8c2faee58dcabe112444e3214b1ec87e1d5 100644 (file)
@@ -225,7 +225,7 @@ int main(int argc, char *argv[], char *envp[])
        /* thread master */
        master = om6->master;
 
-       vrf_init(NULL, NULL, NULL, NULL, NULL);
+       ospf6_vrf_init();
        access_list_init();
        prefix_list_init();
 
index 7aedd3df45a624c41f2a559b0a38a139f7ffa473..d2dcfd81d4e31d92a8d0f138bbdb249a85bf7e60 100644 (file)
@@ -94,7 +94,7 @@ static void ospf6_header_print(struct ospf6_header *oh)
                   ntohs(oh->checksum), oh->instance_id);
 }
 
-void ospf6_hello_print(struct ospf6_header *oh)
+void ospf6_hello_print(struct ospf6_header *oh, int action)
 {
        struct ospf6_hello *hello;
        char options[16];
@@ -115,15 +115,21 @@ void ospf6_hello_print(struct ospf6_header *oh)
                   ntohs(hello->hello_interval), ntohs(hello->dead_interval));
        zlog_debug("    DR:%pI4 BDR:%pI4", &hello->drouter, &hello->bdrouter);
 
-       for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
-            p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
-            p += sizeof(uint32_t))
-               zlog_debug("    Neighbor: %pI4", (in_addr_t *)p);
+       if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
+            && action == OSPF6_ACTION_RECV)
+           || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
+               && action == OSPF6_ACTION_SEND)) {
 
-       assert(p == OSPF6_MESSAGE_END(oh));
+               for (p = (char *)((caddr_t)hello + sizeof(struct ospf6_hello));
+                    p + sizeof(uint32_t) <= OSPF6_MESSAGE_END(oh);
+                    p += sizeof(uint32_t))
+                       zlog_debug("    Neighbor: %pI4", (in_addr_t *)p);
+
+               assert(p == OSPF6_MESSAGE_END(oh));
+       }
 }
 
-void ospf6_dbdesc_print(struct ospf6_header *oh)
+void ospf6_dbdesc_print(struct ospf6_header *oh, int action)
 {
        struct ospf6_dbdesc *dbdesc;
        char options[16];
@@ -145,34 +151,52 @@ void ospf6_dbdesc_print(struct ospf6_header *oh)
                   (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT) ? "m" : "s"),
                   (unsigned long)ntohl(dbdesc->seqnum));
 
-       for (p = (char *)((caddr_t)dbdesc + sizeof(struct ospf6_dbdesc));
-            p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
-            p += sizeof(struct ospf6_lsa_header))
-               ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p);
+       if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
+            && action == OSPF6_ACTION_RECV)
+           || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
+               && action == OSPF6_ACTION_SEND)) {
 
-       assert(p == OSPF6_MESSAGE_END(oh));
+               for (p = (char *)((caddr_t)dbdesc
+                                 + sizeof(struct ospf6_dbdesc));
+                    p + sizeof(struct ospf6_lsa_header)
+                    <= OSPF6_MESSAGE_END(oh);
+                    p += sizeof(struct ospf6_lsa_header))
+                       ospf6_lsa_header_print_raw(
+                               (struct ospf6_lsa_header *)p);
+
+               assert(p == OSPF6_MESSAGE_END(oh));
+       }
 }
 
-void ospf6_lsreq_print(struct ospf6_header *oh)
+void ospf6_lsreq_print(struct ospf6_header *oh, int action)
 {
        char *p;
 
        ospf6_header_print(oh);
        assert(oh->type == OSPF6_MESSAGE_TYPE_LSREQ);
 
-       for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
-            p + sizeof(struct ospf6_lsreq_entry) <= OSPF6_MESSAGE_END(oh);
-            p += sizeof(struct ospf6_lsreq_entry)) {
-               struct ospf6_lsreq_entry *e = (struct ospf6_lsreq_entry *)p;
+       if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
+            && action == OSPF6_ACTION_RECV)
+           || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
+               && action == OSPF6_ACTION_SEND)) {
+
+               for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
+                    p + sizeof(struct ospf6_lsreq_entry)
+                    <= OSPF6_MESSAGE_END(oh);
+                    p += sizeof(struct ospf6_lsreq_entry)) {
+                       struct ospf6_lsreq_entry *e =
+                               (struct ospf6_lsreq_entry *)p;
+
+                       zlog_debug("    [%s Id:%pI4 Adv:%pI4]",
+                                  ospf6_lstype_name(e->type), &e->id,
+                                  &e->adv_router);
+               }
 
-               zlog_debug("    [%s Id:%pI4 Adv:%pI4]",
-                          ospf6_lstype_name(e->type), &e->id, &e->adv_router);
+               assert(p == OSPF6_MESSAGE_END(oh));
        }
-
-       assert(p == OSPF6_MESSAGE_END(oh));
 }
 
-void ospf6_lsupdate_print(struct ospf6_header *oh)
+void ospf6_lsupdate_print(struct ospf6_header *oh, int action)
 {
        struct ospf6_lsupdate *lsupdate;
        unsigned long num;
@@ -187,29 +211,45 @@ void ospf6_lsupdate_print(struct ospf6_header *oh)
        num = ntohl(lsupdate->lsa_number);
        zlog_debug("    Number of LSA: %ld", num);
 
-       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)) {
-               ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p);
-       }
+       if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
+            && 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)) {
+                       ospf6_lsa_header_print_raw(
+                               (struct ospf6_lsa_header *)p);
+               }
 
-       assert(p == OSPF6_MESSAGE_END(oh));
+               assert(p == OSPF6_MESSAGE_END(oh));
+       }
 }
 
-void ospf6_lsack_print(struct ospf6_header *oh)
+void ospf6_lsack_print(struct ospf6_header *oh, int action)
 {
        char *p;
 
        ospf6_header_print(oh);
        assert(oh->type == OSPF6_MESSAGE_TYPE_LSACK);
 
-       for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
-            p + sizeof(struct ospf6_lsa_header) <= OSPF6_MESSAGE_END(oh);
-            p += sizeof(struct ospf6_lsa_header))
-               ospf6_lsa_header_print_raw((struct ospf6_lsa_header *)p);
+       if ((IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)
+            && action == OSPF6_ACTION_RECV)
+           || (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)
+               && action == OSPF6_ACTION_SEND)) {
 
-       assert(p == OSPF6_MESSAGE_END(oh));
+               for (p = (char *)((caddr_t)oh + sizeof(struct ospf6_header));
+                    p + sizeof(struct ospf6_lsa_header)
+                    <= OSPF6_MESSAGE_END(oh);
+                    p += sizeof(struct ospf6_lsa_header))
+                       ospf6_lsa_header_print_raw(
+                               (struct ospf6_lsa_header *)p);
+
+               assert(p == OSPF6_MESSAGE_END(oh));
+       }
 }
 
 static void ospf6_hello_recv(struct in6_addr *src, struct in6_addr *dst,
@@ -348,21 +388,21 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
                                         + sizeof(struct ospf6_header));
 
        if (on->state < OSPF6_NEIGHBOR_INIT) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor state less than Init, ignore");
                return;
        }
 
        switch (on->state) {
        case OSPF6_NEIGHBOR_TWOWAY:
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor state is 2-Way, ignore");
                return;
 
        case OSPF6_NEIGHBOR_INIT:
                thread_execute(master, twoway_received, on, 0);
                if (on->state != OSPF6_NEIGHBOR_EXSTART) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Neighbor state is not ExStart, ignore");
                        return;
@@ -395,14 +435,14 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
                            sizeof(struct ospf6_dbdesc))) {
                        /* Duplicated DatabaseDescription is dropped by master
                         */
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Duplicated dbdesc discarded by Master, ignore");
                        return;
                }
 
                if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug("Master/Slave bit mismatch");
                        thread_add_event(master, seqnumber_mismatch, on, 0,
                                         NULL);
@@ -410,7 +450,7 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
                }
 
                if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug("Initialize bit mismatch");
                        thread_add_event(master, seqnumber_mismatch, on, 0,
                                         NULL);
@@ -418,7 +458,7 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
                }
 
                if (memcmp(on->options, dbdesc->options, sizeof(on->options))) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug("Option field mismatch");
                        thread_add_event(master, seqnumber_mismatch, on, 0,
                                         NULL);
@@ -426,7 +466,7 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
                }
 
                if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Sequence number mismatch (%#lx expected)",
                                        (unsigned long)on->dbdesc_seqnum);
@@ -442,13 +482,13 @@ static void ospf6_dbdesc_recv_master(struct ospf6_header *oh,
                            sizeof(struct ospf6_dbdesc))) {
                        /* Duplicated DatabaseDescription is dropped by master
                         */
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Duplicated dbdesc discarded by Master, ignore");
                        return;
                }
 
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Not duplicate dbdesc in state %s",
                                   ospf6_neighbor_state_str[on->state]);
                thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
@@ -553,21 +593,21 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                                         + sizeof(struct ospf6_header));
 
        if (on->state < OSPF6_NEIGHBOR_INIT) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor state less than Init, ignore");
                return;
        }
 
        switch (on->state) {
        case OSPF6_NEIGHBOR_TWOWAY:
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor state is 2-Way, ignore");
                return;
 
        case OSPF6_NEIGHBOR_INIT:
                thread_execute(master, twoway_received, on, 0);
                if (on->state != OSPF6_NEIGHBOR_EXSTART) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Neighbor state is not ExStart, ignore");
                        return;
@@ -611,7 +651,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                            sizeof(struct ospf6_dbdesc))) {
                        /* Duplicated DatabaseDescription causes slave to
                         * retransmit */
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Duplicated dbdesc causes retransmit");
                        THREAD_OFF(on->thread_send_dbdesc);
@@ -622,7 +662,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                }
 
                if (!CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_MSBIT)) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug("Master/Slave bit mismatch");
                        thread_add_event(master, seqnumber_mismatch, on, 0,
                                         NULL);
@@ -630,7 +670,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                }
 
                if (CHECK_FLAG(dbdesc->bits, OSPF6_DBDESC_IBIT)) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug("Initialize bit mismatch");
                        thread_add_event(master, seqnumber_mismatch, on, 0,
                                         NULL);
@@ -638,7 +678,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                }
 
                if (memcmp(on->options, dbdesc->options, sizeof(on->options))) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug("Option field mismatch");
                        thread_add_event(master, seqnumber_mismatch, on, 0,
                                         NULL);
@@ -646,7 +686,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                }
 
                if (ntohl(dbdesc->seqnum) != on->dbdesc_seqnum + 1) {
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Sequence number mismatch (%#lx expected)",
                                        (unsigned long)on->dbdesc_seqnum + 1);
@@ -662,7 +702,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                            sizeof(struct ospf6_dbdesc))) {
                        /* Duplicated DatabaseDescription causes slave to
                         * retransmit */
-                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+                       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                                zlog_debug(
                                        "Duplicated dbdesc causes retransmit");
                        THREAD_OFF(on->thread_send_dbdesc);
@@ -671,7 +711,7 @@ static void ospf6_dbdesc_recv_slave(struct ospf6_header *oh,
                        return;
                }
 
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Not duplicate dbdesc in state %s",
                                   ospf6_neighbor_state_str[on->state]);
                thread_add_event(master, seqnumber_mismatch, on, 0, NULL);
@@ -756,7 +796,7 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
 
        on = ospf6_neighbor_lookup(oh->router_id, oi);
        if (on == NULL) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor not found, ignore");
                return;
        }
@@ -773,7 +813,7 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
        }
 
        if (dbdesc->reserved1 || dbdesc->reserved2) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug(
                                "Non-0 reserved field in %s's DbDesc, correct",
                                on->name);
@@ -788,7 +828,7 @@ static void ospf6_dbdesc_recv(struct in6_addr *src, struct in6_addr *dst,
        else if (ntohl(oi->area->ospf6->router_id) < ntohl(oh->router_id))
                ospf6_dbdesc_recv_slave(oh, on);
        else {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Can't decide which is master, ignore");
        }
 }
@@ -805,7 +845,7 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst,
 
        on = ospf6_neighbor_lookup(oh->router_id, oi);
        if (on == NULL) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor not found, ignore");
                return;
        }
@@ -813,7 +853,7 @@ static void ospf6_lsreq_recv(struct in6_addr *src, struct in6_addr *dst,
        if (on->state != OSPF6_NEIGHBOR_EXCHANGE
            && on->state != OSPF6_NEIGHBOR_LOADING
            && on->state != OSPF6_NEIGHBOR_FULL) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor state less than Exchange, ignore");
                return;
        }
@@ -882,7 +922,7 @@ static unsigned ospf6_prefixes_examin(
        while (length) {
                if (length < OSPF6_PREFIX_MIN_SIZE) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug("%s: undersized IPv6 prefix header",
                                           __func__);
                        return MSG_NG;
@@ -890,7 +930,7 @@ static unsigned ospf6_prefixes_examin(
                /* safe to look deeper */
                if (current->prefix_length > IPV6_MAX_BITLEN) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug("%s: invalid PrefixLength (%u bits)",
                                           __func__, current->prefix_length);
                        return MSG_NG;
@@ -901,7 +941,7 @@ static unsigned ospf6_prefixes_examin(
                        + OSPF6_PREFIX_SPACE(current->prefix_length);
                if (requested_pfx_bytes > length) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug("%s: undersized IPv6 prefix",
                                           __func__);
                        return MSG_NG;
@@ -913,7 +953,8 @@ static unsigned ospf6_prefixes_examin(
                real_num_pfxs++;
        }
        if (real_num_pfxs != req_num_pfxs) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug(
                                "%s: IPv6 prefix number mismatch (%u required, %u real)",
                                __func__, req_num_pfxs, real_num_pfxs);
@@ -945,7 +986,8 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
        ltindex = lsatype & OSPF6_LSTYPE_FCODE_MASK;
        if (ltindex < OSPF6_LSTYPE_SIZE && ospf6_lsa_minlen[ltindex]
            && lsalen < ospf6_lsa_minlen[ltindex] + OSPF6_LSA_HEADER_SIZE) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: undersized (%u B) LSA", __func__,
                                   lsalen);
                return MSG_NG;
@@ -958,7 +1000,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
                if ((lsalen - OSPF6_LSA_HEADER_SIZE - OSPF6_ROUTER_LSA_MIN_SIZE)
                    % OSPF6_ROUTER_LSDESC_FIX_SIZE) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug(
                                        "%s: interface description alignment error",
                                        __func__);
@@ -972,7 +1014,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
                     - OSPF6_NETWORK_LSA_MIN_SIZE)
                    % OSPF6_NETWORK_LSDESC_FIX_SIZE) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug(
                                        "%s: router description alignment error",
                                        __func__);
@@ -997,7 +1039,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
                if (lsalen
                    > OSPF6_LSA_HEADER_SIZE + OSPF6_INTER_ROUTER_LSA_FIX_SIZE) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug("%s: oversized (%u B) LSA", __func__,
                                           lsalen);
                        return MSG_NG;
@@ -1026,7 +1068,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
                   prefix before ospf6_prefix_examin() confirms its sizing. */
                if (exp_length + OSPF6_PREFIX_MIN_SIZE > lsalen) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug("%s: undersized (%u B) LSA header",
                                           __func__, lsalen);
                        return MSG_NG;
@@ -1045,7 +1087,7 @@ static unsigned ospf6_lsa_examin(struct ospf6_lsa_header *lsah,
                   this check does not include any IPv6 prefix fields. */
                if (exp_length > lsalen) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug("%s: undersized (%u B) LSA header",
                                           __func__, lsalen);
                        return MSG_NG;
@@ -1114,7 +1156,7 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
                uint16_t lsalen;
                if (length < OSPF6_LSA_HEADER_SIZE) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug(
                                        "%s: undersized (%zu B) trailing (#%u) LSA header",
                                        __func__, length, counted_lsas);
@@ -1124,7 +1166,7 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
                lsalen = OSPF6_LSA_SIZE(lsah);
                if (lsalen < OSPF6_LSA_HEADER_SIZE) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
-                                                  RECV))
+                                                  RECV_HDR))
                                zlog_debug(
                                        "%s: malformed LSA header #%u, declared length is %u B",
                                        __func__, counted_lsas, lsalen);
@@ -1134,7 +1176,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
                        /* less checks here and in ospf6_lsa_examin() */
                        if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 1)) {
                                if (IS_OSPF6_DEBUG_MESSAGE(
-                                           OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+                                           OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                           RECV_HDR))
                                        zlog_debug(
                                                "%s: anomaly in header-only %s LSA #%u",
                                                __func__,
@@ -1151,7 +1194,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
                         * further checks */
                        if (lsalen > length) {
                                if (IS_OSPF6_DEBUG_MESSAGE(
-                                           OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+                                           OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                           RECV_HDR))
                                        zlog_debug(
                                                "%s: anomaly in %s LSA #%u: declared length is %u B, buffered length is %zu B",
                                                __func__,
@@ -1161,7 +1205,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
                        }
                        if (MSG_OK != ospf6_lsa_examin(lsah, lsalen, 0)) {
                                if (IS_OSPF6_DEBUG_MESSAGE(
-                                           OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+                                           OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                           RECV_HDR))
                                        zlog_debug(
                                                "%s: anomaly in %s LSA #%u",
                                                __func__,
@@ -1177,7 +1222,8 @@ ospf6_lsaseq_examin(struct ospf6_lsa_header *lsah, /* start of buffered data */
        }
 
        if (declared_num_lsas && counted_lsas != declared_num_lsas) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug(
                                "%s: #LSAs declared (%u) does not match actual (%u)",
                                __func__, declared_num_lsas, counted_lsas);
@@ -1195,14 +1241,16 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
 
        /* length, 1st approximation */
        if (bytesonwire < OSPF6_HEADER_SIZE) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: undersized (%u B) packet", __func__,
                                   bytesonwire);
                return MSG_NG;
        }
        /* Now it is safe to access header fields. */
        if (bytesonwire != ntohs(oh->length)) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug(
                                "%s: %s packet length error (%u real, %u declared)",
                                __func__, lookup_msg(ospf6_message_type_str,
@@ -1212,7 +1260,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
        }
        /* version check */
        if (oh->version != OSPFV3_VERSION) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: invalid (%u) protocol version",
                                   __func__, oh->version);
                return MSG_NG;
@@ -1221,7 +1270,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
        if (oh->type < OSPF6_MESSAGE_TYPE_ALL && ospf6_packet_minlen[oh->type]
            && bytesonwire
                       < OSPF6_HEADER_SIZE + ospf6_packet_minlen[oh->type]) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: undersized (%u B) %s packet", __func__,
                                   bytesonwire,
                                   lookup_msg(ospf6_message_type_str, oh->type,
@@ -1238,7 +1288,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
                    == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_HELLO_MIN_SIZE)
                               % 4)
                        return MSG_OK;
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: alignment error in %s packet", __func__,
                                   lookup_msg(ospf6_message_type_str, oh->type,
                                              NULL));
@@ -1261,7 +1312,8 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
                    == (bytesonwire - OSPF6_HEADER_SIZE - OSPF6_LS_REQ_MIN_SIZE)
                               % OSPF6_LSREQ_LSDESC_FIX_SIZE)
                        return MSG_OK;
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: alignment error in %s packet", __func__,
                                   lookup_msg(ospf6_message_type_str, oh->type,
                                              NULL));
@@ -1289,13 +1341,14 @@ static unsigned ospf6_packet_examin(struct ospf6_header *oh,
                        1, 0);
                break;
        default:
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: invalid (%u) message type", __func__,
                                   oh->type);
                return MSG_NG;
        }
        if (test != MSG_OK
-           && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+           && IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV_HDR))
                zlog_debug("%s: anomaly in %s packet", __func__,
                           lookup_msg(ospf6_message_type_str, oh->type, NULL));
        return test;
@@ -1356,7 +1409,7 @@ static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst,
 
        on = ospf6_neighbor_lookup(oh->router_id, oi);
        if (on == NULL) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor not found, ignore");
                return;
        }
@@ -1364,7 +1417,7 @@ static void ospf6_lsupdate_recv(struct in6_addr *src, struct in6_addr *dst,
        if (on->state != OSPF6_NEIGHBOR_EXCHANGE
            && on->state != OSPF6_NEIGHBOR_LOADING
            && on->state != OSPF6_NEIGHBOR_FULL) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor state less than Exchange, ignore");
                return;
        }
@@ -1398,7 +1451,7 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst,
 
        on = ospf6_neighbor_lookup(oh->router_id, oi);
        if (on == NULL) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor not found, ignore");
                return;
        }
@@ -1406,7 +1459,7 @@ static void ospf6_lsack_recv(struct in6_addr *src, struct in6_addr *dst,
        if (on->state != OSPF6_NEIGHBOR_EXCHANGE
            && on->state != OSPF6_NEIGHBOR_LOADING
            && on->state != OSPF6_NEIGHBOR_FULL) {
-               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR))
                        zlog_debug("Neighbor state less than Exchange, ignore");
                return;
        }
@@ -1555,12 +1608,14 @@ int ospf6_receive(struct thread *thread)
        oi = ospf6_interface_lookup_by_ifindex(ifindex, ospf6->vrf_id);
        if (oi == NULL || oi->area == NULL
            || CHECK_FLAG(oi->flag, OSPF6_INTERFACE_DISABLE)) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("Message received on disabled interface");
                return 0;
        }
        if (CHECK_FLAG(oi->flag, OSPF6_INTERFACE_PASSIVE)) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN,
+                                          RECV_HDR))
                        zlog_debug("%s: Ignore message on passive interface %s",
                                   __func__, oi->interface->name);
                return 0;
@@ -1576,7 +1631,7 @@ int ospf6_receive(struct thread *thread)
           which can be dismissed in a cleanup-focused review round later. */
 
        /* Log */
-       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV)) {
+       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, RECV_HDR)) {
                zlog_debug("%s received on %s",
                           lookup_msg(ospf6_message_type_str, oh->type, NULL),
                           oi->interface->name);
@@ -1585,19 +1640,19 @@ int ospf6_receive(struct thread *thread)
 
                switch (oh->type) {
                case OSPF6_MESSAGE_TYPE_HELLO:
-                       ospf6_hello_print(oh);
+                       ospf6_hello_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_DBDESC:
-                       ospf6_dbdesc_print(oh);
+                       ospf6_dbdesc_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_LSREQ:
-                       ospf6_lsreq_print(oh);
+                       ospf6_lsreq_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_LSUPDATE:
-                       ospf6_lsupdate_print(oh);
+                       ospf6_lsupdate_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_LSACK:
-                       ospf6_lsack_print(oh);
+                       ospf6_lsack_print(oh, OSPF6_ACTION_RECV);
                        break;
                default:
                        assert(0);
@@ -1656,7 +1711,7 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
        oh->reserved = 0;
 
        /* Log */
-       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND)) {
+       if (IS_OSPF6_DEBUG_MESSAGE(oh->type, SEND_HDR)) {
                if (src)
                        inet_ntop(AF_INET6, src, srcname, sizeof(srcname));
                else
@@ -1669,19 +1724,19 @@ static void ospf6_send(struct in6_addr *src, struct in6_addr *dst,
 
                switch (oh->type) {
                case OSPF6_MESSAGE_TYPE_HELLO:
-                       ospf6_hello_print(oh);
+                       ospf6_hello_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_DBDESC:
-                       ospf6_dbdesc_print(oh);
+                       ospf6_dbdesc_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_LSREQ:
-                       ospf6_lsreq_print(oh);
+                       ospf6_lsreq_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_LSUPDATE:
-                       ospf6_lsupdate_print(oh);
+                       ospf6_lsupdate_print(oh, OSPF6_ACTION_RECV);
                        break;
                case OSPF6_MESSAGE_TYPE_LSACK:
-                       ospf6_lsack_print(oh);
+                       ospf6_lsack_print(oh, OSPF6_ACTION_RECV);
                        break;
                default:
                        zlog_debug("Unknown message");
@@ -1719,7 +1774,7 @@ int ospf6_hello_send(struct thread *thread)
        oi->thread_send_hello = (struct thread *)NULL;
 
        if (oi->state <= OSPF6_INTERFACE_DOWN) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO, SEND_HDR))
                        zlog_debug("Unable to send Hello on down interface %s",
                                   oi->interface->name);
                return 0;
@@ -1758,7 +1813,7 @@ int ospf6_hello_send(struct thread *thread)
 
                if (p - sendbuf + sizeof(uint32_t) > ospf6_packet_max(oi)) {
                        if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_HELLO,
-                                                  SEND))
+                                                  SEND_HDR))
                                zlog_debug(
                                        "sending Hello message: exceeds I/F MTU");
                        break;
@@ -1790,7 +1845,7 @@ int ospf6_dbdesc_send(struct thread *thread)
        on->thread_send_dbdesc = (struct thread *)NULL;
 
        if (on->state < OSPF6_NEIGHBOR_EXSTART) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_DBDESC, SEND_HDR))
                        zlog_debug(
                                "Quit to send DbDesc to neighbor %s state %s",
                                on->name, ospf6_neighbor_state_str[on->state]);
@@ -1918,7 +1973,7 @@ int ospf6_lsreq_send(struct thread *thread)
        /* LSReq will be sent only in ExStart or Loading */
        if (on->state != OSPF6_NEIGHBOR_EXCHANGE
            && on->state != OSPF6_NEIGHBOR_LOADING) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSREQ, SEND_HDR))
                        zlog_debug("Quit to send LSReq to neighbor %s state %s",
                                   on->name,
                                   ospf6_neighbor_state_str[on->state]);
@@ -2029,11 +2084,12 @@ int ospf6_lsupdate_send_neighbor(struct thread *thread)
        on = (struct ospf6_neighbor *)THREAD_ARG(thread);
        on->thread_send_lsupdate = (struct thread *)NULL;
 
-       if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+       if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
                zlog_debug("LSUpdate to neighbor %s", on->name);
 
        if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
+                                          SEND_HDR))
                        zlog_debug("Quit to send (neighbor state %s)",
                                   ospf6_neighbor_state_str[on->state]);
                return 0;
@@ -2190,7 +2246,7 @@ int ospf6_lsupdate_send_neighbor_now(struct ospf6_neighbor *on,
        lsupdate->lsa_number = htonl(lsa_cnt);
 
        if (IS_OSPF6_DEBUG_FLOODING
-           || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+           || IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND_HDR))
                zlog_debug("%s: Send lsupdate with lsa %s (age %u)", __func__,
                           lsa->name, ntohs(lsa->header->age));
 
@@ -2212,7 +2268,8 @@ int ospf6_lsupdate_send_interface(struct thread *thread)
        oi->thread_send_lsupdate = (struct thread *)NULL;
 
        if (oi->state <= OSPF6_INTERFACE_WAITING) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSUPDATE,
+                                          SEND_HDR))
                        zlog_debug(
                                "Quit to send LSUpdate to interface %s state %s",
                                oi->interface->name,
@@ -2299,7 +2356,7 @@ int ospf6_lsack_send_neighbor(struct thread *thread)
        on->thread_send_lsack = (struct thread *)NULL;
 
        if (on->state < OSPF6_NEIGHBOR_EXCHANGE) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
                        zlog_debug("Quit to send LSAck to neighbor %s state %s",
                                   on->name,
                                   ospf6_neighbor_state_str[on->state]);
@@ -2377,7 +2434,7 @@ int ospf6_lsack_send_interface(struct thread *thread)
        oi->thread_send_lsack = (struct thread *)NULL;
 
        if (oi->state <= OSPF6_INTERFACE_WAITING) {
-               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_LSACK, SEND_HDR))
                        zlog_debug(
                                "Quit to send LSAck to interface %s state %s",
                                oi->interface->name,
@@ -2440,21 +2497,21 @@ int ospf6_lsack_send_interface(struct thread *thread)
 
 
 /* Commands */
-DEFUN (debug_ospf6_message,
-       debug_ospf6_message_cmd,
-       "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
-       DEBUG_STR
-       OSPF6_STR
-       "Debug OSPFv3 message\n"
-       "Debug Unknown message\n"
-       "Debug Hello message\n"
-       "Debug Database Description message\n"
-       "Debug Link State Request message\n"
-       "Debug Link State Update message\n"
-       "Debug Link State Acknowledgement message\n"
-       "Debug All message\n"
-       "Debug only sending message\n"
-       "Debug only receiving message\n")
+DEFUN(debug_ospf6_message, debug_ospf6_message_cmd,
+      "debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
+      DEBUG_STR OSPF6_STR
+      "Debug OSPFv3 message\n"
+      "Debug Unknown message\n"
+      "Debug Hello message\n"
+      "Debug Database Description message\n"
+      "Debug Link State Request message\n"
+      "Debug Link State Update message\n"
+      "Debug Link State Acknowledgement message\n"
+      "Debug All message\n"
+      "Debug only sending message, entire packet\n"
+      "Debug only receiving message, entire packet\n"
+      "Debug only sending message, header only\n"
+      "Debug only receiving message, header only\n")
 {
        int idx_packet = 3;
        int idx_send_recv = 4;
@@ -2480,8 +2537,12 @@ DEFUN (debug_ospf6_message,
 
        if (argc == 4)
                level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
+       else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
+               level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
        else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
                level = OSPF6_DEBUG_MESSAGE_SEND;
+       else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
+               level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
        else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
                level = OSPF6_DEBUG_MESSAGE_RECV;
 
@@ -2494,22 +2555,21 @@ DEFUN (debug_ospf6_message,
        return CMD_SUCCESS;
 }
 
-DEFUN (no_debug_ospf6_message,
-       no_debug_ospf6_message_cmd,
-       "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv>]",
-       NO_STR
-       DEBUG_STR
-       OSPF6_STR
-       "Debug OSPFv3 message\n"
-       "Debug Unknown message\n"
-       "Debug Hello message\n"
-       "Debug Database Description message\n"
-       "Debug Link State Request message\n"
-       "Debug Link State Update message\n"
-       "Debug Link State Acknowledgement message\n"
-       "Debug All message\n"
-       "Debug only sending message\n"
-       "Debug only receiving message\n")
+DEFUN(no_debug_ospf6_message, no_debug_ospf6_message_cmd,
+      "no debug ospf6 message <unknown|hello|dbdesc|lsreq|lsupdate|lsack|all> [<send|recv|send-hdr|recv-hdr>]",
+      NO_STR DEBUG_STR OSPF6_STR
+      "Debug OSPFv3 message\n"
+      "Debug Unknown message\n"
+      "Debug Hello message\n"
+      "Debug Database Description message\n"
+      "Debug Link State Request message\n"
+      "Debug Link State Update message\n"
+      "Debug Link State Acknowledgement message\n"
+      "Debug All message\n"
+      "Debug only sending message, entire pkt\n"
+      "Debug only receiving message, entire pkt\n"
+      "Debug only sending message, header only\n"
+      "Debug only receiving message, header only\n")
 {
        int idx_packet = 4;
        int idx_send_recv = 5;
@@ -2534,9 +2594,15 @@ DEFUN (no_debug_ospf6_message,
                type = OSPF6_MESSAGE_TYPE_ALL;
 
        if (argc == 5)
-               level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV;
+               level = OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_RECV
+                       | OSPF6_DEBUG_MESSAGE_SEND_HDR
+                       | OSPF6_DEBUG_MESSAGE_RECV_HDR;
+       else if (!strncmp(argv[idx_send_recv]->arg, "send-h", 6))
+               level = OSPF6_DEBUG_MESSAGE_SEND_HDR;
        else if (!strncmp(argv[idx_send_recv]->arg, "s", 1))
                level = OSPF6_DEBUG_MESSAGE_SEND;
+       else if (!strncmp(argv[idx_send_recv]->arg, "recv-h", 6))
+               level = OSPF6_DEBUG_MESSAGE_RECV_HDR;
        else if (!strncmp(argv[idx_send_recv]->arg, "r", 1))
                level = OSPF6_DEBUG_MESSAGE_RECV;
 
@@ -2554,16 +2620,23 @@ int config_write_ospf6_debug_message(struct vty *vty)
 {
        const char *type_str[] = {"unknown", "hello",    "dbdesc",
                                  "lsreq",   "lsupdate", "lsack"};
-       unsigned char s = 0, r = 0;
+       unsigned char s = 0, r = 0, sh = 0, rh = 0;
        int i;
 
        for (i = 0; i < 6; i++) {
-               if (IS_OSPF6_DEBUG_MESSAGE(i, SEND))
+               if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
                        s |= 1 << i;
-               if (IS_OSPF6_DEBUG_MESSAGE(i, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
                        r |= 1 << i;
        }
 
+       for (i = 0; i < 6; i++) {
+               if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
+                       sh |= 1 << i;
+               if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
+                       rh |= 1 << i;
+       }
+
        if (s == 0x3f && r == 0x3f) {
                vty_out(vty, "debug ospf6 message all\n");
                return 0;
@@ -2577,6 +2650,14 @@ int config_write_ospf6_debug_message(struct vty *vty)
                return 0;
        }
 
+       if (sh == 0x3f && rh == 0) {
+               vty_out(vty, "debug ospf6 message all send-hdr\n");
+               return 0;
+       } else if (sh == 0 && rh == 0x3f) {
+               vty_out(vty, "debug ospf6 message all recv-hdr\n");
+               return 0;
+       }
+
        /* Unknown message is logged by default */
        if (!IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, SEND)
            && !IS_OSPF6_DEBUG_MESSAGE(OSPF6_MESSAGE_TYPE_UNKNOWN, RECV))
@@ -2587,15 +2668,25 @@ int config_write_ospf6_debug_message(struct vty *vty)
                vty_out(vty, "no debug ospf6 message unknown recv\n");
 
        for (i = 1; i < 6; i++) {
-               if (IS_OSPF6_DEBUG_MESSAGE(i, SEND)
-                   && IS_OSPF6_DEBUG_MESSAGE(i, RECV))
+               if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND)
+                   && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
                        vty_out(vty, "debug ospf6 message %s\n", type_str[i]);
-               else if (IS_OSPF6_DEBUG_MESSAGE(i, SEND))
+               else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND))
                        vty_out(vty, "debug ospf6 message %s send\n",
                                type_str[i]);
-               else if (IS_OSPF6_DEBUG_MESSAGE(i, RECV))
+               else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV))
                        vty_out(vty, "debug ospf6 message %s recv\n",
                                type_str[i]);
+               else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR)
+                        && IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
+                       vty_out(vty, "debug ospf6 message %s; header only\n",
+                               type_str[i]);
+               else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, RECV_HDR))
+                       vty_out(vty, "debug ospf6 message %s recv-hdr\n",
+                               type_str[i]);
+               else if (IS_OSPF6_DEBUG_MESSAGE_ENABLED(i, SEND_HDR))
+                       vty_out(vty, "debug ospf6 message %s send-hdr\n",
+                               type_str[i]);
        }
 
        return 0;
index 7ec8cb785f87a914ab85cf44f7473890b22bc95b..c4cdbd52f4b16e2236cc2c79cfdc121f0c4ba438 100644 (file)
 
 /* Debug option */
 extern unsigned char conf_debug_ospf6_message[];
+#define OSPF6_ACTION_SEND 0x01
+#define OSPF6_ACTION_RECV 0x02
 #define OSPF6_DEBUG_MESSAGE_SEND 0x01
 #define OSPF6_DEBUG_MESSAGE_RECV 0x02
+#define OSPF6_DEBUG_MESSAGE_SEND_HDR 0x04
+#define OSPF6_DEBUG_MESSAGE_RECV_HDR 0x08
+#define OSPF6_DEBUG_MESSAGE_SEND_BOTH                                          \
+       OSPF6_DEBUG_MESSAGE_SEND | OSPF6_DEBUG_MESSAGE_SEND_HDR
+#define OSPF6_DEBUG_MESSAGE_RECV_BOTH                                          \
+       OSPF6_DEBUG_MESSAGE_RECV | OSPF6_DEBUG_MESSAGE_RECV_HDR
+
 #define OSPF6_DEBUG_MESSAGE_ON(type, level)                                    \
        (conf_debug_ospf6_message[type] |= (level))
 #define OSPF6_DEBUG_MESSAGE_OFF(type, level)                                   \
        (conf_debug_ospf6_message[type] &= ~(level))
+
 #define IS_OSPF6_DEBUG_MESSAGE(t, e)                                           \
-       (conf_debug_ospf6_message[t] & OSPF6_DEBUG_MESSAGE_##e)
+       ((OSPF6_DEBUG_MESSAGE_##e) == OSPF6_DEBUG_MESSAGE_RECV_HDR)            \
+               ? (conf_debug_ospf6_message[t]                                 \
+                  & (OSPF6_DEBUG_MESSAGE_RECV_BOTH))                          \
+               : (((OSPF6_DEBUG_MESSAGE_##e) == OSPF6_DEBUG_MESSAGE_SEND_HDR) \
+                          ? (conf_debug_ospf6_message[t]                      \
+                             & (OSPF6_DEBUG_MESSAGE_SEND_BOTH))               \
+                          : (conf_debug_ospf6_message[t]                      \
+                             & (OSPF6_DEBUG_MESSAGE_##e)))
+
+#define IS_OSPF6_DEBUG_MESSAGE_ENABLED(type, e)                                \
+       (conf_debug_ospf6_message[type] & (OSPF6_DEBUG_MESSAGE_##e))
 
 /* Type */
 #define OSPF6_MESSAGE_TYPE_UNKNOWN  0x0
@@ -110,11 +130,11 @@ struct ospf6_lsupdate {
 /* It is just a sequence of LSA Headers */
 
 /* Function definition */
-extern void ospf6_hello_print(struct ospf6_header *);
-extern void ospf6_dbdesc_print(struct ospf6_header *);
-extern void ospf6_lsreq_print(struct ospf6_header *);
-extern void ospf6_lsupdate_print(struct ospf6_header *);
-extern void ospf6_lsack_print(struct ospf6_header *);
+extern void ospf6_hello_print(struct ospf6_header *, int action);
+extern void ospf6_dbdesc_print(struct ospf6_header *, int action);
+extern void ospf6_lsreq_print(struct ospf6_header *, int action);
+extern void ospf6_lsupdate_print(struct ospf6_header *, int action);
+extern void ospf6_lsack_print(struct ospf6_header *, int action);
 
 extern int ospf6_iobuf_size(unsigned int size);
 extern void ospf6_message_terminate(void);
index 485bde4b7b77ce8d62ab5e7fedb1c16251198909..9323da8be3ed94a7673469a654cc5ce083d98b21 100644 (file)
@@ -26,6 +26,7 @@
 #include "linklist.h"
 #include "vty.h"
 #include "command.h"
+#include "lib/bfd.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_lsa.h"
@@ -149,7 +150,7 @@ void ospf6_neighbor_delete(struct ospf6_neighbor *on)
        THREAD_OFF(on->thread_send_lsupdate);
        THREAD_OFF(on->thread_send_lsack);
 
-       ospf6_bfd_reg_dereg_nbr(on, ZEBRA_BFD_DEST_DEREGISTER);
+       bfd_sess_free(&on->bfd_session);
        XFREE(MTYPE_OSPF6_NEIGHBOR, on);
 }
 
@@ -876,8 +877,7 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
                json_object_object_add(json_neighbor, "pendingLsaLsAck",
                                       json_array);
 
-               ospf6_bfd_show_info(vty, on->bfd_info, 0, json_neighbor,
-                                   use_json);
+               bfd_sess_show(vty, json_neighbor, on->bfd_session);
 
                json_object_object_add(json, on->name, json_neighbor);
 
@@ -965,39 +965,28 @@ static void ospf6_neighbor_show_detail(struct vty *vty,
                for (ALL_LSDB(on->lsack_list, lsa, lsanext))
                        vty_out(vty, "      %s\n", lsa->name);
 
-               ospf6_bfd_show_info(vty, on->bfd_info, 0, NULL, use_json);
+               bfd_sess_show(vty, NULL, on->bfd_session);
        }
 }
 
-DEFUN (show_ipv6_ospf6_neighbor,
-       show_ipv6_ospf6_neighbor_cmd,
-       "show ipv6 ospf6 neighbor [<detail|drchoice>] [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Neighbor list\n"
-       "Display details\n"
-       "Display DR choices\n"
-       JSON_STR)
+static void ospf6_neighbor_show_detail_common(struct vty *vty, int argc,
+                                             struct cmd_token **argv,
+                                             struct ospf6 *ospf6, int idx_type,
+                                             int detail_idx, int json_idx)
 {
-       int idx_type = 4;
        struct ospf6_neighbor *on;
        struct ospf6_interface *oi;
        struct ospf6_area *oa;
        struct listnode *i, *j, *k;
-       struct ospf6 *ospf6;
        json_object *json = NULL;
        json_object *json_array = NULL;
        bool uj = use_json(argc, argv);
        void (*showfunc)(struct vty *, struct ospf6_neighbor *,
                         json_object *json, bool use_json);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
        showfunc = ospf6_neighbor_show;
 
-       if ((uj && argc == 6) || (!uj && argc == 5)) {
+       if ((uj && argc == detail_idx) || (!uj && argc == json_idx)) {
                if (!strncmp(argv[idx_type]->arg, "de", 2))
                        showfunc = ospf6_neighbor_show_detail;
                else if (!strncmp(argv[idx_type]->arg, "dr", 2))
@@ -1037,21 +1026,50 @@ DEFUN (show_ipv6_ospf6_neighbor,
                                json, JSON_C_TO_STRING_PRETTY));
                json_object_free(json);
        }
-       return CMD_SUCCESS;
 }
 
+DEFUN(show_ipv6_ospf6_neighbor, show_ipv6_ospf6_neighbor_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] neighbor [<detail|drchoice>] [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Neighbor list\n"
+      "Display details\n"
+      "Display DR choices\n" JSON_STR)
+{
+       int idx_type = 4;
+       int detail_idx = 5;
+       int json_idx = 6;
+       struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_type += 2;
+               detail_idx += 2;
+               json_idx += 2;
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_neighbor_show_detail_common(vty, argc, argv,
+                                                         ospf6, idx_type,
+                                                         detail_idx, json_idx);
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
-DEFUN (show_ipv6_ospf6_neighbor_one,
-       show_ipv6_ospf6_neighbor_one_cmd,
-       "show ipv6 ospf6 neighbor A.B.C.D [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Neighbor list\n"
-       "Specify Router-ID as IPv4 address notation\n"
-       JSON_STR)
+       return CMD_SUCCESS;
+}
+
+static int ospf6_neighbor_show_common(struct vty *vty, int argc,
+                                     struct cmd_token **argv,
+                                     struct ospf6 *ospf6, int idx_ipv4)
 {
-       int idx_ipv4 = 4;
        struct ospf6_neighbor *on;
        struct ospf6_interface *oi;
        struct ospf6_area *oa;
@@ -1059,12 +1077,9 @@ DEFUN (show_ipv6_ospf6_neighbor_one,
        void (*showfunc)(struct vty *, struct ospf6_neighbor *,
                         json_object *json, bool use_json);
        uint32_t router_id;
-       struct ospf6 *ospf6;
        json_object *json = NULL;
        bool uj = use_json(argc, argv);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
        showfunc = ospf6_neighbor_show_detail;
        if (uj)
                json = json_object_new_object();
@@ -1088,6 +1103,39 @@ DEFUN (show_ipv6_ospf6_neighbor_one,
                                json, JSON_C_TO_STRING_PRETTY));
                json_object_free(json);
        }
+
+       return CMD_SUCCESS;
+}
+
+DEFUN(show_ipv6_ospf6_neighbor_one, show_ipv6_ospf6_neighbor_one_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] neighbor A.B.C.D [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Neighbor list\n"
+      "Specify Router-ID as IPv4 address notation\n" JSON_STR)
+{
+       int idx_ipv4 = 4;
+       struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_ipv4 += 2;
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_neighbor_show_common(vty, argc, argv, ospf6,
+                                                  idx_ipv4);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
index f45b3405076aacd127a5de379794ca1c1d07956a..47f8c834e23dcca403da377d6478759f149e1574 100644 (file)
@@ -96,7 +96,7 @@ struct ospf6_neighbor {
        struct thread *thread_send_lsack;
 
        /* BFD information */
-       void *bfd_info;
+       struct bfd_session_params *bfd_session;
 };
 
 /* Neighbor state */
index 9770dd0444be8a5b27ff1c02c7112c78b8ac3d91..2daf119c52f59a0966f3b4d42bed7370a1a9bca9 100644 (file)
@@ -1039,7 +1039,7 @@ void ospf6_route_table_delete(struct ospf6_route_table *table)
 
 /* VTY commands */
 void ospf6_route_show(struct vty *vty, struct ospf6_route *route,
-                     json_object *json_array_routes, bool use_json)
+                     json_object *json_routes, bool use_json)
 {
        int i;
        char destination[PREFIX2STR_BUFFER], nexthop[64];
@@ -1072,7 +1072,6 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route,
 
        if (use_json) {
                json_route = json_object_new_object();
-               json_object_string_add(json_route, "destination", destination);
                json_object_boolean_add(json_route, "isBestRoute",
                                        ospf6_route_is_best(route));
                json_object_string_add(json_route, "destinationType",
@@ -1121,12 +1120,12 @@ void ospf6_route_show(struct vty *vty, struct ospf6_route *route,
        if (use_json) {
                json_object_object_add(json_route, "nextHops",
                                       json_array_next_hops);
-               json_object_array_add(json_array_routes, json_route);
+               json_object_object_add(json_routes, destination, json_route);
        }
 }
 
 void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
-                            json_object *json_array_routes, bool use_json)
+                            json_object *json_routes, bool use_json)
 {
        char destination[PREFIX2STR_BUFFER], nexthop[64];
        char area_id[16], id[16], adv_router[16], capa[16], options[16];
@@ -1158,7 +1157,6 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
 
        if (use_json) {
                json_route = json_object_new_object();
-               json_object_string_add(json_route, "destination", destination);
                json_object_string_add(json_route, "destinationType",
                                       OSPF6_DEST_TYPE_NAME(route->type));
        } else {
@@ -1311,7 +1309,7 @@ void ospf6_route_show_detail(struct vty *vty, struct ospf6_route *route,
        if (use_json) {
                json_object_object_add(json_route, "nextHops",
                                       json_array_next_hops);
-               json_object_array_add(json_array_routes, json_route);
+               json_object_object_add(json_routes, destination, json_route);
        } else
                vty_out(vty, "\n");
 }
@@ -1377,24 +1375,23 @@ static void ospf6_route_show_table_prefix(struct vty *vty,
                                          json_object *json, bool use_json)
 {
        struct ospf6_route *route;
-       json_object *json_array_routes = NULL;
+       json_object *json_routes = NULL;
 
        route = ospf6_route_lookup(prefix, table);
        if (route == NULL)
                return;
 
        if (use_json)
-               json_array_routes = json_object_new_array();
+               json_routes = json_object_new_object();
        ospf6_route_lock(route);
        while (route && ospf6_route_is_prefix(prefix, route)) {
                /* Specifying a prefix will always display details */
-               ospf6_route_show_detail(vty, route, json_array_routes,
-                                       use_json);
+               ospf6_route_show_detail(vty, route, json_routes, use_json);
                route = ospf6_route_next(route);
        }
 
        if (use_json)
-               json_object_object_add(json, "routes", json_array_routes);
+               json_object_object_add(json, "routes", json_routes);
        if (route)
                ospf6_route_unlock(route);
 }
@@ -1405,24 +1402,23 @@ static void ospf6_route_show_table_address(struct vty *vty,
                                           json_object *json, bool use_json)
 {
        struct ospf6_route *route;
-       json_object *json_array_routes = NULL;
+       json_object *json_routes = NULL;
 
        route = ospf6_route_lookup_bestmatch(prefix, table);
        if (route == NULL)
                return;
 
        if (use_json)
-               json_array_routes = json_object_new_array();
+               json_routes = json_object_new_object();
        prefix = &route->prefix;
        ospf6_route_lock(route);
        while (route && ospf6_route_is_prefix(prefix, route)) {
                /* Specifying a prefix will always display details */
-               ospf6_route_show_detail(vty, route, json_array_routes,
-                                       use_json);
+               ospf6_route_show_detail(vty, route, json_routes, use_json);
                route = ospf6_route_next(route);
        }
        if (use_json)
-               json_object_object_add(json, "routes", json_array_routes);
+               json_object_object_add(json, "routes", json_routes);
        if (route)
                ospf6_route_unlock(route);
 }
@@ -1433,24 +1429,23 @@ static void ospf6_route_show_table_match(struct vty *vty, int detail,
                                         json_object *json, bool use_json)
 {
        struct ospf6_route *route;
-       json_object *json_array_routes = NULL;
+       json_object *json_routes = NULL;
 
        assert(prefix->family);
 
        route = ospf6_route_match_head(prefix, table);
        if (use_json)
-               json_array_routes = json_object_new_array();
+               json_routes = json_object_new_object();
        while (route) {
                if (detail)
-                       ospf6_route_show_detail(vty, route, json_array_routes,
+                       ospf6_route_show_detail(vty, route, json_routes,
                                                use_json);
                else
-                       ospf6_route_show(vty, route, json_array_routes,
-                                        use_json);
+                       ospf6_route_show(vty, route, json_routes, use_json);
                route = ospf6_route_match_next(prefix, route);
        }
        if (use_json)
-               json_object_object_add(json, "routes", json_array_routes);
+               json_object_object_add(json, "routes", json_routes);
 }
 
 static void ospf6_route_show_table_type(struct vty *vty, int detail,
@@ -1459,25 +1454,24 @@ static void ospf6_route_show_table_type(struct vty *vty, int detail,
                                        json_object *json, bool use_json)
 {
        struct ospf6_route *route;
-       json_object *json_array_routes = NULL;
+       json_object *json_routes = NULL;
 
        route = ospf6_route_head(table);
        if (use_json)
-               json_array_routes = json_object_new_array();
+               json_routes = json_object_new_object();
        while (route) {
                if (route->path.type == type) {
                        if (detail)
-                               ospf6_route_show_detail(vty, route,
-                                                       json_array_routes,
+                               ospf6_route_show_detail(vty, route, json_routes,
                                                        use_json);
                        else
-                               ospf6_route_show(vty, route, json_array_routes,
+                               ospf6_route_show(vty, route, json_routes,
                                                 use_json);
                }
                route = ospf6_route_next(route);
        }
        if (use_json)
-               json_object_object_add(json, "routes", json_array_routes);
+               json_object_object_add(json, "routes", json_routes);
 }
 
 static void ospf6_route_show_table(struct vty *vty, int detail,
@@ -1485,22 +1479,21 @@ static void ospf6_route_show_table(struct vty *vty, int detail,
                                   json_object *json, bool use_json)
 {
        struct ospf6_route *route;
-       json_object *json_array_routes = NULL;
+       json_object *json_routes = NULL;
 
        route = ospf6_route_head(table);
        if (use_json)
-               json_array_routes = json_object_new_array();
+               json_routes = json_object_new_object();
        while (route) {
                if (detail)
-                       ospf6_route_show_detail(vty, route, json_array_routes,
+                       ospf6_route_show_detail(vty, route, json_routes,
                                                use_json);
                else
-                       ospf6_route_show(vty, route, json_array_routes,
-                                        use_json);
+                       ospf6_route_show(vty, route, json_routes, use_json);
                route = ospf6_route_next(route);
        }
        if (use_json)
-               json_object_object_add(json, "routes", json_array_routes);
+               json_object_object_add(json, "routes", json_routes);
 }
 
 int ospf6_route_table_show(struct vty *vty, int argc_start, int argc,
index b710fefbdfda97a030e289810e7854062b6ea59e..faa992e026567be5ef9624a2bf44536c26b6971c 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "lib/northbound.h"
 #include "lib/routemap.h"
 #include "ospf6_routemap_nb.h"
index 3c7741e47341657b563d9ea7b23938ed57c80a7a..cd0a3260d549f88b8ce2b234332eb01616b4ef10 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "lib/command.h"
 #include "lib/log.h"
 #include "lib/northbound.h"
index b9d413c3df7d1f8fa209d94bf2509c9451641ab9..dcf76c7038e6d50e9d30556377fdf3b3d65f3318 100644 (file)
@@ -30,7 +30,7 @@
 #include "vrf.h"
 #include "smux.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_lsa.h"
index e2cd5c259de9cf04305a9fa3aa8796a9ee3fa4ef..3ab0f1fbb6533887505ce43aa634ab12d34b0f03 100644 (file)
@@ -124,6 +124,104 @@ struct ospf6 *ospf6_lookup_by_vrf_name(const char *name)
        return NULL;
 }
 
+/* This is hook function for vrf create called as part of vrf_init */
+static int ospf6_vrf_new(struct vrf *vrf)
+{
+       return 0;
+}
+
+/* This is hook function for vrf delete call as part of vrf_init */
+static int ospf6_vrf_delete(struct vrf *vrf)
+{
+       return 0;
+}
+
+static void ospf6_set_redist_vrf_bitmaps(struct ospf6 *ospf6, bool set)
+{
+       int type;
+       struct list *red_list;
+
+       for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
+               red_list = ospf6->redist[type];
+               if (!red_list)
+                       continue;
+               if (IS_OSPF6_DEBUG_ZEBRA(RECV))
+                       zlog_debug(
+                               "%s: setting redist vrf %d bitmap for type %d",
+                               __func__, ospf6->vrf_id, type);
+               if (set)
+                       vrf_bitmap_set(zclient->redist[AFI_IP6][type],
+                                      ospf6->vrf_id);
+               else
+                       vrf_bitmap_unset(zclient->redist[AFI_IP6][type],
+                                        ospf6->vrf_id);
+       }
+}
+
+/* Disable OSPF6 VRF instance */
+static int ospf6_vrf_disable(struct vrf *vrf)
+{
+       struct ospf6 *ospf6 = NULL;
+
+       if (vrf->vrf_id == VRF_DEFAULT)
+               return 0;
+
+       ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
+       if (ospf6) {
+               ospf6_zebra_vrf_deregister(ospf6);
+
+               ospf6_set_redist_vrf_bitmaps(ospf6, false);
+
+               /* We have instance configured, unlink
+                * from VRF and make it "down".
+                */
+               ospf6_vrf_unlink(ospf6, vrf);
+               thread_cancel(&ospf6->t_ospf6_receive);
+               close(ospf6->fd);
+               ospf6->fd = -1;
+       }
+
+       /* Note: This is a callback, the VRF will be deleted by the caller. */
+       return 0;
+}
+
+/* Enable OSPF6 VRF instance */
+static int ospf6_vrf_enable(struct vrf *vrf)
+{
+       struct ospf6 *ospf6 = NULL;
+       vrf_id_t old_vrf_id;
+       int ret = 0;
+
+       ospf6 = ospf6_lookup_by_vrf_name(vrf->name);
+       if (ospf6) {
+               old_vrf_id = ospf6->vrf_id;
+               /* We have instance configured, link to VRF and make it "up". */
+               ospf6_vrf_link(ospf6, vrf);
+
+               if (old_vrf_id != ospf6->vrf_id) {
+                       ospf6_set_redist_vrf_bitmaps(ospf6, true);
+
+                       /* start zebra redist to us for new vrf */
+                       ospf6_zebra_vrf_register(ospf6);
+
+                       ret = ospf6_serv_sock(ospf6);
+                       if (ret < 0 || ospf6->fd <= 0)
+                               return 0;
+                       thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
+                                       &ospf6->t_ospf6_receive);
+
+                       ospf6_router_id_update(ospf6);
+               }
+       }
+
+       return 0;
+}
+
+void ospf6_vrf_init(void)
+{
+       vrf_init(ospf6_vrf_new, ospf6_vrf_enable, ospf6_vrf_disable,
+                ospf6_vrf_delete, ospf6_vrf_enable);
+}
 
 static void ospf6_top_lsdb_hook_add(struct ospf6_lsa *lsa)
 {
@@ -292,6 +390,9 @@ struct ospf6 *ospf6_instance_create(const char *name)
        if (ospf6->router_id == 0)
                ospf6_router_id_update(ospf6);
        ospf6_add(ospf6);
+       if (ospf6->fd < 0)
+               return ospf6;
+
        thread_add_read(master, ospf6_receive, ospf6, ospf6->fd,
                        &ospf6->t_ospf6_receive);
 
@@ -309,6 +410,8 @@ void ospf6_delete(struct ospf6 *o)
        ospf6_disable(o);
        ospf6_del(o);
 
+       ospf6_zebra_vrf_deregister(o);
+
        ospf6_serv_close(&o->fd);
 
        for (ALL_LIST_ELEMENTS(o->area_list, node, nnode, oa))
@@ -436,17 +539,20 @@ void ospf6_router_id_update(struct ospf6 *ospf6)
 }
 
 /* start ospf6 */
-DEFUN_NOSH (router_ospf6,
-       router_ospf6_cmd,
-       "router ospf6",
-       ROUTER_STR
-       OSPF6_STR)
+DEFUN_NOSH(router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
+          ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
 {
        struct ospf6 *ospf6;
+       const char *vrf_name = VRF_DEFAULT_NAME;
+       int idx_vrf = 0;
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
+       if (argv_find(argv, argc, "vrf", &idx_vrf)) {
+               vrf_name = argv[idx_vrf + 1]->arg;
+       }
+
+       ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
        if (ospf6 == NULL)
-               ospf6 = ospf6_instance_create(VRF_DEFAULT_NAME);
+               ospf6 = ospf6_instance_create(vrf_name);
 
        /* set current ospf point. */
        VTY_PUSH_CONTEXT(OSPF6_NODE, ospf6);
@@ -455,16 +561,18 @@ DEFUN_NOSH (router_ospf6,
 }
 
 /* stop ospf6 */
-DEFUN (no_router_ospf6,
-       no_router_ospf6_cmd,
-       "no router ospf6",
-       NO_STR
-       ROUTER_STR
-       OSPF6_STR)
+DEFUN(no_router_ospf6, no_router_ospf6_cmd, "no router ospf6 [vrf NAME]",
+      NO_STR ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
 {
        struct ospf6 *ospf6;
+       const char *vrf_name = VRF_DEFAULT_NAME;
+       int idx_vrf = 0;
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
+       if (argv_find(argv, argc, "vrf", &idx_vrf)) {
+               vrf_name = argv[idx_vrf + 1]->arg;
+       }
+
+       ospf6 = ospf6_lookup_by_vrf_name(vrf_name);
        if (ospf6 == NULL)
                vty_out(vty, "OSPFv3 is not configured\n");
        else {
@@ -735,16 +843,19 @@ DEFUN (ospf6_interface_area,
        "OSPF6 area ID in decimal notation\n"
       )
 {
+       VTY_DECLVAR_CONTEXT(ospf6, ospf6);
        int idx_ifname = 1;
        int idx_ipv4 = 3;
        struct ospf6_area *oa;
        struct ospf6_interface *oi;
        struct interface *ifp;
+       vrf_id_t vrf_id = VRF_DEFAULT;
 
-       VTY_DECLVAR_CONTEXT(ospf6, ospf6);
+       if (ospf6->vrf_id != VRF_UNKNOWN)
+               vrf_id = ospf6->vrf_id;
 
        /* find/create ospf6 interface */
-       ifp = if_get_by_name(argv[idx_ifname]->arg, VRF_DEFAULT);
+       ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
        oi = (struct ospf6_interface *)ifp->info;
        if (oi == NULL)
                oi = ospf6_interface_create(ifp);
@@ -788,14 +899,21 @@ DEFUN (no_ospf6_interface_area,
        "OSPF6 area ID in decimal notation\n"
        )
 {
+       VTY_DECLVAR_CONTEXT(ospf6, ospf6);
        int idx_ifname = 2;
        int idx_ipv4 = 4;
        struct ospf6_interface *oi;
        struct ospf6_area *oa;
        struct interface *ifp;
        uint32_t area_id;
+       vrf_id_t vrf_id = VRF_DEFAULT;
+
+       if (ospf6->vrf_id != VRF_UNKNOWN)
+               vrf_id = ospf6->vrf_id;
+
+       /* find/create ospf6 interface */
+       ifp = if_get_by_name(argv[idx_ifname]->arg, vrf_id);
 
-       ifp = if_lookup_by_name(argv[idx_ifname]->arg, VRF_DEFAULT);
        if (ifp == NULL) {
                vty_out(vty, "No such interface %s\n", argv[idx_ifname]->arg);
                return CMD_SUCCESS;
@@ -814,7 +932,7 @@ DEFUN (no_ospf6_interface_area,
        /* Verify Area */
        if (oi->area == NULL) {
                vty_out(vty, "%s not attached to area %s\n",
-                       oi->interface->name, oi->area->name);
+                       oi->interface->name, argv[idx_ipv4]->arg);
                return CMD_SUCCESS;
        }
 
@@ -890,7 +1008,6 @@ static void ospf6_restart_spf(struct ospf6 *ospf6)
 {
        ospf6_route_remove_all(ospf6->route_table);
        ospf6_route_remove_all(ospf6->brouter_table);
-       ospf6_route_remove_all(ospf6->external_table);
 
        /* Trigger SPF */
        ospf6_spf_schedule(ospf6, OSPF6_SPF_FLAGS_CONFIG_CHANGE);
@@ -1120,125 +1237,255 @@ static void ospf6_show(struct vty *vty, struct ospf6 *o, json_object *json,
        }
 }
 
+DEFUN(show_ipv6_ospf6_vrfs, show_ipv6_ospf6_vrfs_cmd,
+      "show ipv6 ospf6 vrfs [json]",
+      SHOW_STR IP6_STR OSPF6_STR "Show OSPF6 VRFs \n" JSON_STR)
+{
+       bool uj = use_json(argc, argv);
+       json_object *json = NULL;
+       json_object *json_vrfs = NULL;
+       struct ospf6 *ospf6 = NULL;
+       struct listnode *node = NULL;
+       int count = 0;
+       char buf[PREFIX_STRLEN];
+       static const char header[] =
+               "Name                       Id     RouterId  ";
+
+       if (uj) {
+               json = json_object_new_object();
+               json_vrfs = json_object_new_object();
+       }
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               json_object *json_vrf = NULL;
+               const char *name = NULL;
+               int64_t vrf_id_ui = 0;
+               struct in_addr router_id;
+
+               router_id.s_addr = ospf6->router_id;
+               count++;
+
+               if (!uj && count == 1)
+                       vty_out(vty, "%s\n", header);
+               if (uj)
+                       json_vrf = json_object_new_object();
+
+               if (ospf6->vrf_id == VRF_DEFAULT)
+                       name = VRF_DEFAULT_NAME;
+               else
+                       name = ospf6->name;
+
+               vrf_id_ui = (ospf6->vrf_id == VRF_UNKNOWN)
+                                   ? -1
+                                   : (int64_t)ospf6->vrf_id;
+
+               if (uj) {
+                       json_object_int_add(json_vrf, "vrfId", vrf_id_ui);
+                       json_object_string_add(json_vrf, "routerId",
+                                              inet_ntop(AF_INET, &router_id,
+                                                        buf, sizeof(buf)));
+                       json_object_object_add(json_vrfs, name, json_vrf);
+
+               } else {
+                       vty_out(vty, "%-25s  %-5d  %-16s  \n", name,
+                               ospf6->vrf_id,
+                               inet_ntop(AF_INET, &router_id, buf,
+                                         sizeof(buf)));
+               }
+       }
+
+       if (uj) {
+               json_object_object_add(json, "vrfs", json_vrfs);
+               json_object_int_add(json, "totalVrfs", count);
+
+               vty_out(vty, "%s\n",
+                       json_object_to_json_string_ext(
+                               json, JSON_C_TO_STRING_PRETTY));
+               json_object_free(json);
+       } else {
+               if (count)
+                       vty_out(vty, "\nTotal number of OSPF VRFs: %d\n",
+                               count);
+       }
+
+       return CMD_SUCCESS;
+}
+
 /* show top level structures */
-DEFUN(show_ipv6_ospf6,
-      show_ipv6_ospf6_cmd,
-      "show ipv6 ospf6 [json]",
-      SHOW_STR
-      IP6_STR
-      OSPF6_STR
-      JSON_STR)
+DEFUN(show_ipv6_ospf6, show_ipv6_ospf6_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR "All VRFs\n" JSON_STR)
 {
        struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
        bool uj = use_json(argc, argv);
        json_object *json = NULL;
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
 
-       if (uj)
-               json = json_object_new_object();
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       if (uj)
+                               json = json_object_new_object();
+                       ospf6_show(vty, ospf6, json, uj);
 
-       ospf6_show(vty, ospf6, json, uj);
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
        if (uj)
                json_object_free(json);
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_route,
-       show_ipv6_ospf6_route_cmd,
-       "show ipv6 ospf6 route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       ROUTE_STR
-       "Display Intra-Area routes\n"
-       "Display Inter-Area routes\n"
-       "Display Type-1 External routes\n"
-       "Display Type-2 External routes\n"
-       "Specify IPv6 address\n"
-       "Specify IPv6 prefix\n"
-       "Detailed information\n"
-       "Summary of route table\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_route, show_ipv6_ospf6_route_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] route [<intra-area|inter-area|external-1|external-2|X:X::X:X|X:X::X:X/M|detail|summary>] [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" ROUTE_STR
+      "Display Intra-Area routes\n"
+      "Display Inter-Area routes\n"
+      "Display Type-1 External routes\n"
+      "Display Type-2 External routes\n"
+      "Specify IPv6 address\n"
+      "Specify IPv6 prefix\n"
+      "Detailed information\n"
+      "Summary of route table\n" JSON_STR)
 {
        struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+       int idx_arg_start = 4;
        bool uj = use_json(argc, argv);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_arg_start += 2;
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_route_table_show(vty, idx_arg_start, argc, argv,
+                                              ospf6->route_table, uj);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
-       ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_route_match,
-       show_ipv6_ospf6_route_match_cmd,
-       "show ipv6 ospf6 route X:X::X:X/M <match|longer> [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       ROUTE_STR
-       "Specify IPv6 prefix\n"
-       "Display routes which match the specified route\n"
-       "Display routes longer than the specified route\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_route_match, show_ipv6_ospf6_route_match_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M <match|longer> [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" ROUTE_STR
+      "Specify IPv6 prefix\n"
+      "Display routes which match the specified route\n"
+      "Display routes longer than the specified route\n" JSON_STR)
 {
        struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+       int idx_start_arg = 4;
        bool uj = use_json(argc, argv);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_start_arg += 2;
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_route_table_show(vty, idx_start_arg, argc, argv,
+                                              ospf6->route_table, uj);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
-       ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_route_match_detail,
-       show_ipv6_ospf6_route_match_detail_cmd,
-       "show ipv6 ospf6 route X:X::X:X/M match detail [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       ROUTE_STR
-       "Specify IPv6 prefix\n"
-       "Display routes which match the specified route\n"
-       "Detailed information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_route_match_detail,
+      show_ipv6_ospf6_route_match_detail_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] route X:X::X:X/M match detail [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" ROUTE_STR
+      "Specify IPv6 prefix\n"
+      "Display routes which match the specified route\n"
+      "Detailed information\n" JSON_STR)
 {
        struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+       int idx_start_arg = 4;
        bool uj = use_json(argc, argv);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_start_arg += 2;
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_route_table_show(vty, idx_start_arg, argc, argv,
+                                              ospf6->route_table, uj);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
-       ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
        return CMD_SUCCESS;
 }
 
-
-DEFUN (show_ipv6_ospf6_route_type_detail,
-       show_ipv6_ospf6_route_type_detail_cmd,
-       "show ipv6 ospf6 route <intra-area|inter-area|external-1|external-2> detail [json]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       ROUTE_STR
-       "Display Intra-Area routes\n"
-       "Display Inter-Area routes\n"
-       "Display Type-1 External routes\n"
-       "Display Type-2 External routes\n"
-       "Detailed information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_route_type_detail, show_ipv6_ospf6_route_type_detail_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] route <intra-area|inter-area|external-1|external-2> detail [json]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n" ROUTE_STR
+      "Display Intra-Area routes\n"
+      "Display Inter-Area routes\n"
+      "Display Type-1 External routes\n"
+      "Display Type-2 External routes\n"
+      "Detailed information\n" JSON_STR)
 {
        struct ospf6 *ospf6;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+       int idx_start_arg = 4;
        bool uj = use_json(argc, argv);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_start_arg += 2;
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_route_table_show(vty, idx_start_arg, argc, argv,
+                                              ospf6->route_table, uj);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
-       ospf6_route_table_show(vty, 4, argc, argv, ospf6->route_table, uj);
        return CMD_SUCCESS;
 }
 
@@ -1295,7 +1542,11 @@ static int config_write_ospf6(struct vty *vty)
                return CMD_SUCCESS;
 
        for (ALL_LIST_ELEMENTS(om6->ospf6, node, nnode, ospf6)) {
-               vty_out(vty, "router ospf6\n");
+               if (ospf6->name && strcmp(ospf6->name, VRF_DEFAULT_NAME))
+                       vty_out(vty, "router ospf6 vrf %s\n", ospf6->name);
+               else
+                       vty_out(vty, "router ospf6\n");
+
                if (ospf6->router_id_static != 0)
                        vty_out(vty, " ospf6 router-id %pI4\n",
                                &ospf6->router_id_static);
@@ -1360,6 +1611,7 @@ void ospf6_top_init(void)
        install_node(&ospf6_node);
 
        install_element(VIEW_NODE, &show_ipv6_ospf6_cmd);
+       install_element(VIEW_NODE, &show_ipv6_ospf6_vrfs_cmd);
        install_element(CONFIG_NODE, &router_ospf6_cmd);
        install_element(CONFIG_NODE, &no_router_ospf6_cmd);
 
index 08b884f23a99a7fb9059ab499cdba577280f67bb..9ba5a0f9a4aa6ceb563839aa120efc6a986febf0 100644 (file)
@@ -171,5 +171,5 @@ void ospf6_vrf_unlink(struct ospf6 *ospf6, struct vrf *vrf);
 struct ospf6 *ospf6_lookup_by_vrf_id(vrf_id_t vrf_id);
 struct ospf6 *ospf6_lookup_by_vrf_name(const char *name);
 const char *ospf6_vrf_id_to_name(vrf_id_t vrf_id);
-
+void ospf6_vrf_init(void);
 #endif /* OSPF6_TOP_H */
index 91d427c78c5a04b9f524bbae9dfb817aa5b06b20..da8c695f6502e0774b33f5cb3f4db24c99a1ef38 100644 (file)
@@ -25,6 +25,7 @@
 #include "vty.h"
 #include "command.h"
 #include "plist.h"
+#include "filter.h"
 
 #include "ospf6_proto.h"
 #include "ospf6_top.h"
@@ -388,161 +389,190 @@ static void ospf6_lsdb_type_show_wrapper(struct vty *vty,
                vty_out(vty, "\n");
 }
 
-DEFUN (show_ipv6_ospf6_database,
-       show_ipv6_ospf6_database_cmd,
-       "show ipv6 ospf6 database [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-        JSON_STR)
+DEFUN(show_ipv6_ospf6_database, show_ipv6_ospf6_database_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
-       int idx_level = 4;
        int level;
-       bool uj = use_json(argc, argv);
+       int idx_level = 4;
+       struct listnode *node;
        struct ospf6 *ospf6;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+       bool uj = use_json(argc, argv);
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_level += 2;
 
        level = parse_show_level(idx_level, argc, argv);
-       ospf6_lsdb_show_wrapper(vty, level, NULL, NULL, NULL, uj, ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_show_wrapper(vty, level, NULL, NULL, NULL,
+                                               uj, ospf6);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_type, show_ipv6_ospf6_database_type_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Router LSAs\n"
-       "Display Network LSAs\n"
-       "Display Inter-Area-Prefix LSAs\n"
-       "Display Inter-Area-Router LSAs\n"
-       "Display As-External LSAs\n"
-       "Display Group-Membership LSAs\n"
-       "Display Type-7 LSAs\n"
-       "Display Link LSAs\n"
-       "Display Intra-Area-Prefix LSAs\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_type, show_ipv6_ospf6_database_type_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Router LSAs\n"
+      "Display Network LSAs\n"
+      "Display Inter-Area-Prefix LSAs\n"
+      "Display Inter-Area-Router LSAs\n"
+      "Display As-External LSAs\n"
+      "Display Group-Membership LSAs\n"
+      "Display Type-7 LSAs\n"
+      "Display Link LSAs\n"
+      "Display Intra-Area-Prefix LSAs\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_lsa = 4;
        int idx_level = 5;
        int level;
-       uint16_t type = 0;
        bool uj = use_json(argc, argv);
+       struct listnode *node;
        struct ospf6 *ospf6;
-
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       uint16_t type = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_level += 2;
+       }
 
        type = parse_type_spec(idx_lsa, argc, argv);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL, NULL, uj, ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL,
+                                                    NULL, uj, ospf6);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_id,
-       show_ipv6_ospf6_database_id_cmd,
-       "show ipv6 ospf6 database <*|linkstate-id> A.B.C.D [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Any Link state Type\n"
-       "Search by Link state ID\n"
-       "Specify Link state ID as IPv4 address notation\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_id, show_ipv6_ospf6_database_id_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <*|linkstate-id> A.B.C.D [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Any Link state Type\n"
+      "Search by Link state ID\n"
+      "Specify Link state ID as IPv4 address notation\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_ipv4 = 5;
        int idx_level = 6;
        int level;
-       uint32_t id = 0;
        bool uj = use_json(argc, argv);
+       struct listnode *node;
        struct ospf6 *ospf6;
+       uint32_t id = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
 
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
-
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
        if (argv[idx_ipv4]->type == IPV4_TKN)
                inet_pton(AF_INET, argv[idx_ipv4]->arg, &id);
 
        level = parse_show_level(idx_level, argc, argv);
-       ospf6_lsdb_show_wrapper(vty, level, NULL, &id, NULL, uj, ospf6);
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_show_wrapper(vty, level, NULL, &id, NULL, uj,
+                                               ospf6);
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_router,
-       show_ipv6_ospf6_database_router_cmd,
-       "show ipv6 ospf6 database <*|adv-router> * A.B.C.D <detail|dump|internal> [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Any Link state Type\n"
-       "Search by Advertising Router\n"
-       "Any Link state ID\n"
-       "Specify Advertising Router as IPv4 address notation\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_router, show_ipv6_ospf6_database_router_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <*|adv-router> * A.B.C.D <detail|dump|internal> [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Any Link state Type\n"
+      "Search by Advertising Router\n"
+      "Any Link state ID\n"
+      "Specify Advertising Router as IPv4 address notation\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_ipv4 = 6;
        int idx_level = 7;
        int level;
+       struct listnode *node;
+       struct ospf6 *ospf6;
        uint32_t adv_router = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
        bool uj = use_json(argc, argv);
-       struct ospf6 *ospf6;
 
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_ipv4 += 2;
+               idx_level += 2;
+       }
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
        inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_show_wrapper(vty, level, NULL, NULL, &adv_router, uj, ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_show_wrapper(vty, level, NULL, NULL,
+                                               &adv_router, uj, ospf6);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN_HIDDEN (show_ipv6_ospf6_database_aggr_router,
-       show_ipv6_ospf6_database_aggr_router_cmd,
-       "show ipv6 ospf6 database aggr adv-router A.B.C.D",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Aggregated Router LSA\n"
-       "Search by Advertising Router\n"
-       "Specify Advertising Router as IPv4 address notation\n")
+static int ipv6_ospf6_database_aggr_router_common(struct vty *vty,
+                                                 uint32_t adv_router,
+                                                 struct ospf6 *ospf6)
 {
        int level = OSPF6_LSDB_SHOW_LEVEL_DETAIL;
        uint16_t type = htons(OSPF6_LSTYPE_ROUTER);
-       int idx_ipv4 = 6;
        struct listnode *i;
-       struct ospf6 *ospf6;
        struct ospf6_area *oa;
        struct ospf6_lsdb *lsdb;
-       uint32_t adv_router = 0;
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
-
-       inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router);
 
        for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, i, oa)) {
                if (adv_router == ospf6->router_id)
@@ -561,225 +591,338 @@ DEFUN_HIDDEN (show_ipv6_ospf6_database_aggr_router,
        }
 
        vty_out(vty, "\n");
+       return CMD_SUCCESS;
+}
+
+DEFUN_HIDDEN(
+       show_ipv6_ospf6_database_aggr_router,
+       show_ipv6_ospf6_database_aggr_router_cmd,
+       "show ipv6 ospf6 [vrf <NAME|all>] database aggr adv-router A.B.C.D",
+       SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+       "All VRFs\n"
+       "Display Link state database\n"
+       "Aggregated Router LSA\n"
+       "Search by Advertising Router\n"
+       "Specify Advertising Router as IPv4 address notation\n")
+{
+       int idx_ipv4 = 6;
+       struct listnode *node;
+       struct ospf6 *ospf6;
+       uint32_t adv_router = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_ipv4 += 2;
+
+       inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router);
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ipv6_ospf6_database_aggr_router_common(vty, adv_router,
+                                                              ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_type_id,
-       show_ipv6_ospf6_database_type_id_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> linkstate-id A.B.C.D [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Router LSAs\n"
-       "Display Network LSAs\n"
-       "Display Inter-Area-Prefix LSAs\n"
-       "Display Inter-Area-Router LSAs\n"
-       "Display As-External LSAs\n"
-       "Display Group-Membership LSAs\n"
-       "Display Type-7 LSAs\n"
-       "Display Link LSAs\n"
-       "Display Intra-Area-Prefix LSAs\n"
-       "Search by Link state ID\n"
-       "Specify Link state ID as IPv4 address notation\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_type_id, show_ipv6_ospf6_database_type_id_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> linkstate-id A.B.C.D [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Router LSAs\n"
+      "Display Network LSAs\n"
+      "Display Inter-Area-Prefix LSAs\n"
+      "Display Inter-Area-Router LSAs\n"
+      "Display As-External LSAs\n"
+      "Display Group-Membership LSAs\n"
+      "Display Type-7 LSAs\n"
+      "Display Link LSAs\n"
+      "Display Intra-Area-Prefix LSAs\n"
+      "Search by Link state ID\n"
+      "Specify Link state ID as IPv4 address notation\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_lsa = 4;
        int idx_ipv4 = 6;
        int idx_level = 7;
        int level;
-       uint16_t type = 0;
-       uint32_t id = 0;
        bool uj = use_json(argc, argv);
+       struct listnode *node;
        struct ospf6 *ospf6;
-
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       uint16_t type = 0;
+       uint32_t id = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_ipv4 += 2;
+               idx_level += 2;
+       }
 
        type = parse_type_spec(idx_lsa, argc, argv);
        inet_pton(AF_INET, argv[idx_ipv4]->arg, &id);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, NULL, uj, ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id,
+                                                    NULL, uj, ospf6);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_type_router,
-       show_ipv6_ospf6_database_type_router_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> <*|adv-router> A.B.C.D [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Router LSAs\n"
-       "Display Network LSAs\n"
-       "Display Inter-Area-Prefix LSAs\n"
-       "Display Inter-Area-Router LSAs\n"
-       "Display As-External LSAs\n"
-       "Display Group-Membership LSAs\n"
-       "Display Type-7 LSAs\n"
-       "Display Link LSAs\n"
-       "Display Intra-Area-Prefix LSAs\n"
-       "Any Link state ID\n"
-       "Search by Advertising Router\n"
-       "Specify Advertising Router as IPv4 address notation\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_type_router,
+      show_ipv6_ospf6_database_type_router_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> <*|adv-router> A.B.C.D [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Router LSAs\n"
+      "Display Network LSAs\n"
+      "Display Inter-Area-Prefix LSAs\n"
+      "Display Inter-Area-Router LSAs\n"
+      "Display As-External LSAs\n"
+      "Display Group-Membership LSAs\n"
+      "Display Type-7 LSAs\n"
+      "Display Link LSAs\n"
+      "Display Intra-Area-Prefix LSAs\n"
+      "Any Link state ID\n"
+      "Search by Advertising Router\n"
+      "Specify Advertising Router as IPv4 address notation\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_lsa = 4;
        int idx_ipv4 = 6;
        int idx_level = 7;
        int level;
-       uint16_t type = 0;
-       uint32_t adv_router = 0;
        bool uj = use_json(argc, argv);
+       struct listnode *node;
        struct ospf6 *ospf6;
+       uint16_t type = 0;
+       uint32_t adv_router = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_ipv4 += 2;
+               idx_level += 2;
+       }
 
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
        type = parse_type_spec(idx_lsa, argc, argv);
        inet_pton(AF_INET, argv[idx_ipv4]->arg, &adv_router);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL, &adv_router, uj,
-                                    ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL,
+                                                    &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-
-DEFUN (show_ipv6_ospf6_database_id_router,
-       show_ipv6_ospf6_database_id_router_cmd,
-       "show ipv6 ospf6 database * A.B.C.D A.B.C.D [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Any Link state Type\n"
-       "Specify Link state ID as IPv4 address notation\n"
-       "Specify Advertising Router as IPv4 address notation\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_id_router,
+      show_ipv6_ospf6_database_id_router_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database * A.B.C.D A.B.C.D [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Any Link state Type\n"
+      "Specify Link state ID as IPv4 address notation\n"
+      "Specify Advertising Router as IPv4 address notation\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_ls_id = 5;
        int idx_adv_rtr = 6;
        int idx_level = 7;
        int level;
-       uint32_t id = 0;
-       uint32_t adv_router = 0;
        bool uj = use_json(argc, argv);
+       struct listnode *node;
        struct ospf6 *ospf6;
+       uint32_t id = 0;
+       uint32_t adv_router = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_ls_id += 2;
+               idx_adv_rtr += 2;
+               idx_level += 2;
+       }
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
        inet_pton(AF_INET, argv[idx_ls_id]->arg, &id);
        inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_show_wrapper(vty, level, NULL, &id, &adv_router, uj, ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_show_wrapper(vty, level, NULL, &id,
+                                               &adv_router, uj, ospf6);
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-
-DEFUN (show_ipv6_ospf6_database_adv_router_linkstate_id,
-       show_ipv6_ospf6_database_adv_router_linkstate_id_cmd,
-       "show ipv6 ospf6 database adv-router A.B.C.D linkstate-id A.B.C.D [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Search by Advertising Router\n"
-       "Specify Advertising Router as IPv4 address notation\n"
-       "Search by Link state ID\n"
-       "Specify Link state ID as IPv4 address notation\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_adv_router_linkstate_id,
+      show_ipv6_ospf6_database_adv_router_linkstate_id_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database adv-router A.B.C.D linkstate-id A.B.C.D [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Search by Advertising Router\n"
+      "Specify Advertising Router as IPv4 address notation\n"
+      "Search by Link state ID\n"
+      "Specify Link state ID as IPv4 address notation\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_adv_rtr = 5;
        int idx_ls_id = 7;
        int idx_level = 8;
        int level;
-       uint32_t id = 0;
-       uint32_t adv_router = 0;
        bool uj = use_json(argc, argv);
+       struct listnode *node;
        struct ospf6 *ospf6;
+       uint32_t id = 0;
+       uint32_t adv_router = 0;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
 
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_adv_rtr += 2;
+               idx_ls_id += 2;
+               idx_level += 2;
+       }
        inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router);
        inet_pton(AF_INET, argv[idx_ls_id]->arg, &id);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_show_wrapper(vty, level, NULL, &id, &adv_router, uj, ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_type_show_wrapper(vty, level, NULL, &id,
+                                                    &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_type_id_router,
-       show_ipv6_ospf6_database_type_id_router_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D A.B.C.D [<dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Router LSAs\n"
-       "Display Network LSAs\n"
-       "Display Inter-Area-Prefix LSAs\n"
-       "Display Inter-Area-Router LSAs\n"
-       "Display As-External LSAs\n"
-       "Display Group-Membership LSAs\n"
-       "Display Type-7 LSAs\n"
-       "Display Link LSAs\n"
-       "Display Intra-Area-Prefix LSAs\n"
-       "Specify Link state ID as IPv4 address notation\n"
-       "Specify Advertising Router as IPv4 address notation\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_type_id_router,
+      show_ipv6_ospf6_database_type_id_router_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D A.B.C.D [<dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Router LSAs\n"
+      "Display Network LSAs\n"
+      "Display Inter-Area-Prefix LSAs\n"
+      "Display Inter-Area-Router LSAs\n"
+      "Display As-External LSAs\n"
+      "Display Group-Membership LSAs\n"
+      "Display Type-7 LSAs\n"
+      "Display Link LSAs\n"
+      "Display Intra-Area-Prefix LSAs\n"
+      "Specify Link state ID as IPv4 address notation\n"
+      "Specify Advertising Router as IPv4 address notation\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_lsa = 4;
        int idx_ls_id = 5;
        int idx_adv_rtr = 6;
        int idx_level = 7;
        int level;
+       bool uj = use_json(argc, argv);
+       struct listnode *node;
+       struct ospf6 *ospf6;
        uint16_t type = 0;
        uint32_t id = 0;
        uint32_t adv_router = 0;
-       bool uj = use_json(argc, argv);
-       struct ospf6 *ospf6;
-
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_ls_id += 2;
+               idx_adv_rtr += 2;
+               idx_level += 2;
+       }
 
        type = parse_type_spec(idx_lsa, argc, argv);
        inet_pton(AF_INET, argv[idx_ls_id]->arg, &id);
        inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj,
-                                    ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id,
+                                                    &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
 
 DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id,
        show_ipv6_ospf6_database_type_adv_router_linkstate_id_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> adv-router A.B.C.D linkstate-id A.B.C.D [<dump|internal>] [json]",
+       "show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> adv-router A.B.C.D linkstate-id A.B.C.D [<dump|internal>] [json]",
        SHOW_STR
        IPV6_STR
        OSPF6_STR
+       VRF_CMD_HELP_STR
+       "All VRFs\n"
        "Display Link state database\n"
        "Display Router LSAs\n"
        "Display Network LSAs\n"
@@ -803,208 +946,278 @@ DEFUN (show_ipv6_ospf6_database_type_adv_router_linkstate_id,
        int idx_ls_id = 8;
        int idx_level = 9;
        int level;
+       bool uj = use_json(argc, argv);
+       struct listnode *node;
+       struct ospf6 *ospf6;
        uint16_t type = 0;
        uint32_t id = 0;
        uint32_t adv_router = 0;
-       bool uj = use_json(argc, argv);
-       struct ospf6 *ospf6;
-
-
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_adv_rtr += 2;
+               idx_ls_id += 2;
+               idx_level += 2;
+       }
 
        type = parse_type_spec(idx_lsa, argc, argv);
        inet_pton(AF_INET, argv[idx_adv_rtr]->arg, &adv_router);
        inet_pton(AF_INET, argv[idx_ls_id]->arg, &id);
        level = parse_show_level(idx_level, argc, argv);
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj,
-                                    ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id,
+                                                    &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_self_originated,
-       show_ipv6_ospf6_database_self_originated_cmd,
-       "show ipv6 ospf6 database self-originated [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Self-originated LSAs\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_self_originated,
+      show_ipv6_ospf6_database_self_originated_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database self-originated [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Self-originated LSAs\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_level = 5;
        int level;
+       struct listnode *node;
+       struct ospf6 *ospf6;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
        uint32_t adv_router = 0;
        bool uj = use_json(argc, argv);
-       struct ospf6 *ospf6;
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_level += 2;
+
        level = parse_show_level(idx_level, argc, argv);
-       adv_router = ospf6->router_id;
 
-       ospf6_lsdb_show_wrapper(vty, level, NULL, NULL, &adv_router, uj, ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               adv_router = ospf6->router_id;
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       ospf6_lsdb_show_wrapper(vty, level, NULL, NULL,
+                                               &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
 
-DEFUN (show_ipv6_ospf6_database_type_self_originated,
-       show_ipv6_ospf6_database_type_self_originated_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Router LSAs\n"
-       "Display Network LSAs\n"
-       "Display Inter-Area-Prefix LSAs\n"
-       "Display Inter-Area-Router LSAs\n"
-       "Display As-External LSAs\n"
-       "Display Group-Membership LSAs\n"
-       "Display Type-7 LSAs\n"
-       "Display Link LSAs\n"
-       "Display Intra-Area-Prefix LSAs\n"
-       "Display Self-originated LSAs\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_type_self_originated,
+      show_ipv6_ospf6_database_type_self_originated_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated [<detail|dump|internal>]  [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Router LSAs\n"
+      "Display Network LSAs\n"
+      "Display Inter-Area-Prefix LSAs\n"
+      "Display Inter-Area-Router LSAs\n"
+      "Display As-External LSAs\n"
+      "Display Group-Membership LSAs\n"
+      "Display Type-7 LSAs\n"
+      "Display Link LSAs\n"
+      "Display Intra-Area-Prefix LSAs\n"
+      "Display Self-originated LSAs\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_lsa = 4;
        int idx_level = 6;
        int level;
+       struct listnode *node;
+       struct ospf6 *ospf6;
        uint16_t type = 0;
        uint32_t adv_router = 0;
        bool uj = use_json(argc, argv);
-       struct ospf6 *ospf6;
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_level += 2;
+       }
+
        type = parse_type_spec(idx_lsa, argc, argv);
        level = parse_show_level(idx_level, argc, argv);
 
-       adv_router = ospf6->router_id;
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       adv_router = ospf6->router_id;
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL,
+                                                    &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, NULL, &adv_router, uj,
-                                    ospf6);
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_type_self_originated_linkstate_id,
-       show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated linkstate-id A.B.C.D [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Router LSAs\n"
-       "Display Network LSAs\n"
-       "Display Inter-Area-Prefix LSAs\n"
-       "Display Inter-Area-Router LSAs\n"
-       "Display As-External LSAs\n"
-       "Display Group-Membership LSAs\n"
-       "Display Type-7 LSAs\n"
-       "Display Link LSAs\n"
-       "Display Intra-Area-Prefix LSAs\n"
-       "Display Self-originated LSAs\n"
-       "Search by Link state ID\n"
-       "Specify Link state ID as IPv4 address notation\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_type_self_originated_linkstate_id,
+      show_ipv6_ospf6_database_type_self_originated_linkstate_id_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> self-originated linkstate-id A.B.C.D [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Router LSAs\n"
+      "Display Network LSAs\n"
+      "Display Inter-Area-Prefix LSAs\n"
+      "Display Inter-Area-Router LSAs\n"
+      "Display As-External LSAs\n"
+      "Display Group-Membership LSAs\n"
+      "Display Type-7 LSAs\n"
+      "Display Link LSAs\n"
+      "Display Intra-Area-Prefix LSAs\n"
+      "Display Self-originated LSAs\n"
+      "Search by Link state ID\n"
+      "Specify Link state ID as IPv4 address notation\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_lsa = 4;
        int idx_ls_id = 7;
        int idx_level = 8;
        int level;
+       bool uj = use_json(argc, argv);
+       struct listnode *node;
+       struct ospf6 *ospf6;
        uint16_t type = 0;
        uint32_t adv_router = 0;
        uint32_t id = 0;
-       bool uj = use_json(argc, argv);
-       struct ospf6 *ospf6;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_ls_id += 2;
+               idx_level += 2;
+       }
+
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
        type = parse_type_spec(idx_lsa, argc, argv);
        inet_pton(AF_INET, argv[idx_ls_id]->arg, &id);
        level = parse_show_level(idx_level, argc, argv);
-       adv_router = ospf6->router_id;
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj,
-                                    ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       adv_router = ospf6->router_id;
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id,
+                                                    &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_database_type_id_self_originated,
-       show_ipv6_ospf6_database_type_id_self_originated_cmd,
-       "show ipv6 ospf6 database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D self-originated [<detail|dump|internal>] [json]",
-       SHOW_STR
-       IPV6_STR
-       OSPF6_STR
-       "Display Link state database\n"
-       "Display Router LSAs\n"
-       "Display Network LSAs\n"
-       "Display Inter-Area-Prefix LSAs\n"
-       "Display Inter-Area-Router LSAs\n"
-       "Display As-External LSAs\n"
-       "Display Group-Membership LSAs\n"
-       "Display Type-7 LSAs\n"
-       "Display Link LSAs\n"
-       "Display Intra-Area-Prefix LSAs\n"
-       "Specify Link state ID as IPv4 address notation\n"
-       "Display Self-originated LSAs\n"
-       "Display details of LSAs\n"
-       "Dump LSAs\n"
-       "Display LSA's internal information\n"
-       JSON_STR)
+DEFUN(show_ipv6_ospf6_database_type_id_self_originated,
+      show_ipv6_ospf6_database_type_id_self_originated_cmd,
+      "show ipv6 ospf6  [vrf <NAME|all>] database <router|network|inter-prefix|inter-router|as-external|group-membership|type-7|link|intra-prefix> A.B.C.D self-originated [<detail|dump|internal>] [json]",
+      SHOW_STR IPV6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display Link state database\n"
+      "Display Router LSAs\n"
+      "Display Network LSAs\n"
+      "Display Inter-Area-Prefix LSAs\n"
+      "Display Inter-Area-Router LSAs\n"
+      "Display As-External LSAs\n"
+      "Display Group-Membership LSAs\n"
+      "Display Type-7 LSAs\n"
+      "Display Link LSAs\n"
+      "Display Intra-Area-Prefix LSAs\n"
+      "Specify Link state ID as IPv4 address notation\n"
+      "Display Self-originated LSAs\n"
+      "Display details of LSAs\n"
+      "Dump LSAs\n"
+      "Display LSA's internal information\n" JSON_STR)
 {
        int idx_lsa = 4;
        int idx_ls_id = 5;
        int idx_level = 7;
        int level;
+       bool uj = use_json(argc, argv);
+       struct listnode *node;
+       struct ospf6 *ospf6;
        uint16_t type = 0;
        uint32_t adv_router = 0;
        uint32_t id = 0;
-       bool uj = use_json(argc, argv);
-       struct ospf6 *ospf6;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_lsa += 2;
+               idx_ls_id += 2;
+               idx_level += 2;
+       }
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
        type = parse_type_spec(idx_lsa, argc, argv);
        inet_pton(AF_INET, argv[idx_ls_id]->arg, &id);
        level = parse_show_level(idx_level, argc, argv);
-       adv_router = ospf6->router_id;
 
-       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id, &adv_router, uj,
-                                    ospf6);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       adv_router = ospf6->router_id;
+                       ospf6_lsdb_type_show_wrapper(vty, level, &type, &id,
+                                                    &adv_router, uj, ospf6);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
        return CMD_SUCCESS;
 }
 
-DEFUN (show_ipv6_ospf6_border_routers,
-       show_ipv6_ospf6_border_routers_cmd,
-       "show ipv6 ospf6 border-routers [<A.B.C.D|detail>]",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Display routing table for ABR and ASBR\n"
-       "Router ID\n"
-       "Show detailed output\n")
+static int show_ospf6_border_routers_common(struct vty *vty, int argc,
+                                           struct cmd_token **argv,
+                                           struct ospf6 *ospf6, int idx_ipv4,
+                                           int idx_argc)
 {
-       int idx_ipv4 = 4;
        uint32_t adv_router;
        struct ospf6_route *ro;
        struct prefix prefix;
-       struct ospf6 *ospf6 = NULL;
 
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
-       if (argc == 5) {
+       if (argc == idx_argc) {
                if (strmatch(argv[idx_ipv4]->text, "detail")) {
                        for (ro = ospf6_route_head(ospf6->brouter_table); ro;
                             ro = ospf6_route_next(ro))
@@ -1017,7 +1230,7 @@ DEFUN (show_ipv6_ospf6_border_routers,
                        if (!ro) {
                                vty_out(vty,
                                        "No Route found for Router ID: %s\n",
-                                       argv[4]->arg);
+                                       argv[idx_ipv4]->arg);
                                return CMD_SUCCESS;
                        }
 
@@ -1035,62 +1248,125 @@ DEFUN (show_ipv6_ospf6_border_routers,
        return CMD_SUCCESS;
 }
 
+DEFUN(show_ipv6_ospf6_border_routers, show_ipv6_ospf6_border_routers_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] border-routers [<A.B.C.D|detail>]",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display routing table for ABR and ASBR\n"
+      "Router ID\n"
+      "Show detailed output\n")
+{
+       int idx_ipv4 = 4;
+       struct ospf6 *ospf6 = NULL;
+       struct listnode *node;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+       int idx_argc = 5;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0) {
+               idx_argc += 2;
+               idx_ipv4 += 2;
+       }
 
-DEFUN (show_ipv6_ospf6_linkstate,
-       show_ipv6_ospf6_linkstate_cmd,
-       "show ipv6 ospf6 linkstate <router A.B.C.D|network A.B.C.D A.B.C.D>",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Display linkstate routing table\n"
-       "Display Router Entry\n"
-       "Specify Router ID as IPv4 address notation\n"
-       "Display Network Entry\n"
-       "Specify Router ID as IPv4 address notation\n"
-       "Specify Link state ID as IPv4 address notation\n")
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       show_ospf6_border_routers_common(vty, argc, argv, ospf6,
+                                                        idx_ipv4, idx_argc);
+
+                       if (!all_vrf)
+                               break;
+               }
+       }
+
+       return CMD_SUCCESS;
+}
+
+
+DEFUN(show_ipv6_ospf6_linkstate, show_ipv6_ospf6_linkstate_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] linkstate <router A.B.C.D|network A.B.C.D A.B.C.D>",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display linkstate routing table\n"
+      "Display Router Entry\n"
+      "Specify Router ID as IPv4 address notation\n"
+      "Display Network Entry\n"
+      "Specify Router ID as IPv4 address notation\n"
+      "Specify Link state ID as IPv4 address notation\n")
 {
        int idx_ipv4 = 5;
-       struct listnode *node;
+       struct listnode *node, *nnode;
        struct ospf6_area *oa;
        struct ospf6 *ospf6 = NULL;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_ipv4 += 2;
+
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, nnode, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
+                               vty_out(vty,
+                                       "\n        SPF Result in Area %s\n\n",
+                                       oa->name);
+                               ospf6_linkstate_table_show(vty, idx_ipv4, argc,
+                                                          argv, oa->spf_table);
+                       }
+                       vty_out(vty, "\n");
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
-       for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
-               vty_out(vty, "\n        SPF Result in Area %s\n\n", oa->name);
-               ospf6_linkstate_table_show(vty, idx_ipv4, argc, argv,
-                                          oa->spf_table);
+                       if (!all_vrf)
+                               break;
+               }
        }
 
-       vty_out(vty, "\n");
        return CMD_SUCCESS;
 }
 
 
-DEFUN (show_ipv6_ospf6_linkstate_detail,
-       show_ipv6_ospf6_linkstate_detail_cmd,
-       "show ipv6 ospf6 linkstate detail",
-       SHOW_STR
-       IP6_STR
-       OSPF6_STR
-       "Display linkstate routing table\n"
-       "Display detailed information\n")
+DEFUN(show_ipv6_ospf6_linkstate_detail, show_ipv6_ospf6_linkstate_detail_cmd,
+      "show ipv6 ospf6 [vrf <NAME|all>] linkstate detail",
+      SHOW_STR IP6_STR OSPF6_STR VRF_CMD_HELP_STR
+      "All VRFs\n"
+      "Display linkstate routing table\n"
+      "Display detailed information\n")
 {
        int idx_detail = 4;
        struct listnode *node;
        struct ospf6_area *oa;
        struct ospf6 *ospf6 = NULL;
+       const char *vrf_name = NULL;
+       bool all_vrf = false;
+       int idx_vrf = 0;
+
 
-       ospf6 = ospf6_lookup_by_vrf_name(VRF_DEFAULT_NAME);
-       OSPF6_CMD_CHECK_RUNNING(ospf6);
+       OSPF6_CMD_CHECK_RUNNING();
+       OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf);
+       if (idx_vrf > 0)
+               idx_detail += 2;
 
-       for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
-               vty_out(vty, "\n        SPF Result in Area %s\n\n", oa->name);
-               ospf6_linkstate_table_show(vty, idx_detail, argc, argv,
-                                          oa->spf_table);
+       for (ALL_LIST_ELEMENTS_RO(om6->ospf6, node, ospf6)) {
+               if (all_vrf || strcmp(ospf6->name, vrf_name) == 0) {
+                       for (ALL_LIST_ELEMENTS_RO(ospf6->area_list, node, oa)) {
+                               vty_out(vty,
+                                       "\n        SPF Result in Area %s\n\n",
+                                       oa->name);
+                               ospf6_linkstate_table_show(vty, idx_detail,
+                                                          argc, argv,
+                                                          oa->spf_table);
+                       }
+                       vty_out(vty, "\n");
+
+                       if (!all_vrf)
+                               break;
+               }
        }
 
-       vty_out(vty, "\n");
        return CMD_SUCCESS;
 }
 
@@ -1123,8 +1399,11 @@ void ospf6_init(struct thread_master *master)
        ospf6_asbr_init();
        ospf6_abr_init();
 
+       /* initialize hooks for modifying filter rules */
        prefix_list_add_hook(ospf6_plist_add);
        prefix_list_delete_hook(ospf6_plist_del);
+       access_list_add_hook(ospf6_filter_update);
+       access_list_delete_hook(ospf6_filter_update);
 
        ospf6_bfd_init();
        install_node(&debug_node);
index dfac57aa2f5d4ef47faa2bb55bae4e259e352817..e054803df357cc0ca6c9ed7c94852e601e18b1ef 100644 (file)
@@ -89,13 +89,21 @@ extern struct thread_master *master;
 #define OSPF6_ROUTER_ID_STR "Specify Router-ID\n"
 #define OSPF6_LS_ID_STR     "Specify Link State ID\n"
 
-#define OSPF6_CMD_CHECK_RUNNING(ospf6)                                         \
-       if (ospf6 == NULL) {                                                   \
+#define OSPF6_CMD_CHECK_RUNNING()                                              \
+       if (om6->ospf6 == NULL) {                                              \
                vty_out(vty, "OSPFv3 is not running\n");                       \
                return CMD_SUCCESS;                                            \
        }
 
 #define IS_OSPF6_ASBR(O) ((O)->flag & OSPF6_FLAG_ASBR)
+#define OSPF6_FIND_VRF_ARGS(argv, argc, idx_vrf, vrf_name, all_vrf)            \
+       if (argv_find(argv, argc, "vrf", &idx_vrf)) {                          \
+               vrf_name = argv[idx_vrf + 1]->arg;                             \
+               all_vrf = strmatch(vrf_name, "all");                           \
+       } else {                                                               \
+               vrf_name = VRF_DEFAULT_NAME;                                   \
+       }
+
 extern struct zebra_privs_t ospf6d_privs;
 
 /* Function Prototypes */
index 5ccae5b27901fcbc2e3a9dbabbb8d7368f23690f..00388afd38fdafedced8ebb9489e568be688a42b 100644 (file)
@@ -80,7 +80,7 @@ ospf6d_ospf6d_SOURCES = \
        # end
 
 ospf6d_ospf6d_snmp_la_SOURCES = ospf6d/ospf6_snmp.c
-ospf6d_ospf6d_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+ospf6d_ospf6d_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 ospf6d_ospf6d_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 ospf6d_ospf6d_snmp_la_LIBADD = lib/libfrrsnmp.la
 
index b5c97eda3c908516156ea0f2073c04a4e64f1eca..a6027ee9d162bc557066b4fcf074fd9b1d1202b3 100644 (file)
@@ -1818,7 +1818,6 @@ static int ospf_abr_task_timer(struct thread *thread)
 
        ospf_abr_task(ospf);
        ospf_abr_nssa_task(ospf); /* if nssa-abr, then scan Type-7 LSDB */
-       ospf_asbr_nssa_redist_task(ospf);
 
        return 0;
 }
index 0b4e5d77626d04bc3b81d66bd75b60bada252e20..b022133dcd011bacc1a2ce03d981a16962c6bbb4 100644 (file)
@@ -113,7 +113,6 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance,
        struct external_info *new;
        struct route_node *rn;
        struct ospf_external *ext;
-       char inetbuf[INET6_BUFSIZ];
 
        ext = ospf_external_lookup(ospf, type, instance);
        if (!ext)
@@ -121,26 +120,23 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance,
 
        rn = route_node_get(EXTERNAL_INFO(ext), (struct prefix *)&p);
        /* If old info exists, -- discard new one or overwrite with new one? */
-       if (rn)
-               if (rn->info) {
-                       new = rn->info;
-                       if ((new->ifindex == ifindex)
-                           && (new->nexthop.s_addr == nexthop.s_addr)
-                           && (new->tag == tag)) {
-                               route_unlock_node(rn);
-                               return NULL; /* NULL => no LSA to refresh */
-                       }
-
-                       inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf,
-                                 sizeof(inetbuf));
-                       if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
-                               zlog_debug(
-                                       "Redistribute[%s][%d][%u]: %pFX discarding old info with NH %s.",
-                                       ospf_redist_string(type), instance,
-                                       ospf->vrf_id, &p, inetbuf);
-                       XFREE(MTYPE_OSPF_EXTERNAL_INFO, rn->info);
+       if (rn && rn->info) {
+               new = rn->info;
+               if ((new->ifindex == ifindex)
+                   && (new->nexthop.s_addr == nexthop.s_addr)
+                   && (new->tag == tag)) {
+                       route_unlock_node(rn);
+                       return NULL; /* NULL => no LSA to refresh */
                }
 
+               if (IS_DEBUG_OSPF(lsa, LSA_GENERATE))
+                       zlog_debug(
+                               "Redistribute[%s][%d][%u]: %pFX discarding old info with NH %pI4.",
+                               ospf_redist_string(type), instance,
+                               ospf->vrf_id, &p, &nexthop.s_addr);
+               XFREE(MTYPE_OSPF_EXTERNAL_INFO, rn->info);
+       }
+
        /* Create new External info instance. */
        new = ospf_external_info_new(type, instance);
        new->p = p;
@@ -155,12 +151,10 @@ ospf_external_info_add(struct ospf *ospf, uint8_t type, unsigned short instance,
                rn->info = new;
 
        if (IS_DEBUG_OSPF(lsa, LSA_GENERATE)) {
-               inet_ntop(AF_INET, (void *)&nexthop.s_addr, inetbuf,
-                         sizeof(inetbuf));
                zlog_debug(
-                       "Redistribute[%s][%u]: %pFX external info created, with NH %s",
-                       ospf_redist_string(type), ospf->vrf_id,
-                       &p, inetbuf);
+                       "Redistribute[%s][%u]: %pFX external info created, with NH %pI4",
+                       ospf_redist_string(type), ospf->vrf_id, &p,
+                       &nexthop.s_addr);
        }
        return new;
 }
@@ -277,10 +271,16 @@ void ospf_asbr_status_update(struct ospf *ospf, uint8_t status)
 /* If there's redistribution configured, we need to refresh external
  * LSAs in order to install Type-7 and flood to all NSSA Areas
  */
-void ospf_asbr_nssa_redist_task(struct ospf *ospf)
+static int ospf_asbr_nssa_redist_update_timer(struct thread *thread)
 {
+       struct ospf *ospf = THREAD_ARG(thread);
        int type;
 
+       ospf->t_asbr_nssa_redist_update = NULL;
+
+       if (IS_DEBUG_OSPF_EVENT)
+               zlog_debug("Running ASBR NSSA redistribution update on timer");
+
        for (type = 0; type < ZEBRA_ROUTE_MAX; type++) {
                struct list *red_list;
                struct listnode *node;
@@ -293,10 +293,22 @@ void ospf_asbr_nssa_redist_task(struct ospf *ospf)
                for (ALL_LIST_ELEMENTS_RO(red_list, node, red))
                        ospf_external_lsa_refresh_type(ospf, type,
                                                       red->instance,
-                                                      LSA_REFRESH_IF_CHANGED);
+                                                      LSA_REFRESH_FORCE);
        }
 
        ospf_external_lsa_refresh_default(ospf);
+
+       return 0;
+}
+
+void ospf_schedule_asbr_nssa_redist_update(struct ospf *ospf)
+{
+       if (IS_DEBUG_OSPF_EVENT)
+               zlog_debug("Scheduling ASBR NSSA redistribution update");
+
+       thread_add_timer(master, ospf_asbr_nssa_redist_update_timer, ospf,
+                        OSPF_ASBR_NSSA_REDIST_UPDATE_DELAY,
+                        &ospf->t_asbr_nssa_redist_update);
 }
 
 void ospf_redistribute_withdraw(struct ospf *ospf, uint8_t type,
@@ -311,25 +323,36 @@ void ospf_redistribute_withdraw(struct ospf *ospf, uint8_t type,
                return;
 
        /* Delete external info for specified type. */
-       if (EXTERNAL_INFO(ext))
-               for (rn = route_top(EXTERNAL_INFO(ext)); rn;
-                    rn = route_next(rn))
-                       if ((ei = rn->info))
-                               if (ospf_external_info_find_lsa(ospf, &ei->p)) {
-                                       if (is_prefix_default(&ei->p)
-                                           && ospf->default_originate
-                                                      != DEFAULT_ORIGINATE_NONE)
-                                               continue;
-                                       ospf_external_lsa_flush(
-                                               ospf, type, &ei->p,
+       if (!EXTERNAL_INFO(ext))
+               return;
+
+       for (rn = route_top(EXTERNAL_INFO(ext)); rn; rn = route_next(rn)) {
+               ei = rn->info;
+
+               if (!ei)
+                       continue;
+
+               struct ospf_external_aggr_rt *aggr;
+
+               if (is_prefix_default(&ei->p)
+                   && ospf->default_originate != DEFAULT_ORIGINATE_NONE)
+                       continue;
+
+               aggr = ei->aggr_route;
+
+               if (aggr)
+                       ospf_unlink_ei_from_aggr(ospf, aggr, ei);
+               else if (ospf_external_info_find_lsa(ospf, &ei->p))
+                       ospf_external_lsa_flush(ospf, type, &ei->p,
                                                ei->ifindex /*, ei->nexthop */);
 
-                                       ospf_external_info_free(ei);
-                                       route_unlock_node(rn);
-                                       rn->info = NULL;
-                               }
+               ospf_external_info_free(ei);
+               route_unlock_node(rn);
+               rn->info = NULL;
+       }
 }
 
+
 /* External Route Aggregator Handlers */
 bool is_valid_summary_addr(struct prefix_ipv4 *p)
 {
index 7759d45455ee9637c901beb1575f58592b3bba27..d3e50903ef128513f71c3cc72477d0e3237ce53f 100644 (file)
@@ -104,6 +104,7 @@ struct ospf_external_aggr_rt {
 };
 
 #define OSPF_ASBR_CHECK_DELAY 30
+#define OSPF_ASBR_NSSA_REDIST_UPDATE_DELAY 9
 
 extern void ospf_external_route_remove(struct ospf *, struct prefix_ipv4 *);
 extern struct external_info *ospf_external_info_new(uint8_t, unsigned short);
@@ -121,7 +122,7 @@ extern struct external_info *ospf_external_info_lookup(struct ospf *, uint8_t,
                                                       unsigned short,
                                                       struct prefix_ipv4 *);
 extern void ospf_asbr_status_update(struct ospf *, uint8_t);
-extern void ospf_asbr_nssa_redist_task(struct ospf *ospf);
+extern void ospf_schedule_asbr_nssa_redist_update(struct ospf *ospf);
 
 extern void ospf_redistribute_withdraw(struct ospf *, uint8_t, unsigned short);
 extern void ospf_asbr_check(void);
index 2ab7db68bdca0174efb31b44f599d1d48129168a..56116cd28d1988d4f3e5c9134135ae126278323f 100644 (file)
@@ -99,7 +99,6 @@ void ospf_neighbor_bfd_apply(struct ospf_neighbor *nbr)
                bfd_sess_set_ipv4_addrs(nbr->bfd_session, NULL, &nbr->src);
                bfd_sess_set_interface(nbr->bfd_session, oi->ifp->name);
                bfd_sess_set_vrf(nbr->bfd_session, oi->ospf->vrf_id);
-               bfd_sess_enable(nbr->bfd_session, true);
        }
 
        /* Set new configuration. */
index 2442f2e781c73030e00d47f3bd37e1490caea057..8f31f90346effa1f9b0654406f4abb1247b917e8 100644 (file)
@@ -169,8 +169,7 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
 /* Making formatted timer strings. */
 #define MINUTE_IN_SECONDS      60
 #define HOUR_IN_SECONDS                (60*MINUTE_IN_SECONDS)
-#define DAY_IN_SECONDS         (24*HOUR_IN_SECONDS)
-#define WEEK_IN_SECONDS                (7*DAY_IN_SECONDS)
+
        unsigned long w, d, h, m, ms, us;
 
        if (!t)
@@ -191,14 +190,14 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
                ms %= 1000;
        }
 
-       if (t->tv_sec > WEEK_IN_SECONDS) {
-               w = t->tv_sec / WEEK_IN_SECONDS;
-               t->tv_sec -= w * WEEK_IN_SECONDS;
+       if (t->tv_sec > ONE_WEEK_SECOND) {
+               w = t->tv_sec / ONE_WEEK_SECOND;
+               t->tv_sec -= w * ONE_WEEK_SECOND;
        }
 
-       if (t->tv_sec > DAY_IN_SECONDS) {
-               d = t->tv_sec / DAY_IN_SECONDS;
-               t->tv_sec -= d * DAY_IN_SECONDS;
+       if (t->tv_sec > ONE_DAY_SECOND) {
+               d = t->tv_sec / ONE_DAY_SECOND;
+               t->tv_sec -= d * ONE_DAY_SECOND;
        }
 
        if (t->tv_sec >= HOUR_IN_SECONDS) {
@@ -221,7 +220,7 @@ const char *ospf_timeval_dump(struct timeval *t, char *buf, size_t size)
                snprintf(buf, size, "%luh%02lum%02lds", h, m, (long)t->tv_sec);
        else if (m)
                snprintf(buf, size, "%lum%02lds", m, (long)t->tv_sec);
-       else if (ms)
+       else if (t->tv_sec > 0 || ms > 0)
                snprintf(buf, size, "%ld.%03lus", (long)t->tv_sec, ms);
        else
                snprintf(buf, size, "%ld usecs", (long)t->tv_usec);
index 6e4bc7abf1e092ddbc7a28e2ed42f9312dd53bdb..334ed33ee0ed587916d82e127840b901c2998072 100644 (file)
@@ -543,6 +543,8 @@ static struct ospf_if_params *ospf_new_if_params(void)
        oip->network_lsa_seqnum = htonl(OSPF_INITIAL_SEQUENCE_NUMBER);
        oip->is_v_wait_set = false;
 
+       oip->ptp_dmvpn = 0;
+
        return oip;
 }
 
index e2d732738169a2032330419532011c19c7be13f6..4a211472468a256d16b5c70515fbe209556228e8 100644 (file)
@@ -118,6 +118,9 @@ struct ospf_if_params {
 
        /* MPLS LDP-IGP Sync configuration */
        struct ldp_sync_info *ldp_sync_info;
+
+       /* point-to-point DMVPN configuration */
+       uint8_t ptp_dmvpn;
 };
 
 enum { MEMBER_ALLROUTERS = 0,
@@ -180,6 +183,9 @@ struct ospf_interface {
        /* OSPF Network Type. */
        uint8_t type;
 
+       /* point-to-point DMVPN configuration */
+       uint8_t ptp_dmvpn;
+
        /* State of Interface State Machine. */
        uint8_t state;
 
index cb1c565d3770f73469ad626e03936985375b3969..6e9df77fb879db8fb5099cfcdac9cc930a901a69 100644 (file)
@@ -469,6 +469,12 @@ char link_info_set(struct stream **s, struct in_addr id, struct in_addr data,
 }
 
 /* Describe Point-to-Point link (Section 12.4.1.1). */
+
+/* Note: If the interface is configured as point-to-point dmvpn then the other
+ * end of link is dmvpn hub with point-to-multipoint ospf network type. The
+ * hub then expects this router to populate the stub network and also Link Data
+ * Field set to IP Address and not MIB-II ifIndex
+ */
 static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
 {
        int links = 0;
@@ -482,7 +488,8 @@ static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
        if ((nbr = ospf_nbr_lookup_ptop(oi)))
                if (nbr->state == NSM_Full) {
                        if (CHECK_FLAG(oi->connected->flags,
-                                      ZEBRA_IFA_UNNUMBERED)) {
+                                      ZEBRA_IFA_UNNUMBERED)
+                           && !oi->ptp_dmvpn) {
                                /* For unnumbered point-to-point networks, the
                                   Link Data field
                                   should specify the interface's MIB-II ifIndex
@@ -500,7 +507,8 @@ static int lsa_link_ptop_set(struct stream **s, struct ospf_interface *oi)
                }
 
        /* no need for a stub link for unnumbered interfaces */
-       if (!CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
+       if (oi->ptp_dmvpn
+           || !CHECK_FLAG(oi->connected->flags, ZEBRA_IFA_UNNUMBERED)) {
                /* Regardless of the state of the neighboring router, we must
                   add a Type 3 link (stub network).
                   N.B. Options 1 & 2 share basically the same logic. */
index 0fd4803c7993efe57e25136834b2168dc25c3d46..aa98d7dd285f51b884bbce74384e3fd05f85630e 100644 (file)
@@ -799,7 +799,13 @@ static int ospf_write(struct thread *thread)
                                &iph.ip_dst, iph.ip_id, iph.ip_off,
                                iph.ip_len, oi->ifp->name, oi->ifp->mtu);
 
-               if (ret < 0)
+               /* sendmsg will return EPERM if firewall is blocking sending.
+                * This is a normal situation when 'ip nhrp map multicast xxx'
+                * is being used to send multicast packets to DMVPN peers. In
+                * that case the original message is blocked with iptables rule
+                * causing the EPERM result
+                */
+               if (ret < 0 && errno != EPERM)
                        flog_err(
                                EC_LIB_SOCKET,
                                "*** sendmsg in ospf_write failed to %pI4, id %d, off %d, len %d, interface %s, mtu %u: %s",
@@ -907,8 +913,11 @@ static void ospf_hello(struct ip *iph, struct ospf_header *ospfh,
 
        /* Compare network mask. */
        /* Checking is ignored for Point-to-Point and Virtual link. */
+       /* Checking is also ignored for Point-to-Multipoint with /32 prefix */
        if (oi->type != OSPF_IFTYPE_POINTOPOINT
-           && oi->type != OSPF_IFTYPE_VIRTUALLINK)
+           && oi->type != OSPF_IFTYPE_VIRTUALLINK
+           && !(oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
+                && oi->address->prefixlen == IPV4_MAX_BITLEN))
                if (oi->address->prefixlen != p.prefixlen) {
                        flog_warn(
                                EC_OSPF_PACKET,
@@ -2427,6 +2436,11 @@ static int ospf_check_network_mask(struct ospf_interface *oi,
            || oi->type == OSPF_IFTYPE_VIRTUALLINK)
                return 1;
 
+       /* Ignore mask check for max prefix length (32) */
+       if (oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
+           && oi->address->prefixlen == IPV4_MAX_BITLEN)
+               return 1;
+
        masklen2ip(oi->address->prefixlen, &mask);
 
        me.s_addr = oi->address->u.prefix4.s_addr & mask.s_addr;
index 1f6b0ef78ccf7ffa8bb7cad98eb2cf41fad24046..e53d009a55be81b31e8848b5740bf132d9827660 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "lib/northbound.h"
 #include "lib/routemap.h"
 #include "ospf_routemap_nb.h"
index bfb18c5e08b02064a4516e0a382a11eeee9d3bbe..9026795425d8a923925f631dc78ff3d116596256 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "lib/command.h"
 #include "lib/log.h"
 #include "lib/northbound.h"
index 43b998ac5bfc1f182fe8405b1f70e5136f5a42ca..432f95f9ddfd5f049e1c7515e07099badbe999f7 100644 (file)
@@ -34,7 +34,7 @@
 #include "memory.h"
 #include "smux.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #include "ospfd/ospfd.h"
 #include "ospfd/ospf_interface.h"
index 95553dacdfdf064785b4e610e01ce1bf7a4dfe80..0164bfac678dc490520e1e7544825f1c301c9c46 100644 (file)
@@ -905,7 +905,9 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
                                 * somehow.
                                 */
                                if (area->ospf->ti_lfa_enabled
-                                   || (oi && oi->type == OSPF_IFTYPE_POINTOPOINT)) {
+                                   || (oi && oi->type == OSPF_IFTYPE_POINTOPOINT)
+                                   || (oi && oi->type == OSPF_IFTYPE_POINTOMULTIPOINT
+                                          && oi->address->prefixlen == IPV4_MAX_BITLEN)) {
                                        struct ospf_neighbor *nbr_w = NULL;
 
                                        /* Calculating node is root node, link
index a7a2e03632f813123ea62584c64b10a49b92d449..d003f3bf7cde438eaab9249db66e41391844c88e 100644 (file)
@@ -1689,7 +1689,8 @@ void ospf_sr_ext_itf_add(struct ext_itf *exti)
                else
                        srl->nhlfe[1].nexthop = exti->rmt_itf_addr.value;
                break;
-       default:
+       case PREF_SID:
+       case LOCAL_SID:
                /* Wrong SID Type. Abort! */
                XFREE(MTYPE_OSPF_SR_PARAMS, srl);
                return;
index f2842538a56a9ac5f378eb0580e8503df09c0e79..1929e3dea40b948fb2cf60c3f72ea7d0be9edac5 100644 (file)
@@ -2153,6 +2153,13 @@ static int ospf_te_parse_te(struct ls_ted *ted, struct ospf_lsa *lsa)
        /* Initialize TLV browsing */
        tlvh = TLV_HDR_TOP(lsa->data);
 
+       uint32_t total_len = TLV_BODY_SIZE(lsa->data) - OSPF_LSA_HEADER_SIZE;
+
+       /* If TE Router-ID is only TLV we are done */
+       if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR
+           && total_len == sizeof(struct te_tlv_router_addr))
+               return 0;
+
        /* Skip TE Router-ID if present */
        if (ntohs(tlvh->type) == TE_TLV_ROUTER_ADDR)
                tlvh = TLV_HDR_NEXT(tlvh);
@@ -2756,7 +2763,7 @@ static int ospf_te_parse_ext_link(struct ls_ted *ted, struct ospf_lsa *lsa)
                  &lsa->data->id, &edge->attributes->standard.local);
 
        /* Initialize TLV browsing */
-       len = TLV_BODY_SIZE(&ext->header);
+       len = TLV_BODY_SIZE(&ext->header) - EXT_TLV_LINK_SIZE;
        tlvh = (struct tlv_header *)((char *)(ext) + TLV_HDR_SIZE
                                     + EXT_TLV_LINK_SIZE);
        for (; sum < len; tlvh = TLV_HDR_NEXT(tlvh)) {
index 2d06e6884d32167d8cd3cc3c0ad8756ccb2d7978..50943c4ccf0543b5a112e7892c2ec16f7df89da6 100644 (file)
@@ -1546,6 +1546,7 @@ static int ospf_area_nssa_cmd_handler(struct vty *vty, int argc,
        /* Flush the external LSA for the specified area */
        ospf_flush_lsa_from_area(ospf, area_id, OSPF_AS_EXTERNAL_LSA);
        ospf_schedule_abr_task(ospf);
+       ospf_schedule_asbr_nssa_redist_update(ospf);
 
        return CMD_SUCCESS;
 }
@@ -3736,6 +3737,31 @@ static void show_ip_ospf_interface_sub(struct vty *vty, struct ospf *ospf,
                                vty_out(vty,
                                        "  No backup designated router on this network\n");
                } else {
+                       nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &DR(oi));
+                       if (nbr) {
+                               if (use_json) {
+                                       json_object_string_add(
+                                               json_interface_sub, "drId",
+                                               inet_ntop(AF_INET,
+                                                         &nbr->router_id, buf,
+                                                         sizeof(buf)));
+                                       json_object_string_add(
+                                               json_interface_sub, "drAddress",
+                                               inet_ntop(
+                                                       AF_INET,
+                                                       &nbr->address.u.prefix4,
+                                                       buf, sizeof(buf)));
+                               } else {
+                                       vty_out(vty,
+                                               "  Designated Router (ID) %pI4",
+                                               &nbr->router_id);
+                                       vty_out(vty,
+                                               " Interface Address %pFX\n",
+                                               &nbr->address);
+                               }
+                       }
+                       nbr = NULL;
+
                        nbr = ospf_nbr_lookup_by_addr(oi->nbrs, &BDR(oi));
                        if (nbr == NULL) {
                                if (!use_json)
@@ -8391,6 +8417,7 @@ DEFUN (no_ip_ospf_hello_interval,
                        continue;
 
                oi->type = IF_DEF_PARAMS(ifp)->type;
+               oi->ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
 
                if (oi->state > ISM_Down) {
                        OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceDown);
@@ -8418,20 +8445,21 @@ DEFUN_HIDDEN (no_ospf_hello_interval,
        return no_ip_ospf_hello_interval(self, vty, argc, argv);
 }
 
-DEFUN (ip_ospf_network,
-       ip_ospf_network_cmd,
-       "ip ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point>",
-       "IP Information\n"
-       "OSPF interface commands\n"
-       "Network type\n"
-       "Specify OSPF broadcast multi-access network\n"
-       "Specify OSPF NBMA network\n"
-       "Specify OSPF point-to-multipoint network\n"
-       "Specify OSPF point-to-point network\n")
+DEFUN(ip_ospf_network, ip_ospf_network_cmd,
+      "ip ospf network <broadcast|non-broadcast|point-to-multipoint|point-to-point [dmvpn]>",
+      "IP Information\n"
+      "OSPF interface commands\n"
+      "Network type\n"
+      "Specify OSPF broadcast multi-access network\n"
+      "Specify OSPF NBMA network\n"
+      "Specify OSPF point-to-multipoint network\n"
+      "Specify OSPF point-to-point network\n"
+      "Specify OSPF point-to-point DMVPN network\n")
 {
        VTY_DECLVAR_CONTEXT(interface, ifp);
        int idx = 0;
        int old_type = IF_DEF_PARAMS(ifp)->type;
+       uint8_t old_ptp_dmvpn = IF_DEF_PARAMS(ifp)->ptp_dmvpn;
        struct route_node *rn;
 
        if (old_type == OSPF_IFTYPE_LOOPBACK) {
@@ -8440,16 +8468,22 @@ DEFUN (ip_ospf_network,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
+       IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
+
        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;
-       else if (argv_find(argv, argc, "point-to-point", &idx))
+       else if (argv_find(argv, argc, "point-to-point", &idx)) {
                IF_DEF_PARAMS(ifp)->type = OSPF_IFTYPE_POINTOPOINT;
+               if (argv_find(argv, argc, "dmvpn", &idx))
+                       IF_DEF_PARAMS(ifp)->ptp_dmvpn = 1;
+       }
 
-       if (IF_DEF_PARAMS(ifp)->type == old_type)
+       if (IF_DEF_PARAMS(ifp)->type == old_type
+           && IF_DEF_PARAMS(ifp)->ptp_dmvpn == old_ptp_dmvpn)
                return CMD_SUCCESS;
 
        SET_IF_PARAM(IF_DEF_PARAMS(ifp), type);
@@ -8501,6 +8535,7 @@ DEFUN (no_ip_ospf_network,
        struct route_node *rn;
 
        IF_DEF_PARAMS(ifp)->type = ospf_default_iftype(ifp);
+       IF_DEF_PARAMS(ifp)->ptp_dmvpn = 0;
 
        if (IF_DEF_PARAMS(ifp)->type == old_type)
                return CMD_SUCCESS;
@@ -9076,14 +9111,13 @@ DEFUN (ospf_redistribute_source,
        int metric = -1;
        struct ospf_redist *red;
        int idx = 0;
+       bool update = false;
 
        /* Get distribute source. */
        source = proto_redistnum(AFI_IP, argv[idx_protocol]->text);
        if (source < 0)
                return CMD_WARNING_CONFIG_FAILED;
 
-       red = ospf_redist_add(ospf, source, 0);
-
        /* Get metric value. */
        if (argv_find(argv, argc, "(0-16777214)", &idx)) {
                if (!str2metric(argv[idx]->arg, &metric))
@@ -9096,13 +9130,25 @@ DEFUN (ospf_redistribute_source,
                        return CMD_WARNING_CONFIG_FAILED;
        }
        idx = 1;
+
+       red = ospf_redist_lookup(ospf, source, 0);
+       if (!red)
+               red = ospf_redist_add(ospf, source, 0);
+       else
+               update = true;
+
        /* Get route-map */
        if (argv_find(argv, argc, "WORD", &idx)) {
                ospf_routemap_set(red, argv[idx]->arg);
        } else
                ospf_routemap_unset(red);
 
-       return ospf_redistribute_set(ospf, source, 0, type, metric);
+       if (update)
+               return ospf_redistribute_update(ospf, red, source, 0, type,
+                                               metric);
+       else
+               return ospf_redistribute_set(ospf, red, source, 0, type,
+                                            metric);
 }
 
 DEFUN (no_ospf_redistribute_source,
@@ -9160,6 +9206,7 @@ DEFUN (ospf_redistribute_instance_source,
        int metric = -1;
        unsigned short instance;
        struct ospf_redist *red;
+       bool update = false;
 
        source = proto_redistnum(AFI_IP, argv[idx_ospf_table]->text);
 
@@ -9192,7 +9239,11 @@ DEFUN (ospf_redistribute_instance_source,
                if (!str2metric_type(argv[idx + 1]->arg, &type))
                        return CMD_WARNING_CONFIG_FAILED;
 
-       red = ospf_redist_add(ospf, source, instance);
+       red = ospf_redist_lookup(ospf, source, instance);
+       if (!red)
+               red = ospf_redist_add(ospf, source, instance);
+       else
+               update = true;
 
        idx = 3;
        if (argv_find(argv, argc, "route-map", &idx))
@@ -9200,7 +9251,12 @@ DEFUN (ospf_redistribute_instance_source,
        else
                ospf_routemap_unset(red);
 
-       return ospf_redistribute_set(ospf, source, instance, type, metric);
+       if (update)
+               return ospf_redistribute_update(ospf, red, source, instance,
+                                               type, metric);
+       else
+               return ospf_redistribute_set(ospf, red, source, instance, type,
+                                            metric);
 }
 
 DEFUN (no_ospf_redistribute_instance_source,
@@ -11643,6 +11699,10 @@ static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
                                        vty_out(vty, " ip ospf network %s",
                                                ospf_int_type_str
                                                        [params->type]);
+                                       if (params->type
+                                                   == OSPF_IFTYPE_POINTOPOINT
+                                           && params->ptp_dmvpn)
+                                               vty_out(vty, " dmvpn");
                                        if (params != IF_DEF_PARAMS(ifp) && rn)
                                                vty_out(vty, " %pI4",
                                                        &rn->p.u.prefix4);
index a2ce4d1ce73be4c41511670971521d6d84bb0aaf..5853b506f81959467103f37e85c97917f85222c8 100644 (file)
@@ -637,7 +637,8 @@ void ospf_zebra_update_prefix_sid(const struct sr_prefix *srp)
                        }
                }
                break;
-       default:
+       case ADJ_SID:
+       case LAN_ADJ_SID:
                return;
        }
 
@@ -765,53 +766,44 @@ int ospf_is_type_redistributed(struct ospf *ospf, int type,
                                           ospf->vrf_id)
                        : ((instance
                            && redist_check_instance(
-                                      &zclient->mi_redist[AFI_IP][type],
-                                      instance))
+                                   &zclient->mi_redist[AFI_IP][type],
+                                   instance))
                           || (!instance
                               && vrf_bitmap_check(
-                                         zclient->redist[AFI_IP][type],
-                                         ospf->vrf_id))));
+                                      zclient->redist[AFI_IP][type],
+                                      ospf->vrf_id))));
 }
 
-int ospf_redistribute_set(struct ospf *ospf, int type, unsigned short instance,
-                         int mtype, int mvalue)
+int ospf_redistribute_update(struct ospf *ospf, struct ospf_redist *red,
+                            int type, unsigned short instance, int mtype,
+                            int mvalue)
 {
        int force = 0;
-       struct ospf_redist *red;
-
-       red = ospf_redist_lookup(ospf, type, instance);
 
-       if (red == NULL) {
-               zlog_err(
-                        "Redistribute[%s][%d]: Lookup failed  Type[%d] , Metric[%d]",
-                        ospf_redist_string(type), instance,
-                        metric_type(ospf, type, instance),
-                        metric_value(ospf, type, instance));
-               return CMD_WARNING_CONFIG_FAILED;
+       if (mtype != red->dmetric.type) {
+               red->dmetric.type = mtype;
+               force = LSA_REFRESH_FORCE;
+       }
+       if (mvalue != red->dmetric.value) {
+               red->dmetric.value = mvalue;
+               force = LSA_REFRESH_FORCE;
        }
 
-       if (ospf_is_type_redistributed(ospf, type, instance)) {
-               if (mtype != red->dmetric.type) {
-                       red->dmetric.type = mtype;
-                       force = LSA_REFRESH_FORCE;
-               }
-               if (mvalue != red->dmetric.value) {
-                       red->dmetric.value = mvalue;
-                       force = LSA_REFRESH_FORCE;
-               }
-
-               ospf_external_lsa_refresh_type(ospf, type, instance, force);
+       ospf_external_lsa_refresh_type(ospf, type, instance, force);
 
-               if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
-                       zlog_debug(
-                               "Redistribute[%s][%d]: Refresh  Type[%d], Metric[%d]",
-                               ospf_redist_string(type), instance,
-                               metric_type(ospf, type, instance),
-                               metric_value(ospf, type, instance));
+       if (IS_DEBUG_OSPF(zebra, ZEBRA_REDISTRIBUTE))
+               zlog_debug(
+                       "Redistribute[%s][%d]: Refresh  Type[%d], Metric[%d]",
+                       ospf_redist_string(type), instance,
+                       metric_type(ospf, type, instance),
+                       metric_value(ospf, type, instance));
 
-               return CMD_SUCCESS;
-       }
+       return CMD_SUCCESS;
+}
 
+int ospf_redistribute_set(struct ospf *ospf, struct ospf_redist *red, int type,
+                         unsigned short instance, int mtype, int mvalue)
+{
        red->dmetric.type = mtype;
        red->dmetric.value = mvalue;
 
@@ -838,9 +830,6 @@ int ospf_redistribute_unset(struct ospf *ospf, int type,
        if (type == zclient->redist_default && instance == zclient->instance)
                return CMD_SUCCESS;
 
-       if (!ospf_is_type_redistributed(ospf, type, instance))
-               return CMD_SUCCESS;
-
        zclient_redistribute(ZEBRA_REDISTRIBUTE_DELETE, zclient, AFI_IP, type,
                             instance, ospf->vrf_id);
 
@@ -1262,104 +1251,92 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
                        return 0;
                }
                if (ospf->router_id.s_addr != INADDR_ANY) {
-                       if (ei) {
-                               if (is_prefix_default(&p))
-                                       ospf_external_lsa_refresh_default(ospf);
-                               else {
-                                       struct ospf_external_aggr_rt *aggr;
-                                       struct as_external_lsa *al;
-                                       struct ospf_lsa *lsa = NULL;
-                                       struct in_addr mask;
-
-                                       aggr = ospf_external_aggr_match(ospf,
-                                                                       &ei->p);
+                       if (is_prefix_default(&p))
+                               ospf_external_lsa_refresh_default(ospf);
+                       else {
+                               struct ospf_external_aggr_rt *aggr;
+                               struct as_external_lsa *al;
+                               struct ospf_lsa *lsa = NULL;
+                               struct in_addr mask;
+
+                               aggr = ospf_external_aggr_match(ospf, &ei->p);
+
+                               if (aggr) {
+                                       /* Check the AS-external-LSA
+                                        * should be originated.
+                                        */
+                                       if (!ospf_redistribute_check(ospf, ei,
+                                                                    NULL))
+                                               return 0;
+
+                                       if (IS_DEBUG_OSPF(lsa, EXTNL_LSA_AGGR))
+                                               zlog_debug(
+                                                       "%s: Send Aggreate LSA (%pI4/%d)",
+                                                       __func__,
+                                                       &aggr->p.prefix,
+                                                       aggr->p.prefixlen);
+
+                                       ospf_originate_summary_lsa(ospf, aggr,
+                                                                  ei);
+
+                                       /* Handling the case where the
+                                        * external route prefix
+                                        * and aggegate prefix is same
+                                        * If same dont flush the
+                                        * originated
+                                        * external LSA.
+                                        */
+                                       if (prefix_same(
+                                                   (struct prefix *)&aggr->p,
+                                                   (struct prefix *)&ei->p))
+                                               return 0;
+
+                                       lsa = ospf_external_info_find_lsa(
+                                               ospf, &ei->p);
+
+                                       if (lsa) {
+                                               al = (struct as_external_lsa *)
+                                                            lsa->data;
+                                               masklen2ip(ei->p.prefixlen,
+                                                          &mask);
+
+                                               if (mask.s_addr
+                                                   != al->mask.s_addr)
+                                                       return 0;
 
-                                       if (aggr) {
-                                               /* Check the AS-external-LSA
-                                                * should be originated.
+                                               ospf_external_lsa_flush(
+                                                       ospf, ei->type, &ei->p,
+                                                       0);
+                                       }
+                               } else {
+                                       struct ospf_lsa *current;
+
+                                       current = ospf_external_info_find_lsa(
+                                               ospf, &ei->p);
+                                       if (!current) {
+                                               /* Check the
+                                                * AS-external-LSA
+                                                * should be
+                                                * originated.
                                                 */
                                                if (!ospf_redistribute_check(
                                                            ospf, ei, NULL))
                                                        return 0;
 
+                                               ospf_external_lsa_originate(
+                                                       ospf, ei);
+                                       } else {
                                                if (IS_DEBUG_OSPF(
-                                                           lsa,
-                                                           EXTNL_LSA_AGGR))
+                                                           zebra,
+                                                           ZEBRA_REDISTRIBUTE))
                                                        zlog_debug(
-                                                               "%s: Send Aggreate LSA (%pI4/%d)",
+                                                               "%s: %pI4 refreshing LSA",
                                                                __func__,
-                                                               &aggr->p.prefix,
-                                                               aggr->p.prefixlen);
-
-                                               ospf_originate_summary_lsa(
-                                                       ospf, aggr, ei);
-
-                                               /* Handling the case where the
-                                                * external route prefix
-                                                * and aggegate prefix is same
-                                                * If same dont flush the
-                                                * originated
-                                                * external LSA.
-                                                */
-                                               if (prefix_same(
-                                                           (struct prefix
-                                                                    *)&aggr->p,
-                                                           (struct prefix *)&ei
-                                                                   ->p))
-                                                       return 0;
-
-                                               lsa = ospf_external_info_find_lsa(
-                                                       ospf, &ei->p);
-
-                                               if (lsa) {
-                                                       al = (struct
-                                                             as_external_lsa *)
-                                                                    lsa->data;
-                                                       masklen2ip(
-                                                               ei->p.prefixlen,
-                                                               &mask);
-
-                                                       if (mask.s_addr
-                                                           != al->mask.s_addr)
-                                                               return 0;
-
-                                                       ospf_external_lsa_flush(
-                                                               ospf, ei->type,
-                                                               &ei->p, 0);
-                                               }
-                                       } else {
-                                               struct ospf_lsa *current;
-
-                                               current =
-                                                       ospf_external_info_find_lsa(
-                                                               ospf, &ei->p);
-                                               if (!current) {
-                                                       /* Check the
-                                                        * AS-external-LSA
-                                                        * should be
-                                                        * originated.
-                                                        */
-                                                       if (!ospf_redistribute_check(
-                                                                   ospf, ei,
-                                                                   NULL))
-                                                               return 0;
-
-                                                       ospf_external_lsa_originate(
-                                                               ospf, ei);
-                                               } else {
-                                                       if (IS_DEBUG_OSPF(
-                                                                   zebra,
-                                                                   ZEBRA_REDISTRIBUTE))
-                                                               zlog_debug(
-                                                                       "%s: %pI4 refreshing LSA",
-                                                                       __func__,
-                                                                       &p.prefix);
-                                                       ospf_external_lsa_refresh(
-                                                               ospf, current,
-                                                               ei,
-                                                               LSA_REFRESH_FORCE,
-                                                               false);
-                                               }
+                                                               &p.prefix);
+                                               ospf_external_lsa_refresh(
+                                                       ospf, current, ei,
+                                                       LSA_REFRESH_FORCE,
+                                                       false);
                                        }
                                }
                        }
@@ -1371,20 +1348,19 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
                 */
                ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
 
-       } else /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
-       {
+       } else { /* if (cmd == ZEBRA_REDISTRIBUTE_ROUTE_DEL) */
                struct ospf_external_aggr_rt *aggr;
 
                ei = ospf_external_info_lookup(ospf, rt_type, api.instance, &p);
                if (ei == NULL)
                        return 0;
-               else
-                       /*
-                        * Check if default-information originate i
-                        * with some routemap prefix/access list match.
-                        * Apply before ei is deleted.
-                        */
-                       ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
+
+               /*
+                * Check if default-information originate i
+                * with some routemap prefix/access list match.
+                * Apply before ei is deleted.
+                */
+               ospf_external_lsa_default_routemap_apply(ospf, ei, cmd);
 
                aggr = ospf_external_aggr_match(ospf, &ei->p);
 
@@ -1405,7 +1381,6 @@ static int ospf_zebra_read_route(ZAPI_CALLBACK_ARGS)
                }
        }
 
-
        return 0;
 }
 
@@ -1490,85 +1465,83 @@ static int ospf_distribute_list_update_timer(struct thread *thread)
                        rt = ext->external_info;
                        if (!rt)
                                continue;
-                       for (rn = route_top(rt); rn; rn = route_next(rn))
-                               if ((ei = rn->info) != NULL) {
-                                       if (is_prefix_default(&ei->p))
-                                               default_refresh = 1;
-                                       else {
-                                               struct ospf_external_aggr_rt
-                                                       *aggr;
-                                               aggr = ospf_external_aggr_match(
-                                                       ospf, &ei->p);
-                                               if (aggr) {
-                                                       /* Check the
-                                                        * AS-external-LSA
-                                                        * should be originated.
-                                                        */
-                                                       if (!ospf_redistribute_check(
-                                                                   ospf, ei,
-                                                                   NULL)) {
-
-                                                               ospf_unlink_ei_from_aggr(
-                                                                       ospf,
-                                                                       aggr,
-                                                                       ei);
-                                                               continue;
-                                                       }
-
-                                                       if (IS_DEBUG_OSPF(
-                                                                   lsa,
-                                                                   EXTNL_LSA_AGGR))
-                                                               zlog_debug(
-                                                                       "%s: Send Aggregate LSA (%pI4/%d)",
-                                                                       __func__,
-                                                                       &aggr->p.prefix,
-                                                                       aggr->p.prefixlen);
-
-                                                       /* Originate Aggregate
-                                                        * LSA
-                                                        */
-                                                       ospf_originate_summary_lsa(
+                       for (rn = route_top(rt); rn; rn = route_next(rn)) {
+                               ei = rn->info;
+                               if (!ei)
+                                       continue;
+
+                               if (is_prefix_default(&ei->p))
+                                       default_refresh = 1;
+                               else {
+                                       struct ospf_external_aggr_rt *aggr;
+
+                                       aggr = ospf_external_aggr_match(ospf,
+                                                                       &ei->p);
+                                       if (aggr) {
+                                               /* Check the
+                                                * AS-external-LSA
+                                                * should be originated.
+                                                */
+                                               if (!ospf_redistribute_check(
+                                                           ospf, ei, NULL)) {
+
+                                                       ospf_unlink_ei_from_aggr(
                                                                ospf, aggr, ei);
-                                               } else if (
-                                                       (lsa = ospf_external_info_find_lsa(
-                                                                ospf,
-                                                                &ei->p))) {
-                                                       int force =
-                                                               LSA_REFRESH_IF_CHANGED;
-                                                       /* If this is a MaxAge
-                                                        * LSA, we need to
-                                                        * force refresh it
-                                                        * because distribute
-                                                        * settings might have
-                                                        * changed and now,
-                                                        * this LSA needs to be
-                                                        * originated, not be
-                                                        * removed.
-                                                        * If we don't force
-                                                        * refresh it, it will
-                                                        * remain a MaxAge LSA
-                                                        * because it will look
-                                                        * like it hasn't
-                                                        * changed. Neighbors
-                                                        * will not receive
-                                                        * updates for this LSA.
-                                                        */
-                                                       if (IS_LSA_MAXAGE(lsa))
-                                                               force = LSA_REFRESH_FORCE;
-
-                                                       ospf_external_lsa_refresh(
-                                                               ospf, lsa, ei,
-                                                               force, false);
-                                               } else {
-                                                       if (!ospf_redistribute_check(
-                                                                   ospf, ei,
-                                                                   NULL))
-                                                               continue;
-                                                       ospf_external_lsa_originate(
-                                                               ospf, ei);
+                                                       continue;
                                                }
+
+                                               if (IS_DEBUG_OSPF(
+                                                           lsa,
+                                                           EXTNL_LSA_AGGR))
+                                                       zlog_debug(
+                                                               "%s: Send Aggregate LSA (%pI4/%d)",
+                                                               __func__,
+                                                               &aggr->p.prefix,
+                                                               aggr->p.prefixlen);
+
+                                               /* Originate Aggregate
+                                                * LSA
+                                                */
+                                               ospf_originate_summary_lsa(
+                                                       ospf, aggr, ei);
+                                       } else if (
+                                               (lsa = ospf_external_info_find_lsa(
+                                                        ospf, &ei->p))) {
+                                               int force =
+                                                       LSA_REFRESH_IF_CHANGED;
+                                               /* If this is a MaxAge
+                                                * LSA, we need to
+                                                * force refresh it
+                                                * because distribute
+                                                * settings might have
+                                                * changed and now,
+                                                * this LSA needs to be
+                                                * originated, not be
+                                                * removed.
+                                                * If we don't force
+                                                * refresh it, it will
+                                                * remain a MaxAge LSA
+                                                * because it will look
+                                                * like it hasn't
+                                                * changed. Neighbors
+                                                * will not receive
+                                                * updates for this LSA.
+                                                */
+                                               if (IS_LSA_MAXAGE(lsa))
+                                                       force = LSA_REFRESH_FORCE;
+
+                                               ospf_external_lsa_refresh(
+                                                       ospf, lsa, ei, force,
+                                                       false);
+                                       } else {
+                                               if (!ospf_redistribute_check(
+                                                           ospf, ei, NULL))
+                                                       continue;
+                                               ospf_external_lsa_originate(
+                                                       ospf, ei);
                                        }
                                }
+                       }
                }
        }
        if (default_refresh)
@@ -1718,17 +1691,16 @@ void ospf_prefix_list_update(struct prefix_list *plist)
                        struct ospf_redist *red;
 
                        red_list = ospf->redist[type];
-                       if (red_list) {
-                               for (ALL_LIST_ELEMENTS_RO(red_list, node,
-                                                         red)) {
-                                       if (ROUTEMAP(red)) {
-                                               /* if route-map is not NULL
-                                                * it may be using
-                                                * this prefix list */
-                                               ospf_distribute_list_update(
-                                                       ospf, type,
-                                                       red->instance);
-                                       }
+                       if (!red_list)
+                               continue;
+
+                       for (ALL_LIST_ELEMENTS_RO(red_list, node, red)) {
+                               if (ROUTEMAP(red)) {
+                                       /* if route-map is not NULL
+                                        * it may be using
+                                        * this prefix list */
+                                       ospf_distribute_list_update(
+                                               ospf, type, red->instance);
                                }
                        }
                }
@@ -1736,28 +1708,24 @@ void ospf_prefix_list_update(struct prefix_list *plist)
                /* Update area filter-lists. */
                for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
                        /* Update filter-list in. */
-                       if (PREFIX_NAME_IN(area))
-                               if (strcmp(PREFIX_NAME_IN(area),
-                                          prefix_list_name(plist))
-                                   == 0) {
-                                       PREFIX_LIST_IN(area) =
-                                               prefix_list_lookup(
-                                                       AFI_IP,
-                                                       PREFIX_NAME_IN(area));
-                                       abr_inv++;
-                               }
+                       if (PREFIX_NAME_IN(area)
+                           && strcmp(PREFIX_NAME_IN(area),
+                                     prefix_list_name(plist))
+                                      == 0) {
+                               PREFIX_LIST_IN(area) = prefix_list_lookup(
+                                       AFI_IP, PREFIX_NAME_IN(area));
+                               abr_inv++;
+                       }
 
                        /* Update filter-list out. */
-                       if (PREFIX_NAME_OUT(area))
-                               if (strcmp(PREFIX_NAME_OUT(area),
-                                          prefix_list_name(plist))
-                                   == 0) {
-                                       PREFIX_LIST_IN(area) =
-                                               prefix_list_lookup(
-                                                       AFI_IP,
-                                                       PREFIX_NAME_OUT(area));
-                                       abr_inv++;
-                               }
+                       if (PREFIX_NAME_OUT(area)
+                           && strcmp(PREFIX_NAME_OUT(area),
+                                     prefix_list_name(plist))
+                                      == 0) {
+                               PREFIX_LIST_IN(area) = prefix_list_lookup(
+                                       AFI_IP, PREFIX_NAME_OUT(area));
+                               abr_inv++;
+                       }
                }
 
                /* Schedule ABR task. */
@@ -1857,14 +1825,17 @@ void ospf_distance_reset(struct ospf *ospf)
        struct route_node *rn;
        struct ospf_distance *odistance;
 
-       for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn))
-               if ((odistance = rn->info) != NULL) {
-                       if (odistance->access_list)
-                               free(odistance->access_list);
-                       ospf_distance_free(odistance);
-                       rn->info = NULL;
-                       route_unlock_node(rn);
-               }
+       for (rn = route_top(ospf->distance_table); rn; rn = route_next(rn)) {
+               odistance = rn->info;
+               if (!odistance)
+                       continue;
+
+               if (odistance->access_list)
+                       free(odistance->access_list);
+               ospf_distance_free(odistance);
+               rn->info = NULL;
+               route_unlock_node(rn);
+       }
 }
 
 uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p,
@@ -1874,18 +1845,16 @@ uint8_t ospf_distance_apply(struct ospf *ospf, struct prefix_ipv4 *p,
        if (ospf == NULL)
                return 0;
 
-       if (ospf->distance_intra)
-               if (or->path_type == OSPF_PATH_INTRA_AREA)
-                       return ospf->distance_intra;
+       if (ospf->distance_intra && or->path_type == OSPF_PATH_INTRA_AREA)
+               return ospf->distance_intra;
 
-       if (ospf->distance_inter)
-               if (or->path_type == OSPF_PATH_INTER_AREA)
-                       return ospf->distance_inter;
+       if (ospf->distance_inter && or->path_type == OSPF_PATH_INTER_AREA)
+               return ospf->distance_inter;
 
-       if (ospf->distance_external)
-               if (or->path_type == OSPF_PATH_TYPE1_EXTERNAL ||
-                   or->path_type == OSPF_PATH_TYPE2_EXTERNAL)
-                       return ospf->distance_external;
+       if (ospf->distance_external
+           && (or->path_type == OSPF_PATH_TYPE1_EXTERNAL ||
+               or->path_type == OSPF_PATH_TYPE2_EXTERNAL))
+               return ospf->distance_external;
 
        if (ospf->distance_all)
                return ospf->distance_all;
index bdc8af04029b81e45ff3ee94692dabad2470c045..3f4edfa29c2ca4d8292bd5d30069b27a31a2d629 100644 (file)
@@ -78,10 +78,12 @@ extern struct ospf_redist *ospf_redist_add(struct ospf *, uint8_t,
                                           unsigned short);
 extern void ospf_redist_del(struct ospf *, uint8_t, unsigned short);
 
-extern int ospf_redistribute_set(struct ospf *, int, unsigned short, int, int);
+extern int ospf_redistribute_update(struct ospf *, struct ospf_redist *, int,
+                                   unsigned short, int, int);
+extern int ospf_redistribute_set(struct ospf *, struct ospf_redist *, int,
+                                unsigned short, int, int);
 extern int ospf_redistribute_unset(struct ospf *, int, unsigned short);
 extern int ospf_redistribute_default_set(struct ospf *, int, int, int);
-extern int ospf_redistribute_default_unset(struct ospf *);
 extern int ospf_distribute_list_out_set(struct ospf *, int, const char *);
 extern int ospf_distribute_list_out_unset(struct ospf *, int, const char *);
 extern void ospf_routemap_set(struct ospf_redist *, const char *);
index 259209a736876c7c92dba9685b7a926d987cdda1..2b9457d8b99619f2408c49f7a26973161ff160ce 100644 (file)
@@ -697,6 +697,7 @@ static void ospf_finish_final(struct ospf *ospf)
        struct ospf_area *area;
        struct ospf_vl_data *vl_data;
        struct listnode *node, *nnode;
+       struct ospf_redist *red;
        int i;
 
        QOBJ_UNREG(ospf);
@@ -710,7 +711,6 @@ static void ospf_finish_final(struct ospf *ospf)
        /* Unregister redistribution */
        for (i = 0; i < ZEBRA_ROUTE_MAX; i++) {
                struct list *red_list;
-               struct ospf_redist *red;
 
                red_list = ospf->redist[i];
                if (!red_list)
@@ -721,7 +721,12 @@ static void ospf_finish_final(struct ospf *ospf)
                        ospf_redist_del(ospf, i, red->instance);
                }
        }
-       ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE, 0, 0);
+       red = ospf_redist_lookup(ospf, DEFAULT_ROUTE, 0);
+       if (red) {
+               ospf_routemap_unset(red);
+               ospf_redist_del(ospf, DEFAULT_ROUTE, 0);
+               ospf_redistribute_default_set(ospf, DEFAULT_ORIGINATE_NONE, 0, 0);
+       }
 
        for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area))
                ospf_remove_vls_through_area(ospf, area);
@@ -791,6 +796,7 @@ static void ospf_finish_final(struct ospf *ospf)
        OSPF_TIMER_OFF(ospf->t_maxage_walker);
        OSPF_TIMER_OFF(ospf->t_abr_task);
        OSPF_TIMER_OFF(ospf->t_asbr_check);
+       OSPF_TIMER_OFF(ospf->t_asbr_nssa_redist_update);
        OSPF_TIMER_OFF(ospf->t_distribute_update);
        OSPF_TIMER_OFF(ospf->t_lsa_refresher);
        OSPF_TIMER_OFF(ospf->t_opaque_lsa_self);
@@ -1076,6 +1082,7 @@ struct ospf_interface *add_ospf_interface(struct connected *co,
        /* If network type is specified previously,
           skip network type setting. */
        oi->type = IF_DEF_PARAMS(co->ifp)->type;
+       oi->ptp_dmvpn = IF_DEF_PARAMS(co->ifp)->ptp_dmvpn;
 
        /* Add pseudo neighbor. */
        ospf_nbr_self_reset(oi, oi->ospf->router_id);
@@ -2156,7 +2163,7 @@ static int ospf_vrf_delete(struct vrf *vrf)
        return 0;
 }
 
-static void ospf_set_redist_vrf_bitmaps(struct ospf *ospf)
+static void ospf_set_redist_vrf_bitmaps(struct ospf *ospf, bool set)
 {
        int type;
        struct list *red_list;
@@ -2169,7 +2176,12 @@ static void ospf_set_redist_vrf_bitmaps(struct ospf *ospf)
                        zlog_debug(
                                "%s: setting redist vrf %d bitmap for type %d",
                                __func__, ospf->vrf_id, type);
-               vrf_bitmap_set(zclient->redist[AFI_IP][type], ospf->vrf_id);
+               if (set)
+                       vrf_bitmap_set(zclient->redist[AFI_IP][type],
+                                      ospf->vrf_id);
+               else
+                       vrf_bitmap_unset(zclient->redist[AFI_IP][type],
+                                        ospf->vrf_id);
        }
 }
 
@@ -2199,18 +2211,12 @@ static int ospf_vrf_enable(struct vrf *vrf)
                                __func__, vrf->name, ospf->vrf_id, old_vrf_id);
 
                if (old_vrf_id != ospf->vrf_id) {
-                       frr_with_privs(&ospfd_privs) {
-                               /* stop zebra redist to us for old vrf */
-                               zclient_send_dereg_requests(zclient,
-                                                           old_vrf_id);
-
-                               ospf_set_redist_vrf_bitmaps(ospf);
+                       ospf_set_redist_vrf_bitmaps(ospf, true);
 
-                               /* start zebra redist to us for new vrf */
-                               ospf_zebra_vrf_register(ospf);
+                       /* start zebra redist to us for new vrf */
+                       ospf_zebra_vrf_register(ospf);
 
-                               ret = ospf_sock_init(ospf);
-                       }
+                       ret = ospf_sock_init(ospf);
                        if (ret < 0 || ospf->fd <= 0)
                                return 0;
                        thread_add_read(master, ospf_read, ospf, ospf->fd,
@@ -2240,6 +2246,10 @@ static int ospf_vrf_disable(struct vrf *vrf)
        if (ospf) {
                old_vrf_id = ospf->vrf_id;
 
+               ospf_zebra_vrf_deregister(ospf);
+
+               ospf_set_redist_vrf_bitmaps(ospf, false);
+
                /* We have instance configured, unlink
                 * from VRF and make it "down".
                 */
index 2093eb2e4202afaf05db071dc696cdd233a28d16..318400e968cf7de24a59398f0bc916c6144abaf6 100644 (file)
@@ -242,6 +242,8 @@ struct ospf {
        /* Threads. */
        struct thread *t_abr_task;        /* ABR task timer. */
        struct thread *t_asbr_check;    /* ASBR check timer. */
+       struct thread *t_asbr_nssa_redist_update; /* ASBR NSSA redistribution
+                                                    update timer. */
        struct thread *t_distribute_update; /* Distirbute list update timer. */
        struct thread *t_spf_calc;        /* SPF calculation timer. */
        struct thread *t_ase_calc;        /* ASE calculation timer. */
index f592a9eec8d659a04c6db0a3bef9dc1a095cf1c5..574e0e3bdf8bb0ad489a3550515cf3dd67297b71 100644 (file)
@@ -115,7 +115,7 @@ ospfd_ospfd_LDADD = ospfd/libfrrospf.a lib/libfrr.la $(LIBCAP) $(LIBM)
 ospfd_ospfd_SOURCES = ospfd/ospf_main.c
 
 ospfd_ospfd_snmp_la_SOURCES = ospfd/ospf_snmp.c
-ospfd_ospfd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+ospfd_ospfd_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 ospfd_ospfd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 ospfd_ospfd_snmp_la_LIBADD = lib/libfrrsnmp.la
 
index cf14aa8c61689e4a3d3e5d2189805f96677bf34f..ecb667f985898e35922e96673c1ae655d640a4d8 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include <float.h>
 #include <math.h>
 #include <zebra.h>
index df0550715a2751a64244109eef046bb2b2144c88..eec57073963f147ab4fdce99aa987f373d5cedf4 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include <string.h>
 #include <stdbool.h>
 #include <time.h>
index d6cd48ecdb207322ee1f388c5a6d489a30aa8060..ad24c2eb02b3aacdc33c8918866de6cd6d17ea9f 100644 (file)
@@ -24,7 +24,7 @@
 #include "command.h"
 #include "libfrr.h"
 #include "printfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "northbound.h"
 #include "frr_pthread.h"
 #include "jhash.h"
@@ -264,7 +264,11 @@ int pathd_candidate_removed_handler(struct srte_candidate *candidate)
 
 /* ------------ Module Functions ------------ */
 
-int pcep_module_late_init(struct thread_master *tm)
+/* this creates threads, therefore must run after fork().  but it must also
+ * run before config load, so the CLI commands don't try to touch things that
+ * aren't set up yet...
+ */
+static int pcep_module_config_pre(struct thread_master *tm)
 {
        assert(pcep_g->fpt == NULL);
        assert(pcep_g->master == NULL);
@@ -280,10 +284,16 @@ int pcep_module_late_init(struct thread_master *tm)
        pcep_g->master = tm;
        pcep_g->fpt = fpt;
 
+       return 0;
+}
+
+static int pcep_module_late_init(struct thread_master *tm)
+{
        hook_register(pathd_candidate_created, pathd_candidate_created_handler);
        hook_register(pathd_candidate_updated, pathd_candidate_updated_handler);
        hook_register(pathd_candidate_removed, pathd_candidate_removed_handler);
 
+       hook_register(frr_config_pre, pcep_module_config_pre);
        hook_register(frr_fini, pcep_module_finish);
 
        pcep_cli_init();
index 14404b1d088233d35940a83a9f01d8821321a4d4..2e4e331ad970f072c001c6d0d654e04c6d2c15a2 100644 (file)
@@ -25,7 +25,7 @@
 #include "command.h"
 #include "libfrr.h"
 #include "printfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "northbound.h"
 #include "frr_pthread.h"
 #include "jhash.h"
index 107475bec9e0c5daf0bb4e9499ef19ae8fedeca1..aacbca4ae9fa7390e33d6f76b4090efd980f2816 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include <northbound.h>
 #include <yang.h>
 #include <printfrr.h>
index db7d2b55a585599627255173d3ce047e4855b3cf..528dcc3539923d7eb66de22a06091401fb314f41 100644 (file)
@@ -22,7 +22,7 @@
 #include "command.h"
 #include "libfrr.h"
 #include "printfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "northbound.h"
 #include "frr_pthread.h"
 #include "jhash.h"
index d222371bbb3925d8ba605cbebc92e27a0649762e..370484dc1b3fa97cd8621f9b21f2c0cabc137c86 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include <string.h>
 #include <stdbool.h>
 #include <time.h>
index a2c1e7cd4cef0363f781780dc6c6136d8a66c852..9af21488190539e21b70dabe3d56d569dc1b23c8 100644 (file)
@@ -33,7 +33,7 @@
 #include "command.h"
 #include "libfrr.h"
 #include "printfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "northbound.h"
 #include "frr_pthread.h"
 #include "jhash.h"
index 276bc9289c4d8be5d1356b410551826292c8034d..8c9357460f5f0daab2f83ddf1414969cb4f6a1e4 100644 (file)
@@ -16,6 +16,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "thread.h"
 #include "log.h"
 #include "lib_errors.h"
index 38df326489ee542dcdf9ec930f523ce7de99e0b6..0666e8d3c8c52ee9aa7427d124bda078bb9fd728 100644 (file)
@@ -5,13 +5,13 @@
 if PATHD
 noinst_LIBRARIES += pathd/libpath.a
 sbin_PROGRAMS += pathd/pathd
-vtysh_scan += $(top_srcdir)/pathd/path_cli.c
+vtysh_scan += pathd/path_cli.c
 vtysh_daemons += pathd
 # TODO add man page
 #man8 += $(MANBUILD)/pathd.8
 
 if PATHD_PCEP
-vtysh_scan += $(top_srcdir)/pathd/path_pcep_cli.c
+vtysh_scan += pathd/path_pcep_cli.c
 module_LTLIBRARIES += pathd/pathd_pcep.la
 endif
 
@@ -75,5 +75,5 @@ pathd_pathd_pcep_la_LIBADD =
 endif
 
 
-pathd_pathd_pcep_la_CFLAGS = $(WERROR)
+#pathd_pathd_pcep_la_CFLAGS = $(AM_CFLAGS)
 pathd_pathd_pcep_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
index 4b73e13c27f463b8da96f03ebdab2575e2a95c5d..eb41bf604365975965c218b1ee2344810599549b 100644 (file)
@@ -50,8 +50,8 @@ struct pbr_interface *pbr_if_new(struct interface *ifp)
 {
        struct pbr_interface *pbr_ifp;
 
-       zassert(ifp);
-       zassert(!ifp->info);
+       assert(ifp);
+       assert(!ifp->info);
 
        pbr_ifp = XCALLOC(MTYPE_PBR_INTERFACE, sizeof(*pbr_ifp));
 
index ec2a237f3010c5ea1ff083ba4abec128c6ea33fa..9bbfc5372b41988ac5f04f1dbabcee61825af2e9 100644 (file)
  * This is the implementation of a High Level PCEP message API.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include <arpa/inet.h>
 #include <stdarg.h>
index 7c8e1b3a1feffcefc338ca08fc22f520aa9385c8..e90ca1cfd8289e382d84be1e1f8aa82f197ea7d8 100644 (file)
  * Encoding and decoding for PCEP messages.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
index a4fd8151cdc2e59f48c05329586454700bc33996..c72dfd7061157a797920fdbc235aaa62cc525934 100644 (file)
  * Author : Brady Johnson <brady@voltanet.io>
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 
 #include "pcep_msg_object_error_types.h"
index 6c943ddc2a5ef02a0ca151c2c607254a58ade8f2..e253fcc540770b5c57e658b114508c7f8bc52098 100644 (file)
  * This is the implementation of a High Level PCEP message object API.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <string.h>
 #include <arpa/inet.h>
 #include <stdarg.h>
index c4089ba5ecfc20d36f84a017ad0e4e3ec6714952..9ab96f7bcec04b3ee9271709ef6865067bd2ce3c 100644 (file)
  * Encoding and decoding for PCEP Objects.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 
index 9c84e71ee155bf068c14620e737a722c13cfc4c9..6298ed4b8db791ab247b4696648003f58b3aeab2 100644 (file)
  * This is the implementation of a High Level PCEP message object TLV API.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdbool.h>
 #include <stdint.h>
 #include <string.h>
index e190d2a8501e78d2db574d59b89f429c46adc41c..8f32f2c537c2e8af234c9b6e7a50e7294c78eb3a 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <errno.h>
 #include <stdio.h>
 #include <string.h>
index 52655914c6c1da7855e2415e0fda522b10e1f540..2ec2fd72a8533295092029aa2c44759664cf2c1c 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <errno.h>
 #include <limits.h>
 #include <pthread.h>
index a6bd41b4f1a162642557bf265d502fadbbb81b6c..fceb15af76f1e95b3988095538ce8d7186253cb6 100644 (file)
  * PCEP session logic counters configuration.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdio.h>
 #include <time.h>
 
index 269aa1e07e8dfe078f02ef84d544a955a31b0c42..4b855c06cd334b839a1aa52abf42e18298904c11 100644 (file)
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <pthread.h>
 #include <stdbool.h>
 #include <stdio.h>
index 3beceefad080c82122b8cd0585d863c54f158246..3e9c701a629f2f3756d26f29481636853138d89c 100644 (file)
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <pthread.h>
 #include <stdbool.h>
 #include <stdio.h>
index d58409c4f3a23294bcd317f097bab292b2cb72b7..d9a6b9ae4822305f6d8e6194a8c27160f68935cd 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <errno.h>
 #include <stdbool.h>
 #include <stddef.h>
index 069d0cf998d7d5a51bad6e63ef7f3728997a1ecf..7a9511e315523af90c3881abde5e273338c02480 100644 (file)
  * created.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <netinet/in.h>
 #include <stdbool.h>
 #include <stdlib.h>
index d0a2349d058785ee8269fa1f57e475b1f9b63f8c..4c06d2b3f772fe7b8607eec6d23309048df83569 100644 (file)
  *  Implementation of public API timer functions.
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <limits.h>
 #include <pthread.h>
 #include <stddef.h>
index 932a53eb2a3968dede94a8087024c189318407d4..8984496717a7b605fa9fa1fbf1e71ed4b464f8d1 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <errno.h>
 #include <stddef.h>
 #include <stdbool.h>
index acdcee05984218936e171cab912ce9f797047f40..696e46632a467546b6d4b02d5ff22457d99c39b8 100644 (file)
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stddef.h>
 #include <string.h>
 
index 65e1abbc034f8f21c75097d616e95f8a5b17b4b7..0286c23078a58eef02f1774b4f19edb080be01cd 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdarg.h>
 #include <stdio.h>
 #include "pcep_utils_logging.h"
index 7362e3433bdffc699a8f21bb3f1721783b0a5ebc..c564705f661924a572e63433a63cb0fd241984aa 100644 (file)
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 
index f5c7f702408801d75ee809a370fa797d452445fc..81eb614494738c042362dc8575a4e3a675127554 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdio.h>
 #include <string.h>
 
index e8c3f2be0e585a8ad7ba3cf4f5dcad7ced36a5a4..627533d01ba89a6d2f0f70ba1cdcdc7d91fce4ca 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdbool.h>
 #include <stdio.h>
 #include <string.h>
index eee2ec28c7050f21143a83fe480eea0044d2e439..2633f678fdb75f1fd0386727b79917d97691bc31 100644 (file)
@@ -1,7 +1,7 @@
 if PATHD_PCEP
 
 noinst_LTLIBRARIES = pceplib/libpcep_pcc.la pceplib/libsocket_comm_mock.la
-pceplib_libpcep_pcc_la_CFLAGS = -fPIC
+pceplib_libpcep_pcc_la_CFLAGS = $(AM_CFLAGS) -fPIC
 pceplib_libpcep_pcc_la_SOURCES = pceplib/pcep_msg_messages.c \
                pceplib/pcep_msg_objects.c \
                pceplib/pcep_msg_tlvs.c \
index b8984a42bc98d523f2a121f092caf9180bfedb17..61fa94047ba0c2b8d499c02ce3f00e80c0c94911 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 
 #include <CUnit/CUnit.h>
index bd85a16530a6a07c5fc2623c8f52301226016af2..f24a797f776acbec177d62233fad145bfede5b4f 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/Basic.h>
 #include <CUnit/CUnit.h>
 #include <CUnit/TestDB.h>
index 7275eaf0982eb0d345947f7b7a907c79d72c089e..b1463751d6d0b1e864b0d6cd7647a45d97ba061c 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdio.h>
 
 #include <CUnit/CUnit.h>
index a4c069945c1685a801b5e943460491728675aa84..e0814de543f8d6cb7362371dece19d076951a5ea 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 
 #include <CUnit/CUnit.h>
index ff5fc62390a053064787d0785b9a04a08d219978..787df2fd7a05dc4cd37aab7ba98a2befeedc7f93 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
index c227dc1a3dc6e05ee7950246b1c59c068600452d..4adbb6374ea04137de88ca2a9f94e6afff166112 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <netdb.h> // gethostbyname
 #include <pthread.h>
 #include <stdlib.h>
index 04895d63409989fb5b90923721c449849f2ca711..5d9e92c1d38d7405bc78647bf85cf9250c28f483 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/Basic.h>
 #include <CUnit/CUnit.h>
 #include <CUnit/TestDB.h>
index 3a40f59bb91fdc2d4690ba290df7f633cd84aa7c..d68b2005498b0f68143b90f8e08dcdb043ca507f 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <pthread.h>
 #include <stdlib.h>
 #include <string.h>
index f75c16e3977fbda8768855f5feccd42653e73297..24741fa345e7ce6507db550ac01323cb2038a1d0 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 
index 66db4fbaea78615311b28c599764a461cb92a26f..503e77c20eb57b7a731b9996ebcb4e279d0317cb 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
index 67bf6e22efe589e6ff60863eb2384055f09f272a..9a15390c1b0914c42a7163a7f9d7ff2c47281528 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/Basic.h>
 #include <CUnit/CUnit.h>
 #include <CUnit/TestDB.h>
index 94f0983ca735b6ef3191bb62df1075e8eef71c74..748cf433e60882c863ef673ceb56fdaad0a3d44d 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <pthread.h>
 #include <stdlib.h>
 
index 35afbcbb131e2bd6b98e9438b75959f2f57cdb32..0ab38bf96e3bc918327450c2c5ea9c96d21bc4c4 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <netinet/in.h>
 
 #include <CUnit/CUnit.h>
index 293678f1a7aa0a6eee876d26164fd05ce7960d0d..6a5839d3d0970a1295ddf9f8cd62670510c43b81 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/Basic.h>
 #include <CUnit/CUnit.h>
 #include <CUnit/TestDB.h>
index ae63601df2d902486ade2b1330349f650f71f3da..79ed84bfeb9ee1371567d95da00e8dfba72d6a4a 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 
 #include <CUnit/CUnit.h>
index 9d9e0f6c1bd6644273700c4669611c9665183f5b..e5be90a8ed3c5cb2ecfb8500e81635b61bee9f0e 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdbool.h>
 #include <CUnit/CUnit.h>
 
index adfea17e29615a70ebea47c5eebe124e7d5da5a1..f3aa8307a7bec30bbba6538d2a8cba5c6fc5bbc3 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/Basic.h>
 #include <CUnit/CUnit.h>
 #include <CUnit/TestDB.h>
index 6f53e4d400a38c33c012fd158e2283e0af133541..bcdce3618840294c9ab624fa721631ebf0f45e24 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 
 #include <CUnit/CUnit.h>
index d2600e66c4a73526588133097f10bf11f77f9043..4eb85816b9f83c66d5b40d101ac41ce55a1fbf1d 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/CUnit.h>
 
 #include "pcep_utils_double_linked_list.h"
index b0b528f08415433a5484fa71032a2ba848f10474..0958626a0cf09b01f8951125880cca2fd405f459 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <stdlib.h>
 #include <stdint.h>
 
index fe9ee58825b2d5c41a96c547b2c2ddec00e7b204..d20f5e68afde269ee44805cb544989daa3257808 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/CUnit.h>
 
 #include "pcep_utils_ordered_list.h"
index 1731457789e4b51d97c45b9541de3aa040aa90fc..061dfbf37b9f5d024cecfcab233d4f58699524db 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/CUnit.h>
 
 #include "pcep_utils_queue.h"
index 452b9fa09cd99fa0c43b2d1f53d11d276eb8d9cd..ad9f76933a7c243a0ef3a7b4b1bf4aa1fcdb5430 100644 (file)
  */
 
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <CUnit/Basic.h>
 #include <CUnit/CUnit.h>
 #include <CUnit/TestDB.h>
index 0ae61d1bcea9841fcf80acfce4421f0772867ce2..88af592679bc0ea0c7dd53c934214fcdb716c54d 100644 (file)
@@ -36,7 +36,7 @@ noinst_HEADERS += pceplib/test/pcep_msg_messages_test.h \
                pceplib/test/pcep_utils_ordered_list_test.h \
                pceplib/test/pcep_utils_queue_test.h
 
-pceplib_test_pcep_msg_tests_CFLAGS =  -I$(top_srcdir)/pceplib
+pceplib_test_pcep_msg_tests_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/pceplib
 pceplib_test_pcep_msg_tests_LDADD = $(top_builddir)/pceplib/libpcep_pcc.la  lib/libfrr.la -lcunit -lpthread
 pceplib_test_pcep_msg_tests_SOURCES = pceplib/test/pcep_msg_messages_test.c \
                pceplib/test/pcep_msg_messages_tests.c \
@@ -47,7 +47,7 @@ pceplib_test_pcep_msg_tests_SOURCES = pceplib/test/pcep_msg_messages_test.c \
 
 # The pcc_api_tests and pcep_session_logic_tests use the
 # socket_comm_mock, so the LDADD variable needs to be modified
-pceplib_test_pcep_pcc_api_tests_CFLAGS =  -I$(top_srcdir)/pceplib
+pceplib_test_pcep_pcc_api_tests_CFLAGS = $(AM_CFLAGS) -I$(top_srcdir)/pceplib
 pceplib_test_pcep_pcc_api_tests_LDADD = $(top_builddir)/pceplib/libsocket_comm_mock.la $(top_builddir)/pceplib/libpcep_pcc.la  lib/libfrr.la -lcunit -lpthread
 pceplib_test_pcep_pcc_api_tests_SOURCES = pceplib/test/pcep_pcc_api_test.c pceplib/test/pcep_pcc_api_tests.c
 
index 957f904714e52b26607d861c7f5d533cbfd18d02..0988938701fe5f337c6229b0975437e6a0a1107d 100644 (file)
@@ -304,7 +304,7 @@ int pim_assert_recv(struct interface *ifp, struct pim_neighbor *neigh,
        msg_metric.ip_address = src_addr;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
        ++pim_ifp->pim_ifstat_assert_recv;
 
        return dispatch_assert(ifp, msg_source_addr.u.prefix4, sg.grp,
index 5e1b9a69e14f337e45e1cb9b15f443b4f937eab4..bc518391a582789ef37325a86aea0b6187ac73f6 100644 (file)
 void pim_bfd_write_config(struct vty *vty, struct interface *ifp)
 {
        struct pim_interface *pim_ifp = ifp->info;
-       struct bfd_info *bfd_info = NULL;
 
-       if (!pim_ifp)
-               return;
-
-       bfd_info = pim_ifp->bfd_info;
-       if (!bfd_info)
+       if (!pim_ifp || !pim_ifp->bfd_config.enabled)
                return;
 
 #if HAVE_BFDD == 0
-       if (CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG))
-               vty_out(vty, " ip pim bfd %d %d %d\n", bfd_info->detect_mult,
-                       bfd_info->required_min_rx, bfd_info->desired_min_tx);
+       if (pim_ifp->bfd_config.detection_multiplier != BFD_DEF_DETECT_MULT
+           || pim_ifp->bfd_config.min_rx != BFD_DEF_MIN_RX
+           || pim_ifp->bfd_config.min_tx != BFD_DEF_MIN_TX)
+               vty_out(vty, " ip pim bfd %d %d %d\n",
+                       pim_ifp->bfd_config.detection_multiplier,
+                       pim_ifp->bfd_config.min_rx, pim_ifp->bfd_config.min_tx);
        else
 #endif /* ! HAVE_BFDD */
                vty_out(vty, " ip pim bfd\n");
+
+       if (pim_ifp->bfd_config.profile)
+               vty_out(vty, " ip pim bfd profile %s\n",
+                       pim_ifp->bfd_config.profile);
 }
 
-/*
- * pim_bfd_show_info - Show BFD info structure
- */
-void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj,
-                      bool use_json, int param_only)
+static void pim_neighbor_bfd_cb(struct bfd_session_params *bsp,
+                               const struct bfd_session_status *bss, void *arg)
 {
-       if (param_only)
-               bfd_show_param(vty, (struct bfd_info *)bfd_info, 1, 0, use_json,
-                              json_obj);
-       else
-               bfd_show_info(vty, (struct bfd_info *)bfd_info, 0, 1, use_json,
-                             json_obj);
+       struct pim_neighbor *nbr = arg;
+
+       if (PIM_DEBUG_PIM_TRACE) {
+               zlog_debug("%s: status %s old_status %s", __func__,
+                          bfd_get_status_str(bss->state),
+                          bfd_get_status_str(bss->previous_state));
+       }
+
+       if (bss->state == BFD_STATUS_DOWN
+           && bss->previous_state == BFD_STATUS_UP)
+               pim_neighbor_delete(nbr->interface, nbr, "BFD Session Expired");
 }
 
 /*
@@ -80,60 +84,20 @@ void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj,
 void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp,
                             struct pim_neighbor *neigh)
 {
-       struct bfd_info *nbr_bfd_info = NULL;
-
        /* Check if Pim Interface BFD is enabled */
-       if (!pim_ifp || !pim_ifp->bfd_info)
-               return;
-
-       if (!neigh->bfd_info)
-               neigh->bfd_info = bfd_info_create();
-
-       if (!neigh->bfd_info)
-               return;
-
-       nbr_bfd_info = neigh->bfd_info;
-       nbr_bfd_info->detect_mult = pim_ifp->bfd_info->detect_mult;
-       nbr_bfd_info->desired_min_tx = pim_ifp->bfd_info->desired_min_tx;
-       nbr_bfd_info->required_min_rx = pim_ifp->bfd_info->required_min_rx;
-}
-
-/*
- * pim_bfd_info_free - Free BFD info structure
- */
-void pim_bfd_info_free(struct bfd_info **bfd_info)
-{
-       bfd_info_free(bfd_info);
-}
-
-static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command)
-{
-       struct pim_interface *pim_ifp = NULL;
-       struct bfd_info *bfd_info = NULL;
-       struct zclient *zclient = NULL;
-       int cbit;
-
-       zclient = pim_zebra_zclient_get();
-
-       if (!nbr)
+       if (!pim_ifp || !pim_ifp->bfd_config.enabled)
                return;
-       pim_ifp = nbr->interface->info;
-       bfd_info = pim_ifp->bfd_info;
-       if (!bfd_info)
-               return;
-       if (PIM_DEBUG_PIM_TRACE) {
-               char str[INET_ADDRSTRLEN];
-               pim_inet4_dump("<bfd_nbr?>", nbr->source_addr, str,
-                              sizeof(str));
-               zlog_debug("%s Nbr %s %s with BFD", __func__, str,
-                          bfd_get_command_dbg_str(command));
-       }
 
-       cbit = CHECK_FLAG(bfd_info->flags, BFD_FLAG_BFD_CBIT_ON);
+       if (neigh->bfd_session == NULL)
+               neigh->bfd_session = bfd_sess_new(pim_neighbor_bfd_cb, neigh);
 
-       bfd_peer_sendmsg(zclient, bfd_info, AF_INET, &nbr->source_addr, NULL,
-                        nbr->interface->name, 0, 0, cbit,
-                        command, 0, VRF_DEFAULT);
+       bfd_sess_set_timers(
+               neigh->bfd_session, pim_ifp->bfd_config.detection_multiplier,
+               pim_ifp->bfd_config.min_rx, pim_ifp->bfd_config.min_tx);
+       bfd_sess_set_ipv4_addrs(neigh->bfd_session, NULL, &neigh->source_addr);
+       bfd_sess_set_interface(neigh->bfd_session, neigh->interface->name);
+       bfd_sess_set_profile(neigh->bfd_session, pim_ifp->bfd_config.profile);
+       bfd_sess_install(neigh->bfd_session);
 }
 
 /*
@@ -142,7 +106,7 @@ static void pim_bfd_reg_dereg_nbr(struct pim_neighbor *nbr, int command)
  *                              zebra for starting/stopping the monitoring of
  *                              the neighbor rechahability.
  */
-int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command)
+void pim_bfd_reg_dereg_all_nbr(struct interface *ifp)
 {
        struct pim_interface *pim_ifp = NULL;
        struct listnode *node = NULL;
@@ -150,197 +114,17 @@ int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command)
 
        pim_ifp = ifp->info;
        if (!pim_ifp)
-               return -1;
-       if (!pim_ifp->bfd_info)
-               return -1;
+               return;
 
        for (ALL_LIST_ELEMENTS_RO(pim_ifp->pim_neighbor_list, node, neigh)) {
-               if (command != ZEBRA_BFD_DEST_DEREGISTER)
+               if (pim_ifp->bfd_config.enabled)
                        pim_bfd_info_nbr_create(pim_ifp, neigh);
                else
-                       pim_bfd_info_free((struct bfd_info **)&neigh->bfd_info);
-
-               pim_bfd_reg_dereg_nbr(neigh, command);
-       }
-
-       return 0;
-}
-
-/*
- * pim_bfd_trigger_event - Neighbor is registered/deregistered with BFD when
- *                          neighbor state is changed to/from 2way.
- */
-void pim_bfd_trigger_event(struct pim_interface *pim_ifp,
-                          struct pim_neighbor *nbr, uint8_t nbr_up)
-{
-       if (nbr_up) {
-               pim_bfd_info_nbr_create(pim_ifp, nbr);
-               pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_REGISTER);
-       } else {
-               pim_bfd_info_free(&nbr->bfd_info);
-               pim_bfd_reg_dereg_nbr(nbr, ZEBRA_BFD_DEST_DEREGISTER);
-       }
-}
-
-/*
- * pim_bfd_if_param_set - Set the configured BFD paramter values for
- *                         interface.
- */
-void pim_bfd_if_param_set(struct interface *ifp, uint32_t min_rx,
-                         uint32_t min_tx, uint8_t detect_mult, int defaults)
-{
-       struct pim_interface *pim_ifp = ifp->info;
-       int command = 0;
-
-       if (!pim_ifp)
-               return;
-       bfd_set_param(&(pim_ifp->bfd_info), min_rx, min_tx, detect_mult, NULL,
-                     defaults, &command);
-
-       if (pim_ifp->bfd_info) {
-               if (PIM_DEBUG_PIM_TRACE)
-                       zlog_debug("%s: interface %s has bfd_info", __func__,
-                                  ifp->name);
-       }
-       if (command)
-               pim_bfd_reg_dereg_all_nbr(ifp, command);
-}
-
-
-/*
- * pim_bfd_interface_dest_update - Find the neighbor for which the BFD status
- *                                  has changed and bring down the neighbor
- *                                  connectivity if the BFD status changed to
- *                                  down.
- */
-static int pim_bfd_interface_dest_update(ZAPI_CALLBACK_ARGS)
-{
-       struct interface *ifp = NULL;
-       struct pim_interface *pim_ifp = NULL;
-       struct prefix p, src_p;
-       int status;
-       char msg[100];
-       int old_status;
-       struct bfd_info *bfd_info = NULL;
-       struct timeval tv;
-       struct listnode *neigh_node = NULL;
-       struct listnode *neigh_nextnode = NULL;
-       struct pim_neighbor *neigh = NULL;
-
-       ifp = bfd_get_peer_info(zclient->ibuf, &p, &src_p, &status, NULL,
-                               vrf_id);
-
-       if ((ifp == NULL) || (p.family != AF_INET))
-               return 0;
-
-       pim_ifp = ifp->info;
-       if (!pim_ifp)
-               return 0;
-
-       if (!pim_ifp->bfd_info) {
-               if (PIM_DEBUG_PIM_TRACE)
-                       zlog_debug("%s: pim interface %s BFD is disabled ",
-                                  __func__, ifp->name);
-               return 0;
+                       bfd_sess_free(&neigh->bfd_session);
        }
-
-       if (PIM_DEBUG_PIM_TRACE)
-               zlog_debug("%s: interface %s bfd destination %pFX %s", __func__,
-                          ifp->name, &p, bfd_get_status_str(status));
-
-       for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node,
-                              neigh_nextnode, neigh)) {
-               /* Check neigh address matches with BFD address */
-               if (neigh->source_addr.s_addr != p.u.prefix4.s_addr)
-                       continue;
-
-               bfd_info = (struct bfd_info *)neigh->bfd_info;
-               if (bfd_info->status == status) {
-                       if (PIM_DEBUG_PIM_TRACE) {
-                               char str[INET_ADDRSTRLEN];
-                               pim_inet4_dump("<nht_nbr?>", neigh->source_addr,
-                                              str, sizeof(str));
-                               zlog_debug("%s: bfd status is same for nbr %s",
-                                          __func__, str);
-                       }
-                       continue;
-               }
-               old_status = bfd_info->status;
-               BFD_SET_CLIENT_STATUS(bfd_info->status, status);
-               monotime(&tv);
-               bfd_info->last_update = tv.tv_sec;
-
-               if (PIM_DEBUG_PIM_TRACE) {
-                       zlog_debug("%s: status %s old_status %s", __func__,
-                                  bfd_get_status_str(status),
-                                  bfd_get_status_str(old_status));
-               }
-               if ((status == BFD_STATUS_DOWN)
-                   && (old_status == BFD_STATUS_UP)) {
-                       snprintf(msg, sizeof(msg), "BFD Session Expired");
-                       pim_neighbor_delete(ifp, neigh, msg);
-               }
-       }
-       return 0;
-}
-
-/*
- * pim_bfd_nbr_replay - Replay all the neighbors that have BFD enabled
- *                       to zebra
- */
-static int pim_bfd_nbr_replay(ZAPI_CALLBACK_ARGS)
-{
-       struct interface *ifp = NULL;
-       struct pim_interface *pim_ifp = NULL;
-       struct pim_neighbor *neigh = NULL;
-       struct listnode *neigh_node;
-       struct listnode *neigh_nextnode;
-       struct vrf *vrf = NULL;
-
-       /* Send the client registration */
-       bfd_client_sendmsg(zclient, ZEBRA_BFD_CLIENT_REGISTER, vrf_id);
-
-       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
-               FOR_ALL_INTERFACES (vrf, ifp) {
-                       pim_ifp = ifp->info;
-
-                       if (!pim_ifp)
-                               continue;
-
-                       if (pim_ifp->pim_sock_fd < 0)
-                               continue;
-
-                       for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list,
-                                              neigh_node, neigh_nextnode,
-                                              neigh)) {
-                               if (!neigh->bfd_info)
-                                       continue;
-                               if (PIM_DEBUG_PIM_TRACE) {
-                                       char str[INET_ADDRSTRLEN];
-
-                                       pim_inet4_dump("<bfd_nbr?>",
-                                                      neigh->source_addr, str,
-                                                      sizeof(str));
-                                       zlog_debug(
-                                               "%s: Replaying Pim Neigh %s to BFD vrf_id %u",
-                                               __func__, str, vrf->vrf_id);
-                               }
-                               pim_bfd_reg_dereg_nbr(neigh,
-                                                     ZEBRA_BFD_DEST_UPDATE);
-                       }
-               }
-       }
-       return 0;
 }
 
 void pim_bfd_init(void)
 {
-       struct zclient *zclient = NULL;
-
-       zclient = pim_zebra_zclient_get();
-
-       bfd_gbl_init();
-
-       zclient->interface_bfd_dest_update = pim_bfd_interface_dest_update;
-       zclient->bfd_dest_replay = pim_bfd_nbr_replay;
+       bfd_protocol_integration_init(pim_zebra_zclient_get(), router->master);
 }
index 962b727f88f3ea0b8bb53c4d969fbda9256ea38a..3bfbb7486ee078e1660ed97cb63daa1cb001e708 100644 (file)
 
 #include "if.h"
 
+/**
+ * Initializes PIM BFD integration code.
+ */
 void pim_bfd_init(void);
+
+/**
+ * Write configuration to `show running-config`.
+ *
+ * \param vty the vty output pointer.
+ * \param ifp the interface pointer that has the configuration.
+ */
 void pim_bfd_write_config(struct vty *vty, struct interface *ifp);
-void pim_bfd_show_info(struct vty *vty, void *bfd_info, json_object *json_obj,
-                      bool use_json, int param_only);
-void pim_bfd_if_param_set(struct interface *ifp, uint32_t min_rx,
-                         uint32_t min_tx, uint8_t detect_mult, int defaults);
-int pim_bfd_reg_dereg_all_nbr(struct interface *ifp, int command);
-void pim_bfd_trigger_event(struct pim_interface *pim_ifp,
-                          struct pim_neighbor *nbr, uint8_t nbr_up);
+
+/**
+ * Enables or disables all peers BFD sessions.
+ *
+ * \param ifp interface pointer.
+ * \param enable session state to set.
+ */
+void pim_bfd_reg_dereg_all_nbr(struct interface *ifp);
+
+/**
+ * Create and configure peer BFD session if it does not exist. It will use
+ * the interface configured parameters as the peer configuration.
+ *
+ * \param pim_ifp the interface configuration pointer.
+ * \param neigh the neighbor configuration pointer.
+ */
 void pim_bfd_info_nbr_create(struct pim_interface *pim_ifp,
                             struct pim_neighbor *neigh);
-void pim_bfd_info_free(struct bfd_info **bfd_info);
+
 #endif /* _PIM_BFD_H */
index f43a31fde261d9a808acff75e15af672942a8b75..3fbe3317ba9ca52e552e6cbc3b29ddf19baa8279 100644 (file)
@@ -43,8 +43,8 @@ static inline void pim_g2rp_timer_restart(struct bsm_rpinfo *bsrp,
 
 /* Memory Types */
 DEFINE_MTYPE_STATIC(PIMD, PIM_BSGRP_NODE, "PIM BSR advertised grp info");
-DEFINE_MTYPE_STATIC(PIMD, PIM_BSRP_NODE, "PIM BSR advertised RP info");
-DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_INFO, "PIM BSM Info");
+DEFINE_MTYPE_STATIC(PIMD, PIM_BSRP_INFO, "PIM BSR advertised RP info");
+DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_FRAG, "PIM BSM fragment");
 DEFINE_MTYPE_STATIC(PIMD, PIM_BSM_PKT_VAR_MEM, "PIM BSM Packet");
 
 /* All bsm packets forwarded shall be fit within ip mtu less iphdr(max) */
@@ -63,12 +63,24 @@ void pim_bsm_write_config(struct vty *vty, struct interface *ifp)
        }
 }
 
+static void pim_bsm_rpinfo_free(struct bsm_rpinfo *bsrp_info)
+{
+       THREAD_OFF(bsrp_info->g2rp_timer);
+       XFREE(MTYPE_PIM_BSRP_INFO, bsrp_info);
+}
+
+void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head)
+{
+       struct bsm_rpinfo *bsrp_info;
+
+       while ((bsrp_info = bsm_rpinfos_pop(head)))
+               pim_bsm_rpinfo_free(bsrp_info);
+}
+
 void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node)
 {
-       if (bsgrp_node->bsrp_list)
-               list_delete(&bsgrp_node->bsrp_list);
-       if (bsgrp_node->partial_bsrp_list)
-               list_delete(&bsgrp_node->partial_bsrp_list);
+       pim_bsm_rpinfos_free(bsgrp_node->bsrp_list);
+       pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
        XFREE(MTYPE_PIM_BSGRP_NODE, bsgrp_node);
 }
 
@@ -84,14 +96,21 @@ void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp)
        }
 }
 
-static void pim_bsm_node_free(struct bsm_info *bsm)
+static void pim_bsm_frag_free(struct bsm_frag *bsfrag)
 {
-       XFREE(MTYPE_PIM_BSM_PKT_VAR_MEM, bsm->bsm);
-       XFREE(MTYPE_PIM_BSM_INFO, bsm);
+       XFREE(MTYPE_PIM_BSM_FRAG, bsfrag);
 }
 
-static int pim_g2rp_list_compare(struct bsm_rpinfo *node1,
-                                struct bsm_rpinfo *node2)
+void pim_bsm_frags_free(struct bsm_scope *scope)
+{
+       struct bsm_frag *bsfrag;
+
+       while ((bsfrag = bsm_frags_pop(scope->bsm_frags)))
+               pim_bsm_frag_free(bsfrag);
+}
+
+int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo *node1,
+                      const struct bsm_rpinfo *node2)
 {
        /* RP election Algo :
         * Step-1 : Loweset Rp priority  will have higher precedance.
@@ -115,27 +134,6 @@ static int pim_g2rp_list_compare(struct bsm_rpinfo *node1,
        return 0;
 }
 
-static void pim_free_bsrp_node(struct bsm_rpinfo *bsrp_info)
-{
-       THREAD_OFF(bsrp_info->g2rp_timer);
-       XFREE(MTYPE_PIM_BSRP_NODE, bsrp_info);
-}
-
-static struct list *pim_alloc_bsrp_list(void)
-{
-       struct list *new_list = NULL;
-
-       new_list = list_new();
-
-       if (!new_list)
-               return NULL;
-
-       new_list->cmp = (int (*)(void *, void *))pim_g2rp_list_compare;
-       new_list->del = (void (*)(void *))pim_free_bsrp_node;
-
-       return new_list;
-}
-
 static struct bsgrp_node *pim_bsm_new_bsgrp_node(struct route_table *rt,
                                                 struct prefix *grp)
 {
@@ -150,14 +148,8 @@ static struct bsgrp_node *pim_bsm_new_bsgrp_node(struct route_table *rt,
        bsgrp = XCALLOC(MTYPE_PIM_BSGRP_NODE, sizeof(struct bsgrp_node));
 
        rn->info = bsgrp;
-       bsgrp->bsrp_list = pim_alloc_bsrp_list();
-       bsgrp->partial_bsrp_list = pim_alloc_bsrp_list();
-
-       if ((!bsgrp->bsrp_list) || (!bsgrp->partial_bsrp_list)) {
-               route_unlock_node(rn);
-               pim_free_bsgrp_data(bsgrp);
-               return NULL;
-       }
+       bsm_rpinfos_init(bsgrp->bsrp_list);
+       bsm_rpinfos_init(bsgrp->partial_bsrp_list);
 
        prefix_copy(&bsgrp->group, grp);
        return bsgrp;
@@ -197,7 +189,7 @@ static int pim_on_bs_timer(struct thread *t)
        scope->current_bsr_first_ts = 0;
        scope->current_bsr_last_ts = 0;
        scope->bsm_frag_tag = 0;
-       list_delete_all_node(scope->bsm_list);
+       pim_bsm_frags_free(scope);
 
        for (rn = route_top(scope->bsrp_table); rn; rn = route_next(rn)) {
 
@@ -208,16 +200,13 @@ static int pim_on_bs_timer(struct thread *t)
                        continue;
                }
                /* Give grace time for rp to continue for another hold time */
-               if ((bsgrp_node->bsrp_list) && (bsgrp_node->bsrp_list->count)) {
-                       bsrp = listnode_head(bsgrp_node->bsrp_list);
+               bsrp = bsm_rpinfos_first(bsgrp_node->bsrp_list);
+               if (bsrp)
                        pim_g2rp_timer_restart(bsrp, bsrp->rp_holdtime);
-               }
+
                /* clear pending list */
-               if ((bsgrp_node->partial_bsrp_list)
-                   && (bsgrp_node->partial_bsrp_list->count)) {
-                       list_delete_all_node(bsgrp_node->partial_bsrp_list);
-                       bsgrp_node->pend_rp_cnt = 0;
-               }
+               pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
+               bsgrp_node->pend_rp_cnt = 0;
        }
        return 0;
 }
@@ -260,8 +249,7 @@ void pim_bsm_proc_init(struct pim_instance *pim)
        pim->global_scope.accept_nofwd_bsm = true;
        pim->global_scope.state = NO_INFO;
        pim->global_scope.pim = pim;
-       pim->global_scope.bsm_list = list_new();
-       pim->global_scope.bsm_list->del = (void (*)(void *))pim_bsm_node_free;
+       bsm_frags_init(pim->global_scope.bsm_frags);
        pim_bs_timer_start(&pim->global_scope, PIM_BS_TIME);
 }
 
@@ -271,9 +259,7 @@ void pim_bsm_proc_free(struct pim_instance *pim)
        struct bsgrp_node *bsgrp;
 
        pim_bs_timer_stop(&pim->global_scope);
-
-       if (pim->global_scope.bsm_list)
-               list_delete(&pim->global_scope.bsm_list);
+       pim_bsm_frags_free(&pim->global_scope);
 
        for (rn = route_top(pim->global_scope.bsrp_table); rn;
             rn = route_next(rn)) {
@@ -303,7 +289,6 @@ static int pim_on_g2rp_timer(struct thread *t)
        struct bsm_rpinfo *bsrp;
        struct bsm_rpinfo *bsrp_node;
        struct bsgrp_node *bsgrp_node;
-       struct listnode *bsrp_ln;
        struct pim_instance *pim;
        struct rp_info *rp_info;
        struct route_node *rn;
@@ -319,14 +304,17 @@ static int pim_on_g2rp_timer(struct thread *t)
        bsrp_addr = bsrp->rp_address;
 
        /* update elapse for all bsrp nodes */
-       for (ALL_LIST_ELEMENTS_RO(bsgrp_node->bsrp_list, bsrp_ln, bsrp_node))
+       frr_each_safe (bsm_rpinfos, bsgrp_node->bsrp_list, bsrp_node) {
                bsrp_node->elapse_time += elapse;
 
-       /* remove the expired nodes from the list */
-       list_filter_out_nodes(bsgrp_node->bsrp_list, is_hold_time_elapsed);
+               if (is_hold_time_elapsed(bsrp_node)) {
+                       bsm_rpinfos_del(bsgrp_node->bsrp_list, bsrp_node);
+                       pim_bsm_rpinfo_free(bsrp_node);
+               }
+       }
 
        /* Get the next elected rp node */
-       bsrp = listnode_head(bsgrp_node->bsrp_list);
+       bsrp = bsm_rpinfos_first(bsgrp_node->bsrp_list);
        pim = bsgrp_node->scope->pim;
        rn = route_node_lookup(pim->rp_table, &bsgrp_node->group);
 
@@ -356,8 +344,8 @@ static int pim_on_g2rp_timer(struct thread *t)
                }
        }
 
-       if ((!bsgrp_node->bsrp_list->count)
-           && (!bsgrp_node->partial_bsrp_list->count)) {
+       if (!bsm_rpinfos_count(bsgrp_node->bsrp_list)
+           && !bsm_rpinfos_count(bsgrp_node->partial_bsrp_list)) {
                pim_free_bsgrp_node(pim->global_scope.bsrp_table,
                                    &bsgrp_node->group);
                pim_free_bsgrp_data(bsgrp_node);
@@ -420,7 +408,6 @@ static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node)
 {
        struct bsm_rpinfo *active;
        struct bsm_rpinfo *pend;
-       struct list *temp;
        struct rp_info *rp_info;
        struct route_node *rn;
        struct pim_instance *pim;
@@ -429,11 +416,14 @@ static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node)
        bool had_rp_node = true;
 
        pim = bsgrp_node->scope->pim;
-       active = listnode_head(bsgrp_node->bsrp_list);
+       active = bsm_rpinfos_first(bsgrp_node->bsrp_list);
 
        /* Remove nodes with hold time 0 & check if list still has a head */
-       list_filter_out_nodes(bsgrp_node->partial_bsrp_list, is_hold_time_zero);
-       pend = listnode_head(bsgrp_node->partial_bsrp_list);
+       frr_each_safe (bsm_rpinfos, bsgrp_node->partial_bsrp_list, pend)
+               if (is_hold_time_zero(pend))
+                       bsm_rpinfos_del(bsgrp_node->partial_bsrp_list, pend);
+
+       pend = bsm_rpinfos_first(bsgrp_node->partial_bsrp_list);
 
        if (!str2prefix("224.0.0.0/4", &group_all))
                return;
@@ -541,14 +531,12 @@ static void pim_instate_pend_list(struct bsgrp_node *bsgrp_node)
         *    pend is head of bsrp list
         * So check appriate head after swap and clean the new partial list
         */
-       temp = bsgrp_node->bsrp_list;
-       bsgrp_node->bsrp_list = bsgrp_node->partial_bsrp_list;
-       bsgrp_node->partial_bsrp_list = temp;
+       bsm_rpinfos_swap_all(bsgrp_node->bsrp_list,
+                            bsgrp_node->partial_bsrp_list);
 
-       if (active) {
+       if (active)
                pim_g2rp_timer_stop(active);
-               list_delete_all_node(bsgrp_node->partial_bsrp_list);
-       }
+       pim_bsm_rpinfos_free(bsgrp_node->partial_bsrp_list);
 }
 
 static bool pim_bsr_rpf_check(struct pim_instance *pim, struct in_addr bsr,
@@ -896,8 +884,7 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
        struct in_addr dst_addr;
        struct pim_interface *pim_ifp;
        struct bsm_scope *scope;
-       struct listnode *bsm_ln;
-       struct bsm_info *bsminfo;
+       struct bsm_frag *bsfrag;
        char neigh_src_str[INET_ADDRSTRLEN];
        uint32_t pim_mtu;
        bool no_fwd = true;
@@ -929,7 +916,7 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
 
        scope = &pim_ifp->pim->global_scope;
 
-       if (!scope->bsm_list->count) {
+       if (!bsm_frags_count(scope->bsm_frags)) {
                if (PIM_DEBUG_BSM)
                        zlog_debug("%s: BSM list for the scope is empty",
                                   __func__);
@@ -950,10 +937,10 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
        pim_mtu = ifp->mtu - MAX_IP_HDR_LEN;
        pim_hello_require(ifp);
 
-       for (ALL_LIST_ELEMENTS_RO(scope->bsm_list, bsm_ln, bsminfo)) {
-               if (pim_mtu < bsminfo->size) {
-                       ret = pim_bsm_frag_send(bsminfo->bsm, bsminfo->size,
-                                               ifp, pim_mtu, dst_addr, no_fwd);
+       frr_each (bsm_frags, scope->bsm_frags, bsfrag) {
+               if (pim_mtu < bsfrag->size) {
+                       ret = pim_bsm_frag_send(bsfrag->data, bsfrag->size, ifp,
+                                               pim_mtu, dst_addr, no_fwd);
                        if (!ret) {
                                if (PIM_DEBUG_BSM)
                                        zlog_debug(
@@ -962,10 +949,10 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp)
                        }
                } else {
                        /* Pim header needs to be constructed */
-                       pim_msg_build_header(bsminfo->bsm, bsminfo->size,
+                       pim_msg_build_header(bsfrag->data, bsfrag->size,
                                             PIM_MSG_TYPE_BOOTSTRAP, no_fwd);
-                       ret = pim_bsm_send_intf(bsminfo->bsm, bsminfo->size,
-                                               ifp, dst_addr);
+                       ret = pim_bsm_send_intf(bsfrag->data, bsfrag->size, ifp,
+                                               dst_addr);
                        if (!ret) {
                                if (PIM_DEBUG_BSM)
                                        zlog_debug(
@@ -1035,7 +1022,7 @@ static bool pim_install_bsm_grp_rp(struct pim_instance *pim,
        uint8_t hashMask_len = pim->global_scope.hashMasklen;
 
        /*memory allocation for bsm_rpinfo */
-       bsm_rpinfo = XCALLOC(MTYPE_PIM_BSRP_NODE, sizeof(*bsm_rpinfo));
+       bsm_rpinfo = XCALLOC(MTYPE_PIM_BSRP_INFO, sizeof(*bsm_rpinfo));
 
        bsm_rpinfo->rp_prio = rp->rp_pri;
        bsm_rpinfo->rp_holdtime = rp->rp_holdtime;
@@ -1049,7 +1036,7 @@ static bool pim_install_bsm_grp_rp(struct pim_instance *pim,
        /* update hash for this rp node */
        bsm_rpinfo->hash = hash_calc_on_grp_rp(grpnode->group, rp->rpaddr.addr,
                                               hashMask_len);
-       if (listnode_add_sort_nodup(grpnode->partial_bsrp_list, bsm_rpinfo)) {
+       if (bsm_rpinfos_add(grpnode->partial_bsrp_list, bsm_rpinfo) == NULL) {
                if (PIM_DEBUG_BSM)
                        zlog_debug(
                                "%s, bs_rpinfo node added to the partial bs_rplist.",
@@ -1060,7 +1047,7 @@ static bool pim_install_bsm_grp_rp(struct pim_instance *pim,
        if (PIM_DEBUG_BSM)
                zlog_debug("%s: list node not added", __func__);
 
-       XFREE(MTYPE_PIM_BSRP_NODE, bsm_rpinfo);
+       XFREE(MTYPE_PIM_BSRP_INFO, bsm_rpinfo);
        return false;
 }
 
@@ -1078,7 +1065,7 @@ static void pim_update_pending_rp_cnt(struct bsm_scope *sz,
                                zlog_debug(
                                        "%s,Received a new BSM ,so clear the pending bs_rpinfo list.",
                                        __func__);
-                       list_delete_all_node(bsgrp->partial_bsrp_list);
+                       pim_bsm_rpinfos_free(bsgrp->partial_bsrp_list);
                        bsgrp->pend_rp_cnt = total_rp_count;
                }
        } else
@@ -1227,7 +1214,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf,
        int sz = PIM_GBL_SZ_ID;
        struct bsmmsg_grpinfo *msg_grp;
        struct pim_interface *pim_ifp = NULL;
-       struct bsm_info *bsminfo;
+       struct bsm_frag *bsfrag;
        struct pim_instance *pim;
        char bsr_str[INET_ADDRSTRLEN];
        uint16_t frag_tag;
@@ -1383,7 +1370,7 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf,
                                   pim_ifp->pim->global_scope.bsm_frag_tag,
                                   frag_tag);
                }
-               list_delete_all_node(pim_ifp->pim->global_scope.bsm_list);
+               pim_bsm_frags_free(&pim_ifp->pim->global_scope);
                pim_ifp->pim->global_scope.bsm_frag_tag = frag_tag;
        }
 
@@ -1392,13 +1379,13 @@ int pim_bsm_process(struct interface *ifp, struct ip *ip_hdr, uint8_t *buf,
 
        if (!no_fwd) {
                pim_bsm_fwd_whole_sz(pim_ifp->pim, buf, buf_size, sz);
-               bsminfo = XCALLOC(MTYPE_PIM_BSM_INFO, sizeof(struct bsm_info));
-
-               bsminfo->bsm = XCALLOC(MTYPE_PIM_BSM_PKT_VAR_MEM, buf_size);
+               bsfrag = XCALLOC(MTYPE_PIM_BSM_FRAG,
+                                sizeof(struct bsm_frag) + buf_size);
 
-               bsminfo->size = buf_size;
-               memcpy(bsminfo->bsm, buf, buf_size);
-               listnode_add(pim_ifp->pim->global_scope.bsm_list, bsminfo);
+               bsfrag->size = buf_size;
+               memcpy(bsfrag->data, buf, buf_size);
+               bsm_frags_add_tail(pim_ifp->pim->global_scope.bsm_frags,
+                                  bsfrag);
        }
 
        return 0;
index 2829c1e05a46d06e8fec78525f41bfd22b1229b5..dbfeeceec883c1c09407a6b046290c3446c3c7bd 100644 (file)
@@ -25,7 +25,7 @@
 
 #include "if.h"
 #include "vty.h"
-#include "linklist.h"
+#include "typesafe.h"
 #include "table.h"
 #include "pim_rp.h"
 #include "pim_msg.h"
@@ -54,6 +54,8 @@ enum ncbsr_state {
        ACCEPT_PREFERRED
 };
 
+PREDECL_DLIST(bsm_frags);
+
 /* BSM scope - bsm processing is per scope */
 struct bsm_scope {
        int sz_id;                      /* scope zone id */
@@ -66,36 +68,49 @@ struct bsm_scope {
        uint16_t bsm_frag_tag;          /* Last received frag tag from E-BSR */
        uint8_t hashMasklen;            /* Mask in hash calc RFC 7761 4.7.2 */
        struct pim_instance *pim;       /* Back pointer to pim instance */
-       struct list *bsm_list;          /* list of bsm frag for frowarding */
+
+       /* current set of fragments for forwarding */
+       struct bsm_frags_head bsm_frags[1];
+
        struct route_table *bsrp_table; /* group2rp mapping rcvd from BSR */
        struct thread *bs_timer;        /* Boot strap timer */
-       struct thread *sz_timer;
 };
 
-/* BSM packet - this is stored as list in bsm_list inside scope
+/* BSM packet (= fragment) - this is stored as list in bsm_frags inside scope
  * This is used for forwarding to new neighbors or restarting mcast routers
  */
-struct bsm_info {
-       uint32_t size;      /* size of the packet */
-       unsigned char *bsm; /* Actual packet */
+struct bsm_frag {
+       struct bsm_frags_item item;
+
+       uint32_t size;   /* size of the packet */
+       uint8_t data[0]; /* Actual packet (dyn size) */
 };
 
+DECLARE_DLIST(bsm_frags, struct bsm_frag, item);
+
+PREDECL_SORTLIST_UNIQ(bsm_rpinfos);
+
 /* This is the group node of the bsrp table in scope.
  * this node maintains the list of rp for the group.
  */
 struct bsgrp_node {
        struct prefix group;            /* Group range */
        struct bsm_scope *scope;        /* Back ptr to scope */
-       struct list *bsrp_list;         /* list of RPs adv by BSR */
-       struct list *partial_bsrp_list; /* maintained until all RPs received */
+
+       /* RPs advertised by BSR, and temporary list while receiving new set */
+       struct bsm_rpinfos_head bsrp_list[1];
+       struct bsm_rpinfos_head partial_bsrp_list[1];
+
        int pend_rp_cnt;                /* Total RP - Received RP */
        uint16_t frag_tag;              /* frag tag to identify the fragment */
 };
 
-/* This is the list node of bsrp_list and partial bsrp list in
- * bsgrp_node. Hold info of each RP received for the group
+/* Items on [partial_]bsrp_list above.
+ * Holds info of each candidate RP received for the bsgrp_node's prefix.
  */
 struct bsm_rpinfo {
+       struct bsm_rpinfos_item item;
+
        uint32_t hash;                  /* Hash Value as per RFC 7761 4.7.2 */
        uint32_t elapse_time;           /* upd at expiry of elected RP node */
        uint16_t rp_prio;               /* RP priority */
@@ -105,6 +120,10 @@ struct bsm_rpinfo {
        struct thread *g2rp_timer;      /* Run only for elected RP node */
 };
 
+extern int pim_bsm_rpinfo_cmp(const struct bsm_rpinfo *a,
+                             const struct bsm_rpinfo *b);
+DECLARE_SORTLIST_UNIQ(bsm_rpinfos, struct bsm_rpinfo, item, pim_bsm_rpinfo_cmp);
+
 /*  Structures to extract Bootstrap Message header and Grp to RP Mappings
  *  =====================================================================
  *  BSM Format:
@@ -196,6 +215,8 @@ bool pim_bsm_new_nbr_fwd(struct pim_neighbor *neigh, struct interface *ifp);
 struct bsgrp_node *pim_bsm_get_bsgrp_node(struct bsm_scope *scope,
                                          struct prefix *grp);
 void pim_bs_timer_stop(struct bsm_scope *scope);
+void pim_bsm_frags_free(struct bsm_scope *scope);
+void pim_bsm_rpinfos_free(struct bsm_rpinfos_head *head);
 void pim_free_bsgrp_data(struct bsgrp_node *bsgrp_node);
 void pim_free_bsgrp_node(struct route_table *rt, struct prefix *grp);
 #endif
index 4bbe7d35f089426e5927e28f177fdbe70b0e47bc..90aa15beee2d4d81bbd49a4bf15c62cada046884 100644 (file)
@@ -1955,8 +1955,8 @@ static void pim_show_neighbors_single(struct pim_instance *pim, struct vty *vty,
                                vty_out(vty,
                                        "    Hello Option - T-bit           : %s\n",
                                        option_t_bit ? "yes" : "no");
-                               pim_bfd_show_info(vty, neigh->bfd_info,
-                                                 json_ifp, uj, 0);
+                               bfd_sess_show(vty, json_ifp,
+                                             neigh->bfd_session);
                                vty_out(vty, "\n");
                        }
                }
@@ -3000,15 +3000,14 @@ static void pim_show_nexthop(struct pim_instance *pim, struct vty *vty)
 /* Display the bsm database details */
 static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
 {
-       struct listnode *bsmnode;
        int count = 0;
        int fragment = 1;
-       struct bsm_info *bsm;
+       struct bsm_frag *bsfrag;
        json_object *json = NULL;
        json_object *json_group = NULL;
        json_object *json_row = NULL;
 
-       count = pim->global_scope.bsm_list->count;
+       count = bsm_frags_count(pim->global_scope.bsm_frags);
 
        if (uj) {
                json = json_object_new_object();
@@ -3019,7 +3018,7 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
                vty_out(vty, "\n");
        }
 
-       for (ALL_LIST_ELEMENTS_RO(pim->global_scope.bsm_list, bsmnode, bsm)) {
+       frr_each (bsm_frags, pim->global_scope.bsm_frags, bsfrag) {
                char grp_str[PREFIX_STRLEN];
                char rp_str[INET_ADDRSTRLEN];
                char bsr_str[INET_ADDRSTRLEN];
@@ -3032,8 +3031,8 @@ static void pim_show_bsm_db(struct pim_instance *pim, struct vty *vty, bool uj)
                uint32_t len = 0;
                uint32_t frag_rp_cnt = 0;
 
-               buf = bsm->bsm;
-               len = bsm->size;
+               buf = bsfrag->data;
+               len = bsfrag->size;
 
                /* skip pim header */
                buf += PIM_MSG_HEADER_LEN;
@@ -3160,7 +3159,6 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
                                            struct vty *vty, bool uj)
 {
        struct bsgrp_node *bsgrp;
-       struct listnode *rpnode;
        struct bsm_rpinfo *bsm_rp;
        struct route_node *rn;
        char bsr_str[INET_ADDRSTRLEN];
@@ -3209,42 +3207,33 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
                        vty_out(vty, "(ACTIVE)\n");
                }
 
-               if (bsgrp->bsrp_list) {
-                       for (ALL_LIST_ELEMENTS_RO(bsgrp->bsrp_list, rpnode,
-                                                 bsm_rp)) {
-                               char rp_str[INET_ADDRSTRLEN];
+               frr_each (bsm_rpinfos, bsgrp->bsrp_list, bsm_rp) {
+                       char rp_str[INET_ADDRSTRLEN];
 
-                               pim_inet4_dump("<Rp Address?>",
-                                              bsm_rp->rp_address, rp_str,
-                                              sizeof(rp_str));
+                       pim_inet4_dump("<Rp Address?>", bsm_rp->rp_address,
+                                      rp_str, sizeof(rp_str));
 
-                               if (uj) {
-                                       json_row = json_object_new_object();
-                                       json_object_string_add(
-                                               json_row, "Rp Address", rp_str);
-                                       json_object_int_add(
-                                               json_row, "Rp HoldTime",
-                                               bsm_rp->rp_holdtime);
-                                       json_object_int_add(json_row,
-                                                           "Rp Priority",
-                                                           bsm_rp->rp_prio);
-                                       json_object_int_add(json_row,
-                                                           "Hash Val",
-                                                           bsm_rp->hash);
-                                       json_object_object_add(
-                                               json_group, rp_str, json_row);
+                       if (uj) {
+                               json_row = json_object_new_object();
+                               json_object_string_add(json_row, "Rp Address",
+                                                      rp_str);
+                               json_object_int_add(json_row, "Rp HoldTime",
+                                                   bsm_rp->rp_holdtime);
+                               json_object_int_add(json_row, "Rp Priority",
+                                                   bsm_rp->rp_prio);
+                               json_object_int_add(json_row, "Hash Val",
+                                                   bsm_rp->hash);
+                               json_object_object_add(json_group, rp_str,
+                                                      json_row);
 
-                               } else {
-                                       vty_out(vty,
-                                               "%-15s %-15u %-15u %-15u\n",
-                                               rp_str, bsm_rp->rp_prio,
-                                               bsm_rp->rp_holdtime,
-                                               bsm_rp->hash);
-                               }
+                       } else {
+                               vty_out(vty, "%-15s %-15u %-15u %-15u\n",
+                                       rp_str, bsm_rp->rp_prio,
+                                       bsm_rp->rp_holdtime, bsm_rp->hash);
                        }
-                       if (!bsgrp->bsrp_list->count && !uj)
-                               vty_out(vty, "Active List is empty.\n");
                }
+               if (!bsm_rpinfos_count(bsgrp->bsrp_list) && !uj)
+                       vty_out(vty, "Active List is empty.\n");
 
                if (uj) {
                        json_object_int_add(json_group, "Pending RP count",
@@ -3259,40 +3248,32 @@ static void pim_show_group_rp_mappings_info(struct pim_instance *pim,
                                        "Hash");
                }
 
-               if (bsgrp->partial_bsrp_list) {
-                       for (ALL_LIST_ELEMENTS_RO(bsgrp->partial_bsrp_list,
-                                                 rpnode, bsm_rp)) {
-                               char rp_str[INET_ADDRSTRLEN];
+               frr_each (bsm_rpinfos, bsgrp->partial_bsrp_list, bsm_rp) {
+                       char rp_str[INET_ADDRSTRLEN];
 
-                               pim_inet4_dump("<Rp Addr?>", bsm_rp->rp_address,
-                                              rp_str, sizeof(rp_str));
+                       pim_inet4_dump("<Rp Addr?>", bsm_rp->rp_address, rp_str,
+                                      sizeof(rp_str));
 
-                               if (uj) {
-                                       json_row = json_object_new_object();
-                                       json_object_string_add(
-                                               json_row, "Rp Address", rp_str);
-                                       json_object_int_add(
-                                               json_row, "Rp HoldTime",
-                                               bsm_rp->rp_holdtime);
-                                       json_object_int_add(json_row,
-                                                           "Rp Priority",
-                                                           bsm_rp->rp_prio);
-                                       json_object_int_add(json_row,
-                                                           "Hash Val",
-                                                           bsm_rp->hash);
-                                       json_object_object_add(
-                                               json_group, rp_str, json_row);
-                               } else {
-                                       vty_out(vty,
-                                               "%-15s %-15u %-15u %-15u\n",
-                                               rp_str, bsm_rp->rp_prio,
-                                               bsm_rp->rp_holdtime,
-                                               bsm_rp->hash);
-                               }
+                       if (uj) {
+                               json_row = json_object_new_object();
+                               json_object_string_add(json_row, "Rp Address",
+                                                      rp_str);
+                               json_object_int_add(json_row, "Rp HoldTime",
+                                                   bsm_rp->rp_holdtime);
+                               json_object_int_add(json_row, "Rp Priority",
+                                                   bsm_rp->rp_prio);
+                               json_object_int_add(json_row, "Hash Val",
+                                                   bsm_rp->hash);
+                               json_object_object_add(json_group, rp_str,
+                                                      json_row);
+                       } else {
+                               vty_out(vty, "%-15s %-15u %-15u %-15u\n",
+                                       rp_str, bsm_rp->rp_prio,
+                                       bsm_rp->rp_holdtime, bsm_rp->hash);
                        }
-                       if (!bsgrp->partial_bsrp_list->count && !uj)
-                               vty_out(vty, "Partial List is empty\n");
                }
+               if (!bsm_rpinfos_count(bsgrp->partial_bsrp_list) && !uj)
+                       vty_out(vty, "Partial List is empty\n");
 
                if (!uj)
                        vty_out(vty, "\n");
@@ -3847,6 +3828,31 @@ static void clear_interfaces(struct pim_instance *pim)
                return CMD_WARNING_CONFIG_FAILED;                       \
        }
 
+/**
+ * Get current node VRF name.
+ *
+ * NOTE:
+ * In case of failure it will print error message to user.
+ *
+ * \returns name or NULL if failed to get VRF.
+ */
+static const char *pim_cli_get_vrf_name(struct vty *vty)
+{
+       const struct lyd_node *vrf_node;
+
+       /* Not inside any VRF context. */
+       if (vty->xpath_index == 0)
+               return VRF_DEFAULT_NAME;
+
+       vrf_node = yang_dnode_get(vty->candidate_config->dnode, VTY_CURR_XPATH);
+       if (vrf_node == NULL) {
+               vty_out(vty, "%% Failed to get vrf dnode in configuration\n");
+               return NULL;
+       }
+
+       return yang_dnode_get_string(vrf_node, "./name");
+}
+
 DEFUN (clear_ip_interfaces,
        clear_ip_interfaces_cmd,
        "clear ip interfaces [vrf NAME]",
@@ -4083,7 +4089,7 @@ static void clear_pim_bsr_db(struct pim_instance *pim)
        pim->global_scope.current_bsr_first_ts = 0;
        pim->global_scope.current_bsr_last_ts = 0;
        pim->global_scope.bsm_frag_tag = 0;
-       list_delete_all_node(pim->global_scope.bsm_list);
+       pim_bsm_frags_free(&pim->global_scope);
 
        pim_bs_timer_stop(&pim->global_scope);
 
@@ -6925,25 +6931,13 @@ DEFUN (ip_pim_spt_switchover_infinity,
        "SPT-Switchover\n"
        "Never switch to SPT Tree\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char spt_plist_xpath[XPATH_MAXLEN];
        char spt_action_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
                 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
@@ -6976,25 +6970,13 @@ DEFUN (ip_pim_spt_switchover_infinity_plist,
        "Prefix-List to control which groups to switch\n"
        "Prefix-List name\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char spt_plist_xpath[XPATH_MAXLEN];
        char spt_action_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
                 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
@@ -7025,25 +7007,13 @@ DEFUN (no_ip_pim_spt_switchover_infinity,
        "SPT_Switchover\n"
        "Never switch to SPT Tree\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char spt_plist_xpath[XPATH_MAXLEN];
        char spt_action_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
                 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
@@ -7075,25 +7045,13 @@ DEFUN (no_ip_pim_spt_switchover_infinity_plist,
        "Prefix-List to control which groups to switch\n"
        "Prefix-List name\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char spt_plist_xpath[XPATH_MAXLEN];
        char spt_action_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(spt_plist_xpath, sizeof(spt_plist_xpath),
                 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
@@ -7123,22 +7081,12 @@ DEFPY (pim_register_accept_list,
        "Only accept registers from a specific source prefix list\n"
        "Prefix-List name\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char reg_alist_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(reg_alist_xpath, sizeof(reg_alist_xpath),
                 FRR_PIM_AF_XPATH, "frr-pim:pimd", "pim", vrfname,
@@ -7233,22 +7181,12 @@ DEFUN (ip_pim_rp_keep_alive,
        "Keep alive Timer\n"
        "Seconds\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char rp_ka_timer_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
                 FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
@@ -7271,26 +7209,16 @@ DEFUN (no_ip_pim_rp_keep_alive,
        "Keep alive Timer\n"
        "Seconds\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char rp_ka_timer[5];
        char rp_ka_timer_xpath[XPATH_MAXLEN];
 
-       snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%d", PIM_KEEPALIVE_PERIOD);
-
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       snprintf(rp_ka_timer, sizeof(rp_ka_timer), "%d",
+                               PIM_RP_KEEPALIVE_PERIOD);
 
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(rp_ka_timer_xpath, sizeof(rp_ka_timer_xpath),
                 FRR_PIM_XPATH, "frr-pim:pimd", "pim", vrfname);
@@ -7311,22 +7239,12 @@ DEFUN (ip_pim_keep_alive,
        "Keep alive Timer\n"
        "Seconds\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ka_timer_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
                 "frr-pim:pimd", "pim", vrfname);
@@ -7347,25 +7265,15 @@ DEFUN (no_ip_pim_keep_alive,
        "Keep alive Timer\n"
        "Seconds\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ka_timer[5];
        char ka_timer_xpath[XPATH_MAXLEN];
 
        snprintf(ka_timer, sizeof(ka_timer), "%d", PIM_KEEPALIVE_PERIOD);
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ka_timer_xpath, sizeof(ka_timer_xpath), FRR_PIM_XPATH,
                 "frr-pim:pimd", "pim", vrfname);
@@ -7447,22 +7355,12 @@ DEFUN (ip_pim_v6_secondary,
        "pim multicast routing\n"
        "Send v6 secondary addresses\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char send_v6_secondary_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
                 FRR_PIM_AF_XPATH,
@@ -7484,22 +7382,12 @@ DEFUN (no_ip_pim_v6_secondary,
        "pim multicast routing\n"
        "Send v6 secondary addresses\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char send_v6_secondary_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(send_v6_secondary_xpath, sizeof(send_v6_secondary_xpath),
                 FRR_PIM_AF_XPATH,
@@ -7522,7 +7410,6 @@ DEFUN (ip_pim_rp,
        "ip address of RP\n"
        "Group Address range to cover\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        int idx_rp = 3, idx_group = 4;
        char rp_group_xpath[XPATH_MAXLEN];
@@ -7558,20 +7445,9 @@ DEFUN (ip_pim_rp,
                return CMD_WARNING_CONFIG_FAILED;
        }
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(rp_group_xpath, sizeof(rp_group_xpath),
                 FRR_PIM_STATIC_RP_XPATH,
@@ -7595,24 +7471,12 @@ DEFUN (ip_pim_rp_prefix_list,
        "Name of a prefix-list\n")
 {
        int idx_rp = 3, idx_plist = 5;
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char rp_plist_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(rp_plist_xpath, sizeof(rp_plist_xpath),
                 FRR_PIM_STATIC_RP_XPATH,
@@ -7642,24 +7506,12 @@ DEFUN (no_ip_pim_rp,
        char group_list_xpath[XPATH_MAXLEN + 32];
        char group_xpath[XPATH_MAXLEN + 64];
        char rp_xpath[XPATH_MAXLEN];
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        const struct lyd_node *group_dnode;
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
                 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
@@ -7702,23 +7554,13 @@ DEFUN (no_ip_pim_rp_prefix_list,
        int idx_plist = 6;
        char rp_xpath[XPATH_MAXLEN];
        char plist_xpath[XPATH_MAXLEN];
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        const struct lyd_node *plist_dnode;
        const char *plist;
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(rp_xpath, sizeof(rp_xpath), FRR_PIM_STATIC_RP_XPATH,
                 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4",
@@ -7755,22 +7597,12 @@ DEFUN (ip_pim_ssm_prefix_list,
        "group range prefix-list filter\n"
        "Name of a prefix-list\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ssm_plist_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath), FRR_PIM_AF_XPATH,
                 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
@@ -7790,22 +7622,12 @@ DEFUN (no_ip_pim_ssm_prefix_list,
        "Source Specific Multicast\n"
        "group range prefix-list filter\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ssm_plist_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
                 FRR_PIM_AF_XPATH,
@@ -7827,27 +7649,14 @@ DEFUN (no_ip_pim_ssm_prefix_list_name,
        "group range prefix-list filter\n"
        "Name of a prefix-list\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        const struct lyd_node *ssm_plist_dnode;
        char ssm_plist_xpath[XPATH_MAXLEN];
        const char *ssm_plist_name;
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
-
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ssm_plist_xpath, sizeof(ssm_plist_xpath),
                 FRR_PIM_AF_XPATH,
@@ -8001,22 +7810,12 @@ DEFUN (ip_ssmpingd,
 {
        int idx_ipv4 = 2;
        const char *source_str = (argc == 3) ? argv[idx_ipv4]->arg : "0.0.0.0";
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ssmpingd_ip_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
                 FRR_PIM_AF_XPATH,
@@ -8038,24 +7837,14 @@ DEFUN (no_ip_ssmpingd,
        CONF_SSMPINGD_STR
        "Source address\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        int idx_ipv4 = 3;
        const char *source_str = (argc == 4) ? argv[idx_ipv4]->arg : "0.0.0.0";
        char ssmpingd_ip_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ssmpingd_ip_xpath, sizeof(ssmpingd_ip_xpath),
                 FRR_PIM_AF_XPATH,
@@ -8076,22 +7865,12 @@ DEFUN (ip_pim_ecmp,
        "pim multicast routing\n"
        "Enable PIM ECMP \n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ecmp_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
                 "frr-pim:pimd", "pim", vrfname);
@@ -8109,22 +7888,12 @@ DEFUN (no_ip_pim_ecmp,
        "pim multicast routing\n"
        "Disable PIM ECMP \n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ecmp_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
                 "frr-pim:pimd", "pim", vrfname);
@@ -8143,23 +7912,13 @@ DEFUN (ip_pim_ecmp_rebalance,
        "Enable PIM ECMP \n"
        "Enable PIM ECMP Rebalance\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ecmp_xpath[XPATH_MAXLEN];
        char ecmp_rebalance_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ecmp_xpath, sizeof(ecmp_xpath), FRR_PIM_XPATH,
                 "frr-pim:pimd", "pim", vrfname);
@@ -8185,22 +7944,12 @@ DEFUN (no_ip_pim_ecmp_rebalance,
        "Disable PIM ECMP \n"
        "Disable PIM ECMP Rebalance\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char ecmp_rebalance_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(ecmp_rebalance_xpath, sizeof(ecmp_rebalance_xpath),
                 FRR_PIM_XPATH,
@@ -9676,19 +9425,16 @@ DEFUN (interface_no_pim_use_source,
                                    "frr-routing:ipv4");
 }
 
-DEFUN (ip_pim_bfd,
+DEFPY (ip_pim_bfd,
        ip_pim_bfd_cmd,
-       "ip pim bfd",
+       "ip pim bfd [profile BFDPROF$prof]",
        IP_STR
        PIM_STR
-       "Enables BFD support\n")
+       "Enables BFD support\n"
+       "Use BFD profile\n"
+       "Use BFD profile name\n")
 {
-       struct bfd_info *bfd_info = NULL;
-       char default_rx_interval[5];
-       char default_tx_interval[5];
-       char default_detect_mult[3];
        const struct lyd_node *igmp_enable_dnode;
-       char bfd_xpath[XPATH_MAXLEN + 20];
 
        igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
                                           "%s/frr-igmp:igmp/igmp-enable",
@@ -9702,31 +9448,25 @@ DEFUN (ip_pim_bfd,
                                              "true");
        }
 
-       snprintf(default_rx_interval, sizeof(default_rx_interval), "%d",
-                BFD_DEF_MIN_RX);
-       snprintf(default_tx_interval, sizeof(default_tx_interval), "%d",
-                BFD_DEF_MIN_TX);
-       snprintf(default_detect_mult, sizeof(default_detect_mult), "%d",
-                BFD_DEF_DETECT_MULT);
-
-       snprintf(bfd_xpath, sizeof(bfd_xpath), "%s/frr-pim:pim/bfd",
-                VTY_CURR_XPATH);
-       bfd_info = nb_running_get_entry(NULL, bfd_xpath, false);
+       nb_cli_enqueue_change(vty, "./bfd", NB_OP_CREATE, NULL);
+       if (prof)
+               nb_cli_enqueue_change(vty, "./bfd/profile", NB_OP_MODIFY, prof);
 
-       if (!bfd_info ||
-           !CHECK_FLAG(bfd_info->flags, BFD_FLAG_PARAM_CFG)) {
-               nb_cli_enqueue_change(vty, "./bfd/min-rx-interval",
-                                     NB_OP_MODIFY, default_rx_interval);
-               nb_cli_enqueue_change(vty, "./bfd/min-tx-interval",
-                                     NB_OP_MODIFY, default_tx_interval);
-               nb_cli_enqueue_change(vty, "./bfd/detect_mult",
-                                     NB_OP_MODIFY,
-                                     default_detect_mult);
+       return nb_cli_apply_changes(vty, "./frr-pim:pim");
+}
 
-               return nb_cli_apply_changes(vty, "./frr-pim:pim");
-       }
+DEFPY(no_ip_pim_bfd_profile, no_ip_pim_bfd_profile_cmd,
+      "no ip pim bfd profile [BFDPROF]",
+      NO_STR
+      IP_STR
+      PIM_STR
+      "Enables BFD support\n"
+      "Disable BFD profile\n"
+      "BFD Profile name\n")
+{
+       nb_cli_enqueue_change(vty, "./bfd/profile", NB_OP_DESTROY, NULL);
 
-       return NB_OK;
+       return nb_cli_apply_changes(vty, "./frr-pim:pim");
 }
 
 DEFUN (no_ip_pim_bfd,
@@ -9847,19 +9587,8 @@ DEFUN_HIDDEN(
        int idx_number = 3;
        int idx_number_2 = 4;
        int idx_number_3 = 5;
-       uint32_t rx_val;
-       uint32_t tx_val;
-       uint8_t dm_val;
-       int ret;
        const struct lyd_node *igmp_enable_dnode;
 
-       if ((ret = bfd_validate_param(vty, argv[idx_number]->arg,
-                                     argv[idx_number_2]->arg,
-                                     argv[idx_number_3]->arg, &dm_val, &rx_val,
-                                     &tx_val))
-           != CMD_SUCCESS)
-               return ret;
-
        igmp_enable_dnode = yang_dnode_get(vty->candidate_config->dnode,
                                           "%s/frr-igmp:igmp/igmp-enable",
                                           VTY_CURR_XPATH);
@@ -9872,6 +9601,7 @@ DEFUN_HIDDEN(
                                              "true");
        }
 
+       nb_cli_enqueue_change(vty, "./bfd", NB_OP_CREATE, NULL);
        nb_cli_enqueue_change(vty, "./bfd/min-rx-interval", NB_OP_MODIFY,
                              argv[idx_number_2]->arg);
        nb_cli_enqueue_change(vty, "./bfd/min-tx-interval", NB_OP_MODIFY,
@@ -9901,23 +9631,13 @@ ALIAS(no_ip_pim_bfd, no_ip_pim_bfd_param_cmd,
               "Source address for TCP connection\n"
               "local ip address\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char temp_xpath[XPATH_MAXLEN];
        char msdp_peer_source_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(msdp_peer_source_xpath, sizeof(msdp_peer_source_xpath),
                 FRR_PIM_AF_XPATH,
@@ -9943,23 +9663,13 @@ DEFUN (no_ip_msdp_peer,
        "Delete MSDP peer\n"
        "peer ip address\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char msdp_peer_xpath[XPATH_MAXLEN];
        char temp_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(msdp_peer_xpath, sizeof(msdp_peer_xpath),
                 FRR_PIM_AF_XPATH,
@@ -9985,23 +9695,13 @@ DEFUN (ip_msdp_mesh_group_member,
        "mesh group member\n"
        "peer ip address\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char msdp_mesh_group_name_xpath[XPATH_MAXLEN];
        char msdp_mesh_group_member_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath),
                 FRR_PIM_AF_XPATH,
@@ -10034,7 +9734,6 @@ DEFUN (no_ip_msdp_mesh_group_member,
        "mesh group member\n"
        "peer ip address\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char pim_af_xpath[XPATH_MAXLEN];
        char mesh_group_xpath[XPATH_MAXLEN + 32];
@@ -10045,18 +9744,9 @@ DEFUN (no_ip_msdp_mesh_group_member,
        const char *mesh_group_name;
        const struct lyd_node *member_dnode;
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(pim_af_xpath, sizeof(pim_af_xpath), FRR_PIM_AF_XPATH,
                 "frr-pim:pimd", "pim", vrfname, "frr-routing:ipv4");
@@ -10122,23 +9812,13 @@ DEFUN (ip_msdp_mesh_group_source,
        "mesh group local address\n"
        "source ip address for the TCP connection\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char msdp_mesh_source_ip_xpath[XPATH_MAXLEN];
        char msdp_mesh_group_name_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(msdp_mesh_group_name_xpath, sizeof(msdp_mesh_group_name_xpath),
                 FRR_PIM_AF_XPATH,
@@ -10171,7 +9851,6 @@ DEFUN (no_ip_msdp_mesh_group_source,
        "mesh group source\n"
        "mesh group local address\n")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        char msdp_mesh_xpath[XPATH_MAXLEN];
        char source_xpath[XPATH_MAXLEN];
@@ -10179,18 +9858,9 @@ DEFUN (no_ip_msdp_mesh_group_source,
        char mesh_group_name_xpath[XPATH_MAXLEN];
        const char *mesh_group_name;
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        snprintf(msdp_mesh_xpath, sizeof(msdp_mesh_xpath),
                 FRR_PIM_AF_XPATH,
@@ -10245,24 +9915,14 @@ DEFUN (no_ip_msdp_mesh_group,
        "Delete MSDP mesh-group\n"
        "mesh group name")
 {
-       const struct lyd_node *vrf_dnode;
        const char *vrfname;
        const char *mesh_group_name;
        char xpath[XPATH_MAXLEN];
        char msdp_mesh_xpath[XPATH_MAXLEN];
 
-       if (vty->xpath_index) {
-               vrf_dnode =
-                       yang_dnode_get(vty->candidate_config->dnode,
-                                      VTY_CURR_XPATH);
-               if (!vrf_dnode) {
-                       vty_out(vty,
-                               "%% Failed to get vrf dnode in candidate db\n");
-                       return CMD_WARNING_CONFIG_FAILED;
-               }
-               vrfname = yang_dnode_get_string(vrf_dnode, "./name");
-       } else
-               vrfname = VRF_DEFAULT_NAME;
+       vrfname = pim_cli_get_vrf_name(vty);
+       if (vrfname == NULL)
+               return CMD_WARNING_CONFIG_FAILED;
 
        if (argc == 5) {
                snprintf(xpath, sizeof(xpath), FRR_PIM_AF_XPATH, "frr-pim:pimd",
@@ -11431,9 +11091,7 @@ void pim_cmd_init(void)
        install_element(CONFIG_NODE, &ip_pim_ssm_prefix_list_cmd);
        install_element(VRF_NODE, &ip_pim_ssm_prefix_list_cmd);
        install_element(CONFIG_NODE, &ip_pim_register_suppress_cmd);
-       install_element(VRF_NODE, &ip_pim_register_suppress_cmd);
        install_element(CONFIG_NODE, &no_ip_pim_register_suppress_cmd);
-       install_element(VRF_NODE, &no_ip_pim_register_suppress_cmd);
        install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_cmd);
        install_element(VRF_NODE, &ip_pim_spt_switchover_infinity_cmd);
        install_element(CONFIG_NODE, &ip_pim_spt_switchover_infinity_plist_cmd);
@@ -11446,9 +11104,7 @@ void pim_cmd_init(void)
        install_element(CONFIG_NODE, &pim_register_accept_list_cmd);
        install_element(VRF_NODE, &pim_register_accept_list_cmd);
        install_element(CONFIG_NODE, &ip_pim_joinprune_time_cmd);
-       install_element(VRF_NODE, &ip_pim_joinprune_time_cmd);
        install_element(CONFIG_NODE, &no_ip_pim_joinprune_time_cmd);
-       install_element(VRF_NODE, &no_ip_pim_joinprune_time_cmd);
        install_element(CONFIG_NODE, &ip_pim_keep_alive_cmd);
        install_element(VRF_NODE, &ip_pim_keep_alive_cmd);
        install_element(CONFIG_NODE, &ip_pim_rp_keep_alive_cmd);
@@ -11458,9 +11114,7 @@ void pim_cmd_init(void)
        install_element(CONFIG_NODE, &no_ip_pim_rp_keep_alive_cmd);
        install_element(VRF_NODE, &no_ip_pim_rp_keep_alive_cmd);
        install_element(CONFIG_NODE, &ip_pim_packets_cmd);
-       install_element(VRF_NODE, &ip_pim_packets_cmd);
        install_element(CONFIG_NODE, &no_ip_pim_packets_cmd);
-       install_element(VRF_NODE, &no_ip_pim_packets_cmd);
        install_element(CONFIG_NODE, &ip_pim_v6_secondary_cmd);
        install_element(VRF_NODE, &ip_pim_v6_secondary_cmd);
        install_element(CONFIG_NODE, &no_ip_pim_v6_secondary_cmd);
@@ -11731,6 +11385,7 @@ void pim_cmd_init(void)
        /* Install BFD command */
        install_element(INTERFACE_NODE, &ip_pim_bfd_cmd);
        install_element(INTERFACE_NODE, &ip_pim_bfd_param_cmd);
+       install_element(INTERFACE_NODE, &no_ip_pim_bfd_profile_cmd);
        install_element(INTERFACE_NODE, &no_ip_pim_bfd_cmd);
 #if HAVE_BFDD == 0
        install_element(INTERFACE_NODE, &no_ip_pim_bfd_param_cmd);
index 6f5c4174e277827d10788cd9615a6539580ba79d..e48a4bdd4dbe1a38572cc81ca7906c065aaaba20 100644 (file)
@@ -141,14 +141,14 @@ int pim_hello_recv(struct interface *ifp, struct in_addr src_addr,
                on_trace(__func__, ifp, src_addr);
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        ++pim_ifp->pim_ifstat_hello_recv;
 
        /*
          Parse PIM hello TLVs
         */
-       zassert(tlv_buf_size >= 0);
+       assert(tlv_buf_size >= 0);
        tlv_curr = tlv_buf;
        tlv_pastend = tlv_buf + tlv_buf_size;
 
@@ -539,11 +539,11 @@ void pim_hello_require(struct interface *ifp)
 {
        struct pim_interface *pim_ifp;
 
-       zassert(ifp);
+       assert(ifp);
 
        pim_ifp = ifp->info;
 
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        if (pim_ifp->pim_ifstat_hello_sent)
                return;
index 62d19f7619c6b969552e80e9a857418095ee0658..834399053b8d06780a983ea4b69a3944ac26b908 100644 (file)
@@ -115,8 +115,8 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
 {
        struct pim_interface *pim_ifp;
 
-       zassert(ifp);
-       zassert(!ifp->info);
+       assert(ifp);
+       assert(!ifp->info);
 
        pim_ifp = XCALLOC(MTYPE_PIM_INTERFACE, sizeof(*pim_ifp));
 
@@ -145,8 +145,8 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
          The number of seconds represented by the [Query Response Interval]
          must be less than the [Query Interval].
         */
-       zassert(pim_ifp->igmp_query_max_response_time_dsec
-               < pim_ifp->igmp_default_query_interval);
+       assert(pim_ifp->igmp_query_max_response_time_dsec
+              < pim_ifp->igmp_default_query_interval);
 
        if (pim)
                PIM_IF_DO_PIM(pim_ifp->options);
@@ -198,9 +198,9 @@ void pim_if_delete(struct interface *ifp)
        struct pim_interface *pim_ifp;
        struct pim_ifchannel *ch;
 
-       zassert(ifp);
+       assert(ifp);
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        if (pim_ifp->igmp_join_list) {
                pim_if_igmp_join_del_all(ifp);
@@ -238,7 +238,7 @@ void pim_if_update_could_assert(struct interface *ifp)
        struct pim_ifchannel *ch;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
                pim_ifchannel_update_could_assert(ch);
@@ -251,7 +251,7 @@ static void pim_if_update_my_assert_metric(struct interface *ifp)
        struct pim_ifchannel *ch;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
                pim_ifchannel_update_my_assert_metric(ch);
@@ -263,7 +263,7 @@ static void pim_addr_change(struct interface *ifp)
        struct pim_interface *pim_ifp;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        pim_if_dr_election(ifp); /* router's own DR Priority (addr) changes --
                                    Done TODO T30 */
@@ -507,10 +507,10 @@ void pim_if_addr_add(struct connected *ifc)
        struct in_addr ifaddr;
        bool vxlan_term;
 
-       zassert(ifc);
+       assert(ifc);
 
        ifp = ifc->ifp;
-       zassert(ifp);
+       assert(ifp);
        pim_ifp = ifp->info;
        if (!pim_ifp)
                return;
@@ -708,9 +708,9 @@ void pim_if_addr_del(struct connected *ifc, int force_prim_as_any)
 {
        struct interface *ifp;
 
-       zassert(ifc);
+       assert(ifc);
        ifp = ifc->ifp;
-       zassert(ifp);
+       assert(ifp);
 
        if (PIM_DEBUG_ZEBRA)
                zlog_debug("%s: %s ifindex=%d disconnected IP address %pFX %s",
@@ -945,7 +945,7 @@ int pim_if_add_vif(struct interface *ifp, bool ispimreg, bool is_vxlan_term)
        struct in_addr ifaddr;
        unsigned char flags = 0;
 
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        if (pim_ifp->mroute_vif_index > 0) {
                zlog_warn("%s: vif_index=%d > 0 on interface %s ifindex=%d",
@@ -1063,8 +1063,8 @@ int pim_if_lan_delay_enabled(struct interface *ifp)
        struct pim_interface *pim_ifp;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
-       zassert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
+       assert(pim_ifp);
+       assert(pim_ifp->pim_number_of_nonlandelay_neighbors >= 0);
 
        return pim_ifp->pim_number_of_nonlandelay_neighbors == 0;
 }
@@ -1128,7 +1128,7 @@ struct pim_neighbor *pim_if_find_neighbor(struct interface *ifp,
        struct pim_interface *pim_ifp;
        struct prefix p;
 
-       zassert(ifp);
+       assert(ifp);
 
        pim_ifp = ifp->info;
        if (!pim_ifp) {
@@ -1171,7 +1171,7 @@ long pim_if_t_suppressed_msec(struct interface *ifp)
        uint32_t ramount = 0;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        /* join suppression disabled ? */
        if (PIM_IF_TEST_PIM_CAN_DISABLE_JOIN_SUPPRESSION(pim_ifp->options))
@@ -1196,7 +1196,7 @@ static struct igmp_join *igmp_join_find(struct list *join_list,
        struct listnode *node;
        struct igmp_join *ij;
 
-       zassert(join_list);
+       assert(join_list);
 
        for (ALL_LIST_ELEMENTS_RO(join_list, node, ij)) {
                if ((group_addr.s_addr == ij->group_addr.s_addr)
@@ -1245,7 +1245,7 @@ static struct igmp_join *igmp_join_new(struct interface *ifp,
        int join_fd;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        join_fd = igmp_join_sock(ifp->name, ifp->ifindex, group_addr,
                                 source_addr);
@@ -1416,7 +1416,7 @@ void pim_if_assert_on_neighbor_down(struct interface *ifp,
        struct pim_ifchannel *ch;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
                /* Is (S,G,I) assert loser ? */
index 664ab319490daefc704601483ff83d2424a66c4e..92784103fe4e5928e4a506cf39cd6f62fbc6aa71 100644 (file)
@@ -158,9 +158,16 @@ struct pim_interface {
        uint32_t pim_ifstat_bsm_cfg_miss;
        uint32_t pim_ifstat_ucast_bsm_cfg_miss;
        uint32_t pim_ifstat_bsm_invalid_sz;
-       struct bfd_info *bfd_info;
        bool bsm_enable; /* bsm processing enable */
        bool ucast_bsm_accept; /* ucast bsm processing */
+
+       struct {
+               bool enabled;
+               uint32_t min_rx;
+               uint32_t min_tx;
+               uint8_t detection_multiplier;
+               char *profile;
+       } bfd_config;
 };
 
 /*
index cdaf7bcdd403b2c9d28f80d0157c13f0102c73ab..579824c88dce5951d9c483517b0d5702b56e7c13 100644 (file)
@@ -498,7 +498,7 @@ void pim_ifchannel_membership_clear(struct interface *ifp)
        struct pim_ifchannel *ch;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb)
                ifmembership_set(ch, PIM_IFMEMBERSHIP_NOINFO);
@@ -510,7 +510,7 @@ void pim_ifchannel_delete_on_noinfo(struct interface *ifp)
        struct pim_ifchannel *ch, *ch_tmp;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        RB_FOREACH_SAFE (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb, ch_tmp)
                delete_on_noinfo(ch);
@@ -825,7 +825,7 @@ static int nonlocal_upstream(int is_join, struct interface *recv_ifp,
        int is_local; /* boolean */
 
        recv_pim_ifp = recv_ifp->info;
-       zassert(recv_pim_ifp);
+       assert(recv_pim_ifp);
 
        is_local = (upstream.s_addr == recv_pim_ifp->primary_address.s_addr);
 
@@ -913,7 +913,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
        }
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        switch (ch->ifjoin_state) {
        case PIM_IFJOIN_NOINFO:
@@ -939,7 +939,7 @@ void pim_ifchannel_join_add(struct interface *ifp, struct in_addr neigh_addr,
                }
                break;
        case PIM_IFJOIN_JOIN:
-               zassert(!ch->t_ifjoin_prune_pending_timer);
+               assert(!ch->t_ifjoin_prune_pending_timer);
 
                /*
                  In the JOIN state ch->t_ifjoin_expiry_timer may be NULL due to
index 73e42e9d83867785bc9830a3471bb8c787851dca..f2b909e268f223d97ad27ef6e0eafd78bbe408e6 100644 (file)
@@ -159,7 +159,7 @@ static int pim_igmp_other_querier_expire(struct thread *t)
 
        igmp = THREAD_ARG(t);
 
-       zassert(!igmp->t_igmp_query_timer);
+       assert(!igmp->t_igmp_query_timer);
 
        if (PIM_DEBUG_IGMP_TRACE) {
                char ifaddr_str[INET_ADDRSTRLEN];
@@ -185,9 +185,9 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp)
        long other_querier_present_interval_msec;
        struct pim_interface *pim_ifp;
 
-       zassert(igmp);
-       zassert(igmp->interface);
-       zassert(igmp->interface->info);
+       assert(igmp);
+       assert(igmp->interface);
+       assert(igmp->interface->info);
 
        pim_ifp = igmp->interface->info;
 
@@ -218,7 +218,7 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp)
          Since this socket is starting the other-querier-present timer,
          there should not be periodic query timer for this socket.
         */
-       zassert(!igmp->t_igmp_query_timer);
+       assert(!igmp->t_igmp_query_timer);
 
        /*
          RFC 3376: 8.5. Other Querier Present Interval
@@ -255,7 +255,7 @@ void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp)
 
 void pim_igmp_other_querier_timer_off(struct igmp_sock *igmp)
 {
-       zassert(igmp);
+       assert(igmp);
 
        if (PIM_DEBUG_IGMP_TRACE) {
                if (igmp->t_other_querier_timer) {
@@ -589,9 +589,9 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp)
          Since this socket is starting as querier,
          there should not exist a timer for other-querier-present.
         */
-       zassert(!igmp->t_other_querier_timer);
+       assert(!igmp->t_other_querier_timer);
        pim_ifp = igmp->interface->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        /*
          RFC 3376: 8.6. Startup Query Interval
@@ -638,7 +638,7 @@ void pim_igmp_general_query_on(struct igmp_sock *igmp)
 
 void pim_igmp_general_query_off(struct igmp_sock *igmp)
 {
-       zassert(igmp);
+       assert(igmp);
 
        if (PIM_DEBUG_IGMP_TRACE) {
                if (igmp->t_igmp_query_timer) {
@@ -664,8 +664,8 @@ static int pim_igmp_general_query(struct thread *t)
 
        igmp = THREAD_ARG(t);
 
-       zassert(igmp->interface);
-       zassert(igmp->interface->info);
+       assert(igmp->interface);
+       assert(igmp->interface->info);
 
        pim_ifp = igmp->interface->info;
 
@@ -835,19 +835,19 @@ void igmp_group_delete(struct igmp_group *group)
 
 void igmp_group_delete_empty_include(struct igmp_group *group)
 {
-       zassert(!group->group_filtermode_isexcl);
-       zassert(!listcount(group->group_source_list));
+       assert(!group->group_filtermode_isexcl);
+       assert(!listcount(group->group_source_list));
 
        igmp_group_delete(group);
 }
 
 void igmp_sock_free(struct igmp_sock *igmp)
 {
-       zassert(!igmp->t_igmp_read);
-       zassert(!igmp->t_igmp_query_timer);
-       zassert(!igmp->t_other_querier_timer);
-       zassert(igmp->igmp_group_list);
-       zassert(!listcount(igmp->igmp_group_list));
+       assert(!igmp->t_igmp_read);
+       assert(!igmp->t_igmp_query_timer);
+       assert(!igmp->t_other_querier_timer);
+       assert(igmp->igmp_group_list);
+       assert(!listcount(igmp->igmp_group_list));
 
        list_delete(&igmp->igmp_group_list);
        hash_free(igmp->igmp_group_hash);
@@ -1076,7 +1076,7 @@ static int igmp_group_timer(struct thread *t)
                           group_str, group->group_igmp_sock->interface->name);
        }
 
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        group->group_filtermode_isexcl = 0;
 
@@ -1085,7 +1085,7 @@ static int igmp_group_timer(struct thread *t)
 
        igmp_source_delete_expired(group->group_source_list);
 
-       zassert(!group->group_filtermode_isexcl);
+       assert(!group->group_filtermode_isexcl);
 
        /*
          RFC 3376: 6.2.2. Definition of Group Timers
@@ -1137,7 +1137,7 @@ void igmp_group_timer_on(struct igmp_group *group, long interval_msec,
          it represents the time for the *filter-mode* of the group to
          expire and switch to INCLUDE mode.
        */
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        thread_add_timer_msec(router->master, igmp_group_timer, group,
                              interval_msec, &group->t_group_timer);
@@ -1228,8 +1228,8 @@ struct igmp_group *igmp_add_group_by_addr(struct igmp_sock *igmp,
          it represents the time for the *filter-mode* of the group to
          expire and switch to INCLUDE mode.
        */
-       zassert(!group->group_filtermode_isexcl); /* INCLUDE mode */
-       zassert(!group->t_group_timer);           /* group timer == 0 */
+       assert(!group->group_filtermode_isexcl); /* INCLUDE mode */
+       assert(!group->t_group_timer);           /* group timer == 0 */
 
        /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
        igmp_anysource_forward_stop(group);
index 7f3c7a0f8cb8c0902b6d42b8e9fbfe764b8a924b..6eadf87c83637d13989e0cbc9819a5ef652a6937 100644 (file)
@@ -54,7 +54,7 @@ void igmp_v2_send_query(struct igmp_group *group, int fd, const char *ifname,
        /* max_resp_code must be non-zero else this will look like an IGMP v1
         * query */
        max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec);
-       zassert(max_resp_code > 0);
+       assert(max_resp_code > 0);
 
        query_buf[0] = PIM_IGMP_MEMBERSHIP_QUERY;
        query_buf[1] = max_resp_code;
index 425adfe166686c58ef14b814b6dc2b34bbacefa9..3ae7744eb0adb37e3ad75ebc8dcc5eedb5e3e4a4 100644 (file)
@@ -103,7 +103,7 @@ void igmp_group_reset_gmi(struct igmp_group *group)
          it represents the time for the *filter-mode* of the group to
          expire and switch to INCLUDE mode.
        */
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        igmp_group_timer_on(group, group_membership_interval_msec, ifp->name);
 }
@@ -314,7 +314,7 @@ static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group)
 {
        struct pim_interface *pim_ifp = group->group_igmp_sock->interface->info;
 
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        if (listcount(group->group_source_list) < 1) {
                igmp_anysource_forward_start(pim_ifp->pim, group);
@@ -324,7 +324,7 @@ static void group_exclude_fwd_anysrc_ifempty(struct igmp_group *group)
 void igmp_source_free(struct igmp_source *source)
 {
        /* make sure there is no source timer running */
-       zassert(!source->t_source_timer);
+       assert(!source->t_source_timer);
 
        XFREE(MTYPE_PIM_IGMP_GROUP_SOURCE, source);
 }
@@ -557,7 +557,7 @@ static void isex_excl(struct igmp_group *group, int num_sources,
        int i;
 
        /* EXCLUDE mode */
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        /* E.1: set deletion flag for known sources (X,Y) */
        source_mark_delete_flag(group);
@@ -577,10 +577,10 @@ static void isex_excl(struct igmp_group *group, int num_sources,
                        /* E.4: if not found, create source with timer=GMI:
                         * (A-X-Y) */
                        source = source_new(group, *src_addr);
-                       zassert(!source->t_source_timer); /* timer == 0 */
+                       assert(!source->t_source_timer); /* timer == 0 */
                        igmp_source_reset_gmi(group->group_igmp_sock, group,
                                              source);
-                       zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
+                       assert(source->t_source_timer); /* (A-X-Y) timer > 0 */
                }
 
        } /* scan received sources */
@@ -610,7 +610,7 @@ static void isex_incl(struct igmp_group *group, int num_sources,
        int i;
 
        /* INCLUDE mode */
-       zassert(!group->group_filtermode_isexcl);
+       assert(!group->group_filtermode_isexcl);
 
        /* I.1: set deletion flag for known sources (A) */
        source_mark_delete_flag(group);
@@ -631,7 +631,7 @@ static void isex_incl(struct igmp_group *group, int num_sources,
                        /* I.4: if not found, create source with timer=0 (B-A)
                         */
                        source = source_new(group, *src_addr);
-                       zassert(!source->t_source_timer); /* (B-A) timer=0 */
+                       assert(!source->t_source_timer); /* (B-A) timer=0 */
                }
 
        } /* scan received sources */
@@ -641,7 +641,7 @@ static void isex_incl(struct igmp_group *group, int num_sources,
 
        group->group_filtermode_isexcl = 1; /* boolean=true */
 
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        group_exclude_fwd_anysrc_ifempty(group);
 }
@@ -675,10 +675,10 @@ void igmpv3_report_isex(struct igmp_sock *igmp, struct in_addr from,
        } else {
                /* INCLUDE mode */
                isex_incl(group, num_sources, sources);
-               zassert(group->group_filtermode_isexcl);
+               assert(group->group_filtermode_isexcl);
        }
 
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        igmp_group_reset_gmi(group);
 }
@@ -807,7 +807,7 @@ static void toex_incl(struct igmp_group *group, int num_sources,
        int num_sources_tosend = 0;
        int i;
 
-       zassert(!group->group_filtermode_isexcl);
+       assert(!group->group_filtermode_isexcl);
 
        /* Set DELETE flag for all known sources (A) */
        source_mark_delete_flag(group);
@@ -834,7 +834,7 @@ static void toex_incl(struct igmp_group *group, int num_sources,
                        /* If source not found, create source with timer=0:
                         * (B-A)=0 */
                        source = source_new(group, *src_addr);
-                       zassert(!source->t_source_timer); /* (B-A) timer=0 */
+                       assert(!source->t_source_timer); /* (B-A) timer=0 */
                }
 
        } /* Scan received sources (B) */
@@ -849,7 +849,7 @@ static void toex_incl(struct igmp_group *group, int num_sources,
                source_query_send_by_flag(group, num_sources_tosend);
        }
 
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        group_exclude_fwd_anysrc_ifempty(group);
 }
@@ -894,17 +894,17 @@ static void toex_excl(struct igmp_group *group, int num_sources,
                        long group_timer_msec;
                        source = source_new(group, *src_addr);
 
-                       zassert(!source->t_source_timer); /* timer == 0 */
+                       assert(!source->t_source_timer); /* timer == 0 */
                        group_timer_msec = igmp_group_timer_remain_msec(group);
                        igmp_source_timer_on(group, source, group_timer_msec);
-                       zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
+                       assert(source->t_source_timer); /* (A-X-Y) timer > 0 */
 
                        /* make sure source is created with DELETE flag unset */
-                       zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
+                       assert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
                }
 
                /* make sure reported source has DELETE flag unset */
-               zassert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
+               assert(!IGMP_SOURCE_TEST_DELETE(source->source_flags));
 
                if (source->t_source_timer) {
                        /* if source timer>0 mark SEND flag: Q(G,A-Y) */
@@ -948,9 +948,9 @@ void igmpv3_report_toex(struct igmp_sock *igmp, struct in_addr from,
        } else {
                /* INCLUDE mode */
                toex_incl(group, num_sources, sources);
-               zassert(group->group_filtermode_isexcl);
+               assert(group->group_filtermode_isexcl);
        }
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        /* Group Timer=GMI */
        igmp_group_reset_gmi(group);
@@ -1347,7 +1347,7 @@ static void source_query_send_by_flag(struct igmp_group *group,
        long lmqi_msec; /* Last Member Query Interval */
        long lmqt_msec; /* Last Member Query Time */
 
-       zassert(num_sources_tosend > 0);
+       assert(num_sources_tosend > 0);
 
        igmp = group->group_igmp_sock;
        pim_ifp = igmp->interface->info;
@@ -1408,10 +1408,10 @@ static void block_excl(struct igmp_group *group, int num_sources,
                        long group_timer_msec;
                        source = source_new(group, *src_addr);
 
-                       zassert(!source->t_source_timer); /* timer == 0 */
+                       assert(!source->t_source_timer); /* timer == 0 */
                        group_timer_msec = igmp_group_timer_remain_msec(group);
                        igmp_source_timer_on(group, source, group_timer_msec);
-                       zassert(source->t_source_timer); /* (A-X-Y) timer > 0 */
+                       assert(source->t_source_timer); /* (A-X-Y) timer > 0 */
                }
 
                if (source->t_source_timer) {
@@ -1523,7 +1523,7 @@ void igmp_group_timer_lower_to_lmqt(struct igmp_group *group)
                        lmqt_msec);
        }
 
-       zassert(group->group_filtermode_isexcl);
+       assert(group->group_filtermode_isexcl);
 
        igmp_group_timer_on(group, lmqt_msec, ifname);
 }
@@ -1581,7 +1581,7 @@ void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname,
        socklen_t tolen;
        uint16_t checksum;
 
-       zassert(num_sources >= 0);
+       assert(num_sources >= 0);
 
        msg_size = IGMP_V3_SOURCES_OFFSET + (num_sources << 2);
        if (msg_size > query_buf_size) {
@@ -1593,7 +1593,7 @@ void igmp_v3_send_query(struct igmp_group *group, int fd, const char *ifname,
        }
 
        s_flag = PIM_FORCE_BOOLEAN(s_flag);
-       zassert((s_flag == 0) || (s_flag == 1));
+       assert((s_flag == 0) || (s_flag == 1));
 
        max_resp_code = igmp_msg_encode16to8(query_max_response_time_dsec);
        qqic = igmp_msg_encode16to8(querier_query_interval);
index 2766a6d2b51e9d5e0c376c2b8cf0dec48bb3c810..c7a80ca8e05f7a7868eb5c083a0b6586d5be3259 100644 (file)
@@ -71,7 +71,7 @@ static void recv_join(struct interface *ifp, struct pim_neighbor *neigh,
        }
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        ++pim_ifp->pim_ifstat_join_recv;
 
@@ -134,7 +134,7 @@ static void recv_prune(struct interface *ifp, struct pim_neighbor *neigh,
        }
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        ++pim_ifp->pim_ifstat_prune_recv;
 
index 70c233848a8b1ae601e90b3302e32a43de013122..96132c44256d214eebc93f65482a78e34f37d9c2 100644 (file)
@@ -21,7 +21,7 @@
 
 #include "log.h"
 #include "privs.h"
-#include "version.h"
+#include "lib/version.h"
 #include <getopt.h>
 #include "command.h"
 #include "thread.h"
@@ -32,7 +32,7 @@
 #include "filter.h"
 #include "vty.h"
 #include "sigevent.h"
-#include "version.h"
+#include "lib/version.h"
 #include "prefix.h"
 #include "plist.h"
 #include "vrf.h"
index 7336cdfef8b8c6c2962e81a0fb0217194b084553..9cf73c38c3aba6570cdb1d69fb0a58ec3955e954 100644 (file)
@@ -1562,6 +1562,26 @@ int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty,
        return count;
 }
 
+bool pim_msdp_peer_config_write(struct vty *vty, struct pim_instance *pim,
+                               const char *spaces)
+{
+       struct pim_msdp_peer *mp;
+       struct listnode *node;
+       bool written = false;
+
+       for (ALL_LIST_ELEMENTS_RO(pim->msdp.peer_list, node, mp)) {
+               /* Non meshed peers have the group name set to 'default'. */
+               if (strcmp(mp->mesh_group_name, "default"))
+                       continue;
+
+               vty_out(vty, "%sip msdp peer %pI4 source %pI4\n", spaces,
+                       &mp->peer, &mp->local);
+               written = true;
+       }
+
+       return written;
+}
+
 /* Enable feature including active/periodic timers etc. on the first peer
  * config. Till then MSDP should just stay quiet. */
 static void pim_msdp_enable(struct pim_instance *pim)
index 15a1041e2181f771f48325def6a4177472d4df02..4d01880fbfc46cfe6e7b4ba67ca353352a525b81 100644 (file)
@@ -234,6 +234,8 @@ char *pim_msdp_peer_key_dump(struct pim_msdp_peer *mp, char *buf, int buf_size,
                             bool long_format);
 int pim_msdp_config_write(struct pim_instance *pim, struct vty *vty,
                          const char *spaces);
+bool pim_msdp_peer_config_write(struct vty *vty, struct pim_instance *pim,
+                               const char *spaces);
 void pim_msdp_peer_pkt_txed(struct pim_msdp_peer *mp);
 void pim_msdp_sa_ref(struct pim_instance *pim, struct pim_msdp_peer *mp,
                     struct prefix_sg *sg, struct in_addr rp);
index 8ca0e0780b56399f4cd46d8cc12185e8680a2cde..37c539883d643c7a25d755f441462f47d0a3f675 100644 (file)
@@ -258,6 +258,13 @@ const struct frr_yang_module_info frr_pim_info = {
                                .modify = lib_interface_pim_bfd_detect_mult_modify,
                        }
                },
+               {
+                       .xpath = "/frr-interface:lib/interface/frr-pim:pim/bfd/profile",
+                       .cbs = {
+                               .modify = lib_interface_pim_bfd_profile_modify,
+                               .destroy = lib_interface_pim_bfd_profile_destroy,
+                       }
+               },
                {
                        .xpath = "/frr-interface:lib/interface/frr-pim:pim/bsm",
                        .cbs = {
index 78eb6801036800771ccefc2a2fa81d18aad0dce5..440384e45ccd583b6a7d02c1a287a395786cec69 100644 (file)
@@ -121,6 +121,8 @@ int lib_interface_pim_bfd_min_rx_interval_modify(struct nb_cb_modify_args *args)
 int lib_interface_pim_bfd_min_tx_interval_modify(
        struct nb_cb_modify_args *args);
 int lib_interface_pim_bfd_detect_mult_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_bfd_profile_modify(struct nb_cb_modify_args *args);
+int lib_interface_pim_bfd_profile_destroy(struct nb_cb_destroy_args *args);
 int lib_interface_pim_bsm_modify(struct nb_cb_modify_args *args);
 int lib_interface_pim_unicast_bsm_modify(struct nb_cb_modify_args *args);
 int lib_interface_pim_active_active_modify(struct nb_cb_modify_args *args);
index 475e393cf0aadd8027879a80e376f430c8da44e2..4598297f93b3c7e93689583caec7d80a85bcd8be 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "pimd.h"
 #include "pim_nb.h"
 #include "lib/northbound_cli.h"
@@ -36,7 +38,7 @@ static void pim_if_membership_clear(struct interface *ifp)
        struct pim_interface *pim_ifp;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        if (PIM_IF_TEST_PIM(pim_ifp->options)
            && PIM_IF_TEST_IGMP(pim_ifp->options)) {
@@ -62,7 +64,7 @@ static void pim_if_membership_refresh(struct interface *ifp)
        struct igmp_sock *igmp;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        if (!PIM_IF_TEST_PIM(pim_ifp->options))
                return;
@@ -576,7 +578,7 @@ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
        struct interface *ifp;
        struct pim_interface *pim_ifp;
 
-       zassert(igmp);
+       assert(igmp);
 
        /* other querier present? */
 
@@ -585,8 +587,8 @@ static void igmp_sock_query_interval_reconfig(struct igmp_sock *igmp)
 
        /* this is the querier */
 
-       zassert(igmp->interface);
-       zassert(igmp->interface->info);
+       assert(igmp->interface);
+       assert(igmp->interface->info);
 
        ifp = igmp->interface;
        pim_ifp = ifp->info;
@@ -616,25 +618,25 @@ static void igmp_sock_query_reschedule(struct igmp_sock *igmp)
 
        if (igmp->t_igmp_query_timer) {
                /* other querier present */
-               zassert(igmp->t_igmp_query_timer);
-               zassert(!igmp->t_other_querier_timer);
+               assert(igmp->t_igmp_query_timer);
+               assert(!igmp->t_other_querier_timer);
 
                pim_igmp_general_query_off(igmp);
                pim_igmp_general_query_on(igmp);
 
-               zassert(igmp->t_igmp_query_timer);
-               zassert(!igmp->t_other_querier_timer);
+               assert(igmp->t_igmp_query_timer);
+               assert(!igmp->t_other_querier_timer);
        } else {
                /* this is the querier */
 
-               zassert(!igmp->t_igmp_query_timer);
-               zassert(igmp->t_other_querier_timer);
+               assert(!igmp->t_igmp_query_timer);
+               assert(igmp->t_other_querier_timer);
 
                pim_igmp_other_querier_timer_off(igmp);
                pim_igmp_other_querier_timer_on(igmp);
 
-               zassert(!igmp->t_igmp_query_timer);
-               zassert(igmp->t_other_querier_timer);
+               assert(!igmp->t_igmp_query_timer);
+               assert(igmp->t_other_querier_timer);
        }
 }
 
@@ -755,18 +757,14 @@ int pim_join_prune_interval_modify(struct nb_cb_modify_args *args)
  */
 int pim_register_suppress_time_modify(struct nb_cb_modify_args *args)
 {
-       struct vrf *vrf;
-       struct pim_instance *pim;
-
        switch (args->event) {
        case NB_EV_VALIDATE:
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
                break;
        case NB_EV_APPLY:
-               vrf = nb_running_get_entry(args->dnode, NULL, true);
-               pim = vrf->info;
-               pim->keep_alive_time = yang_dnode_get_uint16(args->dnode, NULL);
+               pim_update_suppress_timers(
+                       yang_dnode_get_uint16(args->dnode, NULL));
                break;
        }
 
@@ -1886,11 +1884,19 @@ int lib_interface_pim_hello_holdtime_destroy(struct nb_cb_destroy_args *args)
  */
 int lib_interface_pim_bfd_create(struct nb_cb_create_args *args)
 {
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+
        switch (args->event) {
        case NB_EV_VALIDATE:
        case NB_EV_PREPARE:
        case NB_EV_ABORT:
+               /* NOTHING */
+               break;
        case NB_EV_APPLY:
+               ifp = nb_running_get_entry(args->dnode, NULL, true);
+               pim_ifp = ifp->info;
+               pim_ifp->bfd_config.enabled = true;
                break;
        }
 
@@ -1916,13 +1922,10 @@ int lib_interface_pim_bfd_destroy(struct nb_cb_destroy_args *args)
        case NB_EV_PREPARE:
                break;
        case NB_EV_APPLY:
-               ifp = nb_running_get_entry(args->dnode->parent, NULL, true);
+               ifp = nb_running_get_entry(args->dnode, NULL, true);
                pim_ifp = ifp->info;
-               if (pim_ifp->bfd_info) {
-                       pim_bfd_reg_dereg_all_nbr(ifp,
-                                       ZEBRA_BFD_DEST_DEREGISTER);
-                       bfd_info_free(&(pim_ifp->bfd_info));
-               }
+               pim_ifp->bfd_config.enabled = false;
+               pim_bfd_reg_dereg_all_nbr(ifp);
                break;
        }
 
@@ -1936,11 +1939,8 @@ void lib_interface_pim_bfd_apply_finish(struct nb_cb_apply_finish_args *args)
 {
        struct interface *ifp;
        struct pim_interface *pim_ifp;
-       uint32_t min_rx;
-       uint32_t min_tx;
-       uint8_t detect_mult;
 
-       ifp = nb_running_get_entry(args->dnode->parent, NULL, true);
+       ifp = nb_running_get_entry(args->dnode, NULL, true);
        pim_ifp = ifp->info;
 
        if (!pim_ifp) {
@@ -1948,17 +1948,14 @@ void lib_interface_pim_bfd_apply_finish(struct nb_cb_apply_finish_args *args)
                return;
        }
 
-       min_rx = yang_dnode_get_uint16(args->dnode, "./min-rx-interval");
-       min_tx = yang_dnode_get_uint16(args->dnode, "./min-tx-interval");
-       detect_mult = yang_dnode_get_uint8(args->dnode, "./detect_mult");
-
-       if ((min_rx == BFD_DEF_MIN_RX) && (min_tx == BFD_DEF_MIN_TX)
-                       && (detect_mult == BFD_DEF_DETECT_MULT))
-               pim_bfd_if_param_set(ifp, min_rx, min_tx, detect_mult, 1);
-       else
-               pim_bfd_if_param_set(ifp, min_rx, min_tx, detect_mult, 0);
+       pim_ifp->bfd_config.detection_multiplier =
+               yang_dnode_get_uint8(args->dnode, "./detect_mult");
+       pim_ifp->bfd_config.min_rx =
+               yang_dnode_get_uint16(args->dnode, "./min-rx-interval");
+       pim_ifp->bfd_config.min_tx =
+               yang_dnode_get_uint16(args->dnode, "./min-tx-interval");
 
-       nb_running_set_entry(args->dnode, pim_ifp->bfd_info);
+       pim_bfd_reg_dereg_all_nbr(ifp);
 }
 
 /*
@@ -2009,6 +2006,53 @@ int lib_interface_pim_bfd_detect_mult_modify(struct nb_cb_modify_args *args)
        return NB_OK;
 }
 
+/*
+ * XPath: /frr-interface:lib/interface/frr-pim:pim/bfd/profile
+ */
+int lib_interface_pim_bfd_profile_modify(struct nb_cb_modify_args *args)
+{
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+       case NB_EV_PREPARE:
+       case NB_EV_ABORT:
+               /* NOTHING */
+               break;
+       case NB_EV_APPLY:
+               ifp = nb_running_get_entry(args->dnode, NULL, true);
+               pim_ifp = ifp->info;
+               XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
+               pim_ifp->bfd_config.profile = XSTRDUP(
+                       MTYPE_TMP, yang_dnode_get_string(args->dnode, NULL));
+               break;
+       }
+
+       return NB_OK;
+}
+
+int lib_interface_pim_bfd_profile_destroy(struct nb_cb_destroy_args *args)
+{
+       struct interface *ifp;
+       struct pim_interface *pim_ifp;
+
+       switch (args->event) {
+       case NB_EV_VALIDATE:
+       case NB_EV_PREPARE:
+       case NB_EV_ABORT:
+               /* NOTHING */
+               break;
+       case NB_EV_APPLY:
+               ifp = nb_running_get_entry(args->dnode, NULL, true);
+               pim_ifp = ifp->info;
+               XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
+               break;
+       }
+
+       return NB_OK;
+}
+
 /*
  * XPath: /frr-interface:lib/interface/frr-pim:pim/bsm
  */
index 167aa3c604377a4843f1a7781d9d3104340eaada..48b1a30f2d8c4bb9f6a6d78c69ef9c0a8ad0aaa7 100644 (file)
@@ -49,7 +49,7 @@ static void dr_election_by_addr(struct interface *ifp)
        struct pim_neighbor *neigh;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        pim_ifp->pim_dr_addr = pim_ifp->primary_address;
 
@@ -73,7 +73,7 @@ static void dr_election_by_pri(struct interface *ifp)
        uint32_t dr_pri;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        pim_ifp->pim_dr_addr = pim_ifp->primary_address;
        dr_pri = pim_ifp->pim_dr_priority;
@@ -310,9 +310,9 @@ pim_neighbor_new(struct interface *ifp, struct in_addr source_addr,
        struct pim_neighbor *neigh;
        char src_str[INET_ADDRSTRLEN];
 
-       zassert(ifp);
+       assert(ifp);
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        neigh = XCALLOC(MTYPE_PIM_NEIGHBOR, sizeof(*neigh));
 
@@ -377,7 +377,7 @@ pim_neighbor_new(struct interface *ifp, struct in_addr source_addr,
        }
 
        // Register PIM Neighbor with BFD
-       pim_bfd_trigger_event(pim_ifp, neigh, 1);
+       pim_bfd_info_nbr_create(pim_ifp, neigh);
 
        return neigh;
 }
@@ -412,15 +412,14 @@ static void delete_prefix_list(struct pim_neighbor *neigh)
 
 void pim_neighbor_free(struct pim_neighbor *neigh)
 {
-       zassert(!neigh->t_expire_timer);
+       assert(!neigh->t_expire_timer);
 
        delete_prefix_list(neigh);
 
        list_delete(&neigh->upstream_jp_agg);
        THREAD_OFF(neigh->jp_timer);
 
-       if (neigh->bfd_info)
-               pim_bfd_info_free(&neigh->bfd_info);
+       bfd_sess_free(&neigh->bfd_session);
 
        XFREE(MTYPE_PIM_NEIGHBOR, neigh);
 }
@@ -504,7 +503,7 @@ pim_neighbor_add(struct interface *ifp, struct in_addr source_addr,
        }
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        listnode_add(pim_ifp->pim_neighbor_list, neigh);
 
@@ -567,7 +566,7 @@ static uint16_t find_neighbors_next_highest_propagation_delay_msec(
        uint16_t next_highest_delay_msec;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        next_highest_delay_msec = pim_ifp->pim_propagation_delay_msec;
 
@@ -591,7 +590,7 @@ static uint16_t find_neighbors_next_highest_override_interval_msec(
        uint16_t next_highest_interval_msec;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        next_highest_interval_msec = pim_ifp->pim_override_interval_msec;
 
@@ -614,7 +613,7 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
        char src_str[INET_ADDRSTRLEN];
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        pim_inet4_dump("<src?>", neigh->source_addr, src_str, sizeof(src_str));
        zlog_info("PIM NEIGHBOR DOWN: neighbor %s on interface %s: %s", src_str,
@@ -638,10 +637,10 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
                --pim_ifp->pim_dr_num_nondrpri_neighbors;
        }
 
-       zassert(neigh->propagation_delay_msec
-               <= pim_ifp->pim_neighbors_highest_propagation_delay_msec);
-       zassert(neigh->override_interval_msec
-               <= pim_ifp->pim_neighbors_highest_override_interval_msec);
+       assert(neigh->propagation_delay_msec
+              <= pim_ifp->pim_neighbors_highest_propagation_delay_msec);
+       assert(neigh->override_interval_msec
+              <= pim_ifp->pim_neighbors_highest_override_interval_msec);
 
        if (pim_if_lan_delay_enabled(ifp)) {
 
@@ -669,9 +668,6 @@ void pim_neighbor_delete(struct interface *ifp, struct pim_neighbor *neigh,
                           __func__, src_str, ifp->name);
        }
 
-       // De-Register PIM Neighbor with BFD
-       pim_bfd_trigger_event(pim_ifp, neigh, 0);
-
        listnode_delete(pim_ifp->pim_neighbor_list, neigh);
 
        pim_neighbor_free(neigh);
@@ -687,7 +683,7 @@ void pim_neighbor_delete_all(struct interface *ifp, const char *delete_message)
        struct pim_neighbor *neigh;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        for (ALL_LIST_ELEMENTS(pim_ifp->pim_neighbor_list, neigh_node,
                               neigh_nextnode, neigh)) {
@@ -732,9 +728,9 @@ static void delete_from_neigh_addr(struct interface *ifp,
        struct pim_interface *pim_ifp;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
-       zassert(addr_list);
+       assert(addr_list);
 
        /*
          Scan secondary address list
index a4f2e10c8812241ebba1a5513e968dc5c4415584..b461098a602d8274656071fc01a72239f5ac1ea8 100644 (file)
@@ -43,7 +43,7 @@ struct pim_neighbor {
 
        struct thread *jp_timer;
        struct list *upstream_jp_agg;
-       struct bfd_info *bfd_info;
+       struct bfd_session_params *bfd_session;
 };
 
 void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime);
index 3ec0720fc4e53478aa0b901721680b41356d924a..0a4e3e1a6f6ab0ee14f742da08fbe0002cdbaa4e 100644 (file)
@@ -219,8 +219,8 @@ int pim_channel_del_oif(struct channel_oil *channel_oil, struct interface *oif,
 {
        struct pim_interface *pim_ifp;
 
-       zassert(channel_oil);
-       zassert(oif);
+       assert(channel_oil);
+       assert(oif);
 
        pim_ifp = oif->info;
 
index 2ccff8b84a51d09073c06432cd6a2cdd9ae475d8..4ba08a19d8e0ebcfa287e1ea12ad5b328775fced 100644 (file)
@@ -407,8 +407,8 @@ static void pim_sock_read_on(struct interface *ifp)
 {
        struct pim_interface *pim_ifp;
 
-       zassert(ifp);
-       zassert(ifp->info);
+       assert(ifp);
+       assert(ifp->info);
 
        pim_ifp = ifp->info;
 
@@ -444,7 +444,7 @@ void pim_ifstat_reset(struct interface *ifp)
 {
        struct pim_interface *pim_ifp;
 
-       zassert(ifp);
+       assert(ifp);
 
        pim_ifp = ifp->info;
        if (!pim_ifp) {
@@ -462,8 +462,8 @@ void pim_sock_reset(struct interface *ifp)
 {
        struct pim_interface *pim_ifp;
 
-       zassert(ifp);
-       zassert(ifp->info);
+       assert(ifp);
+       assert(ifp->info);
 
        pim_ifp = ifp->info;
 
@@ -671,8 +671,8 @@ static int hello_send(struct interface *ifp, uint16_t holdtime)
 
        pim_msg_size = pim_tlv_size + PIM_PIM_MIN_LEN;
 
-       zassert(pim_msg_size >= PIM_PIM_MIN_LEN);
-       zassert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
+       assert(pim_msg_size >= PIM_PIM_MIN_LEN);
+       assert(pim_msg_size <= PIM_PIM_BUFSIZE_WRITE);
 
        pim_msg_build_header(pim_msg, pim_msg_size, PIM_MSG_TYPE_HELLO, false);
 
@@ -846,7 +846,7 @@ int pim_sock_add(struct interface *ifp)
        uint32_t old_genid;
 
        pim_ifp = ifp->info;
-       zassert(pim_ifp);
+       assert(pim_ifp);
 
        if (pim_ifp->pim_sock_fd >= 0) {
                if (PIM_DEBUG_PIM_PACKETS)
index dbba6b66d89b0ff98eae3601692e8a5f20e4bf98..feaeea929d7dca5dd61861ce64eda32b3c0503f3 100644 (file)
@@ -702,7 +702,7 @@ int pim_rp_del(struct pim_instance *pim, struct in_addr rp_addr,
                bsgrp = pim_bsm_get_bsgrp_node(&pim->global_scope, &group);
 
                if (bsgrp) {
-                       bsrp = listnode_head(bsgrp->bsrp_list);
+                       bsrp = bsm_rpinfos_first(bsgrp->bsrp_list);
                        if (bsrp) {
                                if (PIM_DEBUG_PIM_TRACE) {
                                        char bsrp_str[INET_ADDRSTRLEN];
index f4d3547b3faa009c7e08873bddc2b5b315425b41..03e77de161f33b45aa4cd5aebf98db2a60d35296 100644 (file)
@@ -41,12 +41,12 @@ void pim_ssmpingd_init(struct pim_instance *pim)
 {
        int result;
 
-       zassert(!pim->ssmpingd_list);
+       assert(!pim->ssmpingd_list);
 
        result = inet_pton(AF_INET, PIM_SSMPINGD_REPLY_GROUP,
                           &pim->ssmpingd_group_addr);
 
-       zassert(result > 0);
+       assert(result > 0);
 }
 
 void pim_ssmpingd_destroy(struct pim_instance *pim)
@@ -197,7 +197,7 @@ static int ssmpingd_socket(struct in_addr addr, int port, int mttl)
 
 static void ssmpingd_delete(struct ssmpingd_sock *ss)
 {
-       zassert(ss);
+       assert(ss);
 
        THREAD_OFF(ss->t_sock_read);
 
index 9878fcf6b401f30ad7a73e46d687060609eb8d81..c88ee7554b5c2d9a94fad1f7f578180b2e519bc2 100644 (file)
@@ -106,7 +106,7 @@ int pim_time_mmss(char *buf, int buf_size, long sec)
        long mm;
        int wr;
 
-       zassert(buf_size >= 5);
+       assert(buf_size >= 5);
 
        mm = sec / 60;
        sec %= 60;
@@ -122,7 +122,7 @@ static int pim_time_hhmmss(char *buf, int buf_size, long sec)
        long mm;
        int wr;
 
-       zassert(buf_size >= 8);
+       assert(buf_size >= 8);
 
        hh = sec / 3600;
        sec %= 3600;
@@ -156,7 +156,7 @@ void pim_time_timer_to_hhmmss(char *buf, int buf_size, struct thread *t_timer)
 
 void pim_time_uptime(char *buf, int buf_size, int64_t uptime_sec)
 {
-       zassert(buf_size >= 8);
+       assert(buf_size >= 8);
 
        pim_time_hhmmss(buf, buf_size, uptime_sec);
 }
index 633bb207bd6d6449b31dd14bed9ec0a0ed3b97d2..f21c369b8d84f20fe5516ee99d154a33a4aef507 100644 (file)
@@ -662,7 +662,7 @@ int pim_tlv_parse_addr_list(const char *ifname, struct in_addr src_addr,
        const uint8_t *addr;
        const uint8_t *pastend;
 
-       zassert(hello_option_addr_list);
+       assert(hello_option_addr_list);
 
        /*
          Scan addr list
index 9899172e6cefca138b8cdcaef8ee48bec42b59a7..918a9a9c7d7630e6f8840b22da3c279cbcf03000 100644 (file)
@@ -407,6 +407,28 @@ static void pim_upstream_join_timer_restart_msec(struct pim_upstream *up,
                              &up->t_join_timer);
 }
 
+void pim_update_suppress_timers(uint32_t suppress_time)
+{
+       struct pim_instance *pim;
+       struct vrf *vrf;
+       unsigned int old_rp_ka_time;
+
+       /* stash the old one so we know which values were manually configured */
+       old_rp_ka_time =  (3 * router->register_suppress_time
+                          + router->register_probe_time);
+       router->register_suppress_time = suppress_time;
+
+       RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name) {
+               pim = vrf->info;
+               if (!pim)
+                       continue;
+
+               /* Only adjust if not manually configured */
+               if (pim->rp_keep_alive_time == old_rp_ka_time)
+                       pim->rp_keep_alive_time = PIM_RP_KEEPALIVE_PERIOD;
+       }
+}
+
 void pim_upstream_join_suppress(struct pim_upstream *up,
                                struct in_addr rpf_addr, int holdtime)
 {
index adea3cd9efa25fd76b139b87f66a4f646b3e0ebe..56039d56057b02310d3bb622852dbfdaace0d6af 100644 (file)
@@ -317,6 +317,7 @@ int pim_upstream_eval_inherit_if(struct pim_upstream *up,
 void pim_upstream_update_join_desired(struct pim_instance *pim,
                                      struct pim_upstream *up);
 
+void pim_update_suppress_timers(uint32_t suppress_time);
 void pim_upstream_join_suppress(struct pim_upstream *up,
                                struct in_addr rpf_addr, int holdtime);
 
index 57a0c691661a18664aa0a2ec4cab1242e064e5ed..929d35101ea84cc024a34d9e6ec9a6cae7236941 100644 (file)
@@ -176,6 +176,7 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
        else
                snprintf(spaces, sizeof(spaces), "%s", " ");
 
+       writes += pim_msdp_peer_config_write(vty, pim, spaces);
        writes += pim_msdp_config_write(pim, vty, spaces);
 
        if (!pim->send_v6_secondary) {
@@ -185,16 +186,24 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
 
        writes += pim_rp_config_write(pim, vty, spaces);
 
-       if (router->register_suppress_time
-           != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) {
-               vty_out(vty, "%sip pim register-suppress-time %d\n", spaces,
-                       router->register_suppress_time);
-               ++writes;
-       }
-       if (router->t_periodic != PIM_DEFAULT_T_PERIODIC) {
-               vty_out(vty, "%sip pim join-prune-interval %d\n", spaces,
-                       router->t_periodic);
-               ++writes;
+       if (pim->vrf_id == VRF_DEFAULT) {
+               if (router->register_suppress_time
+                   != PIM_REGISTER_SUPPRESSION_TIME_DEFAULT) {
+                       vty_out(vty, "%sip pim register-suppress-time %d\n",
+                                       spaces, router->register_suppress_time);
+                       ++writes;
+               }
+               if (router->t_periodic != PIM_DEFAULT_T_PERIODIC) {
+                       vty_out(vty, "%sip pim join-prune-interval %d\n",
+                               spaces, router->t_periodic);
+                       ++writes;
+               }
+
+               if (router->packet_process != PIM_DEFAULT_PACKET_PROCESS) {
+                       vty_out(vty, "%sip pim packets %d\n", spaces,
+                               router->packet_process);
+                       ++writes;
+               }
        }
        if (pim->keep_alive_time != PIM_KEEPALIVE_PERIOD) {
                vty_out(vty, "%sip pim keep-alive-timer %d\n", spaces,
@@ -206,11 +215,6 @@ int pim_global_config_write_worker(struct pim_instance *pim, struct vty *vty)
                        pim->rp_keep_alive_time);
                ++writes;
        }
-       if (router->packet_process != PIM_DEFAULT_PACKET_PROCESS) {
-               vty_out(vty, "%sip pim packets %d\n", spaces,
-                       router->packet_process);
-               ++writes;
-       }
        if (ssm->plist_name) {
                vty_out(vty, "%sip pim ssm prefix-list %s\n", spaces,
                        ssm->plist_name);
index f0eae955cceaea4912249524df65b8b44ab32420..6f933e9e721b2af48740fb553fb96f078016cedc 100644 (file)
@@ -471,8 +471,8 @@ void igmp_anysource_forward_start(struct pim_instance *pim,
        struct igmp_source *source;
        struct in_addr src_addr = {.s_addr = 0};
        /* Any source (*,G) is forwarded only if mode is EXCLUDE {empty} */
-       zassert(group->group_filtermode_isexcl);
-       zassert(listcount(group->group_source_list) < 1);
+       assert(group->group_filtermode_isexcl);
+       assert(listcount(group->group_source_list) < 1);
 
        source = source_new(group, src_addr);
        if (!source) {
index 05c9af8734b73071c46f773909916d8aad7466c6..72505a69931f041aafc9566d5dd95b242a6289d3 100644 (file)
@@ -600,7 +600,8 @@ int pim_zlookup_sg_statistics(struct channel_oil *c_oil)
        }
 
        stream_get(&lastused, s, sizeof(lastused));
-       stream_getl(s);
+       /* signed success value from netlink_talk; currently unused */
+       (void)stream_getl(s);
 
        c_oil->cc.lastused = lastused;
 
index 811dc96b5602684c2c0440cc32301dab6b581247..1679480794fc433f7dcc1a7ba6a3c403b56239f0 100644 (file)
@@ -126,7 +126,7 @@ void pim_init(void)
                        "%s %s: could not solve %s to group address: errno=%d: %s",
                        __FILE__, __func__, PIM_ALL_PIM_ROUTERS, errno,
                        safe_strerror(errno));
-               zassert(0);
+               assert(0);
                return;
        }
 
index bf50f33a334f6d5feadf10c51415878abd9c34f5..892e9da8d650ffb7b3d97fdf17162e044686f5a7 100644 (file)
@@ -1,30 +1,90 @@
-#
 # check that the first header included in C files is either
 # zebra.h or config.h
 #
+# Copyright (C) 2020  David Lamparter for NetDEF, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of the GNU General Public License as published by the Free
+# Software Foundation; either version 2 of the License, or (at your option)
+# any later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; see the file COPYING; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
 
-import sys, os, re, subprocess
+import sys
+import os
+import re
+import subprocess
+import argparse
+
+argp = argparse.ArgumentParser(description="include fixer")
+argp.add_argument("--autofix", action="store_const", const=True)
+argp.add_argument("--warn-empty", action="store_const", const=True)
+argp.add_argument("--pipe", action="store_const", const=True)
 
 include_re = re.compile('^#\s*include\s+["<]([^ ">]+)[">]', re.M)
 
-errors = 0
+ignore = [
+    lambda fn: fn.startswith("tools/"),
+    lambda fn: fn
+    in [
+        "lib/elf_py.c",
+    ],
+]
+
+
+def run(args):
+    out = []
+
+    files = subprocess.check_output(["git", "ls-files"]).decode("ASCII")
+    for fn in files.splitlines():
+        if not fn.endswith(".c"):
+            continue
+        if max([i(fn) for i in ignore]):
+            continue
+
+        with open(fn, "r") as fd:
+            data = fd.read()
 
-files = subprocess.check_output(["git", "ls-files"]).decode("ASCII")
-for fn in files.splitlines():
-    if not fn.endswith(".c"):
-        continue
-    if fn.startswith("tools/"):
-        continue
-    with open(fn, "r") as fd:
-        data = fd.read()
         m = include_re.search(data)
         if m is None:
-            # sys.stderr.write('no #include in %s?\n' % (fn))
+            if args.warn_empty:
+                sys.stderr.write("no #include in %s?\n" % (fn))
             continue
         if m.group(1) in ["config.h", "zebra.h", "lib/zebra.h"]:
             continue
-        sys.stderr.write("%s: %s\n" % (fn, m.group(0)))
-        errors += 1
 
-if errors:
-    sys.exit(1)
+        if args.autofix:
+            sys.stderr.write("%s: %s - fixing\n" % (fn, m.group(0)))
+            if fn.startswith("pceplib/"):
+                insert = '#ifdef HAVE_CONFIG_H\n#include "config.h"\n#endif\n\n'
+            else:
+                insert = "#include <zebra.h>\n\n"
+
+            pos = m.span()[0]
+
+            data = data[:pos] + insert + data[pos:]
+            with open(fn + ".new", "w") as fd:
+                fd.write(data)
+            os.rename(fn + ".new", fn)
+        else:
+            sys.stderr.write("%s: %s\n" % (fn, m.group(0)))
+            out.append(fn)
+
+    if len(out):
+        if args.pipe:
+            # for "vim `firstheader.py`"
+            print("\n".join(out))
+        return 1
+    return 0
+
+
+if __name__ == "__main__":
+    args = argp.parse_args()
+    sys.exit(run(args))
diff --git a/python/vtysh-cmd-check.py b/python/vtysh-cmd-check.py
new file mode 100644 (file)
index 0000000..ef9eea4
--- /dev/null
@@ -0,0 +1,72 @@
+#!/usr/bin/env python3
+#
+# Quick demo program that checks whether files define commands that aren't
+# in vtysh.  Execute after building.
+#
+# This is free and unencumbered software released into the public domain.
+#
+# Anyone is free to copy, modify, publish, use, compile, sell, or
+# distribute this software, either in source code form or as a compiled
+# binary, for any purpose, commercial or non-commercial, and by any
+# means.
+#
+# In jurisdictions that recognize copyright laws, the author or authors
+# of this software dedicate any and all copyright interest in the
+# software to the public domain. We make this dedication for the benefit
+# of the public at large and to the detriment of our heirs and
+# successors. We intend this dedication to be an overt act of
+# relinquishment in perpetuity of all present and future rights to this
+# software under copyright law.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+# OTHER DEALINGS IN THE SOFTWARE.
+#
+# For more information, please refer to <http://unlicense.org/>
+
+import os
+import json
+import subprocess
+
+os.chdir(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+
+with open("frr.xref", "r") as fd:
+    data = json.load(fd)
+
+vtysh_scan, _ = subprocess.Popen(
+    ["make", "var-vtysh_scan"], stdout=subprocess.PIPE
+).communicate()
+vtysh_scan = set(vtysh_scan.decode("US-ASCII").split())
+
+check = set()
+vtysh = {}
+
+for cmd, defs in data["cli"].items():
+    for binary, clidef in defs.items():
+        if clidef["defun"]["file"].startswith("vtysh/"):
+            vtysh[clidef["string"]] = clidef
+
+for cmd, defs in data["cli"].items():
+    for binary, clidef in defs.items():
+        if clidef["defun"]["file"].startswith("vtysh/"):
+            continue
+
+        if clidef["defun"]["file"] not in vtysh_scan:
+            vtysh_def = vtysh.get(clidef["string"])
+            if vtysh_def is not None:
+                print(
+                    "\033[33m%s defines %s, has a custom define in vtysh %s\033[m"
+                    % (clidef["defun"]["file"], cmd, vtysh_def["defun"]["file"])
+                )
+            else:
+                print(
+                    "\033[31m%s defines %s, not in vtysh_scan\033[m"
+                    % (clidef["defun"]["file"], cmd)
+                )
+                check.add(clidef["defun"]["file"])
+
+print("\nfiles to check:\n\t" + " ".join(sorted(check)))
index 80f8f3aca9272457b6f74ed87f0fc604578fa806..704efc5930f54d986408c5ff4391e28473ef8fc2 100644 (file)
@@ -35,7 +35,7 @@ if HAVE_PROTOBUF
 
 # Rules
 .proto.pb.h:
-       $(PROTOC) -I$(top_srcdir) --cpp_out=$(top_srcdir) $(top_srcdir)/$^
+       $(PROTOC) -I$(top_srcdir) --cpp_out=$(top_builddir) $^
 
 AM_V_PROTOC_C = $(am__v_PROTOC_C_$(V))
 am__v_PROTOC_C_ = $(am__v_PROTOC_C_$(AM_DEFAULT_VERBOSITY))
@@ -43,7 +43,8 @@ am__v_PROTOC_C_0 = @echo "  PROTOC_C" $@;
 am__v_PROTOC_C_1 =
 
 .proto.pb-c.c:
-       $(AM_V_PROTOC_C)$(PROTOC_C) -I$(top_srcdir) --c_out=$(top_srcdir) $(top_srcdir)/$^
+       $(AM_V_PROTOC_C)$(PROTOC_C) -I$(top_srcdir) --c_out=$(top_builddir) $^
+       $(AM_V_GEN)$(SED) -e '1i#include "config.h"' -i $@
 .pb-c.c.pb-c.h:
        @/bin/true
 
index 87098ece64574442219f51cd1ad19a1d0c15a22a..43e5b21fa1fb73e021b0e102aaf3dc50a1cad10f 100644 (file)
@@ -1019,11 +1019,56 @@ DEFPY_YANG (clear_ip_rip,
        return ret;
 }
 
+DEFUN (rip_distribute_list,
+       rip_distribute_list_cmd,
+       "distribute-list [prefix] WORD <in|out> [WORD]",
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[1]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_parser(prefix, true, argv[2 + prefix]->text,
+                                     argv[1 + prefix]->arg, ifname);
+}
+
+DEFUN (rip_no_distribute_list,
+       rip_no_distribute_list_cmd,
+       "no distribute-list [prefix] WORD <in|out> [WORD]",
+       NO_STR
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_no_parser(vty, prefix, true,
+                                        argv[3 + prefix]->text,
+                                        argv[2 + prefix]->arg, ifname);
+}
+
 void rip_cli_init(void)
 {
        install_element(CONFIG_NODE, &router_rip_cmd);
        install_element(CONFIG_NODE, &no_router_rip_cmd);
 
+       install_element(RIP_NODE, &rip_distribute_list_cmd);
+       install_element(RIP_NODE, &rip_no_distribute_list_cmd);
+
        install_element(RIP_NODE, &rip_allow_ecmp_cmd);
        install_element(RIP_NODE, &rip_default_information_originate_cmd);
        install_element(RIP_NODE, &rip_default_metric_cmd);
index b922d669123e28089d520511d2b7b8f92b743564..d49d360b7ee70713e73eff97b7352d48cb82ab11 100644 (file)
@@ -31,7 +31,7 @@
 #include "table.h"
 #include "smux.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #include "ripd/ripd.h"
 
index 1c23575bf3b8986e3fd05e13d34a30bcccf11e44..9832c7c52a4ebdd4d1ba58b9b4ad7d8d983307eb 100644 (file)
@@ -3722,9 +3722,6 @@ void rip_init(void)
        prefix_list_add_hook(rip_distribute_update_all);
        prefix_list_delete_hook(rip_distribute_update_all);
 
-       /* Distribute list install. */
-       distribute_list_init(RIP_NODE);
-
        /* Route-map */
        rip_route_map_init();
 
index 99979bff0dd2d1d6eec75a4aa8d6b44e8bbc2190..8de0fc4b5a10d2dbb3f03b34f8a8a88456d62237 100644 (file)
@@ -56,6 +56,6 @@ nodist_ripd_ripd_SOURCES = \
        # end
 
 ripd_ripd_snmp_la_SOURCES = ripd/rip_snmp.c
-ripd_ripd_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+ripd_ripd_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 ripd_ripd_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 ripd_ripd_snmp_la_LIBADD = lib/libfrrsnmp.la
index 365082f8067d69374085fae117aafce8f9f77303..7e0d0140864a7211feb817ee56b34cec6502963c 100644 (file)
@@ -503,11 +503,58 @@ DEFPY_YANG (clear_ipv6_rip,
        return ret;
 }
 
+DEFUN (ripng_ipv6_distribute_list,
+       ripng_ipv6_distribute_list_cmd,
+       "ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
+       "IPv6\n"
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[2]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_parser(prefix, false, argv[3 + prefix]->text,
+                                     argv[2 + prefix]->arg, ifname);
+}
+
+DEFUN (ripng_no_ipv6_distribute_list,
+       ripng_no_ipv6_distribute_list_cmd,
+       "no ipv6 distribute-list [prefix] WORD <in|out> [WORD]",
+       NO_STR
+       "IPv6\n"
+       "Filter networks in routing updates\n"
+       "Specify a prefix\n"
+       "Access-list name\n"
+       "Filter incoming routing updates\n"
+       "Filter outgoing routing updates\n"
+       "Interface name\n")
+{
+       const char *ifname = NULL;
+       int prefix = (argv[3]->type == WORD_TKN) ? 1 : 0;
+
+       if (argv[argc - 1]->type == VARIABLE_TKN)
+               ifname = argv[argc - 1]->arg;
+
+       return distribute_list_no_parser(vty, prefix, false,
+                                        argv[4 + prefix]->text,
+                                        argv[3 + prefix]->arg, ifname);
+}
+
 void ripng_cli_init(void)
 {
        install_element(CONFIG_NODE, &router_ripng_cmd);
        install_element(CONFIG_NODE, &no_router_ripng_cmd);
 
+       install_element(RIPNG_NODE, &ripng_ipv6_distribute_list_cmd);
+       install_element(RIPNG_NODE, &ripng_no_ipv6_distribute_list_cmd);
+
        install_element(RIPNG_NODE, &ripng_allow_ecmp_cmd);
        install_element(RIPNG_NODE, &ripng_default_information_originate_cmd);
        install_element(RIPNG_NODE, &ripng_default_metric_cmd);
index 0e831401493b0f210f88d7c24694433117c45ca9..5a71928fbdb81213a8cfa4f1fd9558a684da9715 100644 (file)
@@ -2723,9 +2723,6 @@ void ripng_init(void)
        prefix_list_add_hook(ripng_distribute_update_all);
        prefix_list_delete_hook(ripng_distribute_update_all);
 
-       /* Distribute list install. */
-       distribute_list_init(RIPNG_NODE);
-
        /* Route-map for interface. */
        ripng_route_map_init();
 
index 002336616c52d231b11319a8e4648664fc00a450..1ff0591d5e390b88dab319bccf56dd6acfaf188d 100644 (file)
 #include "sharpd/sharp_vty_clippy.c"
 #endif
 
+DEFPY(watch_redistribute, watch_redistribute_cmd,
+      "sharp watch [vrf NAME$vrf_name] redistribute " FRR_REDIST_STR_SHARPD,
+      "Sharp routing Protocol\n"
+      "Watch for changes\n"
+      "The vrf we would like to watch if non-default\n"
+      "The NAME of the vrf\n"
+      "Redistribute into Sharp\n"
+      FRR_REDIST_HELP_STR_SHARPD)
+{
+       struct vrf *vrf;
+       int source;
+
+       if (!vrf_name)
+               vrf_name = VRF_DEFAULT_NAME;
+       vrf = vrf_lookup_by_name(vrf_name);
+       if (!vrf) {
+               vty_out(vty, "The vrf NAME specified: %s does not exist\n",
+                       vrf_name);
+               return CMD_WARNING;
+       }
+
+       source = proto_redistnum(AFI_IP, argv[argc-1]->text);
+       sharp_redistribute_vrf(vrf, source);
+
+       return CMD_SUCCESS;
+}
+
 DEFPY(watch_nexthop_v6, watch_nexthop_v6_cmd,
       "sharp watch [vrf NAME$vrf_name] <nexthop$n X:X::X:X$nhop|import$import X:X::X:X/M$inhop>  [connected$connected]",
       "Sharp routing Protocol\n"
@@ -485,7 +512,7 @@ DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
         (0-100000)$inlabel\
         [nexthop-group NHGNAME$nhgname] \
         [prefix A.B.C.D/M$pfx\
-       " FRR_IP_REDIST_STR_SHARPD "$type_str [instance (0-255)$instance]]",
+       " FRR_IP_REDIST_STR_ZEBRA "$type_str [instance (0-255)$instance]]",
       "Sharp Routing Protocol\n"
       "Remove data\n"
       "Remove an LSP\n"
@@ -494,7 +521,7 @@ DEFPY(sharp_remove_lsp_prefix_v4, sharp_remove_lsp_prefix_v4_cmd,
       "The nexthop-group name\n"
       "Specify a v4 prefix\n"
       "The v4 prefix to label\n"
-      FRR_IP_REDIST_HELP_STR_SHARPD
+      FRR_IP_REDIST_HELP_STR_ZEBRA
       "Routing instance\n"
       "Instance to use\n")
 {
@@ -844,6 +871,7 @@ void sharp_vty_init(void)
        install_element(ENABLE_NODE, &remove_routes_cmd);
        install_element(ENABLE_NODE, &vrf_label_cmd);
        install_element(ENABLE_NODE, &sharp_nht_data_dump_cmd);
+       install_element(ENABLE_NODE, &watch_redistribute_cmd);
        install_element(ENABLE_NODE, &watch_nexthop_v6_cmd);
        install_element(ENABLE_NODE, &watch_nexthop_v4_cmd);
        install_element(ENABLE_NODE, &sharp_lsp_prefix_v4_cmd);
index 0f2c6340498d513592ddbefa0f84537c503764c1..128cfe2de6bf9f7dbf8ea91b99de401151ff00ab 100644 (file)
@@ -714,6 +714,12 @@ static int sharp_redistribute_route(ZAPI_CALLBACK_ARGS)
        return 0;
 }
 
+void sharp_redistribute_vrf(struct vrf *vrf, int type)
+{
+       zebra_redistribute_send(ZEBRA_REDISTRIBUTE_ADD, zclient, AFI_IP, type,
+                               0, vrf->vrf_id);
+}
+
 /* Add a zclient with a specified session id, for testing. */
 int sharp_zclient_create(uint32_t session_id)
 {
index ffddb9e78041b7651f7c02b1f612928ae46f3972..4355f49a2f0ecd67883fd2497f1026b3d67e1f89 100644 (file)
@@ -63,4 +63,6 @@ extern void sharp_zebra_send_arp(const struct interface *ifp,
 /* Register Link State Opaque messages */
 extern void sharp_zebra_register_te(void);
 
+extern void sharp_redistribute_vrf(struct vrf *vrf, int source);
+
 #endif
index a2a14751cf83e8d8c17ed3fcb561494073874d05..aa9076aa881fc3bd2ea46362e8a32fb8d3cd2d90 100644 (file)
@@ -16,6 +16,8 @@
  * 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 "northbound.h"
 #include "libfrr.h"
 #include "static_nb.h"
index db154992f921ace187c887823f4e3276ed788039..e78f5172a31226e12b5f8d2f930c567558602bae 100644 (file)
@@ -16,6 +16,8 @@
  * 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 "northbound.h"
 #include "libfrr.h"
 #include "log.h"
index ca20b0ecac2c5f48ae3df51c98f304bbb356fa3b..0c938beab67a5bfbce28b6a580e4d6ab4fd325ee 100644 (file)
@@ -21,6 +21,7 @@
 /lib/cli/test_commands_defun.c
 /lib/northbound/test_oper_data
 /lib/cxxcompat
+/lib/test_assert
 /lib/test_atomlist
 /lib/test_buffer
 /lib/test_checksum
@@ -52,4 +53,4 @@
 /lib/test_zmq
 /ospf6d/test_lsdb
 /ospf6d/test_lsdb_clippy.c
-/zebra/test_lm_plugin
\ No newline at end of file
+/zebra/test_lm_plugin
index 1a9183c472af50af3d93ffca063a813fa685e0fb..aaf3fd2aa4d4eef650153773edd0a170803869ec 100644 (file)
@@ -892,7 +892,7 @@ static int validate(struct aspath *as, const struct test_spec *sp)
 
        /* Excercise AS4 parsing a bit, with a dogfood test */
        if (!s)
-               s = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
+               s = stream_new(BGP_MAX_PACKET_SIZE);
        bytes4 = aspath_put(s, as, 1);
        as4 = make_aspath(STREAM_DATA(s), bytes4, 1);
 
@@ -1201,13 +1201,13 @@ static int handle_attr_test(struct aspath_tests *t)
 
        asp = make_aspath(t->segment->asdata, t->segment->len, 0);
 
-       peer.curr = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
+       peer.curr = stream_new(BGP_MAX_PACKET_SIZE);
        peer.obuf = stream_fifo_new();
        peer.bgp = &bgp;
        peer.host = (char *)"none";
        peer.fd = -1;
        peer.cap = t->cap;
-       peer.max_packet_size = BGP_MAX_PACKET_SIZE;
+       peer.max_packet_size = BGP_STANDARD_MESSAGE_MAX_PACKET_SIZE;
 
        stream_write(peer.curr, t->attrheader, t->len);
        datalen = aspath_put(peer.curr, asp, t->as4 == AS4_DATA);
index 91c0cce80c5e2f2ffc46a060363bcf6c1227b24f..153b83897d988b3ed11a76656e43b356a1e8959c 100644 (file)
@@ -935,7 +935,7 @@ int main(void)
                        peer->afc_adv[i][j] = 1;
                }
 
-       peer->curr = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
+       peer->curr = stream_new(BGP_MAX_PACKET_SIZE);
 
        i = 0;
        while (mp_segments[i].name)
index 8de0604c45185fb84c6765225e9590bf286e547a..f51076091357f83cd4083a658d6a14959ff0eab3 100644 (file)
@@ -1100,7 +1100,7 @@ int main(void)
        peer = peer_create_accept(bgp);
        peer->host = (char *)"foo";
        peer->status = Established;
-       peer->curr = stream_new(BGP_MAX_EXTENDED_MESSAGE_PACKET_SIZE);
+       peer->curr = stream_new(BGP_MAX_PACKET_SIZE);
 
        ifp.ifindex = 0;
        peer->nexthop.ifp = &ifp;
index e06944a037e2ec267e5a358f277b25034acb9c64..8fe1ad0b8ae74dbf13400f210fe31dfc66d0e256 100644 (file)
@@ -556,7 +556,6 @@ int main(int argc, char **argv)
        /* IS-IS inits. */
        yang_module_load("frr-isisd");
        isis = isis_new(VRF_DEFAULT_NAME);
-       listnode_add(im->isis, isis);
        SET_FLAG(im->options, F_ISIS_UNIT_TEST);
        debug_spf_events |= DEBUG_SPF_EVENTS;
        debug_lfa |= DEBUG_LFA;
index fde0d6af520f63a8a1503a67e6e5c9388927be97..2589fca6141b92c05886db739a3c5f496feb43a9 100644 (file)
 #include "lib/yang.h"
 #include "lib/yang_translator.h"
 #include "lib/yang_wrappers.h"
-#include "lib/zassert.h"
 #include "lib/zclient.h"
 
 PREDECL_RBTREE_UNIQ(footree);
diff --git a/tests/lib/test_assert.c b/tests/lib/test_assert.c
new file mode 100644 (file)
index 0000000..8f1f4f2
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+ * Quick test for assert()
+ * Copyright (C) 2021  David Lamparter for NetDEF, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; see the file COPYING; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+/* make sure this works with assert.h & nothing else.  also check the include
+ * shadowing, we don't want to pick up system assert.h
+ */
+#include <assert.h>
+
+__attribute__((noinline))
+void func_for_bt(int number)
+{
+       assert(number > 2);
+       assertf(number > 3, "(A) the number was %d", number);
+}
+
+#include <zebra.h>
+#include "lib/zlog.h"
+#include "lib/thread.h"
+#include "lib/sigevent.h"
+
+int main(int argc, char **argv)
+{
+       int number = 10;
+       struct thread_master *master;
+
+       zlog_aux_init("NONE: ", LOG_DEBUG);
+
+       if (argc > 1)
+               number = atoi(argv[1]);
+
+       assert(number > 0);
+       assertf(number > 1, "(B) the number was %d", number);
+
+       /* set up SIGABRT handler */
+       master = thread_master_create("test");
+       signal_init(master, 0, NULL);
+
+       func_for_bt(number);
+       assert(number > 4);
+       assertf(number > 5, "(C) the number was %d", number);
+
+       assertf(number > 10, "(D) the number was %d", number);
+       return 0;
+}
diff --git a/tests/lib/test_assert.py b/tests/lib/test_assert.py
new file mode 100644 (file)
index 0000000..67c88e6
--- /dev/null
@@ -0,0 +1,56 @@
+import frrtest
+import os
+import re
+import subprocess
+import inspect
+
+basedir = os.path.dirname(__file__)
+program = os.path.join(basedir, "test_assert")
+
+
+def check(number, rex=None):
+    proc = subprocess.Popen(
+        [frrtest.binpath(program), str(number)],
+        stdout=subprocess.PIPE,
+        stderr=subprocess.PIPE,
+    )
+    out, err = proc.communicate()
+    exitcode = proc.wait()
+
+    if rex is None:
+        assert exitcode == 0
+    else:
+        assert exitcode != 0
+
+        text = out.decode("US-ASCII") + err.decode("US-ASCII")
+        rex = re.compile(rex, re.M | re.S)
+        m = rex.search(text)
+        assert m is not None, "non-matching output: %s" % text
+
+
+def test_assert_0():
+    check(0, r"test_assert\.c:\d+.*number > 0")
+
+
+def test_assert_1():
+    check(1, r"test_assert\.c:\d+.*number > 1.*\(B\) the number was 1")
+
+
+def test_assert_2():
+    check(2, r"test_assert\.c:\d+.*number > 2")
+
+
+def test_assert_3():
+    check(3, r"test_assert\.c:\d+.*number > 3.*\(A\) the number was 3")
+
+
+def test_assert_4():
+    check(4, r"test_assert\.c:\d+.*number > 4")
+
+
+def test_assert_10():
+    check(10, r"test_assert\.c:\d+.*number > 10.*\(D\) the number was 10")
+
+
+def test_assert_11():
+    check(11)
diff --git a/tests/lib/test_nexthop.c b/tests/lib/test_nexthop.c
new file mode 100644 (file)
index 0000000..659d207
--- /dev/null
@@ -0,0 +1,201 @@
+/*
+ * Nexthop module test.
+ *
+ * Copyright (C) 2021 by Volta Networks, Inc.
+ *
+ * This file is part of FRR.
+ *
+ * FRR 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, or (at your option) any
+ * later version.
+ *
+ * FRR 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 <nexthop.h>
+
+static bool verbose;
+
+static void test_run_first(void)
+{
+       int ret, i;
+       struct nexthop *nh1, *nh2;
+       struct in_addr addr;
+       struct in6_addr addr6;
+       mpls_label_t labels[MPLS_MAX_LABELS];
+
+       /* Test comparison apis */
+
+       /* ifindex comparisons */
+       nh1 = nexthop_from_ifindex(11, 0);
+       nh2 = nexthop_from_ifindex(12, 0);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret < 0);
+
+       nexthop_free(nh1);
+       nh1 = nexthop_from_ifindex(12, 0);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret == 0);
+
+       nexthop_free(nh1);
+       nexthop_free(nh2);
+
+       /* ipv4, vrf */
+       addr.s_addr = 0x04030201;
+       nh1 = nexthop_from_ipv4(&addr, NULL, 0);
+       nh2 = nexthop_from_ipv4(&addr, NULL, 111);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       nexthop_free(nh2);
+
+       addr.s_addr = 0x04030202;
+       nh2 = nexthop_from_ipv4(&addr, NULL, 0);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       nexthop_free(nh2);
+
+       addr.s_addr = 0x04030201;
+       nh2 = nexthop_from_ipv4(&addr, NULL, 0);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret == 0);
+
+       /* Weight */
+       nh2->weight = 20;
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       nexthop_free(nh1);
+       nexthop_free(nh2);
+
+       /* ipv6 */
+       memset(addr6.s6_addr, 0, sizeof(addr6.s6_addr));
+       nh1 = nexthop_from_ipv6(&addr6, 0);
+       nh2 = nexthop_from_ipv6(&addr6, 0);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret == 0);
+
+       nexthop_free(nh2);
+
+       nh2 = nexthop_from_ipv6(&addr6, 1);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       nexthop_free(nh2);
+
+       addr6.s6_addr[14] = 1;
+       addr6.s6_addr[15] = 1;
+       nh2 = nexthop_from_ipv6(&addr6, 0);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       nexthop_free(nh1);
+       nexthop_free(nh2);
+
+       /* Blackhole */
+       nh1 = nexthop_from_blackhole(BLACKHOLE_REJECT);
+       nh2 = nexthop_from_blackhole(BLACKHOLE_REJECT);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret == 0);
+
+       nexthop_free(nh2);
+
+       nh2 = nexthop_from_blackhole(BLACKHOLE_NULL);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       /* Labels */
+       addr.s_addr = 0x04030201;
+       nh1 = nexthop_from_ipv4(&addr, NULL, 0);
+       nh2 = nexthop_from_ipv4(&addr, NULL, 0);
+
+       memset(labels, 0, sizeof(labels));
+       labels[0] = 111;
+       labels[1] = 222;
+
+       nexthop_add_labels(nh1, ZEBRA_LSP_STATIC, 2, labels);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       nexthop_add_labels(nh2, ZEBRA_LSP_STATIC, 2, labels);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret == 0);
+
+       nexthop_free(nh2);
+
+       /* LSP type isn't included */
+       nh2 = nexthop_from_ipv4(&addr, NULL, 0);
+       nexthop_add_labels(nh2, ZEBRA_LSP_LDP, 2, labels);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret == 0);
+
+       nexthop_free(nh2);
+
+       labels[2] = 333;
+       nh2 = nexthop_from_ipv4(&addr, NULL, 0);
+       nexthop_add_labels(nh2, ZEBRA_LSP_LDP, 3, labels);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       nexthop_free(nh1);
+       nexthop_free(nh2);
+
+       nh1 = nexthop_from_ipv4(&addr, NULL, 0);
+       nh2 = nexthop_from_ipv4(&addr, NULL, 0);
+
+       for (i = 0; i < MPLS_MAX_LABELS; i++)
+               labels[i] = 111 * (i + 1);
+
+       nexthop_add_labels(nh1, ZEBRA_LSP_LDP, MPLS_MAX_LABELS, labels);
+       nexthop_add_labels(nh2, ZEBRA_LSP_LDP, MPLS_MAX_LABELS, labels);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret == 0);
+
+       nexthop_free(nh2);
+
+       /* Test very last label in stack */
+       labels[15] = 999;
+       nh2 = nexthop_from_ipv4(&addr, NULL, 0);
+       nexthop_add_labels(nh2, ZEBRA_LSP_LDP, MPLS_MAX_LABELS, labels);
+
+       ret = nexthop_cmp_basic(nh1, nh2);
+       assert(ret != 0);
+
+       /* End */
+       nexthop_free(nh1);
+       nexthop_free(nh2);
+}
+
+int main(int argc, char **argv)
+{
+       if (argc >= 2 && !strcmp("-v", argv[1]))
+               verbose = true;
+       test_run_first();
+       printf("Simple test passed.\n");
+}
diff --git a/tests/lib/test_nexthop.py b/tests/lib/test_nexthop.py
new file mode 100644 (file)
index 0000000..81bfa43
--- /dev/null
@@ -0,0 +1,8 @@
+import frrtest
+
+
+class TestNexthopIter(frrtest.TestMultiOut):
+    program = "./test_nexthop"
+
+
+TestNexthopIter.onesimple("Simple test passed.")
index 7ba5a29b6225d55e106dd6996ed1bdca1269e3e2..4ac62940b872a09ea4ce852a1acb2604e7322431 100644 (file)
@@ -93,7 +93,7 @@ int main(int argc, char **argv)
        assert(ringbuf_get(soil, &compost, BUFSIZ) == BUFSIZ);
 
        validate_state(soil, BUFSIZ, 0);
-       assert(soil->empty = true);
+       assert(soil->empty == true);
        assert(soil->start == soil->end);
        assert(soil->start == 15);
 
index 639c2bdc2bc1c25628a634067eb93e121bb66dfb..768307d56dbf7e09b029a6d5ef7dde7b55068c04 100644 (file)
@@ -32,6 +32,7 @@
 
 #include "monotime.h"
 #include "seqlock.h"
+#include "printfrr.h"
 
 static struct seqlock sqlo;
 static pthread_t thr1;
@@ -43,7 +44,7 @@ static void writestr(const char *str)
        char buf[32];
        int64_t usec = monotime_since(&start, NULL);
 
-       snprintf(buf, sizeof(buf), "[%02"PRId64"] ", usec / 100000);
+       snprintfrr(buf, sizeof(buf), "[%02" PRId64 "] ", usec / 100000);
 
        iov[0].iov_base = buf;
        iov[0].iov_len = strlen(buf);
index 32331c14a03788006a7e6348114a8c998717e773..379a2396b46fbd50a7952fc35298e9808b5c659e 100644 (file)
@@ -17,6 +17,7 @@
 /* C++ called, they want their templates back */
 #define item           concat(item_, TYPE)
 #define itm            concat(itm_, TYPE)
+#define itmswap                concat(itmswap_, TYPE)
 #define head           concat(head_, TYPE)
 #define list           concat(TYPE, )
 #define list_head      concat(TYPE, _head)
@@ -40,8 +41,9 @@
 #define list_find_gteq concat(TYPE, _find_gteq)
 #define list_del       concat(TYPE, _del)
 #define list_pop       concat(TYPE, _pop)
+#define list_swap_all  concat(TYPE, _swap_all)
 
-#define ts_hash                concat(ts_hash_, TYPE)
+#define ts_hash_head   concat(ts_hash_head_, TYPE)
 
 #ifndef REALTYPE
 #define REALTYPE TYPE
@@ -89,10 +91,12 @@ DECLARE(REALTYPE, list, struct item, itm);
 #endif
 
 #define NITEM 10000
-struct item itm[NITEM];
+#define NITEM_SWAP 100 /* other container for swap */
+struct item itm[NITEM], itmswap[NITEM_SWAP];
 static struct list_head head = concat(INIT_, REALTYPE)(head);
 
-static void ts_hash(const char *text, const char *expect)
+static void ts_hash_head(struct list_head *h, const char *text,
+                        const char *expect)
 {
        int64_t us = monotime_since(&ref, NULL);
        SHA256_CTX ctx;
@@ -102,13 +106,13 @@ static void ts_hash(const char *text, const char *expect)
        char hashtext[65];
        uint32_t swap_count, count;
 
-       count = list_count(&head);
+       count = list_count(h);
        swap_count = htonl(count);
 
        SHA256_Init(&ctx);
        SHA256_Update(&ctx, &swap_count, sizeof(swap_count));
 
-       frr_each (list, &head, item) {
+       frr_each (list, h, item) {
                struct {
                        uint32_t val_upper, val_lower, index;
                } hashitem = {
@@ -135,15 +139,20 @@ static void ts_hash(const char *text, const char *expect)
 }
 /* hashes will have different item ordering */
 #if IS_HASH(REALTYPE) || IS_HEAP(REALTYPE)
-#define ts_hashx(pos, csum) ts_hash(pos, NULL)
+#define ts_hash(pos, csum) ts_hash_head(&head, pos, NULL)
+#define ts_hashx(pos, csum) ts_hash_head(&head, pos, NULL)
+#define ts_hash_headx(head, pos, csum) ts_hash_head(head, pos, NULL)
 #else
-#define ts_hashx(pos, csum) ts_hash(pos, csum)
+#define ts_hash(pos, csum) ts_hash_head(&head, pos, csum)
+#define ts_hashx(pos, csum) ts_hash_head(&head, pos, csum)
+#define ts_hash_headx(head, pos, csum) ts_hash_head(head, pos, csum)
 #endif
 
 static void concat(test_, TYPE)(void)
 {
        size_t i, j, k, l;
        struct prng *prng;
+       struct prng *prng_swap __attribute__((unused));
        struct item *item, *prev __attribute__((unused));
        struct item dummy __attribute__((unused));
 
@@ -151,6 +160,10 @@ static void concat(test_, TYPE)(void)
        for (i = 0; i < NITEM; i++)
                itm[i].val = i;
 
+       memset(itmswap, 0, sizeof(itmswap));
+       for (i = 0; i < NITEM_SWAP; i++)
+               itmswap[i].val = i;
+
        printfrr("%s start\n", str(TYPE));
        ts_start();
 
@@ -178,6 +191,56 @@ static void concat(test_, TYPE)(void)
        assert(list_first(&head) != NULL);
        ts_hashx("fill", "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
 
+#if !IS_ATOMIC(REALTYPE)
+       struct list_head other;
+
+       list_init(&other);
+       list_swap_all(&head, &other);
+
+       assert(list_count(&head) == 0);
+       assert(!list_first(&head));
+       assert(list_count(&other) == k);
+       assert(list_first(&other) != NULL);
+       ts_hash_headx(
+               &other, "swap1",
+               "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
+
+       prng_swap = prng_new(0x1234dead);
+       l = 0;
+       for (i = 0; i < NITEM_SWAP; i++) {
+               j = prng_rand(prng_swap) % NITEM_SWAP;
+               if (itmswap[j].scratchpad == 0) {
+                       list_add(&head, &itmswap[j]);
+                       itmswap[j].scratchpad = 1;
+                       l++;
+               }
+#if !IS_HEAP(REALTYPE)
+               else {
+                       struct item *rv = list_add(&head, &itmswap[j]);
+                       assert(rv == &itmswap[j]);
+               }
+#endif
+       }
+       assert(list_count(&head) == l);
+       assert(list_first(&head) != NULL);
+       ts_hash_headx(
+               &head, "swap-fill",
+               "26df437174051cf305d1bbb62d779ee450ca764167a1e7a94be1aece420008e6");
+
+       list_swap_all(&head, &other);
+
+       assert(list_count(&other) == l);
+       assert(list_first(&other));
+       ts_hash_headx(
+               &other, "swap2a",
+               "26df437174051cf305d1bbb62d779ee450ca764167a1e7a94be1aece420008e6");
+       assert(list_count(&head) == k);
+       assert(list_first(&head) != NULL);
+       ts_hash_headx(
+               &head, "swap2b",
+               "a538546a6e6ab0484e925940aa8dd02fd934408bbaed8cb66a0721841584d838");
+#endif /* !IS_ATOMIC */
+
        k = 0;
 
 #if IS_ATOMIC(REALTYPE)
@@ -344,6 +407,50 @@ static void concat(test_, TYPE)(void)
        assert(list_first(&head) != NULL);
        ts_hash("fill / add_tail", "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
 
+#if !IS_ATOMIC(REALTYPE)
+       struct list_head other;
+
+       list_init(&other);
+       list_swap_all(&head, &other);
+
+       assert(list_count(&head) == 0);
+       assert(!list_first(&head));
+       assert(list_count(&other) == k);
+       assert(list_first(&other) != NULL);
+       ts_hash_head(
+               &other, "swap1",
+               "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
+
+       prng_swap = prng_new(0x1234dead);
+       l = 0;
+       for (i = 0; i < NITEM_SWAP; i++) {
+               j = prng_rand(prng_swap) % NITEM_SWAP;
+               if (itmswap[j].scratchpad == 0) {
+                       list_add_tail(&head, &itmswap[j]);
+                       itmswap[j].scratchpad = 1;
+                       l++;
+               }
+       }
+       assert(list_count(&head) == l);
+       assert(list_first(&head) != NULL);
+       ts_hash_head(
+               &head, "swap-fill",
+               "833e6ae437e322dfbd36eda8cfc33a61109be735b43f15d256c05e52d1b01909");
+
+       list_swap_all(&head, &other);
+
+       assert(list_count(&other) == l);
+       assert(list_first(&other));
+       ts_hash_head(
+               &other, "swap2a",
+               "833e6ae437e322dfbd36eda8cfc33a61109be735b43f15d256c05e52d1b01909");
+       assert(list_count(&head) == k);
+       assert(list_first(&head) != NULL);
+       ts_hash_head(
+               &head, "swap2b",
+               "eabfcf1413936daaf20965abced95762f45110a6619b84aac7d38481bce4ea19");
+#endif
+
        for (i = 0; i < NITEM / 2; i++) {
                j = prng_rand(prng) % NITEM;
                if (itm[j].scratchpad == 1) {
@@ -546,10 +653,14 @@ static void concat(test_, TYPE)(void)
        printfrr("%s end\n", str(TYPE));
 }
 
+#undef ts_hash
 #undef ts_hashx
+#undef ts_hash_head
+#undef ts_hash_headx
 
 #undef item
 #undef itm
+#undef itmswap
 #undef head
 #undef list
 #undef list_head
@@ -571,6 +682,7 @@ static void concat(test_, TYPE)(void)
 #undef list_find_gteq
 #undef list_del
 #undef list_pop
+#undef list_swap_all
 
 #undef REALTYPE
 #undef TYPE
index 370e6a49a96b3e961b3a3d885e50c6d9d3288421..43fad29fa24ece05eba0b15008be41ae58ec9541 100644 (file)
@@ -66,6 +66,7 @@ clippy_scan += \
 
 check_PROGRAMS = \
        tests/lib/cxxcompat \
+       tests/lib/test_assert \
        tests/lib/test_atomlist \
        tests/lib/test_buffer \
        tests/lib/test_checksum \
@@ -75,6 +76,7 @@ check_PROGRAMS = \
        tests/lib/test_idalloc \
        tests/lib/test_memory \
        tests/lib/test_nexthop_iter \
+       tests/lib/test_nexthop \
        tests/lib/test_ntop \
        tests/lib/test_prefix2str \
        tests/lib/test_printfrr \
@@ -148,6 +150,7 @@ TESTS_CPPFLAGS = $(AM_CPPFLAGS) \
        -I$(top_builddir)/tests/helpers/c \
        # end
 TESTS_CFLAGS = \
+       $(AC_CFLAGS) \
        $(LIBYANG_CFLAGS) \
        $(SAN_FLAGS) \
        # end
@@ -248,6 +251,10 @@ tests_lib_northbound_test_oper_data_CPPFLAGS = $(TESTS_CPPFLAGS)
 tests_lib_northbound_test_oper_data_LDADD = $(ALL_TESTS_LDADD)
 tests_lib_northbound_test_oper_data_SOURCES = tests/lib/northbound/test_oper_data.c
 nodist_tests_lib_northbound_test_oper_data_SOURCES = yang/frr-test-module.yang.c
+tests_lib_test_assert_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_assert_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_assert_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_assert_SOURCES = tests/lib/test_assert.c
 tests_lib_test_atomlist_CFLAGS = $(TESTS_CFLAGS)
 tests_lib_test_atomlist_CPPFLAGS = $(TESTS_CPPFLAGS)
 tests_lib_test_atomlist_LDADD = $(ALL_TESTS_LDADD)
@@ -287,8 +294,12 @@ tests_lib_test_nexthop_iter_CFLAGS = $(TESTS_CFLAGS)
 tests_lib_test_nexthop_iter_CPPFLAGS = $(TESTS_CPPFLAGS)
 tests_lib_test_nexthop_iter_LDADD = $(ALL_TESTS_LDADD)
 tests_lib_test_nexthop_iter_SOURCES = tests/lib/test_nexthop_iter.c tests/helpers/c/prng.c
+tests_lib_test_nexthop_CFLAGS = $(TESTS_CFLAGS)
+tests_lib_test_nexthop_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_nexthop_LDADD = $(ALL_TESTS_LDADD)
+tests_lib_test_nexthop_SOURCES = tests/lib/test_nexthop.c
 tests_lib_test_ntop_CFLAGS = $(TESTS_CFLAGS)
-tests_lib_test_ntop_CPPFLAGS = $(TESTS_CPPFLAGS)
+tests_lib_test_ntop_CPPFLAGS = $(CPPFLAGS_BASE) # no assert override
 tests_lib_test_ntop_LDADD = # none
 tests_lib_test_ntop_SOURCES = tests/lib/test_ntop.c tests/helpers/c/prng.c
 tests_lib_test_prefix2str_CFLAGS = $(TESTS_CFLAGS)
@@ -403,8 +414,10 @@ EXTRA_DIST += \
        tests/lib/northbound/test_oper_data.in \
        tests/lib/northbound/test_oper_data.py \
        tests/lib/northbound/test_oper_data.refout \
+       tests/lib/test_assert.py \
        tests/lib/test_atomlist.py \
        tests/lib/test_nexthop_iter.py \
+       tests/lib/test_nexthop.py \
        tests/lib/test_ntop.py \
        tests/lib/test_prefix2str.py \
        tests/lib/test_printfrr.py \
index c9110d2db9268a451c686b0a5c69f7dbac70b91c..1503e67d31dce81a733223040bc3a5861e0b22f8 100644 (file)
@@ -44,6 +44,7 @@ RUN export DEBIAN_FRONTEND=noninteractive \
         xterm \
     && pip install \
         exabgp==3.4.17 \
+        "scapy>=2.4.2" \
         ipaddr \
         pytest \
     && rm -rf /var/lib/apt/lists/*
index 6cc23a465c8bdb9ff8b0d5fc7f47e82efa46587f..b38701a53d94a2029b4e066795249940f87cf35b 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * 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
index 2f348a7b77cc8610b337cfed670a4b26080211e1..82b64c0d98d8fa51c26502d8e136927a927025ed 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * 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
index d36d04539790bfe8a2ad5e38127f8a6747973aba..fd333b3084cc96a102c00e1504c20505b5f2aa90 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * 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
index 8bb5da72be11b811aadab92145f67718887302c6..20034b7408826a4632868e0dbdf93a681f2c6573 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * 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
index de91b247d86b31c99221b199a44a4334bd852cdc..5b5f8596cfa1f39a01a0b934f1830068232248e1 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * 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
index 1e8f67f3f9a6d6e2749eee21c6a601497cc2a03b..ff856792568af02dbd2fc9cbe30e9f4a4319a9ec 100644 (file)
@@ -4,6 +4,7 @@ r1-eth0 is up
   MTU mismatch detection: enabled
   Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10
   Transmit Delay is 1 sec, State DR, Priority 1
+  Designated Router (ID) 192.168.0.1 Interface Address 192.168.0.1/24
   No backup designated router on this network
   Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters
   Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5
@@ -15,6 +16,7 @@ r1-eth3 is up
   MTU mismatch detection: enabled
   Router ID 192.168.0.1, Network Type BROADCAST, Cost: 10
   Transmit Delay is 1 sec, State DR, Priority 1
+  Designated Router (ID) 192.168.0.1 Interface Address 192.168.3.1/26
   No backup designated router on this network
   Multicast group memberships: OSPFAllRouters OSPFDesignatedRouters
   Timer intervals configured, Hello 10s, Dead 40s, Wait 40s, Retransmit 5
index c7c7b96ee74d0fdc3ff973e79b446f284880a9b5..4984b52cf2e0522e7eaa7c2c2777b520832d8b44 100644 (file)
@@ -3,13 +3,13 @@
         "multihop":true,
         "peer":"2001:db8:4::1",
         "local":"2001:db8:1::1",
-        "status":"up",
+        "status":"init",
         "receive-interval":300,
         "transmit-interval":300,
         "echo-receive-interval":50,
         "echo-transmit-interval":0,
-        "remote-receive-interval":300,
-        "remote-transmit-interval":300,
+        "remote-receive-interval":1000,
+        "remote-transmit-interval":1000,
         "remote-echo-receive-interval":50
     }
 ]
index c73296ac971b2f718800853c8eba6e34860a3f7d..9ab7479979538aa5a6fe25583c7ccfdef35e05af 100644 (file)
@@ -26,7 +26,7 @@
         "local": "*",
         "multihop": false,
         "peer": "*",
-        "receive-interval": 300,
+        "receive-interval": 250,
         "remote-detect-multiplier": 3,
         "remote-diagnostic": "ok",
         "remote-echo-receive-interval": 50,
@@ -34,7 +34,7 @@
         "remote-receive-interval": 300,
         "remote-transmit-interval": 300,
         "status": "up",
-        "transmit-interval": 300,
+        "transmit-interval": 250,
         "uptime": "*",
         "vrf": "default"
     }
index 36ef4f0403a0d8fe02ee9f4545f727a7985ef4bd..4f5e02207776681dec96bb27cd73e538dde82b72 100644 (file)
@@ -3,4 +3,8 @@ debug bfd network
 debug bfd zebra
 !
 bfd
+ profile fast-tx
+  receive-interval 250
+  transmit-interval 250
+ !
 !
index 84157de24d2d4c27e8b55c137af97b5ee69cc38c..4ef28c39caa8be508cab3292d38fce2e7bf4eab7 100644 (file)
@@ -1,5 +1,7 @@
 interface r4-eth1
- ipv6 ospf6 bfd
+ ipv6 ospf6 bfd profile fast-tx
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
 !
 router ospf6
  ospf6 router-id 10.254.254.4
index fcb090959e79b0b860a7653099449a6b23a8f056..0fe56d576bb270b9b85ec8d45ac0c7a334b9fe26 100644 (file)
@@ -11,8 +11,8 @@
         "remote-detect-multiplier": 3,
         "remote-diagnostic": "ok",
         "remote-id": "*",
-        "remote-receive-interval": 300,
-        "remote-transmit-interval": 300,
+        "remote-receive-interval": 250,
+        "remote-transmit-interval": 250,
         "status": "up",
         "transmit-interval": 300,
         "uptime": "*",
index 970c71355864c513d90f9fb73a06ba27307e2b77..20b53cfc555596e779abd7869b013e083a0431df 100644 (file)
@@ -1,5 +1,7 @@
 interface r5-eth0
  ipv6 ospf6 bfd
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
 !
 router ospf6
  ospf6 router-id 10.254.254.5
index f01ce8844f69c561606f4c812b235f06e52c47ac..b2cdef1c9302e102e36e5c273f88271bb7d6439b 100644 (file)
@@ -299,35 +299,48 @@ def configure(conf_file):
                     raise InvalidCLIError("%s" % output)
 
 
-def clear_bgp(vrf=""):
-    " clear bgp configuration for a vrf"
+def clear_bgp():
+    "clear bgp configuration for a vrf"
 
     tgen = get_topogen()
     r1 = tgen.gears["R1"]
     r2 = tgen.gears["R2"]
     r3 = tgen.gears["R3"]
 
-    router_list = tgen.routers()
-    if vrf == "":
-        r1.vtysh_cmd("conf t\nno router bgp 65001")
-        r2.vtysh_cmd("conf t\nno router bgp 65002")
-        r2.vtysh_cmd("conf t\nno router bgp 65003")
-    else:
-        r1.vtysh_cmd("conf t\nno router bgp 65001 vrf {}".format(vrf))
-        r2.vtysh_cmd("conf t\nno router bgp 65002 vrf {}".format(vrf))
-        r3.vtysh_cmd("conf t\nno router bgp 65003 vrf {}".format(vrf))
+    r1.vtysh_cmd("conf t\nno router bgp 65001")
+    r2.vtysh_cmd("conf t\nno router bgp 65002")
+    r3.vtysh_cmd("conf t\nno router bgp 65003")
+    r1.vtysh_cmd("conf t\nno router bgp 65001 vrf blue")
+    r2.vtysh_cmd("conf t\nno router bgp 65002 vrf blue")
+    r3.vtysh_cmd("conf t\nno router bgp 65003 vrf blue")
+    r1.vtysh_cmd("conf t\nno router bgp 65001 vrf red")
+    r2.vtysh_cmd("conf t\nno router bgp 65002 vrf red")
+    r3.vtysh_cmd("conf t\nno router bgp 65003 vrf red")
+
 
+def configure_bgp(conf_file):
+    "configure bgp from file"
 
-def clear_ospf(vrf=""):
+    clear_bgp()
+    configure(conf_file)
+
+
+def clear_ospf():
     "clear ospf configuration for a vrf"
 
     tgen = get_topogen()
     router_list = tgen.routers()
     for rname, router in router_list.items():
-        if vrf == "":
-            router.vtysh_cmd("conf t\nno router ospf")
-        else:
-            router.vtysh_cmd("conf t\nno router ospf vrf {}".format(vrf))
+        router.vtysh_cmd("conf t\nno router ospf")
+        router.vtysh_cmd("conf t\nno router ospf vrf blue")
+        router.vtysh_cmd("conf t\nno router ospf vrf red")
+
+
+def configure_ospf(conf_file):
+    "configure bgp from file"
+
+    clear_ospf()
+    configure(conf_file)
 
 
 def check_neigh_state(router, peer, state, vrf=""):
@@ -344,9 +357,10 @@ def check_neigh_state(router, peer, state, vrf=""):
                 "show bgp vrf {} neighbors {} json".format(vrf, peer)
             )
         neigh_output_json = json.loads(neigh_output)
-        if neigh_output_json[peer]["bgpState"] == state:
-            matched = True
-            break
+        if peer in neigh_output_json.keys():
+            if neigh_output_json[peer]["bgpState"] == state:
+                matched = True
+                break
         count += 1
         sleep(1)
 
@@ -382,6 +396,8 @@ def check_vrf_peer_remove_passwords(vrf="", prefix="no"):
     r2 = tgen.gears["R2"]
     r3 = tgen.gears["R3"]
 
+    check_all_peers_established(vrf)
+
     r1.vtysh_cmd(
         "conf t\nrouter bgp 65001 {}\nno neighbor {} password".format(
             vrf_str(vrf), peer_name("R2", prefix, vrf)
@@ -511,25 +527,26 @@ def check_vrf_peer_change_passwords(vrf="", prefix="no"):
 def test_default_peer_established():
     "default vrf 3 peers same password"
 
+    configure_bgp("bgpd.conf")
+    configure_ospf("ospfd.conf")
     check_all_peers_established()
-    clear_bgp()
     # tgen.mininet_cli()
 
 
 def test_default_peer_remove_passwords():
     "selectively remove passwords checking state"
 
-    configure("bgpd.conf")
+    configure_bgp("bgpd.conf")
+    configure_ospf("ospfd.conf")
     check_vrf_peer_remove_passwords()
-    clear_bgp()
 
 
 def test_default_peer_change_passwords():
     "selectively change passwords checking state"
 
-    configure("bgpd.conf")
+    configure_bgp("bgpd.conf")
+    configure_ospf("ospfd.conf")
     check_vrf_peer_change_passwords()
-    clear_bgp()
 
 
 def test_default_prefix_peer_established():
@@ -539,9 +556,9 @@ def test_default_prefix_peer_established():
     if topotest.version_cmp(platform.release(), "5.3") < 0:
         return
 
-    configure("bgpd_prefix.conf")
+    configure_bgp("bgpd_prefix.conf")
+    configure_ospf("ospfd.conf")
     check_all_peers_established()
-    clear_bgp()
     # tgen.mininet_cli()
 
 
@@ -551,9 +568,10 @@ def test_prefix_peer_remove_passwords():
     # only supported in kernel > 5.3
     if topotest.version_cmp(platform.release(), "5.3") < 0:
         return
-    configure("bgpd_prefix.conf")
+
+    configure_bgp("bgpd_prefix.conf")
+    configure_ospf("ospfd.conf")
     check_vrf_peer_remove_passwords(prefix="yes")
-    clear_bgp()
 
 
 def test_prefix_peer_change_passwords():
@@ -562,38 +580,36 @@ def test_prefix_peer_change_passwords():
     # only supported in kernel > 5.3
     if topotest.version_cmp(platform.release(), "5.3") < 0:
         return
-    configure("bgpd_prefix.conf")
+
+    configure_bgp("bgpd_prefix.conf")
+    configure_ospf("ospfd.conf")
     check_vrf_peer_change_passwords(prefix="yes")
-    clear_bgp()
-    clear_ospf()
 
 
 def test_vrf_peer_established():
     "default vrf 3 peers same password with VRF config"
 
     # clean routers and load vrf config
-    configure("bgpd_vrf.conf")
-    configure("ospfd_vrf.conf")
-
+    configure_bgp("bgpd_vrf.conf")
+    configure_ospf("ospfd_vrf.conf")
     check_all_peers_established("blue")
-    clear_bgp("blue")
     # tgen.mininet_cli()
 
 
 def test_vrf_peer_remove_passwords():
     "selectively remove passwords checking state with VRF config"
 
-    configure("bgpd_vrf.conf")
+    configure_bgp("bgpd_vrf.conf")
+    configure_ospf("ospfd_vrf.conf")
     check_vrf_peer_remove_passwords(vrf="blue")
-    clear_bgp("blue")
 
 
 def test_vrf_peer_change_passwords():
     "selectively change passwords checking state with VRF config"
 
-    configure("bgpd_vrf.conf")
+    configure_bgp("bgpd_vrf.conf")
+    configure_ospf("ospfd_vrf.conf")
     check_vrf_peer_change_passwords(vrf="blue")
-    clear_bgp("blue")
 
 
 def test_vrf_prefix_peer_established():
@@ -601,12 +617,11 @@ def test_vrf_prefix_peer_established():
 
     # only supported in kernel > 5.3
     if topotest.version_cmp(platform.release(), "5.3") < 0:
-        clear_bgp("blue")
         return
 
-    configure("bgpd_vrf_prefix.conf")
+    configure_bgp("bgpd_vrf_prefix.conf")
+    configure_ospf("ospfd_vrf.conf")
     check_all_peers_established("blue")
-    clear_bgp("blue")
 
 
 def test_vrf_prefix_peer_remove_passwords():
@@ -616,65 +631,54 @@ def test_vrf_prefix_peer_remove_passwords():
     if topotest.version_cmp(platform.release(), "5.3") < 0:
         return
 
-    configure("bgpd_vrf_prefix.conf")
+    configure_bgp("bgpd_vrf_prefix.conf")
+    configure_ospf("ospfd_vrf.conf")
     check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
-    clear_bgp("blue")
 
 
 def test_vrf_prefix_peer_change_passwords():
     "selectively change passwords checking state with VRF prefix config"
 
-    tgen = get_topogen()
-    r1 = tgen.gears["R1"]
-    r2 = tgen.gears["R2"]
-    r3 = tgen.gears["R3"]
-
     # only supported in kernel > 5.3
     if topotest.version_cmp(platform.release(), "5.3") < 0:
-        clear_ospf("blue")
         return
 
-    configure("bgpd_vrf_prefix.conf")
+    configure_bgp("bgpd_vrf_prefix.conf")
+    configure_ospf("ospfd_vrf.conf")
     check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
-    clear_bgp("blue")
-    clear_ospf("blue")
 
 
 def test_multiple_vrf_peer_established():
     "default vrf 3 peers same password with multiple VRFs"
 
-    configure("bgpd_multi_vrf.conf")
-    configure("ospfd_multi_vrf.conf")
+    configure_bgp("bgpd_multi_vrf.conf")
+    configure_ospf("ospfd_multi_vrf.conf")
     check_all_peers_established("blue")
     check_all_peers_established("red")
-    clear_bgp("blue")
-    clear_bgp("red")
     # tgen.mininet_cli()
 
 
 def test_multiple_vrf_peer_remove_passwords():
     "selectively remove passwords checking state with multiple VRFs"
 
-    configure("bgpd_multi_vrf.conf")
+    configure_bgp("bgpd_multi_vrf.conf")
+    configure_ospf("ospfd_multi_vrf.conf")
     check_vrf_peer_remove_passwords("blue")
     check_all_peers_established("red")
     check_vrf_peer_remove_passwords("red")
     check_all_peers_established("blue")
-    clear_bgp("blue")
-    clear_bgp("red")
     # tgen.mininet_cli()
 
 
 def test_multiple_vrf_peer_change_passwords():
     "selectively change passwords checking state with multiple VRFs"
 
-    configure("bgpd_multi_vrf.conf")
+    configure_bgp("bgpd_multi_vrf.conf")
+    configure_ospf("ospfd_multi_vrf.conf")
     check_vrf_peer_change_passwords("blue")
     check_all_peers_established("red")
     check_vrf_peer_change_passwords("red")
     check_all_peers_established("blue")
-    clear_bgp("blue")
-    clear_bgp("red")
     # tgen.mininet_cli()
 
 
@@ -685,12 +689,10 @@ def test_multiple_vrf_prefix_peer_established():
     if topotest.version_cmp(platform.release(), "5.3") < 0:
         return
 
-    configure("bgpd_multi_vrf.conf")
-    configure("ospfd_multi_vrf.conf")
+    configure_bgp("bgpd_multi_vrf_prefix.conf")
+    configure_ospf("ospfd_multi_vrf.conf")
     check_all_peers_established("blue")
     check_all_peers_established("red")
-    clear_bgp("blue")
-    clear_bgp("red")
     # tgen.mininet_cli()
 
 
@@ -701,14 +703,12 @@ def test_multiple_vrf_prefix_peer_remove_passwords():
     if topotest.version_cmp(platform.release(), "5.3") < 0:
         return
 
-    configure("bgpd_multi_vrf_prefix.conf")
-    tgen = get_topogen()
+    configure_bgp("bgpd_multi_vrf_prefix.conf")
+    configure_ospf("ospfd_multi_vrf.conf")
     check_vrf_peer_remove_passwords(vrf="blue", prefix="yes")
     check_all_peers_established("red")
     check_vrf_peer_remove_passwords(vrf="red", prefix="yes")
     check_all_peers_established("blue")
-    clear_bgp("blue")
-    clear_bgp("red")
     # tgen.mininet_cli()
 
 
@@ -717,21 +717,14 @@ def test_multiple_vrf_prefix_peer_change_passwords():
 
     # only supported in kernel > 5.3
     if topotest.version_cmp(platform.release(), "5.3") < 0:
-        clear_bgp("blue")
-        clear_bgp("red")
-        clear_ospf("blue")
-        clear_ospf("red")
         return
 
-    configure("bgpd_multi_vrf_prefix.conf")
+    configure_bgp("bgpd_multi_vrf_prefix.conf")
+    configure_ospf("ospfd_multi_vrf.conf")
     check_vrf_peer_change_passwords(vrf="blue", prefix="yes")
     check_all_peers_established("red")
     check_vrf_peer_change_passwords(vrf="red", prefix="yes")
     check_all_peers_established("blue")
-    clear_bgp("blue")
-    clear_bgp("red")
-    clear_ospf("blue")
-    clear_ospf("red")
     # tgen.mininet_cli()
 
 
diff --git a/tests/topotests/bgp-community-alias/__init__.py b/tests/topotests/bgp-community-alias/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp-community-alias/r1/bgpd.conf b/tests/topotests/bgp-community-alias/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..2cf84d0
--- /dev/null
@@ -0,0 +1,9 @@
+!
+bgp community alias 65002:1 community-r2-1
+bgp community alias 65002:2 community-r2-2
+bgp community alias 65002:1:1 large-community-r2-1
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+!
diff --git a/tests/topotests/bgp-community-alias/r1/zebra.conf b/tests/topotests/bgp-community-alias/r1/zebra.conf
new file mode 100644 (file)
index 0000000..b29940f
--- /dev/null
@@ -0,0 +1,4 @@
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/bgp-community-alias/r2/bgpd.conf b/tests/topotests/bgp-community-alias/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..517ef70
--- /dev/null
@@ -0,0 +1,12 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ address-family ipv4 unicast
+  redistribute connected
+  neighbor 192.168.1.1 route-map r1 out
+ exit-address-family
+!
+route-map r1 permit 10
+ set community 65002:1 65002:2
+ set large-community 65002:1:1 65002:2:1
+!
diff --git a/tests/topotests/bgp-community-alias/r2/zebra.conf b/tests/topotests/bgp-community-alias/r2/zebra.conf
new file mode 100644 (file)
index 0000000..cffe827
--- /dev/null
@@ -0,0 +1,4 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
diff --git a/tests/topotests/bgp-community-alias/test_bgp-community-alias.py b/tests/topotests/bgp-community-alias/test_bgp-community-alias.py
new file mode 100644 (file)
index 0000000..a43e5f9
--- /dev/null
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2021 by
+# Donatas Abraitis <donatas.abraitis@gmail.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Test if BGP community alias is visible in CLI outputs
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+    def build(self, *_args, **_opts):
+        tgen = get_topogen(self)
+
+        for routern in range(1, 3):
+            tgen.add_router("r{}".format(routern))
+
+        switch = tgen.add_switch("s1")
+        switch.add_link(tgen.gears["r1"])
+        switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+    tgen = Topogen(TemplateTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+
+    for i, (rname, router) in enumerate(router_list.items(), 1):
+        router.load_config(
+            TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+        )
+
+    tgen.start_router()
+
+
+def teardown_module(mod):
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+def test_bgp_community_alias():
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    router = tgen.gears["r1"]
+
+    def _bgp_converge(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp 192.168.1.0/24 json"))
+        expected = {
+            "paths": [
+                {
+                    "community": {"string": "community-r2-1 community-r2-2"},
+                    "largeCommunity": {"string": "large-community-r2-1 65002:2:1"},
+                }
+            ]
+        }
+        return topotest.json_cmp(output, expected)
+
+    test_func = functools.partial(_bgp_converge, router)
+    success, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+
+    assert result is None, 'Cannot see BGP community aliases "{}"'.format(router)
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
index c1dbf0ebecfa737138b82794be9f37fe6b662f77..f9aa94fd14d39291d1500c8e971c1b5edc08409f 100644 (file)
@@ -34,6 +34,8 @@ 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, "../"))
 
index 19c4c5f87dc55b3c6a01c98585966ca021931e3e..3b99065fe078e55f506490801b5c8e35c3ff38c4 100644 (file)
@@ -40,6 +40,8 @@ import time
 import pytest
 import functools
 
+pytestmark = [pytest.mark.bgpd]
+
 CWD = os.path.dirname(os.path.realpath(__file__))
 sys.path.append(os.path.join(CWD, "../"))
 
index b70626fcce250ea83843dda768fc0621039e49fb..ee57b9c4796e633fe1e05a9624fde17c2646c6df 100644 (file)
@@ -134,7 +134,6 @@ from lib.common_config import (
     check_router_status,
     shutdown_bringup_interface,
     step,
-    kill_mininet_routers_process,
     get_frr_ipv6_linklocal,
     create_route_maps,
     required_linux_kernel_version,
@@ -204,9 +203,6 @@ def setup_module(mod):
     tgen = Topogen(GenerateTopo, mod.__name__)
     # ... and here it calls Mininet initialization functions.
 
-    # Kill stale mininet routers and process
-    kill_mininet_routers_process(tgen)
-
     # Starting topology, create tmp files which are loaded to routers
     #  to start deamons and then start routers
     start_topology(tgen)
@@ -287,272 +283,6 @@ def next_hop_per_address_family(
     return next_hop
 
 
-def test_BGP_GR_TC_46_p1(request):
-    """
-    Test Objective : transition from Peer-level helper to Global Restarting
-    Global Mode : GR Restarting
-    PerPeer Mode :  GR Helper
-    GR Mode effective : GR Helper
-
-    """
-
-    tgen = get_topogen()
-    tc_name = request.node.name
-    write_test_header(tc_name)
-
-    # Check router status
-    check_router_status(tgen)
-
-    # Don't run this test if we have any failure.
-    if tgen.routers_have_failure():
-        pytest.skip(tgen.errors)
-
-    # Creating configuration from JSON
-    reset_config_on_routers(tgen)
-
-    step(
-        "Configure R1 and R2 as GR restarting node in global"
-        " and helper in per-Peer-level"
-    )
-
-    input_dict = {
-        "r1": {
-            "bgp": {
-                "graceful-restart": {
-                    "graceful-restart": True,
-                },
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                },
-            }
-        },
-        "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
-    }
-
-    configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
-    step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    step("Kill BGP on R2")
-
-    kill_router_daemons(tgen, "r2", ["bgpd"])
-
-    step(
-        "Verify that R1 keeps the stale entries in RIB & FIB and R2 keeps stale entries in FIB using"
-    )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, "r1", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    step(
-        "Bring up BGP on R1 and remove Peer-level GR config"
-        " from R1 following by a session reset"
-    )
-
-    start_router_daemons(tgen, "r2", ["bgpd"])
-
-    input_dict = {
-        "r1": {
-            "bgp": {
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": False}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-helper": False}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                }
-            }
-        }
-    }
-
-    result = create_router_bgp(tgen, topo, input_dict)
-    assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
-
-    step("Verify on R2 that R1 advertises GR capabilities as a restarting node")
-
-    input_dict = {
-        "r1": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
-        "r2": {"bgp": {"graceful-restart": {"graceful-restart": True}}},
-    }
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    step("Kill BGP on R1")
-
-    kill_router_daemons(tgen, "r1", ["bgpd"])
-
-    step(
-        "Verify that R1 keeps the stale entries in FIB command and R2 keeps stale entries in RIB & FIB"
-    )
-
-    for addr_type in ADDR_TYPES:
-        protocol = "bgp"
-        next_hop = next_hop_per_address_family(
-            tgen, "r1", "r2", addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {"r2": topo["routers"]["r2"]}
-        result = verify_rib(tgen, addr_type, "r1", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    for addr_type in ADDR_TYPES:
-        next_hop = next_hop_per_address_family(
-            tgen, "r2", "r1", addr_type, NEXT_HOP_IP_1
-        )
-        input_topo = {"r1": topo["routers"]["r1"]}
-        result = verify_bgp_rib(tgen, addr_type, "r2", input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_rib(tgen, addr_type, "r2", input_topo, next_hop, protocol)
-        assert (
-            result is True
-        ), "Testcase {} : Failed \n Routes are still present \n Error {}".format(
-            tc_name, result
-        )
-
-    step("Start BGP on R1")
-
-    start_router_daemons(tgen, "r1", ["bgpd"])
-
-    write_test_footer(tc_name)
-
-
 def BGP_GR_TC_50_p1(request):
     """
     Test Objective : Transition from Peer-level helper to Global inherit helper
@@ -1979,198 +1709,6 @@ def test_BGP_GR_TC_8_p1(request):
     write_test_footer(tc_name)
 
 
-def test_BGP_GR_TC_17_p1(request):
-    """
-    Test Objective : Verify that only GR helper routers keep the stale
-     route entries, not any GR disabled router.
-    """
-
-    tgen = get_topogen()
-    tc_name = request.node.name
-    write_test_header(tc_name)
-
-    # Check router status
-    check_router_status(tgen)
-
-    # Don't run this test if we have any failure.
-    if tgen.routers_have_failure():
-        pytest.skip(tgen.errors)
-
-    # Creating configuration from JSON
-    reset_config_on_routers(tgen)
-
-    logger.info("[Phase 1] : Test Setup [Disable]R1-----R2[Restart] initialized  ")
-
-    # Configure graceful-restart
-    input_dict = {
-        "r1": {
-            "bgp": {
-                "graceful-restart": {
-                    "graceful-restart": True,
-                    "preserve-fw-state": True,
-                },
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-disable": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r2": {
-                                    "dest_link": {
-                                        "r1-link1": {"graceful-restart-disable": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                },
-            }
-        },
-        "r2": {
-            "bgp": {
-                "address_family": {
-                    "ipv4": {
-                        "unicast": {
-                            "neighbor": {
-                                "r1": {
-                                    "dest_link": {
-                                        "r2-link1": {"graceful-restart": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                    "ipv6": {
-                        "unicast": {
-                            "neighbor": {
-                                "r1": {
-                                    "dest_link": {
-                                        "r2-link1": {"graceful-restart": True}
-                                    }
-                                }
-                            }
-                        }
-                    },
-                }
-            }
-        },
-    }
-
-    configure_gr_followed_by_clear(tgen, topo, input_dict, tc_name, dut="r1", peer="r2")
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        # Verifying BGP RIB routes
-        dut = "r1"
-        peer = "r2"
-        next_hop = next_hop_per_address_family(
-            tgen, dut, peer, addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {key: topo["routers"][key] for key in ["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        # Verifying RIB routes
-        protocol = "bgp"
-        result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    logger.info("[Phase 2] : R2 goes for reload  ")
-
-    kill_router_daemons(tgen, "r2", ["bgpd"])
-
-    logger.info(
-        "[Phase 3] : R2 is still down, restart time 120 sec."
-        " So time verify the routes are present in BGP RIB and ZEBRA  "
-    )
-
-    for addr_type in ADDR_TYPES:
-        # Verifying BGP RIB routes
-        next_hop = next_hop_per_address_family(
-            tgen, dut, peer, addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {key: topo["routers"][key] for key in ["r2"]}
-        result = verify_bgp_rib(
-            tgen, addr_type, dut, input_topo, next_hop, expected=False
-        )
-        assert result is not True, (
-            "Testcase {} : Failed \n "
-            "r1: routes are still present in BGP RIB\n Error: {}".format(
-                tc_name, result
-            )
-        )
-        logger.info(" Expected behavior: {}".format(result))
-
-        # Verifying RIB routes
-        result = verify_rib(
-            tgen, addr_type, dut, input_topo, next_hop, protocol, expected=False
-        )
-        assert result is not True, (
-            "Testcase {} : Failed \n "
-            "r1: routes are still present in ZEBRA\n Error: {}".format(tc_name, result)
-        )
-        logger.info(" Expected behavior: {}".format(result))
-
-    logger.info("[Phase 5] : R2 is about to come up now  ")
-    start_router_daemons(tgen, "r2", ["bgpd"])
-
-    logger.info("[Phase 4] : R2 is UP now, so time to collect GR stats  ")
-
-    for addr_type in ADDR_TYPES:
-        result = verify_graceful_restart(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2"
-        )
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        result = verify_r_bit(
-            tgen, topo, addr_type, input_dict, dut="r1", peer="r2", expected=False
-        )
-        assert (
-            result is not True
-        ), "Testcase {} : Failed \n " "r1: R-bit is set to True\n Error: {}".format(
-            tc_name, result
-        )
-
-        # Verifying BGP RIB routes
-        next_hop = next_hop_per_address_family(
-            tgen, dut, peer, addr_type, NEXT_HOP_IP_2
-        )
-        input_topo = {key: topo["routers"][key] for key in ["r2"]}
-        result = verify_bgp_rib(tgen, addr_type, dut, input_topo, next_hop)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-        # Verifying RIB routes
-        result = verify_rib(tgen, addr_type, dut, input_topo, next_hop, protocol)
-        assert result is True, "Testcase {} : Failed \n Error {}".format(
-            tc_name, result
-        )
-
-    write_test_footer(tc_name)
-
-
 def test_BGP_GR_TC_19_p1(request):
     """
     Test Objective : Verify that GR helper routers keeps all the routes received
index 9438b90ef890126925d587e109d47722fc609cd5..b6f8bf4cd9246404d5cb8b3bebb6006315fa65ee 100644 (file)
@@ -133,7 +133,6 @@ from lib.common_config import (
     check_router_status,
     shutdown_bringup_interface,
     step,
-    kill_mininet_routers_process,
     get_frr_ipv6_linklocal,
     create_route_maps,
     required_linux_kernel_version,
index cd845be29641256958eb92e92f176577c751997d..0df2c9cb5a31b0f769b224416f96832c6bfacc4f 100644 (file)
@@ -112,7 +112,7 @@ def test_protocols_convergence():
         test_func = partial(
             topotest.router_json_cmp,
             router,
-            "show ip route json".format(router.name),
+            "show ip route json",
             expected,
         )
         _, result = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
@@ -131,7 +131,7 @@ def test_protocols_convergence():
         test_func = partial(
             topotest.router_json_cmp,
             router,
-            "show ipv6 route json".format(router.name),
+            "show ipv6 route json",
             expected,
         )
         _, result = topotest.run_and_expect(test_func, None, count=160, wait=0.5)
index 5ecaee2ecebb67b5fb8cab4e208a2590550b6a7c..7ea5a24fd73f5663ee7b7a54990982859d0a63a6 100644 (file)
@@ -128,7 +128,6 @@ from lib.common_config import (
     create_static_routes,
     create_prefix_lists,
     create_interface_in_kernel,
-    kill_mininet_routers_process,
     create_bgp_community_lists,
     check_router_status,
     apply_raw_config,
@@ -229,9 +228,6 @@ def setup_module(mod):
     tgen = Topogen(CreateTopo, mod.__name__)
     # ... and here it calls Mininet initialization functions.
 
-    # Kill stale mininet routers and process
-    kill_mininet_routers_process(tgen)
-
     # Starting topology, create tmp files which are loaded to routers
     #  to start deamons and then start routers
     start_topology(tgen)
@@ -2677,14 +2673,12 @@ def test_route_map_within_vrf_to_alter_bgp_attribute_nexthop_p0(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because"
-        " nexthop-self config is deleted \n Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because nexthop-self config is deleted \n Error {}".format(tc_name, result)
 
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because"
-        " nexthop-self config is deleted \n Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behaviour: Routes are rejected because nexthop-self config is deleted \n Error {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
@@ -4958,8 +4952,7 @@ def test_prefix_list_to_permit_deny_prefixes_p0(request):
 
         result = verify_rib(tgen, addr_type, dut, denied_routes, expected=False)
         assert result is not True, "Testcase {} : Failed \n"
-        "Expected behaviour: Routes are denied by prefix-list \n"
-        "Error {}".format(tc_name, result)
+        "{}:Expected behaviour: Routes are denied by prefix-list \nError {}".format(tc_name, result)
 
     step(
         "On router R1, configure prefix-lists to permit 2 "
@@ -5169,9 +5162,7 @@ def test_prefix_list_to_permit_deny_prefixes_p0(request):
         )
 
         result = verify_rib(tgen, addr_type, dut, denied_routes, expected=False)
-        assert result is not True, "Testcase {} : Failed \n"
-        "Expected behaviour: Routes are denied by prefix-list \n"
-        "Error {}".format(tc_name, result)
+        assert result is not True, "Testcase {} : Failed \nExpected behaviour: Routes are denied by prefix-list \nError {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
@@ -5449,8 +5440,7 @@ def test_route_map_set_and_match_tag_p0(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \n"
-        "Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \nError {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
@@ -5853,8 +5843,7 @@ def test_route_map_set_and_match_metric_p0(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert (
             result is not True
-        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \n"
-        "Error {}".format(tc_name, result)
+        ), "Testcase {} : Failed \n Expected Behavior: Routes are denied \nError {}".format(tc_name, result)
 
     write_test_footer(tc_name)
 
index c8d13301225aecf82a9613567da1fbb723c4f070..37da53fc31fddf247e2d5f206ddf0792214e2f53 100644 (file)
@@ -87,7 +87,6 @@ from lib.common_config import (
     create_vrf_cfg,
     create_interfaces_cfg,
     create_interface_in_kernel,
-    kill_mininet_routers_process,
     get_frr_ipv6_linklocal,
     check_router_status,
     apply_raw_config,
@@ -182,9 +181,6 @@ def setup_module(mod):
     tgen = Topogen(CreateTopo, mod.__name__)
     # ... and here it calls Mininet initialization functions.
 
-    # Kill stale mininet routers and process
-    kill_mininet_routers_process(tgen)
-
     # Starting topology, create tmp files which are loaded to routers
     #  to start deamons and then start routers
     start_topology(tgen)
@@ -1571,9 +1567,7 @@ def test_shut_noshut_p1(request):
         sleep(HOLDDOWNTIMER + 1)
 
         result = verify_bgp_convergence(tgen, topo, expected=False)
-        assert result is not True, "Testcase {} : Failed \n "
-        "Expected Behaviour: BGP will not be converged \n "
-        "Error {}".format(tc_name, result)
+        assert result is not True, "Testcase {} : Failed \nExpected Behaviour: BGP will not be converged \nError {}".format(tc_name, result)
 
         for addr_type in ADDR_TYPES:
             dut = "r2"
@@ -1616,14 +1610,10 @@ def test_shut_noshut_p1(request):
             }
 
             result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
-            assert result is not True, "Testcase {} : Failed \n "
-            " Expected Behaviour: Routes are flushed out \n "
-            "Error {}".format(tc_name, result)
+            assert result is not True, "Testcase {} : Failed \nExpected Behaviour: Routes are flushed out \nError {}".format(tc_name, result)
 
             result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
-            assert result is not True, "Testcase {} : Failed \n "
-            " Expected Behaviour: Routes are flushed out \n "
-            "Error {}".format(tc_name, result)
+            assert result is not True, "Testcase {} : Failed \nExpected Behaviour: Routes are flushed out \nError {}".format(tc_name, result)
 
         step("Bring up connecting interface between R1<<>>R2 on R1.")
         for intf in interfaces:
@@ -1862,8 +1852,7 @@ def test_vrf_vlan_routing_table_p1(request):
             result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
             assert (
                 result is not True
-            ), "Testcase {} : Failed \n Expected Behaviour: Routes are"
-            " cleaned \n Error {}".format(tc_name, result)
+            ), "Testcase {} : Failed \n Expected Behaviour: Routes are cleaned \n Error {}".format(tc_name, result)
 
         step("Add/reconfigure the same VRF instance again")
 
@@ -2180,7 +2169,7 @@ def test_restart_bgpd_daemon_p1(request):
     assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
 
     result = verify_bgp_convergence(tgen, topo)
-    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("Kill BGPd daemon on R1.")
     kill_router_daemons(tgen, "r1", ["bgpd"])
@@ -3392,14 +3381,12 @@ def test_vrf_name_significance_p1(request):
         result = verify_rib(tgen, addr_type, dut, input_dict_1, expected=False)
         assert (
             result is not True
-        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-        " present \n Error {}".format(tc_name, result)
+        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
 
         result = verify_bgp_rib(tgen, addr_type, dut, input_dict_1, expected=False)
         assert (
             result is not True
-        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-        " present \n Error {}".format(tc_name, result)
+        ), "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
 
     for addr_type in ADDR_TYPES:
         dut = "blue2"
@@ -3417,14 +3404,12 @@ def test_vrf_name_significance_p1(request):
 
         result = verify_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert result is not True, (
-            "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-            " present \n Error {}".format(tc_name, result)
+            "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
         )
 
         result = verify_bgp_rib(tgen, addr_type, dut, input_dict_2, expected=False)
         assert result is not True, (
-            "Testcase {} :Failed \n Expected Behaviour: Routes are not"
-            " present \n Error {}".format(tc_name, result)
+            "Testcase {} :Failed \n Expected Behaviour: Routes are not present \n Error {}".format(tc_name, result)
         )
 
     step("Create 2 new VRFs PINK_A and GREY_A IN R3")
index 9e30bf2ef09203c7e056b18c1a1cfe89d6df5beb..6b20e1df5a3401badf2810f60f57c9264a48b1e3 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * 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
 *  10.0.1.0/24      172.16.1.5                             0 65005 i
index 2cf87487abdc6a6bfe44f79913885b6e804dde02..5469eaa1cc070ae4f21ba58bb80ca6c9833215ac 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * 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
 *  10.0.1.0/24      172.16.1.5                             0 65005 i
index 39eb3134bed4e95e1cd32096d049c224659ee6f0..a64927c92d7f4a7944928a7a105d7a88e3e38dbe 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * 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
 *  10.0.1.0/24      172.16.1.4                             0 65004 i
index 9d1b948b5cf04eac60b4635bbbad8bab361850d4..8d4a843b843d44935d4a9d0112b1cb621eb3b505 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * 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
 *  10.0.1.0/24      172.16.1.4                             0 65004 i
index fa53d79e8814c44063ec55f34c9fd03db50def77..a3b9ef0888998b4eb50455bf9a55acf636f90a4e 100644 (file)
@@ -3,6 +3,7 @@ Status codes:  s suppressed, d damped, h history, * 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
 *  10.0.1.0/24      172.16.1.8                             0 65008 i
index 8b66fa67ec32c35b7381d7735bd5ed9a00af5448..117e48847ae5ed92f72c9c1926f7103156bf3472 100644 (file)
@@ -4,6 +4,7 @@ Status codes:  s suppressed, d damped, h history, * 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
 *  10.0.1.0/24      172.16.1.8                             0 65008 i
index 2a98cb341dcbc7c5b0f598c7691e9c78b3771b5d..c758c31dc1cc829848c6a9414b4258c376ce5504 100644 (file)
@@ -71,7 +71,6 @@ from lib.common_config import (
     shutdown_bringup_interface,
     addKernelRoute,
     delete_route_maps,
-    kill_mininet_routers_process,
 )
 from lib.topolog import logger
 from lib.bgp import (
diff --git a/tests/topotests/bgp_tcp_mss/__init__.py b/tests/topotests/bgp_tcp_mss/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/bgp_tcp_mss/r1/bgpd.conf b/tests/topotests/bgp_tcp_mss/r1/bgpd.conf
new file mode 100644 (file)
index 0000000..07cfe2e
--- /dev/null
@@ -0,0 +1,6 @@
+router bgp 65000
+  no bgp ebgp-requires-policy
+  neighbor 192.168.255.2 remote-as 65001
+  neighbor 192.168.255.2 timers 3 10
+  exit-address-family
+!
diff --git a/tests/topotests/bgp_tcp_mss/r1/zebra.conf b/tests/topotests/bgp_tcp_mss/r1/zebra.conf
new file mode 100644 (file)
index 0000000..6e9b0b4
--- /dev/null
@@ -0,0 +1,6 @@
+!
+interface r1-eth0
+  ip address 192.168.255.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_tcp_mss/r2/bgpd.conf b/tests/topotests/bgp_tcp_mss/r2/bgpd.conf
new file mode 100644 (file)
index 0000000..b2d9455
--- /dev/null
@@ -0,0 +1,6 @@
+router bgp 65001
+  no bgp ebgp-requires-policy
+  neighbor 192.168.255.1 remote-as 65000
+  neighbor 192.168.255.1 timers 3 10
+  exit-address-family
+!
diff --git a/tests/topotests/bgp_tcp_mss/r2/zebra.conf b/tests/topotests/bgp_tcp_mss/r2/zebra.conf
new file mode 100644 (file)
index 0000000..6c14de5
--- /dev/null
@@ -0,0 +1,6 @@
+!
+interface r2-eth0
+  ip address 192.168.255.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py b/tests/topotests/bgp_tcp_mss/test_bgp_tcp_mss.py
new file mode 100644 (file)
index 0000000..7500c3b
--- /dev/null
@@ -0,0 +1,178 @@
+#!/usr/bin/env python
+
+#
+# bgp_tcp_mss.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 by
+# Abhinay Ramesh <rabhinay@vmware.com>
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+bgp_tcp_mss.py:
+
+Test if works the following commands:
+router bgp 65000
+  neighbor 192.168.255.2 tcp-mss 500
+
+Need to verify if the tcp-mss value is reflected in the TCP session.
+"""
+
+import os
+import sys
+import json
+import time
+import pytest
+import functools
+
+# add after imports, before defining classes or functions:
+pytestmark = [pytest.mark.bgpd]
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.topolog import logger
+from mininet.topo import Topo
+
+
+class TemplateTopo(Topo):
+    def build(self, *_args, **_opts):
+        tgen = get_topogen(self)
+
+        for routern in range(1, 3):
+            tgen.add_router("r{}".format(routern))
+
+        switch = tgen.add_switch("s1")
+        switch.add_link(tgen.gears["r1"])
+        switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+    tgen = Topogen(TemplateTopo, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+
+    for i, (rname, router) in enumerate(router_list.items(), 1):
+        router.load_config(
+            TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+        )
+        router.load_config(
+            TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+        )
+
+    tgen.start_router()
+
+
+def teardown_module(mod):
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+def test_bgp_tcp_mss():
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    router1 = tgen.gears["r1"]
+    router2 = tgen.gears["r2"]
+
+    def _bgp_converge(router):
+        output = json.loads(router.vtysh_cmd("show ip bgp neighbor 192.168.255.2 json"))
+        expected = {
+            "192.168.255.2": {
+                "bgpState": "Established",
+                "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 0}},
+            }
+        }
+        return topotest.json_cmp(output, expected)
+
+    def _bgp_conf_tcp_mss(router, as_num, neigh):
+        router.vtysh_cmd(
+            """configure terminal
+               router bgp {0}
+                 neighbor {1} tcp-mss 500""".format(
+                as_num, neigh
+            )
+        )
+
+    def _bgp_clear_session(router):
+        router.vtysh_cmd("clear bgp *")
+
+    def _bgp_check_neighbor_tcp_mss(router, neigh):
+        output = json.loads(router.vtysh_cmd("show bgp neighbor {} json".format(neigh)))
+        expected = {
+            "{}".format(neigh): {"bgpTcpMssConfigured": 500, "bgpTcpMssSynced": 488}
+        }
+        return topotest.json_cmp(output, expected)
+
+    logger.info("Check if neighbor sessions are up in {}".format(router1.name))
+    test_func = functools.partial(_bgp_converge, router1)
+    success, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5)
+    assert result is None, 'Failed to see BGP convergence in "{}"'.format(router1.name)
+
+    logger.info("BGP neighbor session is up in {}".format(router1.name))
+
+    logger.info(
+        "Configure tcp-mss 500 on {} and reset the session".format(router1.name)
+    )
+    _bgp_conf_tcp_mss(router1, "65000", "192.168.255.2")
+    _bgp_clear_session(router1)
+
+    logger.info(
+        "Configure tcp-mss 500 on {} and reset the session".format(router2.name)
+    )
+    _bgp_conf_tcp_mss(router2, "65001", "192.168.255.1")
+    _bgp_clear_session(router2)
+
+    logger.info(
+        "Check if neighbor session is up after reset in {}".format(router1.name)
+    )
+    test_func = functools.partial(_bgp_converge, router1)
+    success, result = topotest.run_and_expect(test_func, None, count=15, wait=0.5)
+    assert result is None, 'Failed to see BGP convergence after reset in "{}"'.format(
+        router1.name
+    )
+
+    logger.info(
+        "Verify if TCP MSS value is synced with neighbor in {}".format(router1.name)
+    )
+    test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router1, "192.168.255.2")
+    success, result = topotest.run_and_expect(test_func, None, count=3, wait=0.5)
+    assert (
+        result is None
+    ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router1.name)
+    logger.info("TCP MSS value is synced with neighbor in {}".format(router1.name))
+
+    logger.info(
+        "Verify if TCP MSS value is synced with neighbor in {}".format(router2.name)
+    )
+    test_func = functools.partial(_bgp_check_neighbor_tcp_mss, router2, "192.168.255.1")
+    success, result = topotest.run_and_expect(test_func, None, count=3, wait=0.5)
+    assert (
+        result is None
+    ), 'Failed to sync TCP MSS value over BGP session in "{}"'.format(router2.name)
+    logger.info("TCP MSS value is synced with neighbor in {}".format(router2.name))
+
+
+if __name__ == "__main__":
+    args = ["-s"] + sys.argv[1:]
+    sys.exit(pytest.main(args))
index 291a6e7c3a9f2d64eeabba71f0fd8771236d3d53..83682fb36d37460117be33cec49bea9b49dac16a 100644 (file)
@@ -224,6 +224,7 @@ def disable_route_map_to_prefer_global_next_hop(tgen, topo):
 
     """
 
+    tc_name = request.node.name
     logger.info("Remove prefer-global rmap applied on neighbors")
     input_dict = {
         "r1": {
index cf64956bfd22c11713b823cee0d6c09f82432cd3..de5c584e919534738c8ad7d7b9121aa8ea058f62 100755 (executable)
@@ -62,6 +62,7 @@ def pytest_addoption(parser):
     parser.addoption(
         "--topology-only",
         action="store_true",
+        default=False,
         help="Only set up this topology, don't run tests",
     )
 
index 07f3335e237ee71533816a4781eadec786bccabf..04e043847d8cb5003a98318520351c43f96a5d2e 100755 (executable)
@@ -243,15 +243,15 @@ def test_r1_scalar_snmp():
 
 
 circtable_test = {
-    "isisCircAdminState": ["on(1)", "on(1)", "on(1)"],
-    "isisCircExistState": ["active(1)", "active(1)", "active(1)"],
-    "isisCircType": ["broadcast(1)", "ptToPt(2)", "staticIn(3)"],
-    "isisCircExtDomain": ["false(2)", "false(2)", "false(2)"],
-    "isisCircLevelType": ["level1(1)", "level1(1)", "level1and2(3)"],
-    "isisCircPassiveCircuit": ["false(2)", "false(2)", "true(1)"],
-    "isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)", "inactive(1)"],
-    "isisCircSmallHellos": ["false(2)", "false(2)", "false(2)"],
-    "isisCirc3WayEnabled": ["false(2)", "false(2)", "false(2)"],
+    "isisCircAdminState": ["on(1)", "on(1)"],
+    "isisCircExistState": ["active(1)", "active(1)"],
+    "isisCircType": ["broadcast(1)", "ptToPt(2)"],
+    "isisCircExtDomain": ["false(2)", "false(2)"],
+    "isisCircLevelType": ["level1(1)", "level1(1)"],
+    "isisCircPassiveCircuit": ["false(2)", "false(2)"],
+    "isisCircMeshGroupEnabled": ["inactive(1)", "inactive(1)"],
+    "isisCircSmallHellos": ["false(2)", "false(2)"],
+    "isisCirc3WayEnabled": ["false(2)", "false(2)"],
 }
 
 
@@ -266,7 +266,6 @@ def test_r1_isisCircTable():
     oids = []
     oids.append(generate_oid(1, 1, 0))
     oids.append(generate_oid(1, 2, 0))
-    oids.append(generate_oid(1, 3, 0))
 
     # check items
     for item in circtable_test.keys():
@@ -277,21 +276,17 @@ def test_r1_isisCircTable():
 
 
 circleveltable_test = {
-    "isisCircLevelMetric": ["10", "10", "10", "10"],
-    "isisCircLevelWideMetric": ["10", "10", "0", "0"],
-    "isisCircLevelISPriority": ["64", "64", "64", "64"],
-    "isisCircLevelHelloMultiplier": ["10", "10", "10", "10"],
+    "isisCircLevelMetric": ["10", "10"],
+    "isisCircLevelWideMetric": ["10", "10"],
+    "isisCircLevelISPriority": ["64", "64"],
+    "isisCircLevelHelloMultiplier": ["10", "10"],
     "isisCircLevelHelloTimer": [
         "3000 milliseconds",
         "3000 milliseconds",
-        "3000 milliseconds",
-        "3000 milliseconds",
     ],
     "isisCircLevelMinLSPRetransInt": [
         "1 seconds",
         "1 seconds",
-        "0 seconds",
-        "0 seconds",
     ],
 }
 
@@ -307,8 +302,6 @@ def test_r1_isislevelCircTable():
     oids = []
     oids.append(generate_oid(2, 1, "area"))
     oids.append(generate_oid(2, 2, "area"))
-    oids.append(generate_oid(2, 3, "area"))
-    oids.append(generate_oid(2, 3, "domain"))
 
     # check items
     for item in circleveltable_test.keys():
index 148a89474e10269269140f2266d1e08ac439f725..c22bd65d2d6c07c0f59c730162a2a88cc6f28633 100644 (file)
@@ -1002,6 +1002,12 @@ def test_isis_adjacencies_step12():
     tgen.net["rt4"].cmd(
         'vtysh -c "conf t" -c "interface eth-rt5" -c "ipv6 router isis 1"'
     )
+    tgen.net["rt4"].cmd(
+        'vtysh -c "conf t" -c "interface eth-rt5" -c "isis network point-to-point"'
+    )
+    tgen.net["rt4"].cmd(
+        'vtysh -c "conf t" -c "interface eth-rt5" -c "isis hello-multiplier 3"'
+    )
     tgen.net["rt6"].cmd(
         'vtysh -c "conf t" -c "router isis 1" -c "segment-routing global-block 16000 23999"'
     )
index 6d2bbb80c9fb8ce81bc7a94f43bf6c3d871b1e90..337d6bf5ef08ab5b6f6aa51240b6e259e6759af1 100644 (file)
@@ -18,9 +18,9 @@
           "vertex": "r1"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r1(4)",
+          "type": "IP internal",
           "vertex": "10.0.20.0/24"
         },
         {
           "vertex": "r3"
         },
         {
-          "interface": "r3",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r1-eth0",
-          "type": "IP",
+          "interface": "r1-eth0",
+          "metric": "10",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.0.10.0/24"
         },
         {
-          "interface": "r3",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r1-eth0",
-          "type": "IP",
+          "interface": "r1-eth0",
+          "metric": "10",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.0.20.0/24"
         },
         {
-          "interface": "r3",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r1-eth0",
-          "type": "IP",
+          "interface": "r1-eth0",
+          "metric": "10",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.3/32"
         }
       ],
@@ -61,9 +61,9 @@
           "vertex": "r1"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r1(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:1::/64"
         },
         {
           "vertex": "r3"
         },
         {
-          "interface": "r3",
-          "next-hop": "10",
-          "parent": "r1-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r1-eth0",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:1::/64"
         },
         {
-          "interface": "r3",
-          "next-hop": "10",
-          "parent": "r1-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r1-eth0",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::3/128"
         }
       ]
index 396c618caa07c4449dc7065154ed04061bf247dd..de90fb5a32d07ba8a083534a66225cd350a30660 100644 (file)
@@ -18,9 +18,9 @@
           "vertex": "r2"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r2(4)",
+          "type": "IP internal",
           "vertex": "10.0.21.0/24"
         },
         {
           "vertex": "r4"
         },
         {
-          "interface": "r4",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r2-eth0",
-          "type": "IP",
+          "interface": "r2-eth0",
+          "metric": "10",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.0.11.0/24"
         },
         {
-          "interface": "r4",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r2-eth0",
-          "type": "IP",
+          "interface": "r2-eth0",
+          "metric": "10",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.0.21.0/24"
         },
         {
-          "interface": "r4",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r2-eth0",
-          "type": "IP",
+          "interface": "r2-eth0",
+          "metric": "10",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.4/32"
         }
       ],
@@ -61,9 +61,9 @@
           "vertex": "r2"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r2(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:2::/64"
         },
         {
           "vertex": "r4"
         },
         {
-          "interface": "r4",
-          "next-hop": "10",
-          "parent": "r2-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r2-eth0",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:2::/64"
         },
         {
-          "interface": "r4",
-          "next-hop": "10",
-          "parent": "r2-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r2-eth0",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::4/128"
         }
       ]
index 5ab58c41a63624e5adadddef67b07644da321464..2d36f9b427aa0b845a671a89a0025feeb20dcc18 100644 (file)
@@ -6,9 +6,9 @@
           "vertex": "r3"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r3(4)",
+          "type": "IP internal",
           "vertex": "10.0.10.0/24"
         },
         {
           "vertex": "r5"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r3-eth1",
-          "type": "IP",
+          "interface": "r3-eth1",
+          "metric": "10",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP TE",
           "vertex": "10.0.10.0/24"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r3-eth1",
-          "type": "IP",
+          "interface": "r3-eth1",
+          "metric": "10",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP TE",
           "vertex": "10.0.11.0/24"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r3-eth1",
-          "type": "IP",
+          "interface": "r3-eth1",
+          "metric": "10",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.5/32"
         },
         {
           "vertex": "r4"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "20",
-          "parent": "r3-eth1",
-          "type": "IP",
+          "interface": "r3-eth1",
+          "metric": "20",
+          "next-hop": "r5",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.0.21.0/24"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "20",
-          "parent": "r3-eth1",
-          "type": "IP",
+          "interface": "r3-eth1",
+          "metric": "20",
+          "next-hop": "r5",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.4/32"
         }
       ],
@@ -72,9 +72,9 @@
           "vertex": "r3"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:1::/64"
         },
         {
           "vertex": "r5"
         },
         {
-          "interface": "r5",
-          "next-hop": "10",
-          "parent": "r3-eth1",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r3-eth1",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:2::/64"
         },
         {
-          "interface": "r5",
-          "next-hop": "10",
-          "parent": "r3-eth1",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r3-eth1",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::5/128"
         },
         {
           "vertex": "r4"
         },
         {
-          "interface": "r5",
-          "next-hop": "20",
-          "parent": "r3-eth1",
-          "type": "IP6",
+          "metric": "20",
+          "interface": "r3-eth1",
+          "next-hop": "r5",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:2::/64"
         },
         {
-          "interface": "r5",
-          "next-hop": "20",
-          "parent": "r3-eth1",
-          "type": "IP6",
+          "metric": "20",
+          "interface": "r3-eth1",
+          "next-hop": "r5",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::4/128"
         }
       ]
           "vertex": "r3"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r3(4)",
+          "type": "IP internal",
           "vertex": "10.0.20.0/24"
         },
         {
           "vertex": "r1"
         },
         {
-          "interface": "r1",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r3-eth0",
-          "type": "IP",
+          "interface": "r3-eth0",
+          "metric": "10",
+          "next-hop": "r1",
+          "parent": "r1(4)",
+          "type": "IP TE",
           "vertex": "10.0.20.0/24"
         },
         {
-          "interface": "r1",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r3-eth0",
-          "type": "IP",
+          "interface": "r3-eth0",
+          "metric": "10",
+          "next-hop": "r1",
+          "parent": "r1(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.1/32"
         }
       ],
           "vertex": "r3"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:1::/64"
         },
         {
           "vertex": "r1"
         },
         {
-          "interface": "r1",
-          "next-hop": "10",
-          "parent": "r3-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r3-eth0",
+          "next-hop": "r1",
+          "parent": "r1(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::1/128"
         }
       ]
index ae74a609489a9d523ba3545540625ed23befbfd1..e7d78419127be0dde4362e8e7261aef135213e3f 100644 (file)
@@ -6,9 +6,9 @@
           "vertex": "r4"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r4(4)",
+          "type": "IP internal",
           "vertex": "10.0.11.0/24"
         },
         {
           "vertex": "r5"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r4-eth1",
-          "type": "IP",
+          "interface": "r4-eth1",
+          "metric": "10",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP TE",
           "vertex": "10.0.10.0/24"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r4-eth1",
-          "type": "IP",
+          "interface": "r4-eth1",
+          "metric": "10",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP TE",
           "vertex": "10.0.11.0/24"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r4-eth1",
-          "type": "IP",
+          "interface": "r4-eth1",
+          "metric": "10",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.5/32"
         },
         {
           "vertex": "r3"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "20",
-          "parent": "r4-eth1",
-          "type": "IP",
+          "interface": "r4-eth1",
+          "metric": "20",
+          "next-hop": "r5",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.0.20.0/24"
         },
         {
-          "interface": "r5",
-          "metric": "TE",
-          "next-hop": "20",
-          "parent": "r4-eth1",
-          "type": "IP",
+          "interface": "r4-eth1",
+          "metric": "20",
+          "next-hop": "r5",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.3/32"
         }
       ],
@@ -72,9 +72,9 @@
           "vertex": "r4"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:2::/64"
         },
         {
           "vertex": "r5"
         },
         {
-          "interface": "r5",
-          "next-hop": "10",
-          "parent": "r4-eth1",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r4-eth1",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:1::/64"
         },
         {
-          "interface": "r5",
-          "next-hop": "10",
-          "parent": "r4-eth1",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r4-eth1",
+          "next-hop": "r5",
+          "parent": "r5(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::5/128"
         },
         {
           "vertex": "r3"
         },
         {
-          "interface": "r5",
-          "next-hop": "20",
-          "parent": "r4-eth1",
-          "type": "IP6",
+          "metric": "20",
+          "interface": "r4-eth1",
+          "next-hop": "r5",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:1::/64"
         },
         {
-          "interface": "r5",
-          "next-hop": "20",
-          "parent": "r4-eth1",
-          "type": "IP6",
+          "metric": "20",
+          "interface": "r4-eth1",
+          "next-hop": "r5",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::3/128"
         }
       ]
           "vertex": "r4"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r4(4)",
+          "type": "IP internal",
           "vertex": "10.0.21.0/24"
         },
         {
           "vertex": "r2"
         },
         {
-          "interface": "r2",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r4-eth0",
-          "type": "IP",
+          "interface": "r4-eth0",
+          "metric": "10",
+          "next-hop": "r2",
+          "parent": "r2(4)",
+          "type": "IP TE",
           "vertex": "10.0.21.0/24"
         },
         {
-          "interface": "r2",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r4-eth0",
-          "type": "IP",
+          "interface": "r4-eth0",
+          "metric": "10",
+          "next-hop": "r2",
+          "parent": "r2(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.2/32"
         }
       ],
           "vertex": "r4"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:2::/64"
         },
         {
           "vertex": "r2"
         },
         {
-          "interface": "r2",
-          "next-hop": "10",
-          "parent": "r4-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r4-eth0",
+          "next-hop": "r2",
+          "parent": "r2(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::2/128"
         }
       ]
index 0224661411b434bd71f484e5e9690dfe9bd4e851..3d887b7cea69e6196641584a444a24e4c5118841 100644 (file)
@@ -6,15 +6,15 @@
           "vertex": "r5"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r5(4)",
+          "type": "IP internal",
           "vertex": "10.0.10.0/24"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP",
+          "metric": "0",
+          "parent": "r5(4)",
+          "type": "IP internal",
           "vertex": "10.0.11.0/24"
         },
         {
           "vertex": "r4"
         },
         {
-          "interface": "r3",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r5-eth0",
-          "type": "IP",
+          "interface": "r5-eth0",
+          "metric": "10",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.0.10.0/24"
         },
         {
-          "interface": "r3",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r5-eth0",
-          "type": "IP",
+          "interface": "r5-eth0",
+          "metric": "10",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.0.20.0/24"
         },
         {
-          "interface": "r3",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r5-eth0",
-          "type": "IP",
+          "interface": "r5-eth0",
+          "metric": "10",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.3/32"
         },
         {
-          "interface": "r4",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r5-eth1",
-          "type": "IP",
+          "interface": "r5-eth1",
+          "metric": "10",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.0.11.0/24"
         },
         {
-          "interface": "r4",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r5-eth1",
-          "type": "IP",
+          "interface": "r5-eth1",
+          "metric": "10",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.0.21.0/24"
         },
         {
-          "interface": "r4",
-          "metric": "TE",
-          "next-hop": "10",
-          "parent": "r5-eth1",
-          "type": "IP",
+          "interface": "r5-eth1",
+          "metric": "10",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP TE",
           "vertex": "10.254.0.4/32"
         }
       ],
           "vertex": "r5"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r5(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:1::/64"
         },
         {
-          "metric": "internal",
-          "parent": "0",
-          "type": "IP6",
+          "metric": "0",
+          "parent": "r5(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:2:2::/64"
         },
         {
           "vertex": "r4"
         },
         {
-          "interface": "r3",
-          "next-hop": "10",
-          "parent": "r5-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r5-eth0",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:1::/64"
         },
         {
-          "interface": "r3",
-          "next-hop": "10",
-          "parent": "r5-eth0",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r5-eth0",
+          "next-hop": "r3",
+          "parent": "r3(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::3/128"
         },
         {
-          "interface": "r4",
-          "next-hop": "10",
-          "parent": "r5-eth1",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r5-eth1",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:1:2::/64"
         },
         {
-          "interface": "r4",
-          "next-hop": "10",
-          "parent": "r5-eth1",
-          "type": "IP6",
+          "metric": "10",
+          "interface": "r5-eth1",
+          "next-hop": "r4",
+          "parent": "r4(4)",
+          "type": "IP6 internal",
           "vertex": "2001:db8:f::4/128"
         }
       ]
index e7618c7bce7ebce7b495904624ff6886ec8526dc..083a8b1e8d659490edfa7287db464218bf259dcb 100644 (file)
@@ -47,6 +47,20 @@ from mininet.topo import Topo
 
 pytestmark = [pytest.mark.isisd]
 
+VERTEX_TYPE_LIST = [
+    "pseudo_IS",
+    "pseudo_TE-IS",
+    "IS",
+    "TE-IS",
+    "ES",
+    "IP internal",
+    "IP external",
+    "IP TE",
+    "IP6 internal",
+    "IP6 external",
+    "UNKNOWN",
+]
+
 
 class ISISTopo1(Topo):
     "Simple two layer ISIS topology"
@@ -263,6 +277,7 @@ def parse_topology(lines, level):
     areas = {}
     area = None
     ipv = None
+    vertex_type_regex = "|".join(VERTEX_TYPE_LIST)
 
     for line in lines:
         area_match = re.match(r"Area (.+):", line)
@@ -282,44 +297,57 @@ def parse_topology(lines, level):
             ipv = "ipv4"
             continue
 
-        item_match = re.match(r"([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)", line)
-        if item_match is not None:
+        item_match = re.match(
+            r"([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+) ([^\s]+)", line
+        )
+        if (
+            item_match is not None
+            and item_match.group(1) == "Vertex"
+            and item_match.group(2) == "Type"
+            and item_match.group(3) == "Metric"
+            and item_match.group(4) == "Next-Hop"
+            and item_match.group(5) == "Interface"
+            and item_match.group(6) == "Parent"
+        ):
             # Skip header
-            if (
-                item_match.group(1) == "Vertex"
-                and item_match.group(2) == "Type"
-                and item_match.group(3) == "Metric"
-                and item_match.group(4) == "Next-Hop"
-                and item_match.group(5) == "Interface"
-                and item_match.group(6) == "Parent"
-            ):
-                continue
+            continue
 
+        item_match = re.match(
+            r"([^\s]+) ({}) ([0]|([1-9][0-9]*)) ([^\s]+) ([^\s]+) ([^\s]+)".format(
+                vertex_type_regex
+            ),
+            line,
+        )
+        if item_match is not None:
             areas[area][level][ipv].append(
                 {
                     "vertex": item_match.group(1),
                     "type": item_match.group(2),
                     "metric": item_match.group(3),
-                    "next-hop": item_match.group(4),
-                    "interface": item_match.group(5),
-                    "parent": item_match.group(6),
+                    "next-hop": item_match.group(5),
+                    "interface": item_match.group(6),
+                    "parent": item_match.group(7),
                 }
             )
             continue
 
-        item_match = re.match(r"([^ ]+) ([^ ]+) ([^ ]+) ([^ ]+)", line)
+        item_match = re.match(
+            r"([^\s]+) ({}) ([0]|([1-9][0-9]*)) ([^\s]+)".format(vertex_type_regex),
+            line,
+        )
+
         if item_match is not None:
             areas[area][level][ipv].append(
                 {
                     "vertex": item_match.group(1),
                     "type": item_match.group(2),
                     "metric": item_match.group(3),
-                    "parent": item_match.group(4),
+                    "parent": item_match.group(5),
                 }
             )
             continue
 
-        item_match = re.match(r"([^ ]+)", line)
+        item_match = re.match(r"([^\s]+)", line)
         if item_match is not None:
             areas[area][level][ipv].append({"vertex": item_match.group(1)})
             continue
index 9cb70a4758d7c314557c8cc7ea1579bbe848ef49..7180f84d1afea70172b4a19e4be7942d9df9bb2c 100644 (file)
@@ -1,7 +1,7 @@
 {
   "r3-eth1":{
     "ldpIgpSyncEnabled":false,
-    "holdDownTimeInSec":50,
+    "holdDownTimeInSec":0,
     "ldpIgpSyncState":"Sync not required"
   },
   "r3-eth2":{
index 9cb70a4758d7c314557c8cc7ea1579bbe848ef49..7180f84d1afea70172b4a19e4be7942d9df9bb2c 100644 (file)
@@ -1,7 +1,7 @@
 {
   "r3-eth1":{
     "ldpIgpSyncEnabled":false,
-    "holdDownTimeInSec":50,
+    "holdDownTimeInSec":0,
     "ldpIgpSyncState":"Sync not required"
   },
   "r3-eth2":{
index 9cb70a4758d7c314557c8cc7ea1579bbe848ef49..7180f84d1afea70172b4a19e4be7942d9df9bb2c 100644 (file)
@@ -1,7 +1,7 @@
 {
   "r3-eth1":{
     "ldpIgpSyncEnabled":false,
-    "holdDownTimeInSec":50,
+    "holdDownTimeInSec":0,
     "ldpIgpSyncState":"Sync not required"
   },
   "r3-eth2":{
index d2212d180756f36aafc3f0fe58b226cf3946c145..50cb586acdfef0642c7b70c8a4a61bf0b58534b1 100644 (file)
@@ -1309,7 +1309,6 @@ def verify_bgp_community(
 
     command = "show bgp"
 
-    sleep(5)
     for net in network:
         if vrf:
             cmd = "{} vrf {} {} {} json".format(command, vrf, addr_type, net)
index ead593d2ca6ec9a6e507a9929db66b29d24318d5..ba6004861eeb23c7b74b56baeeef5d9e2cf091de 100644 (file)
@@ -401,30 +401,6 @@ def start_router_daemons(tgen, router, daemons):
     return res
 
 
-def kill_mininet_routers_process(tgen):
-    """
-    Kill all mininet stale router' processes
-    * `tgen`  : topogen object
-    """
-
-    router_list = tgen.routers()
-    for rname, router in router_list.items():
-        daemon_list = [
-            "zebra",
-            "ospfd",
-            "ospf6d",
-            "bgpd",
-            "ripd",
-            "ripngd",
-            "isisd",
-            "pimd",
-            "ldpd",
-            "staticd",
-        ]
-        for daemon in daemon_list:
-            router.run("killall -9 {}".format(daemon))
-
-
 def check_router_status(tgen):
     """
     Check if all daemons are running for all routers in topology
index d07b58a774d1038cd5dc8912bb91c50bf7688e79..61a5705a5de2a578720140eeea69499322263977 100644 (file)
@@ -384,50 +384,6 @@ def _enable_disable_pim(tgen, topo, input_dict, router, build=False):
     return result
 
 
-def add_rp_interfaces_and_pim_config(tgen, topo, interface, rp, rp_mapping):
-    """
-    Add physical interfaces tp RP for all the RPs
-
-    Parameters
-    ----------
-    * `tgen` : Topogen object
-    * `topo` : json file data
-    * `interface` : RP interface
-    * `rp` : rp for given topology
-    * `rp_mapping` : dictionary of all groups and RPs
-
-    Returns
-    -------
-    True or False
-    """
-    result = False
-    logger.debug("Entering lib API: {}".format(sys._getframe().f_code.co_name))
-
-    try:
-        config_data = []
-
-        for group, rp_list in rp_mapping.items():
-            for _rp in rp_list:
-                config_data.append("interface {}".format(interface))
-                config_data.append("ip address {}".format(_rp))
-                config_data.append("ip pim")
-
-            result = create_common_configuration(
-                tgen, rp, config_data, "interface_config"
-            )
-            if result is not True:
-                return False
-
-    except InvalidCLIError:
-        # Traceback
-        errormsg = traceback.format_exc()
-        logger.error(errormsg)
-        return errormsg
-
-    logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
-    return result
-
-
 def find_rp_details(tgen, topo):
     """
     Find who is RP in topology and returns list of RPs
@@ -1444,14 +1400,10 @@ def verify_pim_state(
                     errormsg = (
                         "[DUT %s]: Verifying pim state for group"
                         " %s, [FAILED]!! Expected: "
-                        "(iif: %s, oil: %s, installed: %s) ",
+                        "(iif: %s, oil: %s, installed: %s) "
+                        % (dut, grp_addr, iif, oil, "1"),
                         "Found: (iif: %s, oil: %s, installed: %s)"
                         % (
-                            dut,
-                            grp_addr,
-                            iif,
-                            oil,
-                            "1",
                             data["inboundInterface"],
                             data["outboundInterface"],
                             data["installed"],
@@ -2080,7 +2032,7 @@ def add_rp_interfaces_and_pim_config(tgen, topo, interface, rp, rp_mapping):
         logger.error(errormsg)
         return errormsg
 
-    logger.debug("Exiting lib API: add_rp_interfaces_and_pim_config()")
+    logger.debug("Exiting lib API: {}".format(sys._getframe().f_code.co_name))
     return result
 
 
@@ -2425,8 +2377,7 @@ def verify_ip_pim_upstream_rpf(tgen, topo, dut, interface, group_addresses, rp=N
                 if rp is None:
                     rp_details = find_rp_details(tgen, topo)
                 else:
-                    rp_details = {dut: ip}
-                    rp_details[dut] = rp
+                    rp_details = {dut: rp}
 
                 if dut in rp_details:
                     pim_nh_intf_ip = topo["routers"][dut]["links"]["lo"]["ipv4"].split(
@@ -2732,7 +2683,7 @@ def verify_igmp_config(tgen, input_dict, stats_return=False):
 
             if statistics and report:
                 show_ip_igmp_intf_json = run_frr_cmd(
-                    rnode, "{} json".format(cmd, interface), isjson=True
+                    rnode, "{} json".format(cmd), isjson=True
                 )
                 intf_detail_json = show_ip_igmp_intf_json["global"]
             else:
@@ -2808,7 +2759,6 @@ def verify_igmp_config(tgen, input_dict, stats_return=False):
                                         dut,
                                         interface,
                                         value,
-                                        intf_detail_json["reportV2"],
                                     )
                                 )
                                 return errormsg
index 2a46115850dde448c348d28a9ab42b16cce239e3..2a5bd173619cddab72e88598eebb8884d9d6dd9c 100644 (file)
@@ -351,8 +351,8 @@ def run_and_expect(func, what, count=20, wait=3):
         func_name = func.__name__
 
     logger.info(
-        "'{}' polling started (interval {} secs, maximum wait {} secs)".format(
-            func_name, wait, int(wait * count)
+        "'{}' polling started (interval {} secs, maximum {} tries)".format(
+            func_name, wait, count
         )
     )
 
diff --git a/tests/topotests/ospf6-topo1-vrf/README.md b/tests/topotests/ospf6-topo1-vrf/README.md
new file mode 100644 (file)
index 0000000..3ed0b8f
--- /dev/null
@@ -0,0 +1,132 @@
+# OSPFv3 (IPv6) Topology Test
+
+## Topology
+                                                         -----\
+         SW1 - Stub Net 1            SW2 - Stub Net 2          \
+         fc00:1:1:1::/64             fc00:2:2:2::/64            \
+       \___________________/      \___________________/          |
+                 |                          |                    |
+                 |                          |                    |
+                 | ::1                      | ::2                |
+       +---------+---------+      +---------+---------+          |
+       |        R1         |      |        R2         |          |
+       |     FRRouting     |      |     FRRouting     |          |
+       | Rtr-ID: 10.0.0.1  |      | Rtr-ID: 10.0.0.2  |          |
+       +---------+---------+      +---------+---------+          |
+                 | ::1                      | ::2                 \
+                  \______        ___________/                      OSPFv3
+                         \      /                               Area 0.0.0.0
+                          \    /                                  /
+                    ~~~~~~~~~~~~~~~~~~                           |
+                  ~~       SW5        ~~                         |
+                ~~       Switch         ~~                       |
+                  ~~  fc00:A:A:A::/64 ~~                         |
+                    ~~~~~~~~~~~~~~~~~~                           |
+                            |                 /----              |
+                            | ::3            | SW3 - Stub Net 3  | 
+                  +---------+---------+    /-+ fc00:3:3:3::/64   |
+                  |        R3         |   /  |                  /
+                  |     FRRouting     +--/    \----            /
+                  | Rtr-ID: 10.0.0.3  | ::3        ___________/
+                  +---------+---------+                       \
+                            | ::3                              \
+                            |                                   \
+                    ~~~~~~~~~~~~~~~~~~                           |
+                  ~~       SW6        ~~                         |
+                ~~       Switch         ~~                       |
+                  ~~  fc00:B:B:B::/64 ~~                          \
+                    ~~~~~~~~~~~~~~~~~~                             OSPFv3
+                            |                                   Area 0.0.0.1
+                            | ::4                                 /
+                  +---------+---------+       /----              |
+                  |        R4         |      | SW4 - Stub Net 4  |
+                  |     FRRouting     +------+ fc00:4:4:4::/64   |
+                  | Rtr-ID: 10.0.0.4  | ::4  |                   /
+                  +-------------------+       \----             /
+                                                          -----/
+
+## FRR Configuration
+
+Full config as used is in r1 / r2 / r3 / r4 / r5 subdirectories
+
+Simplified `R1` config (R1 is similar)
+
+       hostname r1
+       !
+       interface r1-stubnet vrf r1-cust1
+        ipv6 address fc00:1:1:1::1/64
+        ipv6 ospf6 network broadcast
+       !
+       interface r1-sw5 vrf r1-cust1
+        ipv6 address fc00:a:a:a::1/64
+        ipv6 ospf6 network broadcast
+       !
+       router ospf6 vrf r1-cust1
+        router-id 10.0.0.1
+        log-adjacency-changes detail
+        redistribute static
+        interface r1-stubnet area 0.0.0.0
+        interface r1-sw5 area 0.0.0.0
+       !
+       ipv6 route fc00:1111:1111:1111::/64 fc00:1:1:1::1234 vrf r1-cust1
+
+Simplified `R3` config
+
+       hostname r3
+       !
+       interface r3-stubnet vrf r3-cust1
+        ipv6 address fc00:3:3:3::3/64
+        ipv6 ospf6 network broadcast
+       !
+       interface r3-sw5 vrf r3-cust1
+        ipv6 address fc00:a:a:a::3/64
+        ipv6 ospf6 network broadcast
+       !
+       interface r3-sw6 vrf r3-cust1
+        ipv6 address fc00:b:b:b::3/64
+        ipv6 ospf6 network broadcast
+       !
+       router ospf6 vrf r3-cust1
+        router-id 10.0.0.3
+        log-adjacency-changes detail
+        redistribute static
+        interface r3-stubnet area 0.0.0.0
+        interface r3-sw5 area 0.0.0.0
+        interface r3-sw6 area 0.0.0.1
+       !
+       ipv6 route fc00:3333:3333:3333::/64 fc00:3:3:3::1234 vrf r3-cust1
+
+## Tests executed
+
+### Check if FRR is running
+
+Test is executed by running 
+
+       vtysh -c "show logging" | grep "Logging configuration for"
+       
+on each FRR router. This should return the logging information for all daemons registered
+to Zebra and the list of running daemons is compared to the daemons started for this test (`zebra` and `ospf6d`)
+
+### Verify for OSPFv3 to converge
+
+OSPFv3 is expected to converge on each view within 60s total time. Convergence is verified by executing (on each node)
+
+       vtysh -c "show ipv6 ospf vrf r1-cust1 neigh"
+
+and checking for "Full" neighbor status in the output. An additional 15 seconds after the full converge is waited for routes to populate before the following routing table checks are executed
+
+### Verifying OSPFv3 Routing Tables
+
+Routing table is verified by running 
+
+       vtysh -c "show ipv6 route vrf r1-cust1"
+
+on each node and comparing the result to the stored example config (see `show_ipv6_route.ref` in r1 / r2 / r3 / r4 directories). Link-Local addresses are masked out before the compare.
+
+### Verifying Linux Kernel Routing Table
+
+Linux Kernel IPv6 Routing table is verified on each FRR node with
+
+       ip -6 route vrf r1-cust1
+
+Tables are compared with reference routing table (see `ip_6_address.ref` in r1 / r2 / r3 / r4 directories). Link-Local addresses are translated after getting collected on each node with interface name to make them consistent
diff --git a/tests/topotests/ospf6-topo1-vrf/r1/ip_6_address.nhg.ref b/tests/topotests/ospf6-topo1-vrf/r1/ip_6_address.nhg.ref
new file mode 100644 (file)
index 0000000..11fd9fe
--- /dev/null
@@ -0,0 +1,10 @@
+fc00:1111:1111:1111::/64 nhid XXXX via fc00:1:1:1::1234 dev r1-stubnet proto XXXX metric 20 pref medium
+fc00:1:1:1::/64 dev r1-stubnet proto XXXX metric 256 pref medium
+fc00:2222:2222:2222::/64 nhid XXXX via fe80::__(r2-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium
+fc00:2:2:2::/64 nhid XXXX via fe80::__(r2-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium
+fc00:3333:3333:3333::/64 nhid XXXX via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium
+fc00:3:3:3::/64 nhid XXXX via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium
+fc00:4444:4444:4444::/64 nhid XXXX via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium
+fc00:4:4:4::/64 nhid XXXX via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium
+fc00:a:a:a::/64 dev r1-sw5 proto XXXX metric 256 pref medium
+fc00:b:b:b::/64 nhid XXXX via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium
diff --git a/tests/topotests/ospf6-topo1-vrf/r1/ip_6_address.ref b/tests/topotests/ospf6-topo1-vrf/r1/ip_6_address.ref
new file mode 100644 (file)
index 0000000..f17e1fe
--- /dev/null
@@ -0,0 +1,10 @@
+fc00:1111:1111:1111::/64 via fc00:1:1:1::1234 dev r1-stubnet proto XXXX metric 20 pref medium\r
+fc00:1:1:1::/64 dev r1-stubnet proto XXXX metric 256 pref medium\r
+fc00:2222:2222:2222::/64 via fe80::__(r2-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium\r
+fc00:2:2:2::/64 via fe80::__(r2-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium\r
+fc00:3333:3333:3333::/64 via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium\r
+fc00:3:3:3::/64 via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium\r
+fc00:4444:4444:4444::/64 via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium\r
+fc00:4:4:4::/64 via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium\r
+fc00:a:a:a::/64 dev r1-sw5 proto XXXX metric 256 pref medium\r
+fc00:b:b:b::/64 via fe80::__(r3-sw5)__ dev r1-sw5 proto XXXX metric 20 pref medium\r
diff --git a/tests/topotests/ospf6-topo1-vrf/r1/ospf6d.conf b/tests/topotests/ospf6-topo1-vrf/r1/ospf6d.conf
new file mode 100644 (file)
index 0000000..ed48035
--- /dev/null
@@ -0,0 +1,31 @@
+hostname r1
+log file ospf6d.log
+!
+debug ospf6 message all
+debug ospf6 lsa unknown
+debug ospf6 zebra
+debug ospf6 interface
+debug ospf6 neighbor
+debug ospf6 route table
+debug ospf6 flooding
+!
+interface r1-stubnet vrf r1-cust1
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r1-sw5 vrf r1-cust1
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6 vrf r1-cust1 
+ ospf6 router-id 10.0.0.1
+ log-adjacency-changes detail
+ redistribute static
+ interface r1-stubnet area 0.0.0.0
+ interface r1-sw5 area 0.0.0.0
+!
+line vty
+ exec-timeout 0 0
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/r1/show_ipv6_vrf_route.ref b/tests/topotests/ospf6-topo1-vrf/r1/show_ipv6_vrf_route.ref
new file mode 100644 (file)
index 0000000..a2ddf7c
--- /dev/null
@@ -0,0 +1,9 @@
+O   fc00:1:1:1::/64 [110/10] is directly connected, r1-stubnet, weight 1, XX:XX:XX
+O>* fc00:2:2:2::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r1-sw5, weight 1, XX:XX:XX
+O>* fc00:3:3:3::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r1-sw5, weight 1, XX:XX:XX
+O>* fc00:4:4:4::/64 [110/30] via fe80::XXXX:XXXX:XXXX:XXXX, r1-sw5, weight 1, XX:XX:XX
+O   fc00:a:a:a::/64 [110/10] is directly connected, r1-sw5, weight 1, XX:XX:XX
+O>* fc00:b:b:b::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r1-sw5, weight 1, XX:XX:XX
+O>* fc00:2222:2222:2222::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r1-sw5, weight 1, XX:XX:XX
+O>* fc00:3333:3333:3333::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r1-sw5, weight 1, XX:XX:XX
+O>* fc00:4444:4444:4444::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r1-sw5, weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf6-topo1-vrf/r1/zebra.conf b/tests/topotests/ospf6-topo1-vrf/r1/zebra.conf
new file mode 100644 (file)
index 0000000..abe8a9b
--- /dev/null
@@ -0,0 +1,20 @@
+!
+hostname r1
+log file zebra.log
+!
+debug zebra events
+debug zebra rib
+!
+interface r1-stubnet vrf r1-cust1
+ ipv6 address fc00:1:1:1::1/64
+!
+interface r1-sw5 vrf r1-cust1
+ ipv6 address fc00:a:a:a::1/64
+!
+interface lo
+!
+ipv6 route fc00:1111:1111:1111::/64 fc00:1:1:1::1234 vrf r1-cust1
+!
+!
+line vty
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/r2/ip_6_address.ref b/tests/topotests/ospf6-topo1-vrf/r2/ip_6_address.ref
new file mode 100644 (file)
index 0000000..1a3e67b
--- /dev/null
@@ -0,0 +1,10 @@
+fc00:1111:1111:1111::/64 via fe80::__(r1-sw5)__ dev r2-sw5 proto XXXX metric 20 pref medium\r
+fc00:1:1:1::/64 via fe80::__(r1-sw5)__ dev r2-sw5 proto XXXX metric 20 pref medium\r
+fc00:2222:2222:2222::/64 via fc00:2:2:2::1234 dev r2-stubnet proto XXXX metric 20 pref medium\r
+fc00:2:2:2::/64 dev r2-stubnet proto XXXX metric 256 pref medium\r
+fc00:3333:3333:3333::/64 via fe80::__(r3-sw5)__ dev r2-sw5 proto XXXX metric 20 pref medium\r
+fc00:3:3:3::/64 via fe80::__(r3-sw5)__ dev r2-sw5 proto XXXX metric 20 pref medium\r
+fc00:4444:4444:4444::/64 via fe80::__(r3-sw5)__ dev r2-sw5 proto XXXX metric 20 pref medium\r
+fc00:4:4:4::/64 via fe80::__(r3-sw5)__ dev r2-sw5 proto XXXX metric 20 pref medium\r
+fc00:a:a:a::/64 dev r2-sw5 proto XXXX metric 256 pref medium\r
+fc00:b:b:b::/64 via fe80::__(r3-sw5)__ dev r2-sw5 proto XXXX metric 20 pref medium\r
diff --git a/tests/topotests/ospf6-topo1-vrf/r2/ospf6d.conf b/tests/topotests/ospf6-topo1-vrf/r2/ospf6d.conf
new file mode 100644 (file)
index 0000000..485771e
--- /dev/null
@@ -0,0 +1,31 @@
+hostname r2
+log file ospf6d.log
+!
+debug ospf6 message all
+debug ospf6 lsa unknown
+debug ospf6 zebra
+debug ospf6 interface
+debug ospf6 neighbor
+debug ospf6 route table
+debug ospf6 flooding
+!
+interface r2-stubnet vrf r2-cust1
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 dead-interval 10
+ ipv6 ospf6 hello-interval 2
+!
+interface r2-sw5 vrf r2-cust1
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 dead-interval 10
+ ipv6 ospf6 hello-interval 2
+!
+router ospf6 vrf r2-cust1
+ ospf6 router-id 10.0.0.2
+ log-adjacency-changes detail
+ redistribute static
+ interface r2-stubnet area 0.0.0.0
+ interface r2-sw5 area 0.0.0.0
+!
+line vty
+ exec-timeout 0 0
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/r2/show_ipv6_vrf_route.ref b/tests/topotests/ospf6-topo1-vrf/r2/show_ipv6_vrf_route.ref
new file mode 100644 (file)
index 0000000..3289619
--- /dev/null
@@ -0,0 +1,9 @@
+O>* fc00:1:1:1::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r2-sw5, weight 1, XX:XX:XX
+O   fc00:2:2:2::/64 [110/10] is directly connected, r2-stubnet, weight 1, XX:XX:XX
+O>* fc00:3:3:3::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r2-sw5, weight 1, XX:XX:XX
+O>* fc00:4:4:4::/64 [110/30] via fe80::XXXX:XXXX:XXXX:XXXX, r2-sw5, weight 1, XX:XX:XX
+O   fc00:a:a:a::/64 [110/10] is directly connected, r2-sw5, weight 1, XX:XX:XX
+O>* fc00:b:b:b::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r2-sw5, weight 1, XX:XX:XX
+O>* fc00:1111:1111:1111::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r2-sw5, weight 1, XX:XX:XX
+O>* fc00:3333:3333:3333::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r2-sw5, weight 1, XX:XX:XX
+O>* fc00:4444:4444:4444::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r2-sw5, weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf6-topo1-vrf/r2/zebra.conf b/tests/topotests/ospf6-topo1-vrf/r2/zebra.conf
new file mode 100644 (file)
index 0000000..e1011bd
--- /dev/null
@@ -0,0 +1,20 @@
+!
+hostname r2
+log file zebra.log
+!
+debug zebra events
+debug zebra rib
+!
+interface r2-stubnet vrf r2-cust1
+ ipv6 address fc00:2:2:2::2/64
+!
+interface r2-sw5 vrf r2-cust1
+ ipv6 address fc00:a:a:a::2/64
+!
+interface lo
+!
+ipv6 route fc00:2222:2222:2222::/64 fc00:2:2:2::1234 vrf r2-cust1
+!
+!
+line vty
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/r3/ip_6_address.ref b/tests/topotests/ospf6-topo1-vrf/r3/ip_6_address.ref
new file mode 100644 (file)
index 0000000..d70027f
--- /dev/null
@@ -0,0 +1,10 @@
+fc00:1111:1111:1111::/64 via fe80::__(r1-sw5)__ dev r3-sw5 proto XXXX metric 20 pref medium\r
+fc00:1:1:1::/64 via fe80::__(r1-sw5)__ dev r3-sw5 proto XXXX metric 20 pref medium\r
+fc00:2222:2222:2222::/64 via fe80::__(r2-sw5)__ dev r3-sw5 proto XXXX metric 20 pref medium\r
+fc00:2:2:2::/64 via fe80::__(r2-sw5)__ dev r3-sw5 proto XXXX metric 20 pref medium\r
+fc00:3333:3333:3333::/64 via fc00:3:3:3::1234 dev r3-stubnet proto XXXX metric 20 pref medium\r
+fc00:3:3:3::/64 dev r3-stubnet proto XXXX metric 256 pref medium\r
+fc00:4444:4444:4444::/64 via fe80::__(r4-sw6)__ dev r3-sw6 proto XXXX metric 20 pref medium\r
+fc00:4:4:4::/64 via fe80::__(r4-sw6)__ dev r3-sw6 proto XXXX metric 20 pref medium\r
+fc00:a:a:a::/64 dev r3-sw5 proto XXXX metric 256 pref medium\r
+fc00:b:b:b::/64 dev r3-sw6 proto XXXX metric 256 pref medium\r
diff --git a/tests/topotests/ospf6-topo1-vrf/r3/ospf6d.conf b/tests/topotests/ospf6-topo1-vrf/r3/ospf6d.conf
new file mode 100644 (file)
index 0000000..f5837bf
--- /dev/null
@@ -0,0 +1,37 @@
+hostname r3
+log file ospf6d.log
+!
+debug ospf6 message all
+debug ospf6 lsa unknown
+debug ospf6 zebra
+debug ospf6 interface
+debug ospf6 neighbor
+debug ospf6 route table
+debug ospf6 flooding
+!
+interface r3-stubnet vrf r3-cust1 
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 dead-interval 10
+ ipv6 ospf6 hello-interval 2
+!
+interface r3-sw5 vrf r3-cust1
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 dead-interval 10
+ ipv6 ospf6 hello-interval 2
+!
+interface r3-sw6 vrf r3-cust1
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 dead-interval 10
+ ipv6 ospf6 hello-interval 2
+!
+router ospf6 vrf r3-cust1
+ ospf6 router-id 10.0.0.3
+ log-adjacency-changes detail
+ redistribute static
+ interface r3-stubnet area 0.0.0.0
+ interface r3-sw5 area 0.0.0.0
+ interface r3-sw6 area 0.0.0.1
+!
+line vty
+ exec-timeout 0 0
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/r3/show_ipv6_vrf_route.ref b/tests/topotests/ospf6-topo1-vrf/r3/show_ipv6_vrf_route.ref
new file mode 100644 (file)
index 0000000..ac71319
--- /dev/null
@@ -0,0 +1,9 @@
+O>* fc00:1:1:1::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r3-sw5, weight 1, XX:XX:XX
+O>* fc00:2:2:2::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r3-sw5, weight 1, XX:XX:XX
+O   fc00:3:3:3::/64 [110/10] is directly connected, r3-stubnet, weight 1, XX:XX:XX
+O>* fc00:4:4:4::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r3-sw6, weight 1, XX:XX:XX
+O   fc00:a:a:a::/64 [110/10] is directly connected, r3-sw5, weight 1, XX:XX:XX
+O   fc00:b:b:b::/64 [110/10] is directly connected, r3-sw6, weight 1, XX:XX:XX
+O>* fc00:1111:1111:1111::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r3-sw5, weight 1, XX:XX:XX
+O>* fc00:2222:2222:2222::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r3-sw5, weight 1, XX:XX:XX
+O>* fc00:4444:4444:4444::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r3-sw6, weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf6-topo1-vrf/r3/zebra.conf b/tests/topotests/ospf6-topo1-vrf/r3/zebra.conf
new file mode 100644 (file)
index 0000000..f489f3a
--- /dev/null
@@ -0,0 +1,23 @@
+!
+hostname r3
+log file zebra.log
+!
+debug zebra events
+debug zebra rib
+!
+interface r3-stubnet vrf r3-cust1 
+ ipv6 address fc00:3:3:3::3/64
+!
+interface r3-sw5 vrf r3-cust1
+ ipv6 address fc00:a:a:a::3/64
+!
+interface r3-sw6 vrf r3-cust1
+ ipv6 address fc00:b:b:b::3/64
+!
+interface lo
+!
+ipv6 route fc00:3333:3333:3333::/64 fc00:3:3:3::1234 vrf r3-cust1
+!
+!
+line vty
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/r4/ip_6_address.ref b/tests/topotests/ospf6-topo1-vrf/r4/ip_6_address.ref
new file mode 100644 (file)
index 0000000..0883f3c
--- /dev/null
@@ -0,0 +1,10 @@
+fc00:1111:1111:1111::/64 via fe80::__(r3-sw6)__ dev r4-sw6 proto XXXX metric 20 pref medium\r
+fc00:1:1:1::/64 via fe80::__(r3-sw6)__ dev r4-sw6 proto XXXX metric 20 pref medium\r
+fc00:2222:2222:2222::/64 via fe80::__(r3-sw6)__ dev r4-sw6 proto XXXX metric 20 pref medium\r
+fc00:2:2:2::/64 via fe80::__(r3-sw6)__ dev r4-sw6 proto XXXX metric 20 pref medium\r
+fc00:3333:3333:3333::/64 via fe80::__(r3-sw6)__ dev r4-sw6 proto XXXX metric 20 pref medium\r
+fc00:3:3:3::/64 via fe80::__(r3-sw6)__ dev r4-sw6 proto XXXX metric 20 pref medium\r
+fc00:4444:4444:4444::/64 via fc00:4:4:4::1234 dev r4-stubnet proto XXXX metric 20 pref medium\r
+fc00:4:4:4::/64 dev r4-stubnet proto XXXX metric 256 pref medium\r
+fc00:a:a:a::/64 via fe80::__(r3-sw6)__ dev r4-sw6 proto XXXX metric 20 pref medium\r
+fc00:b:b:b::/64 dev r4-sw6 proto XXXX metric 256 pref medium\r
diff --git a/tests/topotests/ospf6-topo1-vrf/r4/ospf6d.conf b/tests/topotests/ospf6-topo1-vrf/r4/ospf6d.conf
new file mode 100644 (file)
index 0000000..ab67d06
--- /dev/null
@@ -0,0 +1,31 @@
+hostname r4
+log file ospf6d.log
+!
+debug ospf6 message all
+debug ospf6 lsa unknown
+debug ospf6 zebra
+debug ospf6 interface
+debug ospf6 neighbor
+debug ospf6 route table
+debug ospf6 flooding
+!
+interface r4-stubnet vrf r4-cust1 
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+interface r4-sw6 vrf r4-cust1
+ ipv6 ospf6 network broadcast
+ ipv6 ospf6 hello-interval 2
+ ipv6 ospf6 dead-interval 10
+!
+router ospf6 vrf r4-cust1
+ ospf6 router-id 10.0.0.4
+ log-adjacency-changes detail
+ redistribute static
+ interface r4-stubnet area 0.0.0.1
+ interface r4-sw6 area 0.0.0.1
+!
+line vty
+ exec-timeout 0 0
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/r4/show_ipv6_vrf_route.ref b/tests/topotests/ospf6-topo1-vrf/r4/show_ipv6_vrf_route.ref
new file mode 100644 (file)
index 0000000..0df652f
--- /dev/null
@@ -0,0 +1,9 @@
+O>* fc00:1:1:1::/64 [110/30] via fe80::XXXX:XXXX:XXXX:XXXX, r4-sw6, weight 1, XX:XX:XX
+O>* fc00:2:2:2::/64 [110/30] via fe80::XXXX:XXXX:XXXX:XXXX, r4-sw6, weight 1, XX:XX:XX
+O>* fc00:3:3:3::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r4-sw6, weight 1, XX:XX:XX
+O   fc00:4:4:4::/64 [110/10] is directly connected, r4-stubnet, weight 1, XX:XX:XX
+O>* fc00:a:a:a::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r4-sw6, weight 1, XX:XX:XX
+O   fc00:b:b:b::/64 [110/10] is directly connected, r4-sw6, weight 1, XX:XX:XX
+O>* fc00:1111:1111:1111::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r4-sw6, weight 1, XX:XX:XX
+O>* fc00:2222:2222:2222::/64 [110/20] via fe80::XXXX:XXXX:XXXX:XXXX, r4-sw6, weight 1, XX:XX:XX
+O>* fc00:3333:3333:3333::/64 [110/10] via fe80::XXXX:XXXX:XXXX:XXXX, r4-sw6, weight 1, XX:XX:XX
diff --git a/tests/topotests/ospf6-topo1-vrf/r4/zebra.conf b/tests/topotests/ospf6-topo1-vrf/r4/zebra.conf
new file mode 100644 (file)
index 0000000..c59116d
--- /dev/null
@@ -0,0 +1,20 @@
+!
+hostname r4
+log file zebra.log
+!
+debug zebra events
+debug zebra rib
+!
+interface r4-stubnet vrf r4-cust1 
+ ipv6 address fc00:4:4:4::4/64
+!
+interface r4-sw6 vrf r4-cust1
+ ipv6 address fc00:b:b:b::4/64
+!
+interface lo
+!
+ipv6 route fc00:4444:4444:4444::/64 fc00:4:4:4::1234 vrf r4-cust1
+!
+!
+line vty
+!
diff --git a/tests/topotests/ospf6-topo1-vrf/test_ospf6_topo1_vrf.py b/tests/topotests/ospf6-topo1-vrf/test_ospf6_topo1_vrf.py
new file mode 100755 (executable)
index 0000000..fa2784e
--- /dev/null
@@ -0,0 +1,457 @@
+#!/usr/bin/env python
+
+#
+# test_ospf6_topo1_vrf.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 by Niral Networks, Inc. ("Niral Networks")
+# Used Copyright (c) 2016 by Network Device Education Foundation, 
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_ospf6_topo1_vrf.py:
+
+                                                  -----\
+  SW1 - Stub Net 1            SW2 - Stub Net 2          \
+  fc00:1:1:1::/64             fc00:2:2:2::/64            \
+\___________________/      \___________________/          |
+          |                          |                    |
+          |                          |                    |
+          | ::1                      | ::2                |
++---------+---------+      +---------+---------+          |
+|        R1         |      |        R2         |          |
+|     FRRouting     |      |     FRRouting     |          |
+| Rtr-ID: 10.0.0.1  |      | Rtr-ID: 10.0.0.2  |          |
++---------+---------+      +---------+---------+          |
+          | ::1                      | ::2                 \
+           \______        ___________/                      OSPFv3
+                  \      /                               Area 0.0.0.0
+                   \    /                                  /
+             ~~~~~~~~~~~~~~~~~~                           |
+           ~~       SW5        ~~                         |
+         ~~       Switch         ~~                       |
+           ~~  fc00:A:A:A::/64 ~~                         |
+             ~~~~~~~~~~~~~~~~~~                           |
+                     |                 /----              |
+                     | ::3            | SW3 - Stub Net 3  | 
+           +---------+---------+    /-+ fc00:3:3:3::/64   |
+           |        R3         |   /  |                  /
+           |     FRRouting     +--/    \----            /
+           | Rtr-ID: 10.0.0.3  | ::3        ___________/
+           +---------+---------+                       \
+                     | ::3                              \
+                     |                                   \
+             ~~~~~~~~~~~~~~~~~~                           |
+           ~~       SW6        ~~                         |
+         ~~       Switch         ~~                       |
+           ~~  fc00:B:B:B::/64 ~~                          \
+             ~~~~~~~~~~~~~~~~~~                             OSPFv3
+                     |                                   Area 0.0.0.1
+                     | ::4                                 /
+           +---------+---------+       /----              |
+           |        R4         |      | SW4 - Stub Net 4  |
+           |     FRRouting     +------+ fc00:4:4:4::/64   |
+           | Rtr-ID: 10.0.0.4  | ::4  |                   /
+           +-------------------+       \----             /
+                                                   -----/
+"""
+
+import os
+import re
+import sys
+import pytest
+import platform
+from time import sleep
+
+from functools import partial
+
+from mininet.topo import Topo
+
+# Save the Current Working Directory to find configuration files later.
+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.topotest import iproute2_is_vrf_capable
+from lib.common_config import (
+    required_linux_kernel_version,
+    adjust_router_l3mdev,
+)
+
+#####################################################
+##
+##   Network Topology Definition
+##
+#####################################################
+
+
+class NetworkTopo(Topo):
+    "OSPFv3 (IPv6) Test Topology 1"
+
+    def build(self, **_opts):
+        "Build function"
+
+        tgen = get_topogen(self)
+
+        # Create 4 routers
+        for routern in range(1, 5):
+            tgen.add_router("r{}".format(routern))
+
+        #
+        # Wire up the switches and routers
+        # Note that we specify the link names so we match the config files
+        #
+
+        # Create a empty network for router 1
+        switch = tgen.add_switch("s1")
+        switch.add_link(tgen.gears["r1"], nodeif="r1-stubnet")
+
+        # Create a empty network for router 2
+        switch = tgen.add_switch("s2")
+        switch.add_link(tgen.gears["r2"], nodeif="r2-stubnet")
+
+        # Create a empty network for router 3
+        switch = tgen.add_switch("s3")
+        switch.add_link(tgen.gears["r3"], nodeif="r3-stubnet")
+
+        # Create a empty network for router 4
+        switch = tgen.add_switch("s4")
+        switch.add_link(tgen.gears["r4"], nodeif="r4-stubnet")
+
+        # Interconnect routers 1, 2, and 3
+        switch = tgen.add_switch("s5")
+        switch.add_link(tgen.gears["r1"], nodeif="r1-sw5")
+        switch.add_link(tgen.gears["r2"], nodeif="r2-sw5")
+        switch.add_link(tgen.gears["r3"], nodeif="r3-sw5")
+
+        # Interconnect routers 3 and 4
+        switch = tgen.add_switch("s6")
+        switch.add_link(tgen.gears["r3"], nodeif="r3-sw6")
+        switch.add_link(tgen.gears["r4"], nodeif="r4-sw6")
+
+
+#####################################################
+##
+##   Tests starting
+##
+#####################################################
+
+
+def setup_module(mod):
+    "Sets up the pytest environment"
+
+    tgen = Topogen(NetworkTopo, mod.__name__)
+    tgen.start_topology()
+
+    logger.info("** %s: Setup Topology" % mod.__name__)
+    logger.info("******************************************")
+
+    # For debugging after starting net, but before starting FRR,
+    # uncomment the next line
+    # tgen.mininet_cli()
+
+    logger.info("Testing with VRF Lite support")
+
+    cmds = [
+        "ip link add {0}-cust1 type vrf table 1001",
+        "ip link add loop1 type dummy",
+        "ip link set {0}-stubnet master {0}-cust1",
+    ]
+
+    cmds1 = [
+        "ip link set {0}-sw5 master {0}-cust1",
+    ]
+
+    cmds2 = [
+        "ip link set {0}-sw6 master {0}-cust1",
+    ]
+
+    # For all registered routers, load the zebra configuration file
+    for rname, router in tgen.routers().items():
+        # create VRF rx-cust1 and link rx-eth0 to rx-cust1
+        for cmd in cmds:
+            output = tgen.net[rname].cmd(cmd.format(rname))
+        if rname == "r1" or rname == "r2" or rname == "r3":
+            for cmd in cmds1:
+                output = tgen.net[rname].cmd(cmd.format(rname))
+        if rname == "r3" or rname == "r4":
+            for cmd in cmds2:
+                output = tgen.net[rname].cmd(cmd.format(rname))
+
+        # adjust handling of vrf traffic
+        adjust_router_l3mdev(tgen, rname)
+
+    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_OSPF6, os.path.join(CWD, "{}/ospf6d.conf".format(rname))
+        )
+
+    # Initialize all routers.
+    tgen.start_router()
+
+    # For debugging after starting FRR daemons, uncomment the next line
+    # tgen.mininet_cli()
+
+
+def teardown_module(mod):
+    "Teardown the pytest environment"
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+def test_wait_protocol_convergence():
+    "Wait for OSPFv3 to converge"
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info("waiting for protocols to converge")
+
+    def expect_neighbor_full(router, neighbor):
+        "Wait until OSPFv3 convergence."
+        logger.info("waiting OSPFv3 router '{}'".format(router))
+        test_func = partial(
+            topotest.router_json_cmp,
+            tgen.gears[router],
+            "show ipv6 ospf6 vrf {0}-cust1 neighbor json".format(router),
+            {"neighbors": [{"neighborId": neighbor, "state": "Full"}]},
+        )
+        _, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
+        assertmsg = '"{}" convergence failure'.format(router)
+        assert result is None, assertmsg
+
+    expect_neighbor_full("r1", "10.0.0.2")
+    expect_neighbor_full("r1", "10.0.0.3")
+
+    expect_neighbor_full("r2", "10.0.0.1")
+    expect_neighbor_full("r2", "10.0.0.3")
+
+    expect_neighbor_full("r3", "10.0.0.1")
+    expect_neighbor_full("r3", "10.0.0.2")
+    expect_neighbor_full("r3", "10.0.0.4")
+
+
+def compare_show_ipv6_vrf(rname, expected):
+    """
+    Calls 'show ipv6 route' for router `rname` and compare the obtained
+    result with the expected output.
+    """
+    tgen = get_topogen()
+
+    # Use the vtysh output, with some masking to make comparison easy
+    vrf_name = "{0}-cust1".format(rname)
+    current = topotest.ip6_route_zebra(tgen.gears[rname], vrf_name)
+    
+    # Use just the 'O'spf lines of the output
+    linearr = []
+    for line in current.splitlines():
+        if re.match("^O", line):
+            linearr.append(line)
+
+    current = "\n".join(linearr)
+
+    return topotest.difflines(
+        topotest.normalize_text(current),
+        topotest.normalize_text(expected),
+        title1="Current output",
+        title2="Expected output",
+    )
+
+
+def test_ospfv3_routingTable():
+
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip("skipped because of router(s) failure")
+
+    # For debugging, uncomment the next line
+    # tgen.mininet_cli()
+    # Verify OSPFv3 Routing Table
+    for router, rnode in tgen.routers().iteritems():
+        logger.info('Waiting for router "%s" convergence', router)
+
+        # Load expected results from the command
+        reffile = os.path.join(CWD, "{}/show_ipv6_vrf_route.ref".format(router))
+        expected = open(reffile).read()
+
+        # Run test function until we get an result. Wait at most 60 seconds.
+        test_func = partial(compare_show_ipv6_vrf, router, expected)
+        result, diff = topotest.run_and_expect(test_func, "", count=120, wait=0.5)
+        assert result, "OSPFv3 did not converge on {}:\n{}".format(router, diff)
+
+
+def test_linux_ipv6_kernel_routingTable():
+
+    # Required linux kernel version for this suite to run.
+    result = required_linux_kernel_version("4.15")
+    if result is not True:
+        pytest.skip("Kernel requirements are not met")
+
+    # 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")
+
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip("skipped because of router(s) failure")
+
+    # Verify Linux Kernel Routing Table
+    logger.info("Verifying Linux IPv6 Kernel Routing Table")
+
+    failures = 0
+
+    # Get a list of all current link-local addresses first as they change for
+    # each run and we need to translate them
+    linklocals = []
+    for i in range(1, 5):
+        linklocals += tgen.net["r{}".format(i)].get_ipv6_linklocal()
+
+    # Now compare the routing tables (after substituting link-local addresses)
+
+    for i in range(1, 5):
+        # Actual output from router
+        actual = tgen.gears["r{}".format(i)].run("ip -6 route show vrf r{}-cust1".format(i)).rstrip()
+        if "nhid" in actual:
+            refTableFile = os.path.join(CWD, "r{}/ip_6_address.nhg.ref".format(i))
+        else:
+            refTableFile = os.path.join(CWD, "r{}/ip_6_address.ref".format(i))
+
+        if os.path.isfile(refTableFile):
+            expected = open(refTableFile).read().rstrip()
+            # Fix newlines (make them all the same)
+            expected = ("\n".join(expected.splitlines())).splitlines(1)
+
+            # Mask out Link-Local mac addresses
+            for ll in linklocals:
+                actual = actual.replace(ll[1], "fe80::__(%s)__" % ll[0])
+            # Mask out protocol name or number
+            actual = re.sub(r"[ ]+proto [0-9a-z]+ +", "  proto XXXX ", actual)
+            actual = re.sub(r"[ ]+nhid [0-9]+ +", " nhid XXXX ", actual)
+            # Remove ff00::/8 routes (seen on some kernels - not from FRR)
+            actual = re.sub(r"ff00::/8.*", "", actual)
+
+            # Strip empty lines
+            actual = actual.lstrip()
+            actual = actual.rstrip()
+            actual = re.sub(r"  +", " ", actual)
+
+            filtered_lines = []
+            for line in sorted(actual.splitlines()):
+                if line.startswith("fe80::/64 ") or line.startswith(
+                    "unreachable fe80::/64 "
+                ):
+                    continue
+                if 'anycast' in line:
+                    continue
+                if 'multicast' in line:
+                    continue
+                filtered_lines.append(line)
+            actual = "\n".join(filtered_lines).splitlines(1)
+
+            # Print Actual table
+            # logger.info("Router r%s table" % i)
+            # for line in actual:
+            #     logger.info(line.rstrip())
+
+            # Generate Diff
+            diff = topotest.get_textdiff(
+                actual,
+                expected,
+                title1="actual OSPFv3 IPv6 routing table",
+                title2="expected OSPFv3 IPv6 routing table",
+            )
+
+            # Empty string if it matches, otherwise diff contains unified diff
+            if diff:
+                sys.stderr.write(
+                    "r%s failed Linux IPv6 Kernel Routing Table Check:\n%s\n"
+                    % (i, diff)
+                )
+                failures += 1
+            else:
+                logger.info("r%s ok" % i)
+
+            assert failures == 0, (
+                "Linux Kernel IPv6 Routing Table verification failed for router r%s:\n%s"
+                % (i, diff)
+            )
+
+
+def test_shutdown_check_stderr():
+
+    tgen = get_topogen()
+
+    if tgen.routers_have_failure():
+        pytest.skip("skipped because of router(s) failure")
+
+    if os.environ.get("TOPOTESTS_CHECK_STDERR") is None:
+        logger.info(
+            "SKIPPED final check on StdErr output: Disabled (TOPOTESTS_CHECK_STDERR undefined)\n"
+        )
+        pytest.skip("Skipping test for Stderr output")
+
+    net = tgen.net
+
+    logger.info("\n\n** Verifying unexpected STDERR output from daemons")
+    logger.info("******************************************")
+
+    for i in range(1, 5):
+        net["r%s" % i].stopRouter()
+        log = net["r%s" % i].getStdErr("ospf6d")
+        if log:
+            logger.info("\nRouter r%s OSPF6d StdErr Log:\n%s" % (i, log))
+        log = net["r%s" % i].getStdErr("zebra")
+        if log:
+            logger.info("\nRouter r%s Zebra StdErr Log:\n%s" % (i, log))
+
+
+def test_shutdown_check_memleak():
+    "Run the memory leak test and report results."
+
+    if os.environ.get("TOPOTESTS_CHECK_MEMLEAK") is None:
+        logger.info(
+            "SKIPPED final check on Memory leaks: Disabled (TOPOTESTS_CHECK_MEMLEAK undefined)"
+        )
+        pytest.skip("Skipping test for memory leaks")
+
+    tgen = get_topogen()
+
+    net = tgen.net
+
+    for i in range(1, 5):
+        net["r%s" % i].stopRouter()
+        net["r%s" % i].report_memory_leaks(
+            os.environ.get("TOPOTESTS_CHECK_MEMLEAK"), os.path.basename(__file__)
+        )
+
+
+if __name__ == "__main__":
+
+    # To suppress tracebacks, either use the following pytest call or
+    # add "--tb=no" to cli
+    # retval = pytest.main(["-s", "--tb=no"])
+
+    retval = pytest.main(["-s"])
+    sys.exit(retval)
diff --git a/tests/topotests/pim-basic-topo2/__init__.py b/tests/topotests/pim-basic-topo2/__init__.py
new file mode 100644 (file)
index 0000000..e69de29
diff --git a/tests/topotests/pim-basic-topo2/r1/bfdd.conf b/tests/topotests/pim-basic-topo2/r1/bfdd.conf
new file mode 100644 (file)
index 0000000..76c6f82
--- /dev/null
@@ -0,0 +1,6 @@
+bfd
+ profile fast-tx
+  receive-interval 250
+  transmit-interval 250
+ !
+!
diff --git a/tests/topotests/pim-basic-topo2/r1/pimd.conf b/tests/topotests/pim-basic-topo2/r1/pimd.conf
new file mode 100644 (file)
index 0000000..b895d7d
--- /dev/null
@@ -0,0 +1,4 @@
+interface r1-eth0
+ ip pim
+ ip pim bfd profile fast-tx
+!
diff --git a/tests/topotests/pim-basic-topo2/r1/zebra.conf b/tests/topotests/pim-basic-topo2/r1/zebra.conf
new file mode 100644 (file)
index 0000000..6bf02a3
--- /dev/null
@@ -0,0 +1,3 @@
+interface r1-eth0
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/pim-basic-topo2/r2/bfdd.conf b/tests/topotests/pim-basic-topo2/r2/bfdd.conf
new file mode 100644 (file)
index 0000000..ca61e46
--- /dev/null
@@ -0,0 +1,2 @@
+bfd
+!
diff --git a/tests/topotests/pim-basic-topo2/r2/pimd.conf b/tests/topotests/pim-basic-topo2/r2/pimd.conf
new file mode 100644 (file)
index 0000000..0b32ded
--- /dev/null
@@ -0,0 +1,12 @@
+interface r2-eth0
+ ip pim
+ ip pim bfd
+!
+interface r2-eth1
+ ip pim
+ ip pim bfd
+!
+interface r2-eth2
+ ip pim
+ ip pim bfd
+!
diff --git a/tests/topotests/pim-basic-topo2/r2/zebra.conf b/tests/topotests/pim-basic-topo2/r2/zebra.conf
new file mode 100644 (file)
index 0000000..3ceb5f0
--- /dev/null
@@ -0,0 +1,9 @@
+interface r2-eth0
+ ip address 192.168.1.2/24
+!
+interface r2-eth1
+ ip address 192.168.2.1/24
+!
+interface r2-eth2
+ ip address 192.168.3.1/24
+!
diff --git a/tests/topotests/pim-basic-topo2/r3/bfdd.conf b/tests/topotests/pim-basic-topo2/r3/bfdd.conf
new file mode 100644 (file)
index 0000000..ca61e46
--- /dev/null
@@ -0,0 +1,2 @@
+bfd
+!
diff --git a/tests/topotests/pim-basic-topo2/r3/pimd.conf b/tests/topotests/pim-basic-topo2/r3/pimd.conf
new file mode 100644 (file)
index 0000000..691a28e
--- /dev/null
@@ -0,0 +1,4 @@
+interface r3-eth0
+ ip pim
+ ip pim bfd
+!
diff --git a/tests/topotests/pim-basic-topo2/r3/zebra.conf b/tests/topotests/pim-basic-topo2/r3/zebra.conf
new file mode 100644 (file)
index 0000000..3df218e
--- /dev/null
@@ -0,0 +1,3 @@
+interface r3-eth0
+ ip address 192.168.2.3/24
+!
diff --git a/tests/topotests/pim-basic-topo2/r4/bfdd.conf b/tests/topotests/pim-basic-topo2/r4/bfdd.conf
new file mode 100644 (file)
index 0000000..ca61e46
--- /dev/null
@@ -0,0 +1,2 @@
+bfd
+!
diff --git a/tests/topotests/pim-basic-topo2/r4/pimd.conf b/tests/topotests/pim-basic-topo2/r4/pimd.conf
new file mode 100644 (file)
index 0000000..2277b3e
--- /dev/null
@@ -0,0 +1,4 @@
+interface r4-eth0
+ ip pim
+ ip pim bfd
+!
diff --git a/tests/topotests/pim-basic-topo2/r4/zebra.conf b/tests/topotests/pim-basic-topo2/r4/zebra.conf
new file mode 100644 (file)
index 0000000..6ac5c78
--- /dev/null
@@ -0,0 +1,3 @@
+interface r4-eth0
+ ip address 192.168.3.4/24
+!
diff --git a/tests/topotests/pim-basic-topo2/test_pim_basic_topo2.dot b/tests/topotests/pim-basic-topo2/test_pim_basic_topo2.dot
new file mode 100644 (file)
index 0000000..22fce27
--- /dev/null
@@ -0,0 +1,73 @@
+## Color coding:
+#########################
+##  Main FRR: #f08080  red
+##  Switches: #d0e0d0  gray
+##  RIP:      #19e3d9  Cyan
+##  RIPng:    #fcb314  dark yellow
+##  OSPFv2:   #32b835  Green
+##  OSPFv3:   #19e3d9  Cyan
+##  ISIS IPv4 #fcb314  dark yellow
+##  ISIS IPv6 #9a81ec  purple
+##  BGP IPv4  #eee3d3  beige
+##  BGP IPv6  #fdff00  yellow
+##### Colors (see http://www.color-hex.com/)
+
+graph template {
+  label="bfd-topo3";
+
+  # Routers
+  r1 [
+    shape=doubleoctagon,
+    label="r1",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r2 [
+    shape=doubleoctagon
+    label="r2",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r3 [
+    shape=doubleoctagon
+    label="r3",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+  r4 [
+    shape=doubleoctagon
+    label="r4",
+    fillcolor="#f08080",
+    style=filled,
+  ];
+
+  # Switches
+  sw1 [
+    shape=oval,
+    label="sw1\n192.168.1.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw2 [
+    shape=oval,
+    label="sw2\n192.168.2.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+  sw2 [
+    shape=oval,
+    label="sw2\n192.168.3.0/24",
+    fillcolor="#d0e0d0",
+    style=filled,
+  ];
+
+  # Connections
+  r1 -- sw1 [label="eth0\n.1"];
+  r2 -- sw1 [label="eth0\n.2"];
+
+  r2 -- sw2 [label="eth1\n.1"];
+  r3 -- sw2 [label="eth0\n.3"];
+
+  r2 -- sw3 [label="eth1\n.1"];
+  r4 -- sw3 [label="eth2\n.4"];
+}
diff --git a/tests/topotests/pim-basic-topo2/test_pim_basic_topo2.png b/tests/topotests/pim-basic-topo2/test_pim_basic_topo2.png
new file mode 100644 (file)
index 0000000..39139a3
Binary files /dev/null and b/tests/topotests/pim-basic-topo2/test_pim_basic_topo2.png differ
diff --git a/tests/topotests/pim-basic-topo2/test_pim_basic_topo2.py b/tests/topotests/pim-basic-topo2/test_pim_basic_topo2.py
new file mode 100644 (file)
index 0000000..883125c
--- /dev/null
@@ -0,0 +1,238 @@
+#!/usr/bin/env python
+
+#
+# test_pim_basic_topo2.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 by
+# Network Device Education Foundation, Inc. ("NetDEF")
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND NETDEF DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NETDEF BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+test_pim_basic_topo2.py: Test the FRR PIM protocol convergence.
+"""
+
+import os
+import sys
+import json
+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
+
+# Required to instantiate the topology builder class.
+from mininet.topo import Topo
+
+pytestmark = [pytest.mark.bfdd, pytest.mark.pimd]
+
+
+class PimBasicTopo2(Topo):
+    "Test topology builder"
+
+    def build(self, *_args, **_opts):
+        "Build function"
+        tgen = get_topogen(self)
+
+        # Create 4 routers
+        for routern in range(1, 5):
+            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 = tgen.add_switch("s3")
+        switch.add_link(tgen.gears["r2"])
+        switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+    "Sets up the pytest environment"
+    tgen = Topogen(PimBasicTopo2, mod.__name__)
+    tgen.start_topology()
+
+    router_list = tgen.routers()
+    for rname, router in router_list.items():
+        daemon_file = "{}/{}/bfdd.conf".format(CWD, rname)
+        if os.path.isfile(daemon_file):
+            router.load_config(TopoRouter.RD_BFD, daemon_file)
+
+        daemon_file = "{}/{}/pimd.conf".format(CWD, rname)
+        if os.path.isfile(daemon_file):
+            router.load_config(TopoRouter.RD_PIM, daemon_file)
+
+        daemon_file = "{}/{}/zebra.conf".format(CWD, rname)
+        if os.path.isfile(daemon_file):
+            router.load_config(TopoRouter.RD_ZEBRA, daemon_file)
+
+    # Initialize all routers.
+    tgen.start_router()
+
+
+def teardown_module(_mod):
+    "Teardown the pytest environment"
+    tgen = get_topogen()
+    tgen.stop_topology()
+
+
+def expect_neighbor(router, interface, peer):
+    "Wait until peer is present on interface."
+    logger.info("waiting peer {} in {}".format(peer, interface))
+    tgen = get_topogen()
+    test_func = partial(
+        topotest.router_json_cmp,
+        tgen.gears[router],
+        "show ip pim neighbor json",
+        {interface: {peer: {}}}
+    )
+    _, result = topotest.run_and_expect(test_func, None, count=130, wait=1)
+    assertmsg = '"{}" PIM convergence failure'.format(router)
+    assert result is None, assertmsg
+
+
+def test_wait_pim_convergence():
+    "Wait for PIM to converge"
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info("waiting for PIM to converge")
+
+    expect_neighbor('r1', 'r1-eth0', '192.168.1.2')
+    expect_neighbor('r2', 'r2-eth0', '192.168.1.1')
+
+    expect_neighbor('r2', 'r2-eth1', '192.168.2.3')
+    expect_neighbor('r2', 'r2-eth2', '192.168.3.4')
+
+    expect_neighbor('r3', 'r3-eth0', '192.168.2.1')
+    expect_neighbor('r4', 'r4-eth0', '192.168.3.1')
+
+
+def test_bfd_peers():
+    "Wait for BFD peers to show up."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info("waiting for BFD to converge")
+
+    def expect_bfd_peer(router, peer):
+        "Wait until peer is present on interface."
+        logger.info("waiting BFD peer {} in {}".format(peer, router))
+        test_func = partial(
+            topotest.router_json_cmp,
+            tgen.gears[router],
+            "show bfd peers json",
+            [{"peer": peer, "status": "up"}]
+        )
+        _, result = topotest.run_and_expect(test_func, None, count=10, wait=1)
+        assertmsg = '"{}" BFD convergence failure'.format(router)
+        assert result is None, assertmsg
+
+    expect_bfd_peer("r1", "192.168.1.2")
+    expect_bfd_peer("r2", "192.168.1.1")
+    expect_bfd_peer("r2", "192.168.2.3")
+    expect_bfd_peer("r2", "192.168.3.4")
+    expect_bfd_peer("r3", "192.168.2.1")
+    expect_bfd_peer("r4", "192.168.3.1")
+
+
+def test_pim_reconvergence():
+    "Disconnect a peer and expect it to disconnect."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    logger.info("waiting for disconnect convergence")
+    tgen.gears["r4"].link_enable("r4-eth0", enabled=False)
+
+    def expect_neighbor_down(router, interface, peer):
+        "Wait until peer is present on interface."
+        logger.info("waiting peer {} in {} to disappear".format(peer, interface))
+        test_func = partial(
+            topotest.router_json_cmp,
+            tgen.gears[router],
+            "show ip pim neighbor json",
+            {interface: {peer: None}}
+        )
+        _, result = topotest.run_and_expect(test_func, None, count=4, wait=1)
+        assertmsg = '"{}" PIM convergence failure'.format(router)
+        assert result is None, assertmsg
+
+    expect_neighbor_down("r2", "r2-eth2", "192.168.3.4")
+
+    logger.info("waiting for reconvergence")
+    tgen.gears["r4"].link_enable("r4-eth0", enabled=True)
+    expect_neighbor("r2", "r2-eth2", "192.168.3.4")
+
+
+def test_pim_bfd_profile():
+    "Test that the BFD profile is properly applied in BFD."
+    tgen = get_topogen()
+    if tgen.routers_have_failure():
+        pytest.skip(tgen.errors)
+
+    def expect_bfd_peer_settings(router, settings):
+        "Expect the following BFD configuration"
+        logger.info("Verifying BFD peer {} in {}".format(settings["peer"], router))
+        test_func = partial(
+            topotest.router_json_cmp,
+            tgen.gears[router],
+            "show bfd peers json",
+            [settings]
+        )
+        _, result = topotest.run_and_expect(test_func, None, count=4, wait=1)
+        assertmsg = '"{}" BFD convergence failure'.format(router)
+        assert result is None, assertmsg
+
+    expect_bfd_peer_settings("r1", {
+        "peer": "192.168.1.2",
+        "receive-interval": 250,
+        "transmit-interval": 250,
+    })
+
+    expect_bfd_peer_settings("r2", {
+        "peer": "192.168.1.1",
+        "remote-receive-interval": 250,
+        "remote-transmit-interval": 250,
+    })
+
+
+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))
index f4b832691ec3a0ce24cd3c03d0c70f9322d2ed50..c28a971525aeaf76185db21e8b7c21a7b3f971bd 100755 (executable)
@@ -188,17 +188,17 @@ class Vtysh(object):
 class Context(object):
 
     """
-    A Context object represents a section of frr configuration such as:
-!
-interface swp3
- description swp3 -> r8's swp1
- ipv6 nd suppress-ra
- link-detect
-!
+        A Context object represents a section of frr configuration such as:
+    !
+    interface swp3
    description swp3 -> r8's swp1
    ipv6 nd suppress-ra
    link-detect
+    !
 
-or a single line context object such as this:
+    or a single line context object such as this:
 
-ip forwarding
+    ip forwarding
 
     """
 
@@ -423,17 +423,6 @@ class Config(object):
                     re_lege.group(2),
                     re_lege.group(4),
                 )
-            re_lege = re.search(r"(.*)ge\s+(\d+)\s+le\s+(\d+)(.*)", legestr)
-
-            if re_lege and (
-                (re_key_rt.group(1) == "ip" and re_lege.group(3) == "32")
-                or (re_key_rt.group(1) == "ipv6" and re_lege.group(3) == "128")
-            ):
-                legestr = "%sge %s%s" % (
-                    re_lege.group(1),
-                    re_lege.group(2),
-                    re_lege.group(4),
-                )
 
             key[0] = "%s prefix-list%s%s %s%s" % (
                 re_key_rt.group(1),
@@ -1091,7 +1080,7 @@ def check_for_exit_vrf(lines_to_add, lines_to_del):
                 add_exit_vrf = False
 
         if ctx_keys[0].startswith("vrf") and line:
-            if line is not "exit-vrf":
+            if line != "exit-vrf":
                 add_exit_vrf = True
                 prior_ctx_key = ctx_keys[0]
             else:
@@ -1119,12 +1108,15 @@ def ignore_delete_re_add_lines(lines_to_add, lines_to_del):
         # in-place, to avoid requesting spurious label chunks which might fail
         if line and "segment-routing global-block" in line:
             for (add_key, add_line) in lines_to_add:
-                if ctx_keys[0] == add_key[0] and add_line and "segment-routing global-block" in add_line:
+                if (
+                    ctx_keys[0] == add_key[0]
+                    and add_line
+                    and "segment-routing global-block" in add_line
+                ):
                     lines_to_del_to_del.append((ctx_keys, line))
                     break
             continue
 
-
         if ctx_keys[0].startswith("router bgp") and line:
 
             if line.startswith("neighbor "):
index e159d82d4cd2d22d01dc403ea651a17f620d4a7e..6a03a23baa7b33f0ebd47e4823a8b9edba37317f 100644 (file)
@@ -34,9 +34,11 @@ tools_gen_yang_deviations_SOURCES = tools/gen_yang_deviations.c
 tools_gen_yang_deviations_LDADD = lib/libfrr.la $(LIBYANG_LIBS)
 
 tools_ssd_SOURCES = tools/start-stop-daemon.c
+tools_ssd_CPPFLAGS =
 
 # don't bother autoconf'ing these for a simple optional tool
 llvm_version = $(shell echo __clang_major__ | $(CC) -xc -P -E -)
+tools_frr_llvm_cg_CPPFLAGS = $(CPPFLAGS_BASE)
 tools_frr_llvm_cg_CFLAGS = $(AM_CFLAGS) `llvm-config-$(llvm_version) --cflags`
 tools_frr_llvm_cg_LDFLAGS = `llvm-config-$(llvm_version) --ldflags --libs`
 tools_frr_llvm_cg_SOURCES = \
diff --git a/tools/valgrind.supp b/tools/valgrind.supp
new file mode 100644 (file)
index 0000000..fbfb640
--- /dev/null
@@ -0,0 +1,32 @@
+{
+   <zlog_keep_working_at_exit>
+   Memcheck:Leak
+   match-leak-kinds: reachable
+   fun:calloc
+   fun:qcalloc
+   fun:zlog_target_clone
+}
+{
+   <libyang1_1.0.184>
+   Memcheck:Leak
+   match-leak-kinds: reachable
+   fun:calloc
+   fun:_dlerror_run
+   fun:dlopen@@GLIBC_2.2.5
+   obj:/usr/lib/x86_64-linux-gnu/libyang.so.1.9.2
+   fun:ly_load_plugins
+}
+{
+   <zprivs_init leak in a function we do not control>
+   Memcheck:Leak
+   fun:calloc
+   fun:cap_init
+   fun:zprivs_caps_init
+}
+{
+   <sqlite3 leak in a function we do not control>
+   Memcheck:Leak
+   fun:malloc
+   ...
+   fun:sqlite3_step
+}
diff --git a/version.h b/version.h
new file mode 100644 (file)
index 0000000..28e0238
--- /dev/null
+++ b/version.h
@@ -0,0 +1,3 @@
+#include "lib/compiler.h"
+CPP_NOTICE("Trying to include version.h.  Please fix to use lib/version.h.")
+#include "lib/version.h"
index 4855c23f4b15ab837b37614c9b2278bb1a981c5a..37ae0ab189d1bd998ee2d80358783512820fdb95 100755 (executable)
@@ -103,7 +103,7 @@ sub scan_file {
         elsif ($file =~ /lib\/(filter|filter_cli)\.c$/) {
             $protocol = "VTYSH_ACL";
         }
-        elsif ($file =~ /lib\/lib_vty\.c$/) {
+        elsif ($file =~ /lib\/(lib|log)_vty\.c$/) {
             $protocol = "VTYSH_ALL";
         }
        elsif ($file =~ /lib\/agentx\.c$/) {
@@ -119,13 +119,6 @@ sub scan_file {
                 $protocol = "VTYSH_RIPD|VTYSH_OSPFD|VTYSH_BGPD|VTYSH_ZEBRA|VTYSH_PIMD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_ISISD|VTYSH_FABRICD";
             }
         }
-        elsif ($file =~ /lib\/distribute\.c$/) {
-            if ($defun_array[1] =~ m/ipv6/) {
-                $protocol = "VTYSH_RIPNGD";
-            } else {
-                $protocol = "VTYSH_RIPD";
-            }
-        }
         elsif ($file =~ /lib\/if_rmap\.c$/) {
             if ($defun_array[1] =~ m/ipv6/) {
                 $protocol = "VTYSH_RIPNGD";
@@ -133,7 +126,13 @@ sub scan_file {
                 $protocol = "VTYSH_RIPD";
             }
         }
-        elsif ($file =~ /lib\/vty\.c$/) {
+       elsif ($file =~ /lib\/resolver\.c$/) {
+           $protocol = "VTYSH_NHRPD|VTYSH_BGPD";
+       }
+       elsif ($file =~ /lib\/spf_backoff\.c$/) {
+           $protocol = "VTYSH_ISISD";
+       }
+        elsif ($file =~ /lib\/(vty|thread)\.c$/) {
            $protocol = "VTYSH_ALL";
         }
         elsif ($file =~ /librfp\/.*\.c$/ || $file =~ /rfapi\/.*\.c$/) {
@@ -269,7 +268,7 @@ EOF
 foreach (sort keys %odefun) {
     my ($node, $str) = (split (/,/));
     $cmd = $ocmd{$_};
-    $cmd =~ s/_cmd/_cmd_vtysh/;
+    $cmd =~ s/_cmd$/_cmd_vtysh/;
     printf "  install_element ($node, &$cmd);\n";
 }
 
index 75fee1d2979e366310d1894ca74a462e0013cee4..336bd44a49f8d01c5cb2f6478330d21a9110ce9b 100644 (file)
@@ -1976,8 +1976,8 @@ DEFUNSH(VTYSH_BABELD, router_babel, router_babel_cmd, "router babel",
 #endif /* HAVE_BABELD */
 
 #ifdef HAVE_OSPF6D
-DEFUNSH(VTYSH_OSPF6D, router_ospf6, router_ospf6_cmd, "router ospf6",
-       ROUTER_STR OSPF6_STR)
+DEFUNSH(VTYSH_OSPF6D, router_ospf6, router_ospf6_cmd, "router ospf6 [vrf NAME]",
+       ROUTER_STR OSPF6_STR VRF_CMD_HELP_STR)
 {
        vty->node = OSPF6_NODE;
        return CMD_SUCCESS;
@@ -2964,136 +2964,6 @@ DEFUN (vtysh_show_logging,
                               "Logging configuration for %s:\n");
 }
 
-DEFUNSH(VTYSH_ALL, vtysh_log_stdout, vtysh_log_stdout_cmd, "log stdout",
-       "Logging control\n"
-       "Set stdout logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_stdout_level, vtysh_log_stdout_level_cmd,
-       "log stdout <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>",
-       "Logging control\n"
-       "Set stdout logging level\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_stdout, no_vtysh_log_stdout_cmd,
-       "no log stdout [LEVEL]", NO_STR
-       "Logging control\n"
-       "Cancel logging to stdout\n"
-       "Logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_file, vtysh_log_file_cmd, "log file FILENAME",
-       "Logging control\n"
-       "Logging to file\n"
-       "Logging filename\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_file_level, vtysh_log_file_level_cmd,
-       "log file FILENAME <emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>",
-       "Logging control\n"
-       "Logging to file\n"
-       "Logging filename\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_file, no_vtysh_log_file_cmd,
-       "no log file [FILENAME [LEVEL]]", NO_STR
-       "Logging control\n"
-       "Cancel logging to file\n"
-       "Logging file name\n"
-       "Logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_monitor, vtysh_log_monitor_cmd,
-       "log monitor [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
-       "Logging control\n"
-       "Set terminal line (monitor) logging level\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_monitor, no_vtysh_log_monitor_cmd,
-       "no log monitor [LEVEL]", NO_STR
-       "Logging control\n"
-       "Disable terminal line (monitor) logging\n"
-       "Logging level\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_syslog, vtysh_log_syslog_cmd,
-       "log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
-       "Logging control\n"
-       "Set syslog logging level\n" LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_syslog, no_vtysh_log_syslog_cmd,
-       "no log syslog [<emergencies|alerts|critical|errors|warnings|notifications|informational|debugging>]",
-       NO_STR
-       "Logging control\n"
-       "Cancel logging to syslog\n"
-       LOG_LEVEL_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_facility, vtysh_log_facility_cmd,
-       "log facility <kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>",
-       "Logging control\n"
-       "Facility parameter for syslog messages\n" LOG_FACILITY_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_facility, no_vtysh_log_facility_cmd,
-       "no log facility [<kern|user|mail|daemon|auth|syslog|lpr|news|uucp|cron|local0|local1|local2|local3|local4|local5|local6|local7>]",
-       NO_STR
-       "Logging control\n"
-       "Reset syslog facility to default (daemon)\n"
-       LOG_FACILITY_DESC)
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_record_priority, vtysh_log_record_priority_cmd,
-       "log record-priority",
-       "Logging control\n"
-       "Log the priority of the message within the message\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, no_vtysh_log_record_priority,
-       no_vtysh_log_record_priority_cmd, "no log record-priority", NO_STR
-       "Logging control\n"
-       "Do not log the priority of the message within the message\n")
-{
-       return CMD_SUCCESS;
-}
-
-DEFUNSH(VTYSH_ALL, vtysh_log_timestamp_precision,
-       vtysh_log_timestamp_precision_cmd, "log timestamp precision (0-6)",
-       "Logging control\n"
-       "Timestamp configuration\n"
-       "Set the timestamp precision\n"
-       "Number of subsecond digits\n")
-{
-       return CMD_SUCCESS;
-}
-
 DEFUNSH(VTYSH_ALL, vtysh_debug_memstats,
        vtysh_debug_memstats_cmd, "[no] debug memstats-at-exit",
        NO_STR
@@ -3103,16 +2973,6 @@ DEFUNSH(VTYSH_ALL, vtysh_debug_memstats,
        return CMD_SUCCESS;
 }
 
-DEFUNSH(VTYSH_ALL, no_vtysh_log_timestamp_precision,
-       no_vtysh_log_timestamp_precision_cmd, "no log timestamp precision",
-       NO_STR
-       "Logging control\n"
-       "Timestamp configuration\n"
-       "Reset the timestamp precision to the default value of 0\n")
-{
-       return CMD_SUCCESS;
-}
-
 DEFUNSH(VTYSH_ALL, vtysh_service_password_encrypt,
        vtysh_service_password_encrypt_cmd, "service password-encryption",
        "Set up miscellaneous service\n"
@@ -4605,22 +4465,6 @@ void vtysh_init_vty(void)
 
        /* Logging */
        install_element(VIEW_NODE, &vtysh_show_logging_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_stdout_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_stdout_level_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_stdout_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_file_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_file_level_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_file_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_monitor_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_monitor_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_syslog_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_syslog_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_facility_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_facility_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_record_priority_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_record_priority_cmd);
-       install_element(CONFIG_NODE, &vtysh_log_timestamp_precision_cmd);
-       install_element(CONFIG_NODE, &no_vtysh_log_timestamp_precision_cmd);
 
        install_element(CONFIG_NODE, &vtysh_service_password_encrypt_cmd);
        install_element(CONFIG_NODE, &no_vtysh_service_password_encrypt_cmd);
index 3414c764ce39783c5902e8663db87ef2e96c6487..f92b0e920bb17fcd6420174e0dd99e9009a4fd05 100644 (file)
@@ -380,6 +380,9 @@ void vtysh_config_parse_line(void *arg, const char *line)
                                    strlen("bgp large-community-list"))
                                    == 0)
                        config = config_get(COMMUNITY_LIST_NODE, line);
+               else if (strncmp(line, "bgp community alias",
+                                strlen("bgp community alias")) == 0)
+                       config = config_get(COMMUNITY_ALIAS_NODE, line);
                else if (strncmp(line, "ip route", strlen("ip route")) == 0)
                        config = config_get(IP_NODE, line);
                else if (strncmp(line, "ipv6 route", strlen("ipv6 route")) == 0)
@@ -452,11 +455,12 @@ void vtysh_config_parse_line(void *arg, const char *line)
 #define NO_DELIMITER(I)                                                        \
        ((I) == ACCESS_NODE || (I) == PREFIX_NODE || (I) == IP_NODE            \
         || (I) == AS_LIST_NODE || (I) == COMMUNITY_LIST_NODE                  \
-        || (I) == ACCESS_IPV6_NODE || (I) == ACCESS_MAC_NODE                  \
-        || (I) == PREFIX_IPV6_NODE || (I) == FORWARDING_NODE                  \
-        || (I) == DEBUG_NODE || (I) == AAA_NODE || (I) == VRF_DEBUG_NODE      \
-        || (I) == NORTHBOUND_DEBUG_NODE || (I) == RMAP_DEBUG_NODE             \
-        || (I) == RESOLVER_DEBUG_NODE || (I) == MPLS_NODE)
+        || (I) == COMMUNITY_ALIAS_NODE || (I) == ACCESS_IPV6_NODE             \
+        || (I) == ACCESS_MAC_NODE || (I) == PREFIX_IPV6_NODE                  \
+        || (I) == FORWARDING_NODE || (I) == DEBUG_NODE || (I) == AAA_NODE     \
+        || (I) == VRF_DEBUG_NODE || (I) == NORTHBOUND_DEBUG_NODE              \
+        || (I) == RMAP_DEBUG_NODE || (I) == RESOLVER_DEBUG_NODE               \
+        || (I) == MPLS_NODE)
 
 /* Display configuration to file pointer. */
 void vtysh_config_dump(void)
index db7cc312d684ed4d022cc5ef9e2180a460a347bd..fe33bed7f65da19367acb0049410dd3af5b35dfa 100644 (file)
@@ -153,8 +153,10 @@ static void usage(int status)
                        progname);
        else
                printf("Usage : %s [OPTION...]\n\n"
-                      "Integrated shell for FRR (version " FRR_VERSION "). \n"
-                      "Configured with:\n    " FRR_CONFIG_ARGS "\n\n"
+                      "Integrated shell for FRR (version " FRR_VERSION
+                      "). \n"
+                      "Configured with:\n    " FRR_CONFIG_ARGS
+                      "\n\n"
                       "-b, --boot               Execute boot startup configuration\n"
                       "-c, --command            Execute argument as command\n"
                       "-d, --daemon             Connect only to the specified daemon\n"
@@ -167,6 +169,7 @@ static void usage(int status)
                       "-N  --pathspace          Insert prefix into config & socket paths\n"
                       "-u  --user               Run as an unprivileged user\n"
                       "-w, --writeconfig        Write integrated config (frr.conf) and exit\n"
+                      "-H, --histfile           Override history file\n"
                       "-h, --help               Display this help and exit\n\n"
                       "Note that multiple commands may be executed from the command\n"
                       "line by passing multiple -c args, or by embedding linefeed\n"
@@ -189,6 +192,7 @@ struct option longopts[] = {
        {"vty_socket", required_argument, NULL, OPTION_VTYSOCK},
        {"config_dir", required_argument, NULL, OPTION_CONFDIR},
        {"inputfile", required_argument, NULL, 'f'},
+       {"histfile", required_argument, NULL, 'H'},
        {"echo", no_argument, NULL, 'E'},
        {"dryrun", no_argument, NULL, 'C'},
        {"help", no_argument, NULL, 'h'},
@@ -321,6 +325,7 @@ int main(int argc, char **argv, char **env)
        char sysconfdir[MAXPATHLEN];
        const char *pathspace_arg = NULL;
        char pathspace[MAXPATHLEN] = "";
+       const char *histfile = NULL;
 
        /* SUID: drop down to calling user & go back up when needed */
        elevuid = geteuid();
@@ -341,8 +346,8 @@ int main(int argc, char **argv, char **env)
 
        /* Option handling. */
        while (1) {
-               opt = getopt_long(argc, argv, "be:c:d:nf:mEhCwN:u",
-                                 longopts, 0);
+               opt = getopt_long(argc, argv, "be:c:d:nf:H:mEhCwN:u", longopts,
+                                 0);
 
                if (opt == EOF)
                        break;
@@ -409,6 +414,9 @@ int main(int argc, char **argv, char **env)
                case 'h':
                        usage(0);
                        break;
+               case 'H':
+                       histfile = optarg;
+                       break;
                default:
                        usage(1);
                        break;
@@ -569,12 +577,24 @@ int main(int argc, char **argv, char **env)
        /*
         * Setup history file for use by both -c and regular input
         * If we can't find the home directory, then don't store
-        * the history information
+        * the history information.
+        * VTYSH_HISTFILE is prefered over command line
+        * argument (-H/--histfile).
         */
-       homedir = vtysh_get_home();
-       if (homedir) {
-               snprintf(history_file, sizeof(history_file), "%s/.history_frr",
-                        homedir);
+       if (getenv("VTYSH_HISTFILE")) {
+               const char *file = getenv("VTYSH_HISTFILE");
+
+               strlcpy(history_file, file, sizeof(history_file));
+       } else if (histfile) {
+               strlcpy(history_file, histfile, sizeof(history_file));
+       } else {
+               homedir = vtysh_get_home();
+               if (homedir)
+                       snprintf(history_file, sizeof(history_file),
+                                "%s/.history_frr", homedir);
+       }
+
+       if (strlen(history_file) > 0) {
                if (read_history(history_file) != 0) {
                        int fp;
 
index 7c820c96119939b3dd2b1289019c6ee86f2e6abd..4653e6f009a3d41c2687a8a7a6d1856e1cc4a058 100644 (file)
@@ -493,6 +493,13 @@ module frr-isisd {
         description
           "Node protection is provided by the alternate.";
       }
+      leaf link-fallback {
+        type boolean;
+        must ". = 'false' or ../enable = 'true'";
+        default false;
+        description
+          "Fallback to link protection.";
+      }
     }
   }
 
@@ -506,13 +513,6 @@ module frr-isisd {
         "Area-tag associated to this circuit.";
     }
 
-    leaf vrf {
-      type frr-vrf:vrf-ref;
-      default "default";
-      description
-        "VRF NAME.";
-    }
-
     leaf ipv4-routing {
       type boolean;
       default "false";
@@ -791,10 +791,10 @@ module frr-isisd {
       leaf holddown {
         type uint16 {
           range "0..10000";
-      }
-      units "seconds";
-      description
-        "Time to wait for LDP-Sync to occur before restoring interface metric.";
+        }
+        units "seconds";
+        description
+          "Time to wait for LDP-Sync to occur before restoring interface metric.";
       }
     }
 
index 2070649ec205da175fbfe66b46e951e5df6b9926..52d86416130fbf1662c4da6da6899a877297821c 100644 (file)
@@ -331,6 +331,12 @@ module frr-pim {
         description
           "Detect Multiplier";
       }
+
+      leaf profile {
+        type string;
+        description
+          "Use a preconfigure BFD profile.";
+      }
     }
 
     leaf bsm {
index 6f405ca1bbbe533a1cca57e5bbaf11c51c9e5687..1e03f8b639b8a08ef8a10ec7f179857e7f366fbf 100644 (file)
@@ -208,6 +208,9 @@ void connected_up(struct interface *ifp, struct connected *ifc)
        struct zebra_vrf *zvrf;
        uint32_t metric;
        uint32_t flags = 0;
+       uint32_t count = 0;
+       struct listnode *cnode;
+       struct connected *c;
 
        zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
        if (!zvrf) {
@@ -263,6 +266,27 @@ void connected_up(struct interface *ifp, struct connected *ifc)
        if (zrouter.asic_offloaded)
                flags |= ZEBRA_FLAG_OFFLOADED;
 
+       /*
+        * It's possible to add the same network and mask
+        * to an interface over and over.  This would
+        * result in an equivalent number of connected
+        * routes.  Just add one connected route in
+        * for all the addresses on an interface that
+        * resolve to the same network and mask
+        */
+       for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
+               struct prefix cp;
+
+               PREFIX_COPY(&cp, CONNECTED_PREFIX(c));
+               apply_mask(&cp);
+
+               if (prefix_same(&cp, &p))
+                       count++;
+
+               if (count >= 2)
+                       return;
+       }
+
        rib_add(afi, SAFI_UNICAST, zvrf->vrf->vrf_id, ZEBRA_ROUTE_CONNECT, 0,
                flags, &p, NULL, &nh, 0, zvrf->table_id, metric, 0, 0, 0);
 
@@ -358,6 +382,9 @@ void connected_down(struct interface *ifp, struct connected *ifc)
                .vrf_id = ifp->vrf_id,
        };
        struct zebra_vrf *zvrf;
+       uint32_t count = 0;
+       struct listnode *cnode;
+       struct connected *c;
 
        zvrf = zebra_vrf_lookup_by_id(ifp->vrf_id);
        if (!zvrf) {
@@ -396,6 +423,26 @@ void connected_down(struct interface *ifp, struct connected *ifc)
                break;
        }
 
+       /*
+        * It's possible to have X number of addresses
+        * on a interface that all resolve to the same
+        * network and mask.  Find them and just
+        * allow the deletion when are removing the last
+        * one.
+        */
+       for (ALL_LIST_ELEMENTS_RO(ifp->connected, cnode, c)) {
+               struct prefix cp;
+
+               PREFIX_COPY(&cp, CONNECTED_PREFIX(c));
+               apply_mask(&cp);
+
+               if (prefix_same(&p, &cp))
+                       count++;
+
+               if (count >= 2)
+                       return;
+       }
+
        /*
         * Same logic as for connected_up(): push the changes into the
         * head.
index 05eed0d26e9a73a376913f9992640288b5fca16b..88a3d98815e8225a16f50cd0e8b708531ff0b97b 100644 (file)
@@ -178,7 +178,7 @@ DEFPY (debug_zebra_mpls,
        return CMD_SUCCESS;
 }
 
-DEFUN (debug_zebra_vxlan,
+DEFPY (debug_zebra_vxlan,
        debug_zebra_vxlan_cmd,
        "debug zebra vxlan",
        DEBUG_STR
@@ -241,12 +241,6 @@ DEFUN (debug_zebra_kernel,
 {
        SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL);
 
-       if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV)
-               UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV);
-
-       if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND)
-               UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND);
-
        return CMD_SUCCESS;
 }
 
@@ -262,21 +256,11 @@ DEFUN (debug_zebra_kernel_msgdump,
 {
        int idx = 0;
 
-       if (argv_find(argv, argc, "recv", &idx)) {
+       if (argv_find(argv, argc, "recv", &idx))
                SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV);
-
-               if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND)
-                       UNSET_FLAG(zebra_debug_kernel,
-                                  ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND);
-
-       } else if (argv_find(argv, argc, "send", &idx)) {
+       else if (argv_find(argv, argc, "send", &idx))
                SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND);
-
-               if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV)
-                       UNSET_FLAG(zebra_debug_kernel,
-                                  ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV);
-
-       } else {
+       else {
                SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV);
                SET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND);
        }
@@ -476,7 +460,8 @@ DEFUN (no_debug_zebra_kernel,
        "Zebra configuration\n"
        "Debug option set for zebra between kernel interface\n")
 {
-       zebra_debug_kernel = 0;
+       UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL);
+
        return CMD_SUCCESS;
 }
 
@@ -491,7 +476,17 @@ DEFUN (no_debug_zebra_kernel_msgdump,
        "Dump raw netlink messages received\n"
        "Dump raw netlink messages sent\n")
 {
-       zebra_debug_kernel = 0;
+       int idx = 0;
+
+       if (argv_find(argv, argc, "recv", &idx))
+               UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV);
+       else if (argv_find(argv, argc, "send", &idx))
+               UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND);
+       else {
+               UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV);
+               UNSET_FLAG(zebra_debug_kernel, ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND);
+       }
+
        return CMD_SUCCESS;
 }
 
@@ -599,21 +594,21 @@ static int config_write_debug(struct vty *vty)
                }
        }
 
+       if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND
+           && IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) {
+               vty_out(vty, "debug zebra kernel msgdump\n");
+               write++;
+       } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) {
+               vty_out(vty, "debug zebra kernel msgdump recv\n");
+               write++;
+       } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) {
+               vty_out(vty, "debug zebra kernel msgdump send\n");
+               write++;
+       }
+
        if (IS_ZEBRA_DEBUG_KERNEL) {
-               if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND
-                   && IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) {
-                       vty_out(vty, "debug zebra kernel msgdump\n");
-                       write++;
-               } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_RECV) {
-                       vty_out(vty, "debug zebra kernel msgdump recv\n");
-                       write++;
-               } else if (IS_ZEBRA_DEBUG_KERNEL_MSGDUMP_SEND) {
-                       vty_out(vty, "debug zebra kernel msgdump send\n");
-                       write++;
-               } else {
-                       vty_out(vty, "debug zebra kernel\n");
-                       write++;
-               }
+               vty_out(vty, "debug zebra kernel\n");
+               write++;
        }
 
        if (CHECK_FLAG(zebra_debug_rib, ZEBRA_DEBUG_RIB_DETAILED)) {
index 6aaf9d94f3664a9f37aa415953c2b89658548abc..fbf64439e32c9f82ba051c1de58349235cb01b8d 100644 (file)
  * Reference - https://sourceware.org/ml/libc-alpha/2013-01/msg00599.html
  */
 #define _LINUX_IN6_H
+#define _LINUX_IF_H
+#define _LINUX_IP_H
 
 #include <netinet/if_ether.h>
 #include <linux/if_bridge.h>
 #include <linux/if_link.h>
+#include <linux/if_tunnel.h>
 #include <net/if_arp.h>
 #include <linux/sockios.h>
 #include <linux/ethtool.h>
@@ -70,6 +73,7 @@
 #include "zebra/zebra_errors.h"
 #include "zebra/zebra_vxlan.h"
 #include "zebra/zebra_evpn_mh.h"
+#include "zebra/zebra_l2.h"
 
 extern struct zebra_privs_t zserv_privs;
 
@@ -289,6 +293,8 @@ static void netlink_determine_zebra_iftype(const char *kind,
                *zif_type = ZEBRA_IF_BOND;
        else if (strcmp(kind, "bond_slave") == 0)
                *zif_type = ZEBRA_IF_BOND_SLAVE;
+       else if (strcmp(kind, "gre") == 0)
+               *zif_type = ZEBRA_IF_GRE;
 }
 
 #define parse_rtattr_nested(tb, max, rta)                                      \
@@ -458,6 +464,80 @@ uint32_t kernel_get_speed(struct interface *ifp, int *error)
        return get_iflink_speed(ifp, error);
 }
 
+static ssize_t
+netlink_gre_set_msg_encoder(struct zebra_dplane_ctx *ctx, void *buf,
+                           size_t buflen)
+{
+       struct {
+               struct nlmsghdr n;
+               struct ifinfomsg ifi;
+               char buf[];
+       } *req = buf;
+       uint32_t link_idx;
+       unsigned int mtu;
+       struct rtattr *rta_info, *rta_data;
+       const struct zebra_l2info_gre *gre_info;
+
+       if (buflen < sizeof(*req))
+               return 0;
+       memset(req, 0, sizeof(*req));
+
+       req->n.nlmsg_type =  RTM_NEWLINK;
+       req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct ifinfomsg));
+       req->n.nlmsg_flags = NLM_F_REQUEST;
+
+       req->ifi.ifi_index = dplane_ctx_get_ifindex(ctx);
+
+       gre_info = dplane_ctx_gre_get_info(ctx);
+       if (!gre_info)
+               return 0;
+
+       req->ifi.ifi_change = 0xFFFFFFFF;
+       link_idx = dplane_ctx_gre_get_link_ifindex(ctx);
+       mtu = dplane_ctx_gre_get_mtu(ctx);
+
+       if (mtu && !nl_attr_put32(&req->n, buflen, IFLA_MTU, mtu))
+               return 0;
+
+       rta_info = nl_attr_nest(&req->n, buflen, IFLA_LINKINFO);
+       if (!rta_info)
+               return 0;
+
+       if (!nl_attr_put(&req->n, buflen, IFLA_INFO_KIND, "gre", 3))
+               return 0;
+
+       rta_data = nl_attr_nest(&req->n, buflen, IFLA_INFO_DATA);
+       if (!rta_data)
+               return 0;
+
+       if (!nl_attr_put32(&req->n, buflen, IFLA_GRE_LINK, link_idx))
+               return 0;
+
+       if (gre_info->vtep_ip.s_addr &&
+           !nl_attr_put32(&req->n, buflen, IFLA_GRE_LOCAL,
+                          gre_info->vtep_ip.s_addr))
+               return 0;
+
+       if (gre_info->vtep_ip_remote.s_addr &&
+           !nl_attr_put32(&req->n, buflen, IFLA_GRE_REMOTE,
+                          gre_info->vtep_ip_remote.s_addr))
+               return 0;
+
+       if (gre_info->ikey &&
+           !nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY,
+                          gre_info->ikey))
+               return 0;
+       if (gre_info->okey &&
+           !nl_attr_put32(&req->n, buflen, IFLA_GRE_IKEY,
+                          gre_info->okey))
+               return 0;
+
+       nl_attr_nest_end(&req->n, rta_data);
+       nl_attr_nest_end(&req->n, rta_info);
+
+       return NLMSG_ALIGN(req->n.nlmsg_len);
+}
+
 static int netlink_extract_bridge_info(struct rtattr *link_data,
                                       struct zebra_l2info_bridge *bridge_info)
 {
@@ -492,6 +572,47 @@ static int netlink_extract_vlan_info(struct rtattr *link_data,
        return 0;
 }
 
+static int netlink_extract_gre_info(struct rtattr *link_data,
+                                   struct zebra_l2info_gre *gre_info)
+{
+       struct rtattr *attr[IFLA_GRE_MAX + 1];
+
+       memset(gre_info, 0, sizeof(*gre_info));
+       memset(attr, 0, sizeof(attr));
+       parse_rtattr_nested(attr, IFLA_GRE_MAX, link_data);
+
+       if (!attr[IFLA_GRE_LOCAL]) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug(
+                               "IFLA_GRE_LOCAL missing from GRE IF message");
+       } else
+               gre_info->vtep_ip =
+                       *(struct in_addr *)RTA_DATA(attr[IFLA_GRE_LOCAL]);
+       if (!attr[IFLA_GRE_REMOTE]) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug(
+                               "IFLA_GRE_REMOTE missing from GRE IF message");
+       } else
+               gre_info->vtep_ip_remote =
+                       *(struct in_addr *)RTA_DATA(attr[IFLA_GRE_REMOTE]);
+
+       if (!attr[IFLA_GRE_LINK]) {
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("IFLA_GRE_LINK missing from GRE IF message");
+       } else {
+               gre_info->ifindex_link =
+                       *(ifindex_t *)RTA_DATA(attr[IFLA_GRE_LINK]);
+               if (IS_ZEBRA_DEBUG_KERNEL)
+                       zlog_debug("IFLA_GRE_LINK obtained is %u",
+                                  gre_info->ifindex_link);
+       }
+       if (attr[IFLA_GRE_IKEY])
+               gre_info->ikey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_IKEY]);
+       if (attr[IFLA_GRE_OKEY])
+               gre_info->okey = *(uint32_t *)RTA_DATA(attr[IFLA_GRE_OKEY]);
+       return 0;
+}
+
 static int netlink_extract_vxlan_info(struct rtattr *link_data,
                                      struct zebra_l2info_vxlan *vxl_info)
 {
@@ -572,6 +693,16 @@ static void netlink_interface_update_l2info(struct interface *ifp,
                    vxlan_info.ifindex_link)
                        zebra_if_update_link(ifp, vxlan_info.ifindex_link,
                                             link_nsid);
+       } else if (IS_ZEBRA_IF_GRE(ifp)) {
+               struct zebra_l2info_gre gre_info;
+
+               netlink_extract_gre_info(link_data, &gre_info);
+               gre_info.link_nsid = link_nsid;
+               zebra_l2_greif_add_update(ifp, &gre_info, add);
+               if (link_nsid != NS_UNKNOWN &&
+                   gre_info.ifindex_link)
+                       zebra_if_update_link(ifp, gre_info.ifindex_link,
+                                            link_nsid);
        }
 }
 
@@ -934,6 +1065,20 @@ static int netlink_request_intf_addr(struct nlsock *netlink_cmd, int family,
        return netlink_request(netlink_cmd, &req);
 }
 
+enum netlink_msg_status
+netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx)
+{
+       enum dplane_op_e op;
+       enum netlink_msg_status ret;
+
+       op = dplane_ctx_get_op(ctx);
+       assert(op == DPLANE_OP_GRE_SET);
+
+       ret = netlink_batch_add_msg(bth, ctx, netlink_gre_set_msg_encoder, false);
+
+       return ret;
+}
+
 /* Interface lookup by netlink socket. */
 int interface_lookup_netlink(struct zebra_ns *zns)
 {
@@ -974,7 +1119,7 @@ int interface_lookup_netlink(struct zebra_ns *zns)
                return ret;
 
        /* fixup linkages */
-       zebra_if_update_all_links();
+       zebra_if_update_all_links(zns);
        return 0;
 }
 
@@ -1550,6 +1695,9 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
 
                        memcpy(old_hw_addr, ifp->hw_addr, INTERFACE_HWADDR_MAX);
 
+                       /* Update link. */
+                       zebra_if_update_link(ifp, link_ifindex, ns_id);
+
                        netlink_interface_update_hw_addr(tb, ifp);
 
                        if (if_is_no_ptm_operative(ifp)) {
index 0bbba81ca6f96845c41ece361e95995d5ede3fdc..4f09b10b755f285f51269c16084ded384ef95fd5 100644 (file)
@@ -32,6 +32,9 @@ extern int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id,
 extern int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup);
 extern int interface_lookup_netlink(struct zebra_ns *zns);
 
+extern enum netlink_msg_status
+netlink_put_gre_set_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx);
+
 extern enum netlink_msg_status
 netlink_put_address_update_msg(struct nl_batch *bth,
                               struct zebra_dplane_ctx *ctx);
index 4b708496a1dbc0eedaf1bb6dac618c1c3a18dbd2..7fd967dd8b7cdeb7e870aabcb936b6397cb7fc05 100644 (file)
@@ -1066,14 +1066,18 @@ void if_up(struct interface *ifp)
                                                    zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_up(ifp, link_if);
-       } else if (IS_ZEBRA_IF_MACVLAN(ifp))
+       } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
                zebra_vxlan_macvlan_up(ifp);
+       }
 
        if (zif->es_info.es)
                zebra_evpn_es_if_oper_state_change(zif, true /*up*/);
 
        if (zif->flags & ZIF_FLAG_EVPN_MH_UPLINK)
                zebra_evpn_mh_uplink_oper_update(zif);
+
+       thread_add_timer(zrouter.master, if_zebra_speed_update, ifp, 0,
+                        &zif->speed_update);
 }
 
 /* Interface goes down.  We have to manage different behavior of based
@@ -1105,8 +1109,9 @@ void if_down(struct interface *ifp)
                                                    zif->link_ifindex);
                if (link_if)
                        zebra_vxlan_svi_down(ifp, link_if);
-       } else if (IS_ZEBRA_IF_MACVLAN(ifp))
+       } else if (IS_ZEBRA_IF_MACVLAN(ifp)) {
                zebra_vxlan_macvlan_down(ifp);
+       }
 
        if (zif->es_info.es)
                zebra_evpn_es_if_oper_state_change(zif, false /*up*/);
@@ -1148,18 +1153,16 @@ void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
  * during initial link dump kernel does not order lower devices before
  * upper devices so we need to fixup link dependencies at the end of dump
  */
-void zebra_if_update_all_links(void)
+void zebra_if_update_all_links(struct zebra_ns *zns)
 {
        struct route_node *rn;
        struct interface *ifp;
        struct zebra_if *zif;
-       struct zebra_ns *ns;
 
        if (IS_ZEBRA_DEBUG_KERNEL)
                zlog_info("fixup link dependencies");
 
-       ns = zebra_ns_lookup(NS_DEFAULT);
-       for (rn = route_top(ns->if_table); rn; rn = route_next(rn)) {
+       for (rn = route_top(zns->if_table); rn; rn = route_next(rn)) {
                ifp = (struct interface *)rn->info;
                if (!ifp)
                        continue;
@@ -1177,8 +1180,8 @@ void zebra_if_update_all_links(void)
 
                /* update SVI linkages */
                if ((zif->link_ifindex != IFINDEX_INTERNAL) && !zif->link) {
-                       zif->link = if_lookup_by_index_per_ns(ns,
-                                                        zif->link_ifindex);
+                       zif->link = if_lookup_by_index_per_ns(
+                               zns, zif->link_ifindex);
                        if (IS_ZEBRA_DEBUG_KERNEL)
                                zlog_debug("interface %s/%d's lower fixup to %s/%d",
                                                ifp->name, ifp->ifindex,
@@ -1304,6 +1307,9 @@ static const char *zebra_ziftype_2str(zebra_iftype_t zif_type)
        case ZEBRA_IF_MACVLAN:
                return "macvlan";
 
+       case ZEBRA_IF_GRE:
+               return "GRE";
+
        default:
                return "Unknown";
        }
@@ -1576,6 +1582,28 @@ static void if_dump_vty(struct vty *vty, struct interface *ifp)
                                        ifp->name);
                }
                vty_out(vty, "\n");
+       } else if (IS_ZEBRA_IF_GRE(ifp)) {
+               struct zebra_l2info_gre *gre_info;
+
+               gre_info = &zebra_if->l2info.gre;
+               if (gre_info->vtep_ip.s_addr != INADDR_ANY) {
+                       vty_out(vty, "  VTEP IP: %pI4", &gre_info->vtep_ip);
+                       if (gre_info->vtep_ip_remote.s_addr != INADDR_ANY)
+                               vty_out(vty, " , remote %pI4",
+                                       &gre_info->vtep_ip_remote);
+                       vty_out(vty, "\n");
+               }
+               if (gre_info->ifindex_link &&
+                   (gre_info->link_nsid != NS_UNKNOWN)) {
+                       struct interface *ifp;
+
+                       ifp = if_lookup_by_index_per_ns(
+                                       zebra_ns_lookup(gre_info->link_nsid),
+                                       gre_info->ifindex_link);
+                       vty_out(vty, "  Link Interface %s\n",
+                               ifp == NULL ? "Unknown" :
+                               ifp->name);
+               }
        }
 
        if (IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)) {
index 67eb1176b9a2deec121ba1a261a5beb12897d3e1..df4872d48e4fe70df48173b6050bab5665df8ef7 100644 (file)
@@ -263,6 +263,7 @@ typedef enum {
        ZEBRA_IF_VETH,      /* VETH interface*/
        ZEBRA_IF_BOND,      /* Bond */
        ZEBRA_IF_BOND_SLAVE,        /* Bond */
+       ZEBRA_IF_GRE,      /* GRE interface */
 } zebra_iftype_t;
 
 /* Zebra "slave" interface type */
@@ -442,6 +443,9 @@ DECLARE_HOOK(zebra_if_config_wr, (struct vty * vty, struct interface *ifp),
 #define IS_ZEBRA_IF_BOND(ifp)                                                  \
        (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_BOND)
 
+#define IS_ZEBRA_IF_GRE(ifp)                                               \
+       (((struct zebra_if *)(ifp->info))->zif_type == ZEBRA_IF_GRE)
+
 #define IS_ZEBRA_IF_BRIDGE_SLAVE(ifp)                                  \
        (((struct zebra_if *)(ifp->info))->zif_slave_type                      \
         == ZEBRA_IF_SLAVE_BRIDGE)
@@ -482,7 +486,7 @@ extern int ipv6_address_configured(struct interface *ifp);
 extern void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id);
 extern void zebra_if_update_link(struct interface *ifp, ifindex_t link_ifindex,
                                 ns_id_t ns_id);
-extern void zebra_if_update_all_links(void);
+extern void zebra_if_update_all_links(struct zebra_ns *zns);
 extern void zebra_if_set_protodown(struct interface *ifp, bool down);
 extern int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
                                 const char *label, struct prefix *pp);
index 600fc3f2fc8ee8299d287d7684d4e2d36f379f8f..66a6bd0545273ec043cc7753a1133611b7833e07 100644 (file)
@@ -51,7 +51,7 @@
 #include "privs.h"
 #include "libfrr.h"
 #include "lib_errors.h"
-#include "version.h"
+#include "lib/version.h"
 #include "zebra/interface.h"
 #include "zebra/rtadv.h"
 #include "zebra/rib.h"
index adb61023c1f11b0b564baeee4f0dabe42c71b0f9..cd22e95737b1e0da1e16c8ff446a980b270ce800 100644 (file)
@@ -1360,6 +1360,9 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
        case DPLANE_OP_IPSET_ENTRY_DELETE:
                return FRR_NETLINK_ERROR;
 
+       case DPLANE_OP_GRE_SET:
+               return netlink_put_gre_set_msg(bth, ctx);
+
        case DPLANE_OP_NONE:
                return FRR_NETLINK_ERROR;
        }
index 9e675011ee76c8812936a38b369e80e04c68ff0d..7cb426359d8e1c88100f6a1e1f90a0404925411f 100644 (file)
@@ -91,8 +91,7 @@ static void zebra_redistribute_default(struct zserv *client, vrf_id_t vrf_id)
                        continue;
 
                RNODE_FOREACH_RE (rn, newre) {
-                       if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED)
-                           && newre->distance != DISTANCE_INFINITY)
+                       if (CHECK_FLAG(newre->flags, ZEBRA_FLAG_SELECTED))
                                zsend_redistribute_route(
                                        ZEBRA_REDISTRIBUTE_ROUTE_ADD, client,
                                        &rn->p, NULL, newre);
@@ -138,8 +137,6 @@ static void zebra_redistribute(struct zserv *client, int type,
                             && (newre->type != type
                                 || newre->instance != instance)))
                                continue;
-                       if (newre->distance == DISTANCE_INFINITY)
-                               continue;
                        if (!zebra_check_addr(dst_p))
                                continue;
 
@@ -265,13 +262,6 @@ void redistribute_delete(const struct prefix *p, const struct prefix *src_p,
                           new_re ? zebra_route_string(new_re->type) : "None");
        }
 
-       /* Add DISTANCE_INFINITY check. */
-       if (old_re && (old_re->distance == DISTANCE_INFINITY)) {
-               if (IS_ZEBRA_DEBUG_RIB)
-                       zlog_debug("        Skipping due to Infinite Distance");
-               return;
-       }
-
        afi = family2afi(p->family);
        if (!afi) {
                flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
@@ -347,17 +337,12 @@ void zebra_redistribute_add(ZAPI_HANDLER_ARGS)
                                           zvrf_id(zvrf), afi);
                }
        } else {
-               if (!vrf_bitmap_check(client->redist[afi][type],
-                                     zvrf_id(zvrf))) {
-                       if (IS_ZEBRA_DEBUG_EVENT)
-                               zlog_debug(
-                                       "%s: setting vrf %s(%u) redist bitmap",
-                                       __func__, VRF_LOGNAME(zvrf->vrf),
-                                       zvrf_id(zvrf));
-                       vrf_bitmap_set(client->redist[afi][type],
-                                      zvrf_id(zvrf));
-                       zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
-               }
+               if (IS_ZEBRA_DEBUG_EVENT)
+                       zlog_debug("%s: setting vrf %s(%u) redist bitmap",
+                                  __func__, VRF_LOGNAME(zvrf->vrf),
+                                  zvrf_id(zvrf));
+               vrf_bitmap_set(client->redist[afi][type], zvrf_id(zvrf));
+               zebra_redistribute(client, type, 0, zvrf_id(zvrf), afi);
        }
 
 stream_failure:
@@ -374,6 +359,14 @@ void zebra_redistribute_delete(ZAPI_HANDLER_ARGS)
        STREAM_GETC(msg, type);
        STREAM_GETW(msg, instance);
 
+       if (IS_ZEBRA_DEBUG_EVENT)
+               zlog_debug(
+                       "%s: client proto %s afi=%d, no longer wants %s, vrf %s(%u), instance=%d",
+                       __func__, zebra_route_string(client->proto), afi,
+                       zebra_route_string(type), VRF_LOGNAME(zvrf->vrf),
+                       zvrf_id(zvrf), instance);
+
+
        if (afi == 0 || afi >= AFI_MAX) {
                flog_warn(EC_ZEBRA_REDISTRIBUTE_UNKNOWN_AF,
                          "%s: Specified afi %d does not exist", __func__, afi);
index e7676a132455bad1457ccc9bdb800cc37859a32f..75d7ae1b6702fbd9ca56f6602d35c33bc657b290 100644 (file)
@@ -426,7 +426,11 @@ extern int rib_queue_add(struct route_node *rn);
 
 struct nhg_ctx; /* Forward declaration */
 
-extern int rib_queue_nhg_add(struct nhg_ctx *ctx);
+/* Enqueue incoming nhg from OS for processing */
+extern int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx);
+
+/* Enqueue incoming nhg from proto daemon for processing */
+extern int rib_queue_nhe_add(struct nhg_hash_entry *nhe);
 
 extern void meta_queue_free(struct meta_queue *mq);
 extern int zebra_rib_labeled_unicast(struct route_entry *re);
index daaa926a7dc2834617fcacb4be45d1584c35477d..f79ddbe95837f969b48a6c299aceb24357b9c883 100644 (file)
@@ -81,9 +81,6 @@ extern int mpls_kernel_init(void);
 extern uint32_t kernel_get_speed(struct interface *ifp, int *error);
 extern int kernel_get_ipmr_sg_stats(struct zebra_vrf *zvrf, void *mroute);
 
-extern int kernel_configure_if_link(struct interface *ifp,
-                                   struct interface *link_ifp, ns_id_t ns_id);
-
 /*
  * Southbound Initialization routines to get initial starting
  * state.
index ada828d01688879aa0c2bb8b4adb6639cc81996d..006513ac9efbc34bfbfab3f2a2f53b324db3c398 100644 (file)
@@ -394,12 +394,6 @@ enum zebra_dplane_result kernel_mac_update_ctx(struct zebra_dplane_ctx *ctx)
        return ZEBRA_DPLANE_REQUEST_SUCCESS;
 }
 
-int kernel_configure_if_link(struct interface *ifp, struct interface *link_ifp,
-                            ns_id_t ns_id)
-{
-       return 0;
-}
-
 extern int kernel_interface_set_master(struct interface *master,
                                       struct interface *slave)
 {
index 8ffb3870fa6fb019dfc2161565004428239ee76d..1e06b3e0e94432805a047c0257aca5d0cd6ebc8d 100644 (file)
@@ -1063,22 +1063,13 @@ static void zebra_interface_radv_set(ZAPI_HANDLER_ARGS, int enable)
        ifindex_t ifindex;
        struct interface *ifp;
        struct zebra_if *zif;
-       int ra_interval_rxd;
+       uint32_t ra_interval;
 
        s = msg;
 
        /* Get interface index and RA interval. */
        STREAM_GETL(s, ifindex);
-       STREAM_GETL(s, ra_interval_rxd);
-
-       if (ra_interval_rxd < 0) {
-               zlog_warn(
-                       "Requested RA interval %d is garbage; ignoring request",
-                       ra_interval_rxd);
-               return;
-       }
-
-       unsigned int ra_interval = ra_interval_rxd;
+       STREAM_GETL(s, ra_interval);
 
        if (IS_ZEBRA_DEBUG_EVENT) {
                struct vrf *vrf = zvrf->vrf;
index 80ea9ac7b8b272b0f65405a4ed5ff39b04d66fd4..6fc8ef0df5b14117e0b44b2dc83b011145f788df 100644 (file)
@@ -193,7 +193,7 @@ zebra_zebra_irdp_la_SOURCES = \
 zebra_zebra_irdp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 
 zebra_zebra_snmp_la_SOURCES = zebra/zebra_snmp.c
-zebra_zebra_snmp_la_CFLAGS = $(WERROR) $(SNMP_CFLAGS) -std=gnu11
+zebra_zebra_snmp_la_CFLAGS = $(AM_CFLAGS) $(SNMP_CFLAGS) -std=gnu11
 zebra_zebra_snmp_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 zebra_zebra_snmp_la_LIBADD = lib/libfrrsnmp.la
 
@@ -232,7 +232,7 @@ zebra_dplane_fpm_nl_la_SOURCES = zebra/dplane_fpm_nl.c
 zebra_dplane_fpm_nl_la_LDFLAGS = -avoid-version -module -shared -export-dynamic
 zebra_dplane_fpm_nl_la_LIBADD  =
 
-vtysh_scan += $(top_srcdir)/zebra/dplane_fpm_nl.c
+vtysh_scan += zebra/dplane_fpm_nl.c
 endif
 
 if NETLINK_DEBUG
index e854d7ff3a406ec18baa49f8ca434673eca8e5ff..55f8edd2729b3e675d02a4e44643b9c8ccd009f4 100644 (file)
@@ -727,8 +727,8 @@ int zsend_nhg_notify(uint16_t type, uint16_t instance, uint32_t session_id,
        }
 
        if (IS_ZEBRA_DEBUG_SEND)
-               zlog_debug("%s: type %d, id %d, note %d",
-                          __func__, type, id, note);
+               zlog_debug("%s: type %d, id %d, note %s",
+                          __func__, type, id, zapi_nhg_notify_owner2str(note));
 
        s = stream_new(ZEBRA_MAX_PACKET_SIZ);
        stream_reset(s);
@@ -1921,27 +1921,35 @@ static void zread_nhg_add(ZAPI_HANDLER_ARGS)
                return;
        }
 
-       /*
-        * Create the nhg
-        */
-       nhe = zebra_nhg_proto_add(api_nhg.id, api_nhg.proto, client->instance,
-                                 client->session_id, nhg, 0);
+       /* Create a temporary nhe */
+       nhe = zebra_nhg_alloc();
+       nhe->id = api_nhg.id;
+       nhe->type = api_nhg.proto;
+       nhe->zapi_instance = client->instance;
+       nhe->zapi_session = client->session_id;
 
-       nexthop_group_delete(&nhg);
-       zebra_nhg_backup_free(&bnhg);
+       /* Take over the list(s) of nexthops */
+       nhe->nhg.nexthop = nhg->nexthop;
+       nhg->nexthop = NULL;
+
+       if (bnhg) {
+               nhe->backup_info = bnhg;
+               bnhg = NULL;
+       }
 
        /*
         * TODO:
         * Assume fully resolved for now and install.
-        *
         * Resolution is going to need some more work.
         */
 
-       /* If there's a failure, notify sender immediately */
-       if (nhe == NULL)
-               zsend_nhg_notify(api_nhg.proto, client->instance,
-                                client->session_id, api_nhg.id,
-                                ZAPI_NHG_FAIL_INSTALL);
+       /* Enqueue to workqueue for processing */
+       rib_queue_nhe_add(nhe);
+
+       /* Free any local allocations */
+       nexthop_group_delete(&nhg);
+       zebra_nhg_backup_free(&bnhg);
+
 }
 
 static void zread_route_add(ZAPI_HANDLER_ARGS)
@@ -3232,6 +3240,61 @@ stream_failure:
        return;
 }
 
+static inline void zebra_gre_get(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       ifindex_t idx;
+       struct interface *ifp;
+       struct zebra_if *zebra_if = NULL;
+       struct zebra_l2info_gre *gre_info;
+       struct interface *ifp_link = NULL;
+       vrf_id_t vrf_id_link = VRF_UNKNOWN;
+       vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+
+       s = msg;
+       STREAM_GETL(s, idx);
+       ifp  = if_lookup_by_index(idx, vrf_id);
+
+       if (ifp)
+               zebra_if = ifp->info;
+
+       s = stream_new(ZEBRA_MAX_PACKET_SIZ);
+
+       zclient_create_header(s, ZEBRA_GRE_UPDATE, vrf_id);
+
+       if (ifp  && IS_ZEBRA_IF_GRE(ifp) && zebra_if) {
+               gre_info = &zebra_if->l2info.gre;
+
+               stream_putl(s, idx);
+               stream_putl(s, gre_info->ikey);
+               stream_putl(s, gre_info->ikey);
+               stream_putl(s, gre_info->ifindex_link);
+
+               ifp_link = if_lookup_by_index_per_ns(
+                                       zebra_ns_lookup(gre_info->link_nsid),
+                                       gre_info->ifindex_link);
+               if (ifp_link)
+                       vrf_id_link = ifp_link->vrf_id;
+               stream_putl(s, vrf_id_link);
+               stream_putl(s, gre_info->vtep_ip.s_addr);
+               stream_putl(s, gre_info->vtep_ip_remote.s_addr);
+       } else {
+               stream_putl(s, idx);
+               stream_putl(s, 0);
+               stream_putl(s, 0);
+               stream_putl(s, IFINDEX_INTERNAL);
+               stream_putl(s, VRF_UNKNOWN);
+               stream_putl(s, 0);
+       }
+       /* Write packet size. */
+       stream_putw_at(s, 0, stream_get_endp(s));
+       zserv_send_message(client, s);
+
+       return;
+ stream_failure:
+       return;
+}
+
 static inline void zebra_configure_arp(ZAPI_HANDLER_ARGS)
 {
        struct stream *s;
@@ -3365,6 +3428,57 @@ stream_failure:
        return;
 }
 
+static inline void zebra_gre_source_set(ZAPI_HANDLER_ARGS)
+{
+       struct stream *s;
+       ifindex_t idx, link_idx;
+       vrf_id_t link_vrf_id;
+       struct interface *ifp;
+       struct interface *ifp_link;
+       vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+       struct zebra_if *zif, *gre_zif;
+       struct zebra_l2info_gre *gre_info;
+       unsigned int mtu;
+
+       s = msg;
+       STREAM_GETL(s, idx);
+       ifp  = if_lookup_by_index(idx, vrf_id);
+       STREAM_GETL(s, link_idx);
+       STREAM_GETL(s, link_vrf_id);
+       STREAM_GETL(s, mtu);
+
+       ifp_link  = if_lookup_by_index(link_idx, link_vrf_id);
+       if (!ifp_link || !ifp) {
+               zlog_warn("GRE (index %u, VRF %u) or GRE link interface (index %u, VRF %u) not found, when setting GRE params",
+                         idx, vrf_id, link_idx, link_vrf_id);
+               return;
+       }
+
+       if (!IS_ZEBRA_IF_GRE(ifp))
+               return;
+
+       gre_zif = (struct zebra_if *)ifp->info;
+       zif = (struct zebra_if *)ifp_link->info;
+       if (!zif || !gre_zif)
+               return;
+
+       gre_info = &zif->l2info.gre;
+       if (!gre_info)
+               return;
+
+       if (!mtu)
+               mtu = ifp->mtu;
+
+       /* if gre link already set or mtu did not change, do not set it */
+       if (gre_zif->link && gre_zif->link == ifp_link && mtu == ifp->mtu)
+               return;
+
+       dplane_gre_set(ifp, ifp_link, mtu, gre_info);
+
+ stream_failure:
+       return;
+}
+
 static void zsend_error_msg(struct zserv *client, enum zebra_error_types error,
                            struct zmsghdr *bad_hdr)
 {
@@ -3480,6 +3594,8 @@ void (*const zserv_handlers[])(ZAPI_HANDLER_ARGS) = {
        [ZEBRA_NHRP_NEIGH_REGISTER] = zebra_neigh_register,
        [ZEBRA_NHRP_NEIGH_UNREGISTER] = zebra_neigh_unregister,
        [ZEBRA_CONFIGURE_ARP] = zebra_configure_arp,
+       [ZEBRA_GRE_GET] = zebra_gre_get,
+       [ZEBRA_GRE_SOURCE_SET] = zebra_gre_source_set,
 };
 
 /*
index c8ee8f9051223ddce792441f1291209229c2d8f1..a8df0c56ceb369405e4c20083dfbe8c8852be84b 100644 (file)
@@ -271,6 +271,11 @@ struct dplane_rule_info {
        struct dplane_ctx_rule old;
 };
 
+struct dplane_gre_ctx {
+       uint32_t link_ifindex;
+       unsigned int mtu;
+       struct zebra_l2info_gre info;
+};
 /*
  * The context block used to exchange info about route updates across
  * the boundary between the zebra main context (and pthread) and the
@@ -327,6 +332,7 @@ struct zebra_dplane_ctx {
                        struct zebra_pbr_ipset_info info;
                } ipset_entry;
                struct dplane_neigh_table neightable;
+               struct dplane_gre_ctx gre;
        } u;
 
        /* Namespace info, used especially for netlink kernel communication */
@@ -469,6 +475,9 @@ static struct zebra_dplane_globals {
        _Atomic uint32_t dg_neightable_in;
        _Atomic uint32_t dg_neightable_errors;
 
+       _Atomic uint32_t dg_gre_set_in;
+       _Atomic uint32_t dg_gre_set_errors;
+
        /* Dataplane pthread */
        struct frr_pthread *dg_pthread;
 
@@ -713,6 +722,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
                        }
                        list_delete(&ctx->u.iptable.interface_name_list);
                }
+               break;
+       case DPLANE_OP_GRE_SET:
+               break;
        }
 }
 
@@ -979,6 +991,10 @@ const char *dplane_op2str(enum dplane_op_e op)
        case DPLANE_OP_NEIGH_TABLE_UPDATE:
                ret = "NEIGH_TABLE_UPDATE";
                break;
+
+       case DPLANE_OP_GRE_SET:
+               ret = "GRE_SET";
+               break;
        }
 
        return ret;
@@ -1772,6 +1788,31 @@ uint32_t dplane_ctx_neigh_get_update_flags(const struct zebra_dplane_ctx *ctx)
        return ctx->u.neigh.update_flags;
 }
 
+/* Accessor for GRE set */
+uint32_t
+dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.gre.link_ifindex;
+}
+
+unsigned int
+dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return ctx->u.gre.mtu;
+}
+
+const struct zebra_l2info_gre *
+dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx)
+{
+       DPLANE_CTX_VALID(ctx);
+
+       return &ctx->u.gre.info;
+}
+
 /* Accessors for PBR rule information */
 int dplane_ctx_rule_get_sock(const struct zebra_dplane_ctx *ctx)
 {
@@ -4125,6 +4166,71 @@ dplane_pbr_ipset_entry_delete(struct zebra_pbr_ipset_entry *ipset)
        return ipset_entry_update_internal(DPLANE_OP_IPSET_ENTRY_DELETE, ipset);
 }
 
+/*
+ * Common helper api for GRE set
+ */
+enum zebra_dplane_result
+dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
+              unsigned int mtu, const struct zebra_l2info_gre *gre_info)
+{
+       enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       struct zebra_dplane_ctx *ctx;
+       enum dplane_op_e op = DPLANE_OP_GRE_SET;
+       int ret;
+       struct zebra_ns *zns;
+
+       ctx = dplane_ctx_alloc();
+
+       if (!ifp)
+               return result;
+
+       if (IS_ZEBRA_DEBUG_DPLANE_DETAIL) {
+               zlog_debug("init dplane ctx %s: if %s link %s%s",
+                          dplane_op2str(op), ifp->name,
+                          ifp_link ? "set" : "unset", ifp_link ?
+                          ifp_link->name : "");
+       }
+
+       ctx->zd_op = op;
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+       zns = zebra_ns_lookup(ifp->vrf_id);
+       if (!zns)
+               return result;
+       dplane_ctx_ns_init(ctx, zns, false);
+
+       dplane_ctx_set_ifname(ctx, ifp->name);
+       ctx->zd_vrf_id = ifp->vrf_id;
+       ctx->zd_ifindex = ifp->ifindex;
+       if (ifp_link)
+               ctx->u.gre.link_ifindex = ifp_link->ifindex;
+       else
+               ctx->u.gre.link_ifindex = 0;
+       if (gre_info)
+               memcpy(&ctx->u.gre.info, gre_info, sizeof(ctx->u.gre.info));
+       ctx->u.gre.mtu = mtu;
+
+       ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+       /* Enqueue context for processing */
+       ret = dplane_update_enqueue(ctx);
+
+       /* Update counter */
+       atomic_fetch_add_explicit(&zdplane_info.dg_gre_set_in, 1,
+                                 memory_order_relaxed);
+
+       if (ret == AOK)
+               result = ZEBRA_DPLANE_REQUEST_QUEUED;
+       else {
+               atomic_fetch_add_explicit(
+                       &zdplane_info.dg_gre_set_errors, 1,
+                       memory_order_relaxed);
+               if (ctx)
+                       dplane_ctx_free(&ctx);
+               result = ZEBRA_DPLANE_REQUEST_FAILURE;
+       }
+       return result;
+}
+
 /*
  * Handler for 'show dplane'
  */
@@ -4234,6 +4340,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)
                                    memory_order_relaxed);
        vty_out(vty, "Neighbor Table updates:       %"PRIu64"\n", incoming);
        vty_out(vty, "Neighbor Table errors:        %"PRIu64"\n", errs);
+
+       incoming = atomic_load_explicit(&zdplane_info.dg_gre_set_in,
+                                       memory_order_relaxed);
+       errs = atomic_load_explicit(&zdplane_info.dg_gre_set_errors,
+                                   memory_order_relaxed);
+       vty_out(vty, "GRE set updates:       %"PRIu64"\n", incoming);
+       vty_out(vty, "GRE set errors:        %"PRIu64"\n", errs);
        return CMD_SUCCESS;
 }
 
@@ -4680,6 +4793,12 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
                           dplane_ctx_get_ifname(ctx),
                           family2str(dplane_ctx_neightable_get_family(ctx)));
                break;
+       case DPLANE_OP_GRE_SET:
+               zlog_debug("Dplane gre set op %s, ifp %s, link %u",
+                          dplane_op2str(dplane_ctx_get_op(ctx)),
+                          dplane_ctx_get_ifname(ctx),
+                          ctx->u.gre.link_ifindex);
+               break;
        }
 }
 
@@ -4808,6 +4927,12 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
                                memory_order_relaxed);
                break;
 
+       case DPLANE_OP_GRE_SET:
+               if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+                       atomic_fetch_add_explicit(
+                               &zdplane_info.dg_gre_set_errors, 1,
+                               memory_order_relaxed);
+               break;
        /* Ignore 'notifications' - no-op */
        case DPLANE_OP_SYS_ROUTE_ADD:
        case DPLANE_OP_SYS_ROUTE_DELETE:
index 8d51d93cd4bfcd8ac4ad0e1b6aee61ecf47f5eba..3a8536dda50b81e7e3114c676cd7181ee8f25bad 100644 (file)
@@ -171,6 +171,7 @@ enum dplane_op_e {
        DPLANE_OP_NEIGH_IP_DELETE,
 
        DPLANE_OP_NEIGH_TABLE_UPDATE,
+       DPLANE_OP_GRE_SET,
 };
 
 /*
@@ -527,6 +528,14 @@ dplane_ctx_neightable_get_mcast_probes(const struct zebra_dplane_ctx *ctx);
 uint32_t
 dplane_ctx_neightable_get_ucast_probes(const struct zebra_dplane_ctx *ctx);
 
+/* Accessor for GRE set */
+uint32_t
+dplane_ctx_gre_get_link_ifindex(const struct zebra_dplane_ctx *ctx);
+unsigned int
+dplane_ctx_gre_get_mtu(const struct zebra_dplane_ctx *ctx);
+const struct zebra_l2info_gre *
+dplane_ctx_gre_get_info(const struct zebra_dplane_ctx *ctx);
+
 /* Namespace info - esp. for netlink communication */
 const struct zebra_dplane_info *dplane_ctx_get_ns(
        const struct zebra_dplane_ctx *ctx);
@@ -695,6 +704,13 @@ enum zebra_dplane_result dplane_neigh_table_update(const struct interface *ifp,
                                                   const uint32_t ucast_probes,
                                                   const uint32_t mcast_probes);
 
+/*
+ * Enqueue a GRE set
+ */
+enum zebra_dplane_result
+dplane_gre_set(struct interface *ifp, struct interface *ifp_link,
+              unsigned int mtu, const struct zebra_l2info_gre *gre_info);
+
 /* Forward ref of zebra_pbr_rule */
 struct zebra_pbr_rule;
 
index fc0382a6cdaedbf72f2ecf4897f131267522336c..200a977a69f99a4dd9cc95a60e1ccd94dec4ff34 100644 (file)
@@ -134,6 +134,7 @@ enum zebra_log_refs {
        EC_ZEBRA_DUPLICATE_NHG_MESSAGE,
        EC_ZEBRA_VRF_MISCONFIGURED,
        EC_ZEBRA_ES_CREATE,
+       EC_ZEBRA_GRE_SET_UPDATE,
 };
 
 void zebra_error_init(void);
index 80e06d913de097b0706e783f2f2740c733dd8956..30f4a44769e756a649f0378ac6799f9a6778a656 100644 (file)
@@ -1011,6 +1011,7 @@ zebra_evpn_t *zebra_evpn_lookup(vni_t vni)
  */
 zebra_evpn_t *zebra_evpn_add(vni_t vni)
 {
+       char buffer[80];
        struct zebra_vrf *zvrf;
        zebra_evpn_t tmp_zevpn;
        zebra_evpn_t *zevpn = NULL;
@@ -1024,11 +1025,14 @@ zebra_evpn_t *zebra_evpn_add(vni_t vni)
 
        zebra_evpn_es_evi_init(zevpn);
 
+       snprintf(buffer, sizeof(buffer), "Zebra EVPN MAC Table vni: %u", vni);
        /* Create hash table for MAC */
-       zevpn->mac_table = zebra_mac_db_create("Zebra EVPN MAC Table");
+       zevpn->mac_table = zebra_mac_db_create(buffer);
 
+       snprintf(buffer, sizeof(buffer), "Zebra EVPN Neighbor Table vni: %u",
+                vni);
        /* Create hash table for neighbors */
-       zevpn->neigh_table = zebra_neigh_db_create("Zebra EVPN Neighbor Table");
+       zevpn->neigh_table = zebra_neigh_db_create(buffer);
 
        return zevpn;
 }
index 7bbe092d8c89ea60a5ebbcb29ebad32d3aa49871..fe3167dc29b4f5cb6243cb3d8c827c2e629ca289 100644 (file)
@@ -1323,7 +1323,7 @@ int zebra_evpn_mac_send_del_to_client(vni_t vni, struct ethaddr *macaddr,
  */
 struct hash *zebra_mac_db_create(const char *desc)
 {
-       return hash_create(mac_hash_keymake, mac_cmp, desc);
+       return hash_create_size(8, mac_hash_keymake, mac_cmp, desc);
 }
 
 /* program sync mac flags in the dataplane  */
index cabba707a0ce00ee8f1266084fdcc01bbd56fa25..0038689e857f69b9157e47d55a3305e751017675 100644 (file)
@@ -2484,8 +2484,8 @@ void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS)
        memset(&esi, 0, sizeof(esi_t));
        s = msg;
 
-       stream_get(&esi, s, sizeof(esi_t));
-       vtep_ip.s_addr = stream_get_ipv4(s);
+       STREAM_GET(&esi, s, sizeof(esi_t));
+       STREAM_GET(&vtep_ip.s_addr, s, sizeof(vtep_ip.s_addr));
 
        if (hdr->command == ZEBRA_REMOTE_ES_VTEP_ADD) {
                uint32_t zapi_flags;
@@ -2493,16 +2493,19 @@ void zebra_evpn_proc_remote_es(ZAPI_HANDLER_ARGS)
                uint16_t df_pref;
                bool esr_rxed;
 
-               zapi_flags = stream_getl(s);
+               STREAM_GETL(s, zapi_flags);
                esr_rxed = (zapi_flags & ZAPI_ES_VTEP_FLAG_ESR_RXED) ? true
                                                                     : false;
-               df_alg = stream_getc(s);
-               df_pref = stream_getw(s);
+               STREAM_GETC(s, df_alg);
+               STREAM_GETW(s, df_pref);
                zebra_evpn_remote_es_add(&esi, vtep_ip, esr_rxed, df_alg,
                                         df_pref);
        } else {
                zebra_evpn_remote_es_del(&esi, vtep_ip);
        }
+
+stream_failure:
+       return;
 }
 
 void zebra_evpn_es_mac_deref_entry(zebra_mac_t *mac)
index d1b93dbe8ab2437dd7b746d4b70f7f26ea4a0392..4c7a1542fc174540c5fca4778ce12d2fa0f27a54 100644 (file)
@@ -85,7 +85,7 @@ int neigh_list_cmp(void *p1, void *p2)
 
 struct hash *zebra_neigh_db_create(const char *desc)
 {
-       return hash_create(neigh_hash_keymake, neigh_cmp, desc);
+       return hash_create_size(8, neigh_hash_keymake, neigh_cmp, desc);
 }
 
 uint32_t num_dup_detected_neighs(zebra_evpn_t *zevpn)
index 5fe8934a8221f352c3a05e058c331d0c32ef78ff..07a82886056b18c443ec5a2f06042f35752dba00 100644 (file)
@@ -29,7 +29,7 @@
 #include "thread.h"
 #include "network.h"
 #include "command.h"
-#include "version.h"
+#include "lib/version.h"
 #include "jhash.h"
 
 #include "zebra/rib.h"
index c3fbff2723c60edf5398c554982313d1ebd8efaa..71fac556e19006c8638efde60d3dd83834fe5f4d 100644 (file)
@@ -289,6 +289,32 @@ void zebra_l2_vlanif_update(struct interface *ifp,
        memcpy(&zif->l2info.vl, vlan_info, sizeof(*vlan_info));
 }
 
+/*
+ * Update L2 info for a GRE interface. This is called upon interface
+ * addition as well as update. Upon add/update, need to inform
+ * clients about GRE information.
+ */
+void zebra_l2_greif_add_update(struct interface *ifp,
+                              struct zebra_l2info_gre *gre_info, int add)
+{
+       struct zebra_if *zif;
+       struct in_addr old_vtep_ip;
+
+       zif = ifp->info;
+       assert(zif);
+
+       if (add) {
+               memcpy(&zif->l2info.gre, gre_info, sizeof(*gre_info));
+               return;
+       }
+
+       old_vtep_ip = zif->l2info.gre.vtep_ip;
+       if (IPV4_ADDR_SAME(&old_vtep_ip, &gre_info->vtep_ip))
+               return;
+
+       zif->l2info.gre.vtep_ip = gre_info->vtep_ip;
+}
+
 /*
  * Update L2 info for a VxLAN interface. This is called upon interface
  * addition as well as update. Upon add, need to invoke the VNI create
index 1834430287119e39502487d2076499aa564979a2..6572f344c4d0de2cd6fa1fa79f7ed276fb3765bd 100644 (file)
@@ -54,6 +54,18 @@ struct zebra_l2info_vlan {
        vlanid_t vid; /* VLAN id */
 };
 
+/* zebra L2 interface information - GRE interface */
+struct zebra_l2info_gre {
+       struct in_addr vtep_ip; /* IFLA_GRE_LOCAL */
+       struct in_addr vtep_ip_remote; /* IFLA_GRE_REMOTE */
+       uint32_t ikey;
+       uint32_t okey;
+       ifindex_t ifindex_link; /* Interface index of interface
+                                * linked with GRE
+                                */
+       ns_id_t link_nsid;
+};
+
 /* zebra L2 interface information - VXLAN interface */
 struct zebra_l2info_vxlan {
        vni_t vni;              /* VNI */
@@ -75,6 +87,7 @@ union zebra_l2if_info {
        struct zebra_l2info_bridge br;
        struct zebra_l2info_vlan vl;
        struct zebra_l2info_vxlan vxl;
+       struct zebra_l2info_gre gre;
 };
 
 /* NOTE: These macros are to be invoked only in the "correct" context.
@@ -96,11 +109,15 @@ extern void zebra_l2_bridge_add_update(struct interface *ifp,
 extern void zebra_l2_bridge_del(struct interface *ifp);
 extern void zebra_l2_vlanif_update(struct interface *ifp,
                                   struct zebra_l2info_vlan *vlan_info);
+extern void zebra_l2_greif_add_update(struct interface *ifp,
+                                     struct zebra_l2info_gre *vxlan_info,
+                                     int add);
 extern void zebra_l2_vxlanif_add_update(struct interface *ifp,
                                        struct zebra_l2info_vxlan *vxlan_info,
                                        int add);
 extern void zebra_l2_vxlanif_update_access_vlan(struct interface *ifp,
                                                vlanid_t access_vlan);
+extern void zebra_l2_greif_del(struct interface *ifp);
 extern void zebra_l2_vxlanif_del(struct interface *ifp);
 extern void zebra_l2if_update_bridge_slave(struct interface *ifp,
                                           ifindex_t bridge_ifindex,
index aaf93b4dc17ffd7429ecd77d6a4f25117bec917e..b1bba831d2dbf033c74e4740f8cb5cc6433e43af 100644 (file)
@@ -28,7 +28,7 @@
 #include "thread.h"
 #include "frr_pthread.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 #include "network.h"
 
 #include "lib/stream.h"
index 6d42957b24c59b025a67d802ee17c9573e3b9d56..850ca1763682fc9cfd23f3f877e9857260572b82 100644 (file)
@@ -2018,6 +2018,7 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
        int start_count = 0, end_count = 0; /* Installed counts */
        bool changed_p = false;
        bool is_debug = (IS_ZEBRA_DEBUG_DPLANE | IS_ZEBRA_DEBUG_MPLS);
+       enum zebra_sr_policy_update_label_mode update_mode;
 
        if (is_debug)
                zlog_debug("LSP dplane notif, in-label %u",
@@ -2091,10 +2092,21 @@ void zebra_mpls_process_dplane_notify(struct zebra_dplane_ctx *ctx)
        if (end_count > 0) {
                SET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
 
+               /* SR-TE update too */
+               if (start_count == 0)
+                       update_mode = ZEBRA_SR_POLICY_LABEL_CREATED;
+               else
+                       update_mode = ZEBRA_SR_POLICY_LABEL_UPDATED;
+               zebra_sr_policy_label_update(lsp->ile.in_label, update_mode);
+
                if (changed_p)
                        dplane_lsp_notif_update(lsp, DPLANE_OP_LSP_UPDATE, ctx);
 
        } else {
+               /* SR-TE update too */
+               zebra_sr_policy_label_update(lsp->ile.in_label,
+                                            ZEBRA_SR_POLICY_LABEL_REMOVED);
+
                UNSET_FLAG(lsp->flags, LSP_FLAG_INSTALLED);
                clear_nhlfe_installed(lsp);
        }
@@ -3940,11 +3952,18 @@ void zebra_mpls_close_tables(struct zebra_vrf *zvrf)
  */
 void zebra_mpls_init_tables(struct zebra_vrf *zvrf)
 {
+       char buffer[80];
+
        if (!zvrf)
                return;
-       zvrf->slsp_table =
-               hash_create(label_hash, label_cmp, "ZEBRA SLSP table");
-       zvrf->lsp_table = hash_create(label_hash, label_cmp, "ZEBRA LSP table");
+
+       snprintf(buffer, sizeof(buffer), "ZEBRA SLSP table: %s",
+                zvrf->vrf->name);
+       zvrf->slsp_table = hash_create_size(8, label_hash, label_cmp, buffer);
+
+       snprintf(buffer, sizeof(buffer), "ZEBRA LSP table: %s",
+                zvrf->vrf->name);
+       zvrf->lsp_table = hash_create_size(8, label_hash, label_cmp, buffer);
        zvrf->fec_table[AFI_IP] = route_table_init();
        zvrf->fec_table[AFI_IP6] = route_table_init();
        zvrf->mpls_flags = 0;
index 3af805558dd8c1474c2afa18061c9f58466cc282..ef0f2d8924ab4c4750dac8ce7a8ba4358ca949e5 100644 (file)
@@ -65,7 +65,7 @@ stream_failure:
        stream_put_in_addr(s, &mroute.sg.src);
        stream_put_in_addr(s, &mroute.sg.grp);
        stream_put(s, &mroute.lastused, sizeof(mroute.lastused));
-       stream_putl(s, suc);
+       stream_putl(s, (uint32_t)suc);
 
        stream_putw_at(s, 0, stream_get_endp(s));
        zserv_send_message(client, s);
index 7edf022892839a8e0afde5e88286be16a60f9001..6b40eae5b7d4cfb2ff836741cf413420fc25cda0 100644 (file)
@@ -845,6 +845,8 @@ static bool zebra_nhe_find(struct nhg_hash_entry **nhe, /* return value */
                SET_FLAG(backup_nhe->flags, NEXTHOP_GROUP_RECURSIVE);
 
 done:
+       /* Reset time since last update */
+       (*nhe)->uptime = monotime(NULL);
 
        return created;
 }
@@ -990,7 +992,7 @@ static struct nhg_ctx *nhg_ctx_new(void)
        return new;
 }
 
-static void nhg_ctx_free(struct nhg_ctx **ctx)
+void nhg_ctx_free(struct nhg_ctx **ctx)
 {
        struct nexthop *nh;
 
@@ -1191,6 +1193,13 @@ static int nhg_ctx_process_new(struct nhg_ctx *ctx)
        if (IS_ZEBRA_DEBUG_NHG_DETAIL)
                zlog_debug("%s: nhe %p (%u) is new", __func__, nhe, nhe->id);
 
+       /*
+        * If daemon nhg from the kernel, add a refcnt here to indicate the
+        * daemon owns it.
+        */
+       if (PROTO_OWNED(nhe))
+               zebra_nhg_increment_ref(nhe);
+
        SET_FLAG(nhe->flags, NEXTHOP_GROUP_VALID);
        SET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
 
@@ -1233,7 +1242,7 @@ static int queue_add(struct nhg_ctx *ctx)
        if (nhg_ctx_get_status(ctx) == NHG_CTX_QUEUED)
                return 0;
 
-       if (rib_queue_nhg_add(ctx)) {
+       if (rib_queue_nhg_ctx_add(ctx)) {
                nhg_ctx_set_status(ctx, NHG_CTX_FAILURE);
                return -1;
        }
@@ -1811,12 +1820,11 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
        int i, j, idx;
        const struct nexthop *bnh;
        struct nexthop *nh, *newnh;
+       mpls_label_t labels[MPLS_MAX_LABELS];
+       uint8_t num_labels;
 
        assert(nexthop->backup_num <= NEXTHOP_MAX_BACKUPS);
 
-       if (resolve_nhe->backup_info->nhe == NULL)
-               resolve_nhe->backup_info->nhe = zebra_nhg_alloc();
-
        /* Locate backups from the original nexthop's backup index and nhe */
        for (i = 0; i < nexthop->backup_num; i++) {
                idx = nexthop->backup_idx[i];
@@ -1832,6 +1840,8 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
                                map->map[j].new_idx;
                        resolved->backup_num++;
 
+                       SET_FLAG(resolved->flags, NEXTHOP_FLAG_HAS_BACKUP);
+
                        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                                zlog_debug("%s: found map idx orig %d, new %d",
                                           __func__, map->map[j].orig_idx,
@@ -1856,9 +1866,46 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
                if (bnh == NULL)
                        continue;
 
+               if (resolve_nhe->backup_info == NULL)
+                       resolve_nhe->backup_info = zebra_nhg_backup_alloc();
+
                /* Update backup info in the resolving nexthop and its nhe */
                newnh = nexthop_dup_no_recurse(bnh, NULL);
 
+               /* We may need some special handling for mpls labels: the new
+                * backup needs to carry the recursive nexthop's labels,
+                * if any: they may be vrf labels e.g.
+                * The original/inner labels are in the stack of 'resolve_nhe',
+                * if that is longer than the stack in 'nexthop'.
+                */
+               if (newnh->nh_label && resolved->nh_label &&
+                   nexthop->nh_label) {
+                       if (resolved->nh_label->num_labels >
+                           nexthop->nh_label->num_labels) {
+                               /* Prepare new label stack */
+                               num_labels = 0;
+                               for (j = 0; j < newnh->nh_label->num_labels;
+                                    j++) {
+                                       labels[j] = newnh->nh_label->label[j];
+                                       num_labels++;
+                               }
+
+                               /* Include inner labels */
+                               for (j = nexthop->nh_label->num_labels;
+                                    j < resolved->nh_label->num_labels;
+                                    j++) {
+                                       labels[num_labels] =
+                                               resolved->nh_label->label[j];
+                                       num_labels++;
+                               }
+
+                               /* Replace existing label stack in the backup */
+                               nexthop_del_labels(newnh);
+                               nexthop_add_labels(newnh, bnh->nh_label_type,
+                                                  num_labels, labels);
+                       }
+               }
+
                /* Need to compute the new backup index in the new
                 * backup list, and add to map struct.
                 */
@@ -1871,6 +1918,7 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
                        }
 
                        nh->next = newnh;
+                       j++;
 
                } else  /* First one */
                        resolve_nhe->backup_info->nhe->nhg.nexthop = newnh;
@@ -1879,6 +1927,8 @@ static int resolve_backup_nexthops(const struct nexthop *nexthop,
                resolved->backup_idx[resolved->backup_num] = j;
                resolved->backup_num++;
 
+               SET_FLAG(resolved->flags, NEXTHOP_FLAG_HAS_BACKUP);
+
                if (IS_ZEBRA_DEBUG_RIB_DETAILED)
                        zlog_debug("%s: added idx orig %d, new %d",
                                   __func__, idx, j);
@@ -2559,7 +2609,7 @@ int nexthop_active_update(struct route_node *rn, struct route_entry *re)
        struct nhg_hash_entry *curr_nhe;
        uint32_t curr_active = 0, backup_active = 0;
 
-       if (re->nhe->id >= ZEBRA_NHG_PROTO_LOWER)
+       if (PROTO_OWNED(re->nhe))
                return proto_nhg_nexthop_active_update(&re->nhe->nhg);
 
        afi_t rt_afi = family2afi(rn->p.family);
@@ -2861,13 +2911,13 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
                        zebra_nhg_handle_install(nhe);
 
                        /* If daemon nhg, send it an update */
-                       if (nhe->id >= ZEBRA_NHG_PROTO_LOWER)
+                       if (PROTO_OWNED(nhe))
                                zsend_nhg_notify(nhe->type, nhe->zapi_instance,
                                                 nhe->zapi_session, nhe->id,
                                                 ZAPI_NHG_INSTALLED);
                } else {
                        /* If daemon nhg, send it an update */
-                       if (nhe->id >= ZEBRA_NHG_PROTO_LOWER)
+                       if (PROTO_OWNED(nhe))
                                zsend_nhg_notify(nhe->type, nhe->zapi_instance,
                                                 nhe->zapi_session, nhe->id,
                                                 ZAPI_NHG_FAIL_INSTALL);
@@ -2915,6 +2965,7 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
        case DPLANE_OP_IPSET_ENTRY_ADD:
        case DPLANE_OP_IPSET_ENTRY_DELETE:
        case DPLANE_OP_NEIGH_TABLE_UPDATE:
+       case DPLANE_OP_GRE_SET:
                break;
        }
 
@@ -2927,7 +2978,31 @@ static void zebra_nhg_sweep_entry(struct hash_bucket *bucket, void *arg)
 
        nhe = (struct nhg_hash_entry *)bucket->data;
 
-       /* If its being ref'd, just let it be uninstalled via a route removal */
+       /*
+        * same logic as with routes.
+        *
+        * If older than startup time, we know we read them in from the
+        * kernel and have not gotten and update for them since startup
+        * from an upper level proto.
+        */
+       if (zrouter.startup_time < nhe->uptime)
+               return;
+
+       /*
+        * If it's proto-owned and not being used by a route, remove it since
+        * we haven't gotten an update about it from the proto since startup.
+        * This means that either the config for it was removed or the daemon
+        * didn't get started. This handles graceful restart & retain scenario.
+        */
+       if (PROTO_OWNED(nhe) && nhe->refcnt == 1) {
+               zebra_nhg_decrement_ref(nhe);
+               return;
+       }
+
+       /*
+        * If its being ref'd by routes, just let it be uninstalled via a route
+        * removal.
+        */
        if (ZEBRA_NHG_CREATED(nhe) && nhe->refcnt <= 0)
                zebra_nhg_uninstall_kernel(nhe);
 }
@@ -3201,7 +3276,7 @@ static void zebra_nhg_score_proto_entry(struct hash_bucket *bucket, void *arg)
        iter = arg;
 
        /* Needs to match type and outside zebra ID space */
-       if (nhe->type == iter->type && nhe->id >= ZEBRA_NHG_PROTO_LOWER) {
+       if (nhe->type == iter->type && PROTO_OWNED(nhe)) {
                if (IS_ZEBRA_DEBUG_NHG_DETAIL)
                        zlog_debug(
                                "%s: found nhe %p (%u), vrf %d, type %s after client disconnect",
index 38015bf557d3fede57ae50bf70c20de94d8ebabf..3fbf778be2eb4004017b639bb5f8263b73c51533 100644 (file)
@@ -51,6 +51,9 @@ struct nhg_hash_entry {
        afi_t afi;
        vrf_id_t vrf_id;
 
+       /* Time since last update */
+       time_t uptime;
+
        /* Source protocol - zebra or another daemon */
        int type;
 
@@ -147,6 +150,8 @@ enum nhg_type {
 /* Is this an NHE owned by zebra and not an upper level protocol? */
 #define ZEBRA_OWNED(NHE) (NHE->type == ZEBRA_ROUTE_NHG)
 
+#define PROTO_OWNED(NHE) (NHE->id >= ZEBRA_NHG_PROTO_LOWER)
+
 /*
  * Backup nexthops: this is a group object itself, so
  * that the backup nexthops can use the same code as a normal object.
@@ -269,6 +274,7 @@ extern bool zebra_nhg_hash_id_equal(const void *arg1, const void *arg2);
  * the rib meta queue.
  */
 extern int nhg_ctx_process(struct nhg_ctx *ctx);
+void nhg_ctx_free(struct nhg_ctx **ctx);
 
 /* Find via kernel nh creation */
 extern int zebra_nhg_kernel_find(uint32_t id, struct nexthop *nh,
index bea855d1af6f41f1923190a6ec9c6af65a0f9ceb..37d9399054bee70ba7705a6dbe1b583691a06ac3 100644 (file)
@@ -31,7 +31,7 @@
 #include "ptm_lib.h"
 #include "rib.h"
 #include "stream.h"
-#include "version.h"
+#include "lib/version.h"
 #include "vrf.h"
 #include "vty.h"
 #include "lib_errors.h"
index 82a0e6d015701e1f74352d5fa98b2c55d86a25b1..dbc5c77fd99b68a21a2d99f6c5a730fcf5a2e24a 100644 (file)
@@ -62,6 +62,7 @@ DEFINE_MGROUP(ZEBRA, "zebra");
 DEFINE_MTYPE(ZEBRA, RE,       "Route Entry");
 DEFINE_MTYPE_STATIC(ZEBRA, RIB_DEST,       "RIB destination");
 DEFINE_MTYPE_STATIC(ZEBRA, RIB_UPDATE_CTX, "Rib update context object");
+DEFINE_MTYPE_STATIC(ZEBRA, WQ_NHG_WRAPPER, "WQ nhg wrapper");
 
 /*
  * Event, list, and mutex for delivery of dataplane results
@@ -117,6 +118,20 @@ static const struct {
        /* no entry/default: 150 */
 };
 
+/* Wrapper struct for nhg workqueue items; a 'ctx' is an incoming update
+ * from the OS, and an 'nhe' is a nhe update.
+ */
+struct wq_nhg_wrapper {
+       int type;
+       union {
+               struct nhg_ctx *ctx;
+               struct nhg_hash_entry *nhe;
+       } u;
+};
+
+#define WQ_NHG_WRAPPER_TYPE_CTX  0x01
+#define WQ_NHG_WRAPPER_TYPE_NHG  0x02
+
 static void PRINTFRR(5, 6)
 _rnode_zlog(const char *_func, vrf_id_t vrf_id, struct route_node *rn,
            int priority, const char *msgfmt, ...)
@@ -908,6 +923,7 @@ static void rib_process_update_fib(struct zebra_vrf *zvrf,
                if (nh_active) {
                        if (IS_ZEBRA_DEBUG_RIB) {
                                char buf[SRCDEST2STR_BUFFER];
+
                                srcdest_rnode2str(rn, buf, sizeof(buf));
                                if (new != old)
                                        zlog_debug(
@@ -1068,12 +1084,6 @@ static struct route_entry *rib_choose_best(struct route_entry *current,
        return current;
 }
 
-/* Core function for processing nexthop group contexts's off metaq */
-static void rib_nhg_process(struct nhg_ctx *ctx)
-{
-       nhg_ctx_process(ctx);
-}
-
 /* Core function for processing routing information base. */
 static void rib_process(struct route_node *rn)
 {
@@ -2289,21 +2299,60 @@ done:
        dplane_ctx_fini(&ctx);
 }
 
+/*
+ * Process the nexthop-group workqueue subqueue
+ */
 static void process_subq_nhg(struct listnode *lnode)
 {
-       struct nhg_ctx *ctx = NULL;
+       struct nhg_ctx *ctx;
+       struct nhg_hash_entry *nhe, *newnhe;
+       struct wq_nhg_wrapper *w;
        uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
 
-       ctx = listgetdata(lnode);
+       w = listgetdata(lnode);
 
-       if (!ctx)
+       if (!w)
                return;
 
-       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
-               zlog_debug("NHG Context id=%u dequeued from sub-queue %u",
-                          ctx->id, qindex);
+       /* Two types of object - an update from the local kernel, or
+        * an nhg update from a daemon.
+        */
+       if (w->type == WQ_NHG_WRAPPER_TYPE_CTX) {
+               ctx = w->u.ctx;
+
+               if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                       zlog_debug(
+                               "NHG Context id=%u dequeued from sub-queue %u",
+                               ctx->id, qindex);
+
+
+               /* Process nexthop group updates coming 'up' from the OS */
+               nhg_ctx_process(ctx);
 
-       rib_nhg_process(ctx);
+       } else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG) {
+               nhe = w->u.nhe;
+
+               if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+                       zlog_debug("NHG %u dequeued from sub-queue %u",
+                                  nhe->id, qindex);
+
+               /* Process incoming nhg update, probably from a proto daemon */
+               newnhe = zebra_nhg_proto_add(nhe->id, nhe->type,
+                                            nhe->zapi_instance,
+                                            nhe->zapi_session,
+                                            &nhe->nhg, 0);
+
+               /* Report error to daemon via ZAPI */
+               if (newnhe == NULL)
+                       zsend_nhg_notify(nhe->type, nhe->zapi_instance,
+                                        nhe->zapi_session, nhe->id,
+                                        ZAPI_NHG_FAIL_INSTALL);
+
+               /* Free temp nhe - we own that memory. */
+               zebra_nhg_free(nhe);
+       }
+
+       XFREE(MTYPE_WQ_NHG_WRAPPER, w);
 }
 
 static void process_subq_route(struct listnode *lnode, uint8_t qindex)
@@ -2335,8 +2384,8 @@ static void process_subq_route(struct listnode *lnode, uint8_t qindex)
 
                srcdest_rnode2str(rnode, buf, sizeof(buf));
                zlog_debug("%s(%u:%u):%s: rn %p dequeued from sub-queue %u",
-                          zvrf_name(zvrf), zvrf_id(zvrf), re ? re->table : 0, buf,
-                          rnode, qindex);
+                          zvrf_name(zvrf), zvrf_id(zvrf), re ? re->table : 0,
+                          buf, rnode, qindex);
        }
 
        if (rnode->info)
@@ -2369,8 +2418,7 @@ static unsigned int process_subq(struct list *subq, uint8_t qindex)
 
 /* Dispatch the meta queue by picking, processing and unlocking the next RN from
  * a non-empty sub-queue with lowest priority. wq is equal to zebra->ribq and
- * data
- * is pointed to the meta queue structure.
+ * data is pointed to the meta queue structure.
  */
 static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
 {
@@ -2463,17 +2511,23 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
        return 0;
 }
 
-static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
 {
        struct nhg_ctx *ctx = NULL;
        uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
+       struct wq_nhg_wrapper *w;
 
        ctx = (struct nhg_ctx *)data;
 
        if (!ctx)
                return -1;
 
-       listnode_add(mq->subq[qindex], ctx);
+       w = XCALLOC(MTYPE_WQ_NHG_WRAPPER, sizeof(struct wq_nhg_wrapper));
+
+       w->type = WQ_NHG_WRAPPER_TYPE_CTX;
+       w->u.ctx = ctx;
+
+       listnode_add(mq->subq[qindex], w);
        mq->size++;
 
        if (IS_ZEBRA_DEBUG_RIB_DETAILED)
@@ -2483,6 +2537,32 @@ static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
        return 0;
 }
 
+static int rib_meta_queue_nhg_add(struct meta_queue *mq, void *data)
+{
+       struct nhg_hash_entry *nhe = NULL;
+       uint8_t qindex = route_info[ZEBRA_ROUTE_NHG].meta_q_map;
+       struct wq_nhg_wrapper *w;
+
+       nhe = (struct nhg_hash_entry *)data;
+
+       if (!nhe)
+               return -1;
+
+       w = XCALLOC(MTYPE_WQ_NHG_WRAPPER, sizeof(struct wq_nhg_wrapper));
+
+       w->type = WQ_NHG_WRAPPER_TYPE_NHG;
+       w->u.nhe = nhe;
+
+       listnode_add(mq->subq[qindex], w);
+       mq->size++;
+
+       if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+               zlog_debug("NHG id=%u queued into sub-queue %u",
+                          nhe->id, qindex);
+
+       return 0;
+}
+
 static int mq_add_handler(void *data,
                          int (*mq_add_func)(struct meta_queue *mq, void *data))
 {
@@ -2520,14 +2600,50 @@ int rib_queue_add(struct route_node *rn)
                return -1;
        }
 
-       return mq_add_handler(rn, &rib_meta_queue_add);
+       return mq_add_handler(rn, rib_meta_queue_add);
 }
 
-int rib_queue_nhg_add(struct nhg_ctx *ctx)
+/*
+ * Enqueue incoming nhg info from OS for processing
+ */
+int rib_queue_nhg_ctx_add(struct nhg_ctx *ctx)
 {
        assert(ctx);
 
-       return mq_add_handler(ctx, &rib_meta_queue_nhg_add);
+       return mq_add_handler(ctx, rib_meta_queue_nhg_ctx_add);
+}
+
+/*
+ * Enqueue incoming nhg from proto daemon for processing
+ */
+int rib_queue_nhe_add(struct nhg_hash_entry *nhe)
+{
+       if (nhe == NULL)
+               return -1;
+
+       return mq_add_handler(nhe, rib_meta_queue_nhg_add);
+}
+
+/* Clean up the nhg meta-queue list */
+static void nhg_meta_queue_free(struct list *l)
+{
+       struct wq_nhg_wrapper *w;
+       struct listnode *node;
+
+       /* Free the node wrapper object, and the struct it wraps */
+       while ((node = listhead(l)) != NULL) {
+               w = node->data;
+               node->data = NULL;
+
+               if (w->type == WQ_NHG_WRAPPER_TYPE_CTX)
+                       nhg_ctx_free(&w->u.ctx);
+               else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG)
+                       zebra_nhg_free(w->u.nhe);
+
+               XFREE(MTYPE_WQ_NHG_WRAPPER, w);
+
+               list_delete_node(l, node);
+       }
 }
 
 /* Create new meta queue.
@@ -2552,8 +2668,13 @@ void meta_queue_free(struct meta_queue *mq)
 {
        unsigned i;
 
-       for (i = 0; i < MQ_SIZE; i++)
+       for (i = 0; i < MQ_SIZE; i++) {
+               /* Some subqueues may need cleanup - nhgs for example */
+               if (i == route_info[ZEBRA_ROUTE_NHG].meta_q_map)
+                       nhg_meta_queue_free(mq->subq[i]);
+
                list_delete(&mq->subq[i]);
+       }
 
        XFREE(MTYPE_WORK_QUEUE, mq);
 }
@@ -2765,6 +2886,7 @@ static void _route_entry_dump_nh(const struct route_entry *re,
        char backup_str[50];
        char wgt_str[50];
        char temp_str[10];
+       char label_str[MPLS_LABEL_STRLEN];
        int i;
        struct interface *ifp;
        struct vrf *vrf = vrf_lookup_by_id(nexthop->vrf_id);
@@ -2789,6 +2911,15 @@ static void _route_entry_dump_nh(const struct route_entry *re,
                break;
        }
 
+       /* Label stack */
+       label_str[0] = '\0';
+       if (nexthop->nh_label && nexthop->nh_label->num_labels > 0) {
+               mpls_label2str(nexthop->nh_label->num_labels,
+                              nexthop->nh_label->label, label_str,
+                              sizeof(label_str), 0 /*pretty*/);
+               strlcat(label_str, ", ", sizeof(label_str));
+       }
+
        backup_str[0] = '\0';
        if (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_HAS_BACKUP)) {
                snprintf(backup_str, sizeof(backup_str), "backup ");
@@ -2803,9 +2934,9 @@ static void _route_entry_dump_nh(const struct route_entry *re,
        if (nexthop->weight)
                snprintf(wgt_str, sizeof(wgt_str), "wgt %d,", nexthop->weight);
 
-       zlog_debug("%s: %s %s[%u] vrf %s(%u) %s%s with flags %s%s%s%s%s%s%s%s",
+       zlog_debug("%s: %s %s[%u] %svrf %s(%u) %s%s with flags %s%s%s%s%s%s%s%s",
                   straddr, (nexthop->rparent ? "  NH" : "NH"), nhname,
-                  nexthop->ifindex, vrf ? vrf->name : "Unknown",
+                  nexthop->ifindex, label_str, vrf ? vrf->name : "Unknown",
                   nexthop->vrf_id,
                   wgt_str, backup_str,
                   (CHECK_FLAG(nexthop->flags, NEXTHOP_FLAG_ACTIVE)
@@ -3931,6 +4062,7 @@ static int rib_process_dplane_results(struct thread *thread)
                        case DPLANE_OP_NEIGH_DISCOVER:
                        case DPLANE_OP_BR_PORT_UPDATE:
                        case DPLANE_OP_NEIGH_TABLE_UPDATE:
+                       case DPLANE_OP_GRE_SET:
                        case DPLANE_OP_NONE:
                                /* Don't expect this: just return the struct? */
                                dplane_ctx_fini(&ctx);
index 6a42c682ad4e1e45db35ecd6655eb2de065b1e00..d07a49fb6e3726a81dd3b1aaf78f10076cb4de73 100644 (file)
@@ -30,7 +30,7 @@
 #include "plist.h"
 #include "nexthop.h"
 #include "northbound_cli.h"
-#include "route_types.h"
+#include "lib/route_types.h"
 #include "vrf.h"
 #include "frrstr.h"
 
index c82c34dd5300dd7c5e1729b3ea68ea823a1d1ee7..9da4589501e9d88edc82f00d868d91c3050c5d5b 100644 (file)
@@ -17,6 +17,8 @@
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  */
 
+#include <zebra.h>
+
 #include "northbound.h"
 #include "libfrr.h"
 #include "zebra_routemap_nb.h"
index 3e08d83724454a66daba0190df6ccc5e1c90a09c..6fe24dfa5492b0532a32101a40a46829104e3a76 100644 (file)
@@ -36,7 +36,7 @@
 #include "vrf.h"
 #include "hook.h"
 #include "libfrr.h"
-#include "version.h"
+#include "lib/version.h"
 
 #include "zebra/rib.h"
 #include "zebra/zserv.h"
index 212557423b8c4548480a809526067943c4d2a654..a0c63e4202e5034226f78abeef1128ed7a0a74b7 100644 (file)
@@ -103,9 +103,7 @@ static int zebra_vrf_new(struct vrf *vrf)
        if (IS_ZEBRA_DEBUG_EVENT)
                zlog_debug("VRF %s created, id %u", vrf->name, vrf->vrf_id);
 
-       zvrf = zebra_vrf_alloc();
-       vrf->info = zvrf;
-       zvrf->vrf = vrf;
+       zvrf = zebra_vrf_alloc(vrf);
        if (!vrf_is_backend_netns())
                zvrf->zns = zebra_ns_lookup(NS_DEFAULT);
 
@@ -427,12 +425,15 @@ static void zebra_vrf_table_create(struct zebra_vrf *zvrf, afi_t afi,
 }
 
 /* Allocate new zebra VRF. */
-struct zebra_vrf *zebra_vrf_alloc(void)
+struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf)
 {
        struct zebra_vrf *zvrf;
 
        zvrf = XCALLOC(MTYPE_ZEBRA_VRF, sizeof(struct zebra_vrf));
 
+       zvrf->vrf = vrf;
+       vrf->info = zvrf;
+
        zebra_vxlan_init_tables(zvrf);
        zebra_mpls_init_tables(zvrf);
        zebra_pw_init(zvrf);
index 000b5a723825dd68cd262fd4b3e1bb05aa3ecc7e..b2b0fcfbb2a837e41fc43600e0adf0174545e477 100644 (file)
@@ -251,7 +251,7 @@ extern struct route_table *zebra_vrf_get_table_with_table_id(afi_t afi,
 extern void zebra_vrf_update_all(struct zserv *client);
 extern struct zebra_vrf *zebra_vrf_lookup_by_id(vrf_id_t vrf_id);
 extern struct zebra_vrf *zebra_vrf_lookup_by_name(const char *);
-extern struct zebra_vrf *zebra_vrf_alloc(void);
+extern struct zebra_vrf *zebra_vrf_alloc(struct vrf *vrf);
 extern struct route_table *zebra_vrf_table(afi_t, safi_t, vrf_id_t);
 
 extern void zebra_vrf_init(void);
index 283a3e52d664896afcfc95d2484b2cbc5e887045..8061f34d2ba99dde6b6fc834c308c4e116ecf683 100644 (file)
@@ -445,6 +445,16 @@ static void zebra_show_ip_route_opaque(struct vty *vty, struct route_entry *re,
        }
 }
 
+static void uptime2str(time_t uptime, char *buf, size_t bufsize)
+{
+       time_t cur;
+
+       cur = monotime(NULL);
+       cur -= uptime;
+
+       frrtime_to_interval(cur, buf, bufsize);
+}
+
 /* New RIB.  Detailed information for IPv4 route. */
 static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
                                     int mcast, bool use_fib, bool show_ng)
@@ -499,12 +509,7 @@ static void vty_show_ip_route_detail(struct vty *vty, struct route_node *rn,
                        vty_out(vty, ", best");
                vty_out(vty, "\n");
 
-               time_t uptime;
-
-               uptime = monotime(NULL);
-               uptime -= re->uptime;
-
-               frrtime_to_interval(uptime, buf, sizeof(buf));
+               uptime2str(re->uptime, buf, sizeof(buf));
 
                vty_out(vty, "  Last update %s ago\n", buf);
 
@@ -839,17 +844,13 @@ static void vty_show_ip_route(struct vty *vty, struct route_node *rn,
        json_object *json_nexthops = NULL;
        json_object *json_nexthop = NULL;
        json_object *json_route = NULL;
-       time_t uptime;
        const rib_dest_t *dest = rib_dest_from_rnode(rn);
        const struct nexthop_group *nhg;
        char up_str[MONOTIME_STRLEN];
        bool first_p = true;
        bool nhg_from_backup = false;
 
-       uptime = monotime(NULL);
-       uptime -= re->uptime;
-
-       frrtime_to_interval(uptime, up_str, sizeof(up_str));
+       uptime2str(re->uptime, up_str, sizeof(up_str));
 
        /* If showing fib information, use the fib view of the
         * nexthops.
@@ -1339,9 +1340,13 @@ static void show_nexthop_group_out(struct vty *vty, struct nhg_hash_entry *nhe)
        struct nexthop *nexthop = NULL;
        struct nhg_connected *rb_node_dep = NULL;
        struct nexthop_group *backup_nhg;
+       char up_str[MONOTIME_STRLEN];
+
+       uptime2str(nhe->uptime, up_str, sizeof(up_str));
 
        vty_out(vty, "ID: %u (%s)\n", nhe->id, zebra_route_string(nhe->type));
-       vty_out(vty, "     RefCnt: %d\n", nhe->refcnt);
+       vty_out(vty, "     RefCnt: %u\n", nhe->refcnt);
+       vty_out(vty, "     Uptime: %s\n", up_str);
        vty_out(vty, "     VRF: %s\n", vrf_id_to_name(nhe->vrf_id));
 
        if (CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_VALID)) {
index 4cd3b60a0ffc696914945266990dfff9cabdd143..4e86ab3b4f7adc0737a8a2809b30966a73a76678 100644 (file)
@@ -3749,7 +3749,7 @@ zebra_vxlan_remote_macip_helper(bool add, struct stream *s, vni_t *vni,
        memset(ip, 0, sizeof(*ip));
        STREAM_GETL(s, *vni);
        STREAM_GET(macaddr->octet, s, ETH_ALEN);
-       STREAM_GETL(s, *ipa_len);
+       STREAM_GETW(s, *ipa_len);
 
        if (*ipa_len) {
                if (*ipa_len == IPV4_MAX_BYTELEN)
@@ -5752,13 +5752,20 @@ stream_failure:
  */
 void zebra_vxlan_init_tables(struct zebra_vrf *zvrf)
 {
+       char buffer[80];
+
        if (!zvrf)
                return;
-       zvrf->evpn_table =
-               hash_create(zebra_evpn_hash_keymake, zebra_evpn_hash_cmp,
-                           "Zebra VRF EVPN Table");
-       zvrf->vxlan_sg_table = hash_create(zebra_vxlan_sg_hash_key_make,
-                       zebra_vxlan_sg_hash_eq, "Zebra VxLAN SG Table");
+
+       snprintf(buffer, sizeof(buffer), "Zebra VRF EVPN Table: %s",
+                zvrf->vrf->name);
+       zvrf->evpn_table = hash_create_size(8, zebra_evpn_hash_keymake,
+                                           zebra_evpn_hash_cmp, buffer);
+
+       snprintf(buffer, sizeof(buffer), "Zebra VxLAN SG Table: %s",
+                zvrf->vrf->name);
+       zvrf->vxlan_sg_table = hash_create_size(8, zebra_vxlan_sg_hash_key_make,
+                                               zebra_vxlan_sg_hash_eq, buffer);
 }
 
 /* Cleanup EVPN info, but don't free the table. */
index f89b6fe478313ebca5439705b35b3dace1a0af59..0bf4d8ece298eb1ee0368bb436f42bc287179557 100644 (file)
@@ -50,7 +50,6 @@
 #include "lib/thread.h"           /* for thread (ptr only), THREAD_ARG, ... */
 #include "lib/vrf.h"              /* for vrf_info_lookup, VRF_DEFAULT */
 #include "lib/vty.h"              /* for vty_out, vty (ptr only) */
-#include "lib/zassert.h"          /* for assert */
 #include "lib/zclient.h"          /* for zmsghdr, ZEBRA_HEADER_SIZE, ZEBRA... */
 #include "lib/frr_pthread.h"      /* for frr_pthread_new, frr_pthread_stop... */
 #include "lib/frratomic.h"        /* for atomic_load_explicit, atomic_stor... */