summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--babeld/kernel.c4
-rw-r--r--babeld/kernel.h2
-rw-r--r--bfdd/bfd.c21
-rw-r--r--bfdd/bfd.h10
-rw-r--r--bfdd/bfd_packet.c89
-rw-r--r--bfdd/bfdd_vty.c41
-rw-r--r--bgpd/IMPLEMENTATION.txt168
-rw-r--r--bgpd/bgp_advertise.c2
-rw-r--r--bgpd/bgp_aspath.c22
-rw-r--r--bgpd/bgp_aspath.h1
-rw-r--r--bgpd/bgp_attr.c28
-rw-r--r--bgpd/bgp_attr.h1
-rw-r--r--bgpd/bgp_bmp.c23
-rw-r--r--bgpd/bgp_btoa.c2
-rw-r--r--bgpd/bgp_conditional_adv.c213
-rw-r--r--bgpd/bgp_conditional_adv.h19
-rw-r--r--bgpd/bgp_damp.c10
-rw-r--r--bgpd/bgp_debug.c47
-rw-r--r--bgpd/bgp_debug.h3
-rw-r--r--bgpd/bgp_dump.c6
-rw-r--r--bgpd/bgp_ecommunity.c89
-rw-r--r--bgpd/bgp_ecommunity.h40
-rw-r--r--bgpd/bgp_evpn.c56
-rw-r--r--bgpd/bgp_evpn_mh.c60
-rw-r--r--bgpd/bgp_evpn_vty.c176
-rw-r--r--bgpd/bgp_fsm.c24
-rw-r--r--bgpd/bgp_io.c19
-rw-r--r--bgpd/bgp_keepalives.c9
-rw-r--r--bgpd/bgp_labelpool.c671
-rw-r--r--bgpd/bgp_labelpool.h1
-rw-r--r--bgpd/bgp_main.c5
-rw-r--r--bgpd/bgp_memory.c8
-rw-r--r--bgpd/bgp_memory.h8
-rw-r--r--bgpd/bgp_mplsvpn.c49
-rw-r--r--bgpd/bgp_nexthop.c37
-rw-r--r--bgpd/bgp_nexthop.h1
-rw-r--r--bgpd/bgp_nht.c169
-rw-r--r--bgpd/bgp_open.c62
-rw-r--r--bgpd/bgp_packet.c112
-rw-r--r--bgpd/bgp_packet.h2
-rw-r--r--bgpd/bgp_rd.c14
-rw-r--r--bgpd/bgp_route.c392
-rw-r--r--bgpd/bgp_route.h23
-rw-r--r--bgpd/bgp_routemap.c193
-rw-r--r--bgpd/bgp_routemap_nb.c14
-rw-r--r--bgpd/bgp_routemap_nb.h8
-rw-r--r--bgpd/bgp_routemap_nb_config.c107
-rw-r--r--bgpd/bgp_rpki.c12
-rw-r--r--bgpd/bgp_snmp.c4
-rw-r--r--bgpd/bgp_table.h75
-rw-r--r--bgpd/bgp_updgrp.c45
-rw-r--r--bgpd/bgp_updgrp.h4
-rw-r--r--bgpd/bgp_vty.c265
-rw-r--r--bgpd/bgp_zebra.c137
-rw-r--r--bgpd/bgp_zebra.h1
-rw-r--r--bgpd/bgpd.c452
-rw-r--r--bgpd/bgpd.conf.sample277
-rw-r--r--bgpd/bgpd.h121
-rw-r--r--bgpd/rfapi/bgp_rfapi_cfg.c24
-rw-r--r--bgpd/rfapi/rfapi.c32
-rw-r--r--bgpd/rfapi/rfapi_import.c46
-rw-r--r--bgpd/rfapi/rfapi_private.h5
-rw-r--r--bgpd/rfapi/rfapi_rib.c60
-rw-r--r--bgpd/rfapi/rfapi_vty.c12
-rw-r--r--bgpd/rfapi/rfapi_vty.h2
-rw-r--r--bgpd/subdir.am1
-rw-r--r--configure.ac4
-rw-r--r--debian/changelog6
-rw-r--r--debian/control1
-rw-r--r--debian/frr.logrotate2
-rw-r--r--doc/developer/topotests.rst6
-rw-r--r--doc/user/bfd.rst4
-rw-r--r--doc/user/bgp.rst64
-rw-r--r--doc/user/ospfd.rst45
-rw-r--r--doc/user/overview.rst75
-rw-r--r--doc/user/pim.rst2
-rw-r--r--doc/user/pimv6.rst34
-rw-r--r--doc/user/ripd.rst16
-rw-r--r--doc/user/routemap.rst3
-rw-r--r--doc/user/rpki.rst6
-rw-r--r--doc/user/setup.rst2
-rw-r--r--doc/user/vtysh.rst6
-rw-r--r--doc/user/zebra.rst7
-rw-r--r--docker/alpine/Dockerfile26
-rwxr-xr-xdocker/alpine/build.sh12
-rw-r--r--eigrpd/eigrp_network.c4
-rw-r--r--eigrpd/eigrp_packet.c8
-rw-r--r--eigrpd/eigrpd.c3
-rw-r--r--gdb/lib.txt22
-rw-r--r--include/linux/pkt_cls.h776
-rw-r--r--include/linux/rtnetlink.h12
-rw-r--r--isisd/fabricd.c14
-rw-r--r--isisd/isis_adjacency.c12
-rw-r--r--isisd/isis_bpf.c13
-rw-r--r--isisd/isis_circuit.c15
-rw-r--r--isisd/isis_dlpi.c24
-rw-r--r--isisd/isis_dr.c12
-rw-r--r--isisd/isis_ldp_sync.c26
-rw-r--r--isisd/isis_nb_config.c71
-rw-r--r--isisd/isis_pfpacket.c26
-rw-r--r--isisd/isis_spf.c6
-rw-r--r--isisd/isis_sr.c3
-rw-r--r--isisd/isis_te.c105
-rw-r--r--isisd/isis_te.h3
-rw-r--r--isisd/isis_tlvs.c37
-rw-r--r--isisd/isis_tlvs.h1
-rw-r--r--isisd/isisd.c39
-rw-r--r--isisd/isisd.h1
-rw-r--r--ldpd/ldpe.c12
-rw-r--r--lib/bitfield.h69
-rw-r--r--lib/link_state.c11
-rw-r--r--lib/link_state.h2
-rw-r--r--lib/plist.c1
-rw-r--r--lib/prefix.h1
-rw-r--r--lib/routemap.c7
-rw-r--r--lib/routemap.h4
-rw-r--r--lib/routemap_cli.c10
-rw-r--r--lib/sigevent.c3
-rw-r--r--lib/sockopt.c14
-rw-r--r--lib/sockunion.c6
-rw-r--r--lib/subdir.am4
-rw-r--r--lib/termtable.h7
-rw-r--r--lib/thread.c5
-rw-r--r--lib/typesafe.h9
-rw-r--r--lib/yang_wrappers.c2
-rw-r--r--lib/zclient.c16
-rw-r--r--lib/zlog.c10
-rw-r--r--nhrpd/nhrp_interface.c3
-rw-r--r--nhrpd/nhrp_peer.c3
-rw-r--r--ospf6d/ospf6_abr.c7
-rw-r--r--ospf6d/ospf6_interface.c14
-rw-r--r--ospf6d/ospf6_intra.c6
-rw-r--r--ospf6d/ospf6_message.c6
-rw-r--r--ospfclient/ospf_apiclient.c12
-rw-r--r--ospfd/ospf_abr.c420
-rw-r--r--ospfd/ospf_apiserver.c175
-rw-r--r--ospfd/ospf_ase.c9
-rw-r--r--ospfd/ospf_dump.c437
-rw-r--r--ospfd/ospf_flood.c50
-rw-r--r--ospfd/ospf_ia.c113
-rw-r--r--ospfd/ospf_interface.c90
-rw-r--r--ospfd/ospf_interface.h2
-rw-r--r--ospfd/ospf_ldp_sync.c31
-rw-r--r--ospfd/ospf_lsa.c70
-rw-r--r--ospfd/ospf_lsa.h1
-rw-r--r--ospfd/ospf_nsm.c33
-rw-r--r--ospfd/ospf_opaque.c154
-rw-r--r--ospfd/ospf_packet.c274
-rw-r--r--ospfd/ospf_route.c84
-rw-r--r--ospfd/ospf_spf.c33
-rw-r--r--ospfd/ospf_sr.c15
-rw-r--r--ospfd/ospf_vty.c280
-rw-r--r--ospfd/ospfd.c1
-rw-r--r--ospfd/ospfd.h1
-rw-r--r--pathd/path_pcep_pcc.c2
-rw-r--r--pathd/path_ted.c20
-rw-r--r--pbrd/pbr_vty.c54
-rw-r--r--pimd/mtracebis_netlink.c2
-rw-r--r--pimd/pim6_cmd.c160
-rw-r--r--pimd/pim6_cmd.h1
-rw-r--r--pimd/pim6_main.c6
-rw-r--r--pimd/pim6_mld.c296
-rw-r--r--pimd/pim6_mld.h2
-rw-r--r--pimd/pim_addr.h8
-rw-r--r--pimd/pim_cmd.c78
-rw-r--r--pimd/pim_cmd_common.c669
-rw-r--r--pimd/pim_cmd_common.h1
-rw-r--r--pimd/pim_hello.c16
-rw-r--r--pimd/pim_iface.c48
-rw-r--r--pimd/pim_ifchannel.c52
-rw-r--r--pimd/pim_igmp.c80
-rw-r--r--pimd/pim_igmp.h12
-rw-r--r--pimd/pim_igmpv2.c16
-rw-r--r--pimd/pim_igmpv3.c44
-rw-r--r--pimd/pim_instance.c7
-rw-r--r--pimd/pim_instance.h3
-rw-r--r--pimd/pim_main.c6
-rw-r--r--pimd/pim_mroute.c6
-rw-r--r--pimd/pim_nb_config.c61
-rw-r--r--pimd/pim_neighbor.c9
-rw-r--r--pimd/pim_neighbor.h2
-rw-r--r--pimd/pim_nht.c2
-rw-r--r--pimd/pim_register.c2
-rw-r--r--pimd/pim_rp.c61
-rw-r--r--pimd/pim_sock.c40
-rw-r--r--pimd/pim_sock.h2
-rw-r--r--pimd/pim_static.c50
-rw-r--r--pimd/pim_tib.c10
-rw-r--r--pimd/pim_tlv.c12
-rw-r--r--pimd/pim_tlv.h2
-rw-r--r--pimd/pim_upstream.c16
-rw-r--r--pimd/pim_vty.c62
-rw-r--r--pimd/pimd.h72
-rw-r--r--qpb/qpb.h6
-rw-r--r--redhat/frr.logrotate8
-rw-r--r--redhat/frr.spec.in5
-rw-r--r--ripd/ripd.c23
-rw-r--r--sharpd/sharp_vty.c14
-rw-r--r--staticd/static_nb_config.c26
-rw-r--r--tests/lib/test_typelist.h2
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/__init__.py0
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/r1/bgpd.conf21
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/r1/zebra.conf11
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/r2/bgpd.conf11
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/r3/bgpd.conf6
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/r3/zebra.conf6
-rw-r--r--tests/topotests/bgp_aggregate_address_matching_med/test_bgp_aggregate_address_matching_med.py148
-rw-r--r--tests/topotests/bgp_as_override/__init__.py0
-rw-r--r--tests/topotests/bgp_as_override/r1/bgpd.conf10
-rw-r--r--tests/topotests/bgp_as_override/r1/zebra.conf9
-rw-r--r--tests/topotests/bgp_as_override/r2/bgpd.conf10
-rw-r--r--tests/topotests/bgp_as_override/r2/zebra.conf9
-rw-r--r--tests/topotests/bgp_as_override/r3/bgpd.conf13
-rw-r--r--tests/topotests/bgp_as_override/r3/zebra.conf9
-rw-r--r--tests/topotests/bgp_as_override/r4/bgpd.conf7
-rw-r--r--tests/topotests/bgp_as_override/r4/zebra.conf6
-rw-r--r--tests/topotests/bgp_as_override/test_bgp_as_override.py122
-rw-r--r--tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py144
-rw-r--r--tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py396
-rwxr-xr-xtests/topotests/bgp_distance_change/bgp_admin_dist.json402
-rwxr-xr-xtests/topotests/bgp_distance_change/bgp_admin_dist_vrf.json429
-rwxr-xr-xtests/topotests/bgp_distance_change/test_bgp_admin_dist.py1282
-rwxr-xr-xtests/topotests/bgp_distance_change/test_bgp_admin_dist_vrf.py900
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/__init__.py0
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf11
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf8
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf5
-rw-r--r--tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py131
-rw-r--r--tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py196
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py16
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf3
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf4
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf3
-rw-r--r--tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf3
-rw-r--r--tests/topotests/bgp_local_as/__init__.py0
-rw-r--r--tests/topotests/bgp_local_as/r1/bgpd.conf14
-rw-r--r--tests/topotests/bgp_local_as/r1/zebra.conf10
-rw-r--r--tests/topotests/bgp_local_as/r2/bgpd.conf6
-rw-r--r--tests/topotests/bgp_local_as/r2/zebra.conf4
-rw-r--r--tests/topotests/bgp_local_as/r3/bgpd.conf6
-rw-r--r--tests/topotests/bgp_local_as/r3/zebra.conf4
-rw-r--r--tests/topotests/bgp_local_as/test_bgp_local_as.py134
-rw-r--r--tests/topotests/bgp_lu_topo1/R1/labelpool.summ.json2
-rw-r--r--tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json2
-rw-r--r--tests/topotests/bgp_orf/__init__.py0
-rw-r--r--tests/topotests/bgp_orf/r1/bgpd.conf9
-rw-r--r--tests/topotests/bgp_orf/r1/zebra.conf8
-rw-r--r--tests/topotests/bgp_orf/r2/bgpd.conf9
-rw-r--r--tests/topotests/bgp_orf/r2/zebra.conf4
-rw-r--r--tests/topotests/bgp_orf/test_bgp_orf.py159
-rw-r--r--tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py19
-rw-r--r--tests/topotests/bgp_soo/__init__.py0
-rw-r--r--tests/topotests/bgp_soo/cpe1/bgpd.conf10
-rw-r--r--tests/topotests/bgp_soo/cpe1/zebra.conf12
-rw-r--r--tests/topotests/bgp_soo/cpe2/bgpd.conf10
-rw-r--r--tests/topotests/bgp_soo/cpe2/zebra.conf9
-rw-r--r--tests/topotests/bgp_soo/pe1/bgpd.conf27
-rw-r--r--tests/topotests/bgp_soo/pe1/ldpd.conf10
-rw-r--r--tests/topotests/bgp_soo/pe1/ospfd.conf7
-rw-r--r--tests/topotests/bgp_soo/pe1/zebra.conf12
-rw-r--r--tests/topotests/bgp_soo/pe2/bgpd.conf31
-rw-r--r--tests/topotests/bgp_soo/pe2/ldpd.conf10
-rw-r--r--tests/topotests/bgp_soo/pe2/ospfd.conf7
-rw-r--r--tests/topotests/bgp_soo/pe2/zebra.conf12
-rw-r--r--tests/topotests/bgp_soo/test_bgp_soo.py186
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/__init__.py0
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf25
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json50
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf7
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json38
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf25
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf7
-rw-r--r--tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py187
-rw-r--r--tests/topotests/bgp_vpnv4_gre/__init__.py0
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf26
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json50
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r1/zebra.conf14
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r2/bgp_ipv4_routes.json38
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r2/bgpd.conf22
-rw-r--r--tests/topotests/bgp_vpnv4_gre/r2/zebra.conf14
-rw-r--r--tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py191
-rwxr-xr-xtests/topotests/conftest.py5
-rw-r--r--tests/topotests/lib/bgp.py31
-rw-r--r--tests/topotests/lib/common_config.py32
-rw-r--r--tests/topotests/lib/topogen.py2
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py2525
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py1424
-rwxr-xr-xtests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py1799
-rw-r--r--tests/topotests/ospf_topo1/test_ospf_topo1.py30
-rw-r--r--tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py7
-rw-r--r--tools/coccinelle/route_map_apply.cocci15
-rw-r--r--tools/etc/frr/daemons2
-rw-r--r--tools/etc/rsyslog.d/45-frr.conf2
-rwxr-xr-xtools/frr-reload.py1
-rwxr-xr-xtools/frr.in2
-rw-r--r--tools/frr.service.in2
-rw-r--r--tools/frr@.service.in2
-rwxr-xr-xtools/frrcommon.sh.in14
-rw-r--r--vtysh/vtysh.h9
-rw-r--r--vtysh/vtysh_config.c10
-rw-r--r--vtysh/vtysh_main.c82
-rw-r--r--watchfrr/watchfrr.c2
-rw-r--r--yang/frr-bgp-route-map.yang51
-rw-r--r--zebra/debug_nl.c35
-rw-r--r--zebra/dplane_fpm_nl.c3
-rw-r--r--zebra/if_ioctl.c4
-rw-r--r--zebra/if_netlink.c30
-rw-r--r--zebra/if_socket.c11
-rw-r--r--zebra/if_sysctl.c4
-rw-r--r--zebra/interface.c95
-rw-r--r--zebra/interface.h12
-rw-r--r--zebra/kernel_netlink.c37
-rw-r--r--zebra/kernel_socket.c45
-rw-r--r--zebra/netconf_netlink.c53
-rw-r--r--zebra/netconf_netlink.h4
-rw-r--r--zebra/redistribute.c13
-rw-r--r--zebra/rib.h27
-rw-r--r--zebra/rt.h4
-rw-r--r--zebra/rt_netlink.c65
-rw-r--r--zebra/rtadv.c35
-rw-r--r--zebra/subdir.am3
-rw-r--r--zebra/tc_netlink.c468
-rw-r--r--zebra/tc_netlink.h62
-rw-r--r--zebra/tc_socket.c41
-rw-r--r--zebra/zapi_msg.c50
-rw-r--r--zebra/zebra_dplane.c211
-rw-r--r--zebra/zebra_dplane.h27
-rw-r--r--zebra/zebra_fpm.c27
-rw-r--r--zebra/zebra_mpls.c55
-rw-r--r--zebra/zebra_mpls.h36
-rw-r--r--zebra/zebra_nhg.c66
-rw-r--r--zebra/zebra_nhg.h1
-rw-r--r--zebra/zebra_pw.c7
-rw-r--r--zebra/zebra_rib.c1369
-rw-r--r--zebra/zebra_router.c3
-rw-r--r--zebra/zebra_router.h5
-rw-r--r--zebra/zebra_script.c19
-rw-r--r--zebra/zebra_srv6.c1
-rw-r--r--zebra/zebra_vrf.c6
-rw-r--r--zebra/zebra_vxlan.c33
-rw-r--r--zebra/zserv.c12
-rw-r--r--zebra/zserv.h10
344 files changed, 18204 insertions, 7191 deletions
diff --git a/babeld/kernel.c b/babeld/kernel.c
index 3941db8d5f..5aa01ceb44 100644
--- a/babeld/kernel.c
+++ b/babeld/kernel.c
@@ -227,10 +227,10 @@ if_eui64(int ifindex, unsigned char *eui)
/* Like gettimeofday, but returns monotonic time. If POSIX clocks are not
available, falls back to gettimeofday but enforces monotonicity. */
-int
+void
gettime(struct timeval *tv)
{
- return monotime(tv);
+ monotime(tv);
}
/* If /dev/urandom doesn't exist, this will fail with ENOENT, which the
diff --git a/babeld/kernel.h b/babeld/kernel.h
index 5b1437ef3e..f39bc35bdb 100644
--- a/babeld/kernel.h
+++ b/babeld/kernel.h
@@ -43,7 +43,7 @@ int kernel_route(enum babel_kernel_routes operation, const unsigned char *dest,
unsigned int metric, const unsigned char *newgate,
int newifindex, unsigned int newmetric);
int if_eui64(int ifindex, unsigned char *eui);
-int gettime(struct timeval *tv);
+void gettime(struct timeval *tv);
int read_random_bytes(void *buf, size_t len);
#endif /* BABEL_KERNEL_H */
diff --git a/bfdd/bfd.c b/bfdd/bfd.c
index a161926358..4367f253e1 100644
--- a/bfdd/bfd.c
+++ b/bfdd/bfd.c
@@ -348,7 +348,7 @@ int bfd_session_enable(struct bfd_session *bs)
/* Sanity check: don't leak open sockets. */
if (bs->sock != -1) {
if (bglobal.debug_peer_event)
- zlog_debug("session-enable: previous socket open");
+ zlog_debug("%s: previous socket open", __func__);
close(bs->sock);
bs->sock = -1;
@@ -381,6 +381,9 @@ int bfd_session_enable(struct bfd_session *bs)
ptm_bfd_start_xmt_timer(bs, false);
}
+ /* initialize RTT */
+ bfd_rtt_init(bs);
+
return 0;
}
@@ -574,6 +577,9 @@ void ptm_bfd_sess_dn(struct bfd_session *bfd, uint8_t diag)
memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));
/* reset local address ,it might has been be changed after bfd is up*/
memset(&bfd->local_address, 0, sizeof(bfd->local_address));
+
+ /* reset RTT */
+ bfd_rtt_init(bfd);
}
static struct bfd_session *bfd_find_disc(struct sockaddr_any *sa,
@@ -946,7 +952,7 @@ int ptm_bfd_sess_del(struct bfd_peer_cfg *bpc)
}
if (bglobal.debug_peer_event)
- zlog_debug("session-delete: %s", bs_to_string(bs));
+ zlog_debug("%s: %s", __func__, bs_to_string(bs));
control_notify_config(BCM_NOTIFY_CONFIG_DELETE, bs);
@@ -2063,3 +2069,14 @@ unsigned long bfd_get_session_count(void)
{
return bfd_key_hash->count;
}
+
+void bfd_rtt_init(struct bfd_session *bfd)
+{
+ uint8_t i;
+
+ /* initialize RTT */
+ bfd->rtt_valid = 0;
+ bfd->rtt_index = 0;
+ for (i = 0; i < BFD_RTT_SAMPLE; i++)
+ bfd->rtt[i] = 0;
+}
diff --git a/bfdd/bfd.h b/bfdd/bfd.h
index 48a1e0bc31..a5881cddb0 100644
--- a/bfdd/bfd.h
+++ b/bfdd/bfd.h
@@ -86,7 +86,8 @@ struct bfd_echo_pkt {
};
};
uint32_t my_discr;
- uint8_t pad[16];
+ uint64_t time_sent_sec;
+ uint64_t time_sent_usec;
};
@@ -249,6 +250,8 @@ struct bfd_config_timers {
uint32_t required_min_echo_rx;
};
+#define BFD_RTT_SAMPLE 8
+
/*
* Session state information
*/
@@ -311,6 +314,10 @@ struct bfd_session {
struct bfd_timers remote_timers;
uint64_t refcount; /* number of pointers referencing this. */
+
+ uint8_t rtt_valid; /* number of valid samples */
+ uint8_t rtt_index; /* last index added */
+ uint64_t rtt[BFD_RTT_SAMPLE]; /* RRT in usec for echo to be looped */
};
struct peer_label {
@@ -635,6 +642,7 @@ const struct bfd_session *bfd_session_next(const struct bfd_session *bs,
bool mhop);
void bfd_sessions_remove_manual(void);
void bfd_profiles_remove(void);
+void bfd_rtt_init(struct bfd_session *bfd);
/**
* Set the BFD session echo state.
diff --git a/bfdd/bfd_packet.c b/bfdd/bfd_packet.c
index 82b3f09b0c..382f78a0f6 100644
--- a/bfdd/bfd_packet.c
+++ b/bfdd/bfd_packet.c
@@ -55,8 +55,8 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
struct sockaddr_any *peer);
int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
struct sockaddr *to, socklen_t tolen);
-int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
- uint8_t *ttl, uint32_t *my_discr);
+int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd, uint8_t *ttl,
+ uint32_t *my_discr, uint64_t *my_rtt);
#ifdef BFD_LINUX
ssize_t bfd_recv_ipv4_fp(int sd, uint8_t *msgbuf, size_t msgbuflen,
uint8_t *ttl, ifindex_t *ifindex,
@@ -207,6 +207,7 @@ void ptm_bfd_echo_fp_snd(struct bfd_session *bfd)
struct iphdr *iph;
struct bfd_echo_pkt *beph;
static char sendbuff[100];
+ struct timeval time_sent;
if (!bvrf)
return;
@@ -259,6 +260,11 @@ void ptm_bfd_echo_fp_snd(struct bfd_session *bfd)
beph->len = BFD_ECHO_PKT_LEN;
beph->my_discr = htonl(bfd->discrs.my_discr);
+ /* RTT calculation: add starting time in packet */
+ monotime(&time_sent);
+ beph->time_sent_sec = htobe64(time_sent.tv_sec);
+ beph->time_sent_usec = htobe64(time_sent.tv_usec);
+
total_len += sizeof(struct bfd_echo_pkt);
uh->len =
htons(total_len - sizeof(struct iphdr) - sizeof(struct ethhdr));
@@ -338,10 +344,11 @@ static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
{
struct bfd_session *bfd;
uint32_t my_discr = 0;
+ uint64_t my_rtt = 0;
uint8_t ttl = 0;
/* Receive and parse echo packet. */
- if (bp_bfd_echo_in(bvrf, s, &ttl, &my_discr) == -1)
+ if (bp_bfd_echo_in(bvrf, s, &ttl, &my_discr, &my_rtt) == -1)
return 0;
/* Your discriminator not zero - use it to find session */
@@ -360,6 +367,16 @@ static int ptm_bfd_process_echo_pkt(struct bfd_vrf_global *bvrf, int s)
return -1;
}
+ /* RTT Calculation: add current RTT to samples */
+ if (my_rtt != 0) {
+ bfd->rtt[bfd->rtt_index] = my_rtt;
+ bfd->rtt_index++;
+ if (bfd->rtt_index >= BFD_RTT_SAMPLE)
+ bfd->rtt_index = 0;
+ if (bfd->rtt_valid < BFD_RTT_SAMPLE)
+ bfd->rtt_valid++;
+ }
+
bfd->stats.rx_echo_pkt++;
/* Compute detect time */
@@ -561,8 +578,8 @@ ssize_t bfd_recv_ipv4(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
memcpy(&ttlval, CMSG_DATA(cm), sizeof(ttlval));
if (ttlval > 255) {
if (bglobal.debug_network)
- zlog_debug("ipv4-recv: invalid TTL: %u",
- ttlval);
+ zlog_debug("%s: invalid TTL: %u",
+ __func__, ttlval);
return -1;
}
*ttl = ttlval;
@@ -669,8 +686,8 @@ ssize_t bfd_recv_ipv6(int sd, uint8_t *msgbuf, size_t msgbuflen, uint8_t *ttl,
memcpy(&ttlval, CMSG_DATA(cm), sizeof(ttlval));
if (ttlval > 255) {
if (bglobal.debug_network)
- zlog_debug("ipv6-recv: invalid TTL: %u",
- ttlval);
+ zlog_debug("%s: invalid TTL: %u",
+ __func__, ttlval);
return -1;
}
@@ -1003,8 +1020,8 @@ void bfd_recv_cb(struct thread *t)
*
* Returns -1 on error or loopback or 0 on success.
*/
-int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
- uint8_t *ttl, uint32_t *my_discr)
+int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd, uint8_t *ttl,
+ uint32_t *my_discr, uint64_t *my_rtt)
{
struct bfd_echo_pkt *bep;
ssize_t rlen;
@@ -1062,6 +1079,17 @@ int bp_bfd_echo_in(struct bfd_vrf_global *bvrf, int sd,
return -1;
}
+#ifdef BFD_LINUX
+ /* RTT Calculation: determine RTT time of IPv4 echo pkt */
+ if (sd == bvrf->bg_echo) {
+ struct timeval time_sent = {0, 0};
+
+ time_sent.tv_sec = be64toh(bep->time_sent_sec);
+ time_sent.tv_usec = be64toh(bep->time_sent_usec);
+ *my_rtt = monotime_since(&time_sent, NULL);
+ }
+#endif
+
return 0;
}
@@ -1074,11 +1102,10 @@ int bp_udp_send_fp(int sd, uint8_t *data, size_t datalen,
struct bfd_session *bfd)
{
ssize_t wlen;
- struct msghdr msg;
+ struct msghdr msg = {0};
struct iovec iov[1];
uint8_t msgctl[255];
- struct sockaddr_ll sadr_ll;
-
+ struct sockaddr_ll sadr_ll = {0};
sadr_ll.sll_ifindex = bfd->ifp->ifindex;
sadr_ll.sll_halen = ETH_ALEN;
@@ -1089,7 +1116,6 @@ int bp_udp_send_fp(int sd, uint8_t *data, size_t datalen,
iov[0].iov_base = data;
iov[0].iov_len = datalen;
- memset(&msg, 0, sizeof(msg));
memset(msgctl, 0, sizeof(msgctl));
msg.msg_name = &sadr_ll;
msg.msg_namelen = sizeof(sadr_ll);
@@ -1101,13 +1127,13 @@ int bp_udp_send_fp(int sd, uint8_t *data, size_t datalen,
if (wlen <= 0) {
if (bglobal.debug_network)
- zlog_debug("udp-send: loopback failure: (%d) %s", errno,
- strerror(errno));
+ zlog_debug("%s: loopback failure: (%d) %s", __func__,
+ errno, strerror(errno));
return -1;
} else if (wlen < (ssize_t)datalen) {
if (bglobal.debug_network)
- zlog_debug("udp-send: partial send: %zd expected %zu",
- wlen, datalen);
+ zlog_debug("%s: partial send: %zd expected %zu",
+ __func__, wlen, datalen);
return -1;
}
@@ -1168,13 +1194,13 @@ int bp_udp_send(int sd, uint8_t ttl, uint8_t *data, size_t datalen,
wlen = sendmsg(sd, &msg, 0);
if (wlen <= 0) {
if (bglobal.debug_network)
- zlog_debug("udp-send: loopback failure: (%d) %s", errno,
- strerror(errno));
+ zlog_debug("%s: loopback failure: (%d) %s", __func__,
+ errno, strerror(errno));
return -1;
} else if (wlen < (ssize_t)datalen) {
if (bglobal.debug_network)
- zlog_debug("udp-send: partial send: %zd expected %zu",
- wlen, datalen);
+ zlog_debug("%s: partial send: %zd expected %zu",
+ __func__, wlen, datalen);
return -1;
}
@@ -1195,7 +1221,7 @@ int bp_set_ttl(int sd, uint8_t value)
int ttl = value;
if (setsockopt(sd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl)) == -1) {
- zlog_warn("set-ttl: setsockopt(IP_TTL, %d): %s", value,
+ zlog_warn("%s: setsockopt(IP_TTL, %d): %s", __func__, value,
strerror(errno));
return -1;
}
@@ -1208,7 +1234,7 @@ int bp_set_tos(int sd, uint8_t value)
int tos = value;
if (setsockopt(sd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1) {
- zlog_warn("set-tos: setsockopt(IP_TOS, %d): %s", value,
+ zlog_warn("%s: setsockopt(IP_TOS, %d): %s", __func__, value,
strerror(errno));
return -1;
}
@@ -1221,8 +1247,8 @@ static bool bp_set_reuse_addr(int sd)
int one = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one)) == -1) {
- zlog_warn("set-reuse-addr: setsockopt(SO_REUSEADDR, %d): %s",
- one, strerror(errno));
+ zlog_warn("%s: setsockopt(SO_REUSEADDR, %d): %s", __func__, one,
+ strerror(errno));
return false;
}
return true;
@@ -1233,8 +1259,8 @@ static bool bp_set_reuse_port(int sd)
int one = 1;
if (setsockopt(sd, SOL_SOCKET, SO_REUSEPORT, &one, sizeof(one)) == -1) {
- zlog_warn("set-reuse-port: setsockopt(SO_REUSEPORT, %d): %s",
- one, strerror(errno));
+ zlog_warn("%s: setsockopt(SO_REUSEPORT, %d): %s", __func__, one,
+ strerror(errno));
return false;
}
return true;
@@ -1605,7 +1631,7 @@ int bp_echo_socket(const struct vrf *vrf)
zlog_fatal("echo-socket: socket: %s", strerror(errno));
struct sock_fprog pf;
- struct sockaddr_ll sll;
+ struct sockaddr_ll sll = {0};
/* adjust filter for socket to only receive ECHO packets */
pf.filter = my_filterudp;
@@ -1683,6 +1709,8 @@ void bfd_peer_mac_set(int sd, struct bfd_session *bfd,
if (CHECK_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET))
return;
+ if (ifp->flags & IFF_NOARP)
+ return;
if (peer->sa_sin.sin_family == AF_INET) {
/* IPV4 */
@@ -1696,8 +1724,9 @@ void bfd_peer_mac_set(int sd, struct bfd_session *bfd,
strlcpy(arpreq_.arp_dev, ifp->name, sizeof(arpreq_.arp_dev));
if (ioctl(sd, SIOCGARP, &arpreq_) < 0) {
- zlog_warn("BFD: getting peer's mac failed error %s",
- strerror(errno));
+ zlog_warn(
+ "BFD: getting peer's mac on %s failed error %s",
+ ifp->name, strerror(errno));
UNSET_FLAG(bfd->flags, BFD_SESS_FLAG_MAC_SET);
memset(bfd->peer_hw_addr, 0, sizeof(bfd->peer_hw_addr));
diff --git a/bfdd/bfdd_vty.c b/bfdd/bfdd_vty.c
index a9fc716177..21429f06cf 100644
--- a/bfdd/bfdd_vty.c
+++ b/bfdd/bfdd_vty.c
@@ -66,6 +66,9 @@ static void _display_peer_counters_json(struct vty *vty, struct bfd_session *bs)
static void _display_peer_counter_iter(struct hash_bucket *hb, void *arg);
static void _display_peer_counter_json_iter(struct hash_bucket *hb, void *arg);
static void _display_peers_counter(struct vty *vty, char *vrfname, bool use_json);
+static void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
+ struct bfd_session *bs);
+
static struct bfd_session *
_find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
const char *label, const char *peer_str,
@@ -106,6 +109,9 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
{
char buf[256];
time_t now;
+ uint32_t min = 0;
+ uint32_t avg = 0;
+ uint32_t max = 0;
_display_peer_header(vty, bs);
@@ -150,6 +156,8 @@ static void _display_peer(struct vty *vty, struct bfd_session *bs)
vty_out(vty, "\t\tRemote diagnostics: %s\n", diag2str(bs->remote_diag));
vty_out(vty, "\t\tPeer Type: %s\n",
CHECK_FLAG(bs->flags, BFD_SESS_FLAG_CONFIG) ? "configured" : "dynamic");
+ _display_rtt(&min, &avg, &max, bs);
+ vty_out(vty, "\t\tRTT min/avg/max: %u/%u/%u usec\n", min, avg, max);
vty_out(vty, "\t\tLocal timers:\n");
vty_out(vty, "\t\t\tDetect-multiplier: %u\n",
@@ -217,6 +225,9 @@ static struct json_object *_peer_json_header(struct bfd_session *bs)
static struct json_object *__display_peer_json(struct bfd_session *bs)
{
struct json_object *jo = _peer_json_header(bs);
+ uint32_t min = 0;
+ uint32_t avg = 0;
+ uint32_t max = 0;
json_object_int_add(jo, "id", bs->discrs.my_discr);
json_object_int_add(jo, "remote-id", bs->discrs.remote_discr);
@@ -275,6 +286,11 @@ static struct json_object *__display_peer_json(struct bfd_session *bs)
json_object_int_add(jo, "remote-detect-multiplier",
bs->remote_detect_mult);
+ _display_rtt(&min, &avg, &max, bs);
+ json_object_int_add(jo, "rtt-min", min);
+ json_object_int_add(jo, "rtt-avg", avg);
+ json_object_int_add(jo, "rtt-max", max);
+
return jo;
}
@@ -608,6 +624,31 @@ _find_peer_or_error(struct vty *vty, int argc, struct cmd_token **argv,
return bs;
}
+void _display_rtt(uint32_t *min, uint32_t *avg, uint32_t *max,
+ struct bfd_session *bs)
+{
+#ifdef BFD_LINUX
+ uint8_t i;
+ uint32_t average = 0;
+
+ if (bs->rtt_valid == 0)
+ return;
+
+ *max = bs->rtt[0];
+ *min = 1000;
+ *avg = 0;
+
+ for (i = 0; i < bs->rtt_valid; i++) {
+ if (bs->rtt[i] < *min)
+ *min = bs->rtt[i];
+ if (bs->rtt[i] > *max)
+ *max = bs->rtt[i];
+ average += bs->rtt[i];
+ }
+ *avg = average / bs->rtt_valid;
+
+#endif
+}
/*
* Show commands.
diff --git a/bgpd/IMPLEMENTATION.txt b/bgpd/IMPLEMENTATION.txt
deleted file mode 100644
index 5822dbba82..0000000000
--- a/bgpd/IMPLEMENTATION.txt
+++ /dev/null
@@ -1,168 +0,0 @@
-$Id: IMPLEMENTATION.txt,v 1.2 2005/02/15 17:10:03 gdt Exp $
-
-This file contains notes about the internals of the BGP
-implementation. The initial impetus is understanding the memory usage
-of Quagga'a BGP implementation. There may be some inaccuracies; it is
-in the repository in the hopes that it will be significantly more
-helpful than not.
-
-* FILES
-
-bgp_advertise.[hc]:
- data structures: advertised prefixes, attributes
-
-bgp_aspath.[hc]:
- struct aspath:
- These are stored in a hash, apparently in wire format.
-
-bgp_attr.[hc]:
- struct attr: contains all attributes
- size(ILP32) 26 words/104 bytes (poor packing, v6/multicast is 10)
-
- bgp_attr_parse: origin, aspath, next hop probably most of interest
- bgp_attr_origin: set flag bit
- bgp_attr_aspath: put in refcounted hash table, so share pointer
- bgp_attr_nexthop: store in attribute structure
-
-bgp_btoa.c: ? test program
-
-bgp_clist.[hc]:
- data structures: community lists (including permit/deny state)
-
-bgp_community.[hc]:
- data structures: community atttributes (multiple communities per struct)
-
-bgp_damp.[hc]:
- per-route damping data, and damping control information
-
-bgp_debug.[hc]:
- debugging support (vty config, dump of packets)
-
-bgp_dump.[hc]:
- MRT-compatible dump format routines
-
-bgp_ecommunity.[hc]:
- Extended communities attributes (multiple ecommmunities per struct)
-
-bgp_filter.[hc]:
- AS path access list filtering
-
-bgp_fsm.[hc]:
- Per-peer state machine for TCP connection, hold time, etc.
-
-bgp_main.c:
- Daemon startup.
-
-bgp_mplsvpn.[hc]:
- parsing of attribute structures for MPLS VPNs [need better description]
-
-bgp_network.[hc]:
- Opening and binding of sockets, finding addresses for interfaces
-
-bgp_nexthop.[hc]:
- data structures: Nexthop cache [not clear how used, if truly cache
- in sense of memoization, or something else]
-
- importing EGP routes into IGP (thread created)
- "scanning" (thread created)
- bgp_scan: has useful clues to data structure complexity. Scanning
- process iterates over database of received advertisements, and
- builds 'cache' structure.
-
-bgp_open.[ch]:
- Open messages, and capability negotiation
-
-bgp_packet.[hc]
- sending and receiving of UPDATE/WITHDRAW
- collision resolution for simultanteous opens
- bgp_read: top-level read routine: reads whole packet (nonblocking)
- and dispatches to per-message-type receive
-
- bgp_update_receive:
- calls bgp_attr_parse
- reads nrli into struct bgp_nrli update
-
- uninterning of aspath, community, ecommmunity, cluster,
- transit which were interned in bgp_attr_parse
-
-bgp_regex.[ch]:
- Glue to convert BGP regexps to standard (_ means many things).
-
-bgp_route.[hc]:
- data structures: routes as received, static routes
- Application of filters. Lots of route processing.
-
- bgp_nlri_parse:
- sanity checks, then calls bgp_update with peer, prefix, attributes pointer
-
- bgp_update: bgp_update_main, then RS processing
-
- bgp_update_main:
- find 'struct bgp_node *' for this afi/safi
- look for route in table, then 'intern' attributes
- ** interning is process of
- looking for data in hash table, and putting there if missing, refcnt
- using pointer to existing data
- many validity checks
- get new struct bgp_path_info
- call bgp_path_info_add with rn and bgp_path_info
- call bgp_process
-
-bgp_routemap.c
- implementation of route maps (match and set)
-
-bgp_snmp.c
- SNMP glue. Not particularly interesting except to add variables or
- debug SNMP.
-
-bgp_table.[hc]
- data structures: struct bgp_table, struct bgp_node
- allocation/lookup/utility operations - not a lot of protocol processin
-
-bgp_vty.[hc]
- protocol-wide vty hooks
-
-bgp_zebra.[hc]
- Processing interface events from zebra, redistribution of routes.
-
-bgpd.h
- struct bgp_master: daemon main data structure
- struct bgp: per-instance structure
- struct peer_group
- struct bgp_notify: (in-core representation of wire format?)
- struct bgp_nexthop: (v4 and v6 addresses, *ifp)
- struct bgp_filter: distribute, prefix, aslist, route_maps
- struct peer: neighbor structure (very rich/complex)
- struct bgp_nlri: reference to wire format
- #define of protocol constants
- attribute type codes
- fsm states/events
- timer values
-
-bgpd.c
- instance/peer allocation
- configuration
- initialization/termination
-
-* DATA STRUCTURE SIZES
-
-Question: How much memory does quagga's bgpd use as a function of
-state received from peers?
-
-It seems that a struct bgp_path_info is kept for each prefix. The "struct
-attr *" is interned, and variables within that are interned. So, 40
-bytes are kept per received prefix, plus interned shared values. This
-could be 36 if 'int suppress' where changed to a u_char and moved to
-be with the other u_chars. Without MPLS, this could be 32 bytes.
-Note that 8 bytes of this is linked list overhead, meaning that 24
-bytes are the raw per-prefix storage requirements.
-
-Also, a struct bgp_damp_info is apparently maintained per route; this
-is fairly large (about 44 bytes).
-
-[TODO: the role of struct bgp_node.]
-
-* TIME COMPLEXITY
-
-It appears that received prefixes from each peer are stored in a
-linked list.
diff --git a/bgpd/bgp_advertise.c b/bgpd/bgp_advertise.c
index cfbb29df1c..f62a54b03c 100644
--- a/bgpd/bgp_advertise.c
+++ b/bgpd/bgp_advertise.c
@@ -197,7 +197,7 @@ void bgp_adj_in_set(struct bgp_dest *dest, struct peer *peer, struct attr *attr,
adj = XCALLOC(MTYPE_BGP_ADJ_IN, sizeof(struct bgp_adj_in));
adj->peer = peer_lock(peer); /* adj_in peer reference */
adj->attr = bgp_attr_intern(attr);
- adj->uptime = bgp_clock();
+ adj->uptime = monotime(NULL);
adj->addpath_rx_id = addpath_id;
BGP_ADJ_IN_ADD(dest, adj);
bgp_dest_lock_node(dest);
diff --git a/bgpd/bgp_aspath.c b/bgpd/bgp_aspath.c
index 39886337f3..06f6073781 100644
--- a/bgpd/bgp_aspath.c
+++ b/bgpd/bgp_aspath.c
@@ -1209,28 +1209,6 @@ bool aspath_private_as_check(struct aspath *aspath)
return true;
}
-/* Return True if the entire ASPATH consist of the specified ASN */
-bool aspath_single_asn_check(struct aspath *aspath, as_t asn)
-{
- struct assegment *seg;
-
- if (!(aspath && aspath->segments))
- return false;
-
- seg = aspath->segments;
-
- while (seg) {
- int i;
-
- for (i = 0; i < seg->length; i++) {
- if (seg->as[i] != asn)
- return false;
- }
- seg = seg->next;
- }
- return true;
-}
-
/* Replace all instances of the target ASN with our own ASN */
struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn, as_t our_asn)
diff --git a/bgpd/bgp_aspath.h b/bgpd/bgp_aspath.h
index 5caab73c4d..0b58e1adc4 100644
--- a/bgpd/bgp_aspath.h
+++ b/bgpd/bgp_aspath.h
@@ -112,7 +112,6 @@ extern unsigned int aspath_get_first_as(struct aspath *aspath);
extern unsigned int aspath_get_last_as(struct aspath *aspath);
extern int aspath_loop_check(struct aspath *aspath, as_t asno);
extern bool aspath_private_as_check(struct aspath *aspath);
-extern bool aspath_single_asn_check(struct aspath *aspath, as_t asn);
extern struct aspath *aspath_replace_specific_asn(struct aspath *aspath,
as_t target_asn,
as_t our_asn);
diff --git a/bgpd/bgp_attr.c b/bgpd/bgp_attr.c
index 0135acec8f..b7d0958bac 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -983,7 +983,7 @@ struct attr *bgp_attr_aggregate_intern(
{
struct attr attr;
struct attr *new;
- int ret;
+ route_map_result_t ret;
memset(&attr, 0, sizeof(attr));
@@ -1515,6 +1515,19 @@ static int bgp_attr_aspath(struct bgp_attr_parser_args *args)
0);
}
+ /* Conformant BGP speakers SHOULD NOT send BGP
+ * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
+ * such messages, conformant BGP speakers SHOULD use the "Treat-as-
+ * withdraw" error handling behavior as per [RFC7606].
+ */
+ if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
+ flog_err(EC_BGP_ATTR_MAL_AS_PATH,
+ "AS_SET and AS_CONFED_SET are deprecated from %pBP",
+ peer);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ 0);
+ }
+
/* Set aspath attribute flag. */
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS_PATH);
@@ -1595,6 +1608,19 @@ static int bgp_attr_as4_path(struct bgp_attr_parser_args *args,
0);
}
+ /* Conformant BGP speakers SHOULD NOT send BGP
+ * UPDATE messages containing AS_SET or AS_CONFED_SET. Upon receipt of
+ * such messages, conformant BGP speakers SHOULD use the "Treat-as-
+ * withdraw" error handling behavior as per [RFC7606].
+ */
+ if (peer->bgp->reject_as_sets && aspath_check_as_sets(attr->aspath)) {
+ flog_err(EC_BGP_ATTR_MAL_AS_PATH,
+ "AS_SET and AS_CONFED_SET are deprecated from %pBP",
+ peer);
+ return bgp_attr_malformed(args, BGP_NOTIFY_UPDATE_MAL_AS_PATH,
+ 0);
+ }
+
/* Set aspath attribute flag. */
attr->flag |= ATTR_FLAG_BIT(BGP_ATTR_AS4_PATH);
diff --git a/bgpd/bgp_attr.h b/bgpd/bgp_attr.h
index 5007fafc29..4963ea64d0 100644
--- a/bgpd/bgp_attr.h
+++ b/bgpd/bgp_attr.h
@@ -348,6 +348,7 @@ struct attr {
#define BATTR_RMAP_IPV6_LL_NHOP_CHANGED (1 << 5)
#define BATTR_RMAP_IPV6_PREFER_GLOBAL_CHANGED (1 << 6)
#define BATTR_RMAP_LINK_BW_SET (1 << 7)
+#define BATTR_RMAP_L3VPN_ACCEPT_GRE (1 << 8)
/* Router Reflector related structure. */
struct cluster_list {
diff --git a/bgpd/bgp_bmp.c b/bgpd/bgp_bmp.c
index cf196f7390..bcab4099c0 100644
--- a/bgpd/bgp_bmp.c
+++ b/bgpd/bgp_bmp.c
@@ -992,7 +992,7 @@ afibreak:
}
struct bgp_table *table = bmp->targets->bgp->rib[afi][safi];
- struct bgp_dest *bn;
+ struct bgp_dest *bn = NULL;
struct bgp_path_info *bpi = NULL, *bpiter;
struct bgp_adj_in *adjin = NULL, *adjiter;
@@ -1120,6 +1120,9 @@ afibreak:
bmp_monitor(bmp, adjin->peer, 0, bn_p, prd, adjin->attr, afi,
safi, adjin->uptime);
+ if (bn)
+ bgp_dest_unlock_node(bn);
+
return true;
}
@@ -1145,7 +1148,7 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
{
struct bmp_queue_entry *bqe;
struct peer *peer;
- struct bgp_dest *bn;
+ struct bgp_dest *bn = NULL;
bool written = false;
bqe = bmp_pull(bmp);
@@ -1180,11 +1183,13 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
if (!peer_established(peer))
goto out;
- bn = bgp_node_lookup(bmp->targets->bgp->rib[afi][safi], &bqe->p);
- struct prefix_rd *prd = NULL;
- if ((bqe->afi == AFI_L2VPN && bqe->safi == SAFI_EVPN) ||
- (bqe->safi == SAFI_MPLS_VPN))
- prd = &bqe->rd;
+ bool is_vpn = (bqe->afi == AFI_L2VPN && bqe->safi == SAFI_EVPN) ||
+ (bqe->safi == SAFI_MPLS_VPN);
+
+ struct prefix_rd *prd = is_vpn ? &bqe->rd : NULL;
+ bn = bgp_afi_node_lookup(bmp->targets->bgp->rib[afi][safi], afi, safi,
+ &bqe->p, prd);
+
if (bmp->targets->afimon[afi][safi] & BMP_MON_POSTPOLICY) {
struct bgp_path_info *bpi;
@@ -1220,6 +1225,10 @@ static bool bmp_wrqueue(struct bmp *bmp, struct pullwr *pullwr)
out:
if (!bqe->refcount)
XFREE(MTYPE_BMP_QUEUE, bqe);
+
+ if (bn)
+ bgp_dest_unlock_node(bn);
+
return written;
}
diff --git a/bgpd/bgp_btoa.c b/bgpd/bgp_btoa.c
index 13c42d95f4..aa14d99f18 100644
--- a/bgpd/bgp_btoa.c
+++ b/bgpd/bgp_btoa.c
@@ -77,7 +77,7 @@ static void attr_parse(struct stream *s, uint16_t len)
lim = s->getp + len;
- printf("attr_parse s->getp %zd, len %d, lim %d\n", s->getp, len, lim);
+ printf("%s s->getp %zd, len %d, lim %d\n", __func__, s->getp, len, lim);
while (s->getp < lim) {
flag = stream_getc(s);
diff --git a/bgpd/bgp_conditional_adv.c b/bgpd/bgp_conditional_adv.c
index 9c2826fa13..2598361ad2 100644
--- a/bgpd/bgp_conditional_adv.c
+++ b/bgpd/bgp_conditional_adv.c
@@ -53,18 +53,16 @@ bgp_check_rmap_prefixes_in_bgp_table(struct bgp_table *table,
if (ret == RMAP_PERMITMATCH) {
bgp_dest_unlock_node(dest);
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug(
- "%s: Condition map routes present in BGP table",
- __func__);
+ bgp_cond_adv_debug(
+ "%s: Condition map routes present in BGP table",
+ __func__);
return ret;
}
}
}
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Condition map routes not present in BGP table",
+ bgp_cond_adv_debug("%s: Condition map routes not present in BGP table",
__func__);
return ret;
@@ -98,8 +96,7 @@ static void bgp_conditional_adv_routes(struct peer *peer, afi_t afi,
subgrp->pscount = 0;
SET_FLAG(subgrp->sflags, SUBGRP_STATUS_TABLE_REPARSING);
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: %s routes to/from %s for %s", __func__,
+ bgp_cond_adv_debug("%s: %s routes to/from %s for %s", __func__,
update_type == UPDATE_TYPE_ADVERTISE ? "Advertise"
: "Withdraw",
peer->host, get_afi_safi_str(afi, safi, false));
@@ -224,7 +221,7 @@ static void bgp_conditional_adv_timer(struct thread *t)
&& !peer->advmap_table_change)
continue;
- if (BGP_DEBUG(update, UPDATE_OUT)) {
+ if (BGP_DEBUG(cond_adv, COND_ADV)) {
if (peer->advmap_table_change)
zlog_debug(
"%s: %s - routes changed in BGP table.",
@@ -258,23 +255,38 @@ static void bgp_conditional_adv_timer(struct thread *t)
? UPDATE_TYPE_WITHDRAW
: UPDATE_TYPE_ADVERTISE;
+ /*
+ * Update condadv update type so
+ * subgroup_announce_check() can properly apply
+ * outbound policy according to advertisement state
+ */
+ paf = peer_af_find(peer, afi, safi);
+ if (paf && (SUBGRP_PEER(PAF_SUBGRP(paf))
+ ->filter[afi][safi]
+ .advmap.update_type !=
+ filter->advmap.update_type)) {
+ /* Handle change to peer advmap */
+ bgp_cond_adv_debug(
+ "%s: advmap.update_type changed for peer %s, adjusting update_group.",
+ __func__, peer->host);
+
+ update_group_adjust_peer(paf);
+ }
+
/* Send regular update as per the existing policy.
* There is a change in route-map, match-rule, ACLs,
* or route-map filter configuration on the same peer.
*/
if (peer->advmap_config_change[afi][safi]) {
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug(
- "%s: Configuration is changed on peer %s for %s, send the normal update first.",
- __func__, peer->host,
- get_afi_safi_str(afi, safi,
- false));
-
- paf = peer_af_find(peer, afi, safi);
+ bgp_cond_adv_debug(
+ "%s: Configuration is changed on peer %s for %s, send the normal update first.",
+ __func__, peer->host,
+ get_afi_safi_str(afi, safi, false));
if (paf) {
update_subgroup_split_peer(paf, NULL);
subgrp = paf->subgroup;
+
if (subgrp && subgrp->update_group)
subgroup_announce_table(
paf->subgroup, NULL);
@@ -307,8 +319,7 @@ void bgp_conditional_adv_enable(struct peer *peer, afi_t afi, safi_t safi)
* neighbors (AFI/SAFI). So just increment the counter.
*/
if (++bgp->condition_filter_count > 1) {
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: condition_filter_count %d", __func__,
+ bgp_cond_adv_debug("%s: condition_filter_count %d", __func__,
bgp->condition_filter_count);
return;
@@ -331,8 +342,7 @@ void bgp_conditional_adv_disable(struct peer *peer, afi_t afi, safi_t safi)
* So there's nothing to do except decrementing the counter.
*/
if (--bgp->condition_filter_count != 0) {
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: condition_filter_count %d", __func__,
+ bgp_cond_adv_debug("%s: condition_filter_count %d", __func__,
bgp->condition_filter_count);
return;
@@ -341,3 +351,164 @@ void bgp_conditional_adv_disable(struct peer *peer, afi_t afi, safi_t safi)
/* Last filter removed. So cancel conditional routes polling thread. */
THREAD_OFF(bgp->t_condition_check);
}
+
+static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
+ safi_t safi, const char *amap_name,
+ struct route_map *amap,
+ const char *cmap_name,
+ struct route_map *cmap,
+ bool condition, bool set)
+{
+ struct bgp_filter *filter;
+ bool filter_exists = false;
+
+ filter = &peer->filter[afi][safi];
+
+ /* advertise-map is already configured. */
+ if (filter->advmap.aname) {
+ filter_exists = true;
+ XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
+ XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
+ }
+
+ route_map_counter_decrement(filter->advmap.amap);
+
+ /* Removed advertise-map configuration */
+ if (!set) {
+ memset(&filter->advmap, 0, sizeof(filter->advmap));
+
+ /* decrement condition_filter_count delete timer if
+ * this is the last advertise-map to be removed.
+ */
+ if (filter_exists)
+ bgp_conditional_adv_disable(peer, afi, safi);
+
+ /* Process peer route updates. */
+ peer_on_policy_change(peer, afi, safi, 1);
+
+ return;
+ }
+
+ /* Update filter data with newly configured values. */
+ filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
+ filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
+ filter->advmap.amap = amap;
+ filter->advmap.cmap = cmap;
+ filter->advmap.condition = condition;
+ route_map_counter_increment(filter->advmap.amap);
+ peer->advmap_config_change[afi][safi] = true;
+
+ /* Increment condition_filter_count and/or create timer. */
+ if (!filter_exists) {
+ filter->advmap.update_type = UPDATE_TYPE_ADVERTISE;
+ bgp_conditional_adv_enable(peer, afi, safi);
+ }
+
+ /* Process peer route updates. */
+ peer_on_policy_change(peer, afi, safi, 1);
+}
+
+/* Set advertise-map to the peer. */
+int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map, bool condition)
+{
+ struct peer *member;
+ struct listnode *node, *nnode;
+
+ /* Set configuration on peer. */
+ peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
+ advertise_map, condition_name,
+ condition_map, condition, true);
+
+ /* Check if handling a regular peer & Skip peer-group mechanics. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Set override-flag and process peer route updates. */
+ SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP);
+ return 0;
+ }
+
+ /*
+ * Set configuration on all peer-group members, unless they are
+ * explicitly overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP))
+ continue;
+
+ /* Set configuration on peer-group member. */
+ peer_advertise_map_filter_update(
+ member, afi, safi, advertise_name, advertise_map,
+ condition_name, condition_map, condition, true);
+ }
+
+ return 0;
+}
+
+/* Unset advertise-map from the peer. */
+int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map, bool condition)
+{
+ struct peer *member;
+ struct listnode *node, *nnode;
+
+ /* advertise-map is not configured */
+ if (!peer->filter[afi][safi].advmap.aname)
+ return 0;
+
+ /* Unset override-flag unconditionally. */
+ UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP);
+
+ /* Inherit configuration from peer-group if peer is member. */
+ if (peer_group_active(peer)) {
+ PEER_STR_ATTR_INHERIT(peer, peer->group,
+ filter[afi][safi].advmap.aname,
+ MTYPE_BGP_FILTER_NAME);
+ PEER_ATTR_INHERIT(peer, peer->group,
+ filter[afi][safi].advmap.amap);
+ } else
+ peer_advertise_map_filter_update(
+ peer, afi, safi, advertise_name, advertise_map,
+ condition_name, condition_map, condition, false);
+
+ /* Check if handling a regular peer and skip peer-group mechanics. */
+ if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
+ /* Process peer route updates. */
+ bgp_cond_adv_debug("%s: Send normal update to %s for %s",
+ __func__, peer->host,
+ get_afi_safi_str(afi, safi, false));
+
+ return 0;
+ }
+
+ /*
+ * Remove configuration on all peer-group members, unless they are
+ * explicitly overriding peer-group configuration.
+ */
+ for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
+ /* Skip peers with overridden configuration. */
+ if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
+ PEER_FT_ADVERTISE_MAP))
+ continue;
+ /* Remove configuration on peer-group member. */
+ peer_advertise_map_filter_update(
+ member, afi, safi, advertise_name, advertise_map,
+ condition_name, condition_map, condition, false);
+
+ /* Process peer route updates. */
+ bgp_cond_adv_debug("%s: Send normal update to %s for %s ",
+ __func__, member->host,
+ get_afi_safi_str(afi, safi, false));
+ }
+
+ return 0;
+}
diff --git a/bgpd/bgp_conditional_adv.h b/bgpd/bgp_conditional_adv.h
index 371ae856c2..a4f1403a44 100644
--- a/bgpd/bgp_conditional_adv.h
+++ b/bgpd/bgp_conditional_adv.h
@@ -33,6 +33,13 @@
extern "C" {
#endif
+/* Macro to log debug message */
+#define bgp_cond_adv_debug(...) \
+ do { \
+ if (BGP_DEBUG(cond_adv, COND_ADV)) \
+ zlog_debug("" __VA_ARGS__); \
+ } while (0)
+
/* Polling time for monitoring condition-map routes in route table */
#define DEFAULT_CONDITIONAL_ROUTES_POLL_TIME 60
@@ -40,6 +47,18 @@ extern void bgp_conditional_adv_enable(struct peer *peer, afi_t afi,
safi_t safi);
extern void bgp_conditional_adv_disable(struct peer *peer, afi_t afi,
safi_t safi);
+extern int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map,
+ bool condition);
+extern int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
+ const char *advertise_name,
+ struct route_map *advertise_map,
+ const char *condition_name,
+ struct route_map *condition_map,
+ bool condition);
#ifdef __cplusplus
}
#endif
diff --git a/bgpd/bgp_damp.c b/bgpd/bgp_damp.c
index 9acbaf7733..664619078a 100644
--- a/bgpd/bgp_damp.c
+++ b/bgpd/bgp_damp.c
@@ -125,7 +125,7 @@ static void bgp_reuse_timer(struct thread *t)
thread_add_timer(bm->master, bgp_reuse_timer, bdc, DELTA_REUSE,
&bdc->t_reuse);
- t_now = bgp_clock();
+ t_now = monotime(NULL);
/* 1. save a pointer to the current zeroth queue head and zero the
list head entry. */
@@ -189,7 +189,7 @@ int bgp_damp_withdraw(struct bgp_path_info *path, struct bgp_dest *dest,
unsigned int last_penalty = 0;
struct bgp_damp_config *bdc = &damp[afi][safi];
- t_now = bgp_clock();
+ t_now = monotime(NULL);
/* Processing Unreachable Messages. */
if (path->extra)
@@ -273,7 +273,7 @@ int bgp_damp_update(struct bgp_path_info *path, struct bgp_dest *dest,
if (!path->extra || !((bdi = path->extra->damp_info)))
return BGP_DAMP_USED;
- t_now = bgp_clock();
+ t_now = monotime(NULL);
bgp_path_info_unset_flag(dest, path, BGP_PATH_HISTORY);
bdi->lastrecord = BGP_RECORD_UPDATE;
@@ -588,7 +588,7 @@ void bgp_damp_info_vty(struct vty *vty, struct bgp_path_info *path, afi_t afi,
return;
/* Calculate new penalty. */
- t_now = bgp_clock();
+ t_now = monotime(NULL);
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
@@ -642,7 +642,7 @@ const char *bgp_damp_reuse_time_vty(struct vty *vty, struct bgp_path_info *path,
return NULL;
/* Calculate new penalty. */
- t_now = bgp_clock();
+ t_now = monotime(NULL);
t_diff = t_now - bdi->t_updated;
penalty = bgp_damp_decay(t_diff, bdi->penalty, bdc);
diff --git a/bgpd/bgp_debug.c b/bgpd/bgp_debug.c
index d0ab88ee1b..df7262be64 100644
--- a/bgpd/bgp_debug.c
+++ b/bgpd/bgp_debug.c
@@ -70,6 +70,7 @@ unsigned long conf_bgp_debug_pbr;
unsigned long conf_bgp_debug_graceful_restart;
unsigned long conf_bgp_debug_evpn_mh;
unsigned long conf_bgp_debug_bfd;
+unsigned long conf_bgp_debug_cond_adv;
unsigned long term_bgp_debug_as4;
unsigned long term_bgp_debug_neighbor_events;
@@ -90,6 +91,7 @@ unsigned long term_bgp_debug_pbr;
unsigned long term_bgp_debug_graceful_restart;
unsigned long term_bgp_debug_evpn_mh;
unsigned long term_bgp_debug_bfd;
+unsigned long term_bgp_debug_cond_adv;
struct list *bgp_debug_neighbor_events_peers = NULL;
struct list *bgp_debug_keepalive_peers = NULL;
@@ -2108,6 +2110,33 @@ DEFPY(debug_bgp_bfd, debug_bgp_bfd_cmd,
return CMD_SUCCESS;
}
+DEFPY (debug_bgp_cond_adv,
+ debug_bgp_cond_adv_cmd,
+ "[no$no] debug bgp conditional-advertisement",
+ NO_STR
+ DEBUG_STR
+ BGP_STR
+ "BGP conditional advertisement\n")
+{
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(cond_adv, COND_ADV);
+ else
+ DEBUG_ON(cond_adv, COND_ADV);
+ } else {
+ if (no) {
+ TERM_DEBUG_OFF(cond_adv, COND_ADV);
+ vty_out(vty,
+ "BGP conditional advertisement debugging is off\n");
+ } else {
+ TERM_DEBUG_ON(cond_adv, COND_ADV);
+ vty_out(vty,
+ "BGP conditional advertisement debugging is on\n");
+ }
+ }
+ return CMD_SUCCESS;
+}
+
DEFUN (no_debug_bgp,
no_debug_bgp_cmd,
"no debug bgp",
@@ -2152,6 +2181,7 @@ DEFUN (no_debug_bgp,
TERM_DEBUG_OFF(evpn_mh, EVPN_MH_ES);
TERM_DEBUG_OFF(evpn_mh, EVPN_MH_RT);
TERM_DEBUG_OFF(bfd, BFD_LIB);
+ TERM_DEBUG_OFF(cond_adv, COND_ADV);
vty_out(vty, "All possible debugging has been turned off\n");
@@ -2244,6 +2274,10 @@ DEFUN_NOSH (show_debugging_bgp,
if (BGP_DEBUG(bfd, BFD_LIB))
vty_out(vty, " BGP BFD library debugging is on\n");
+ if (BGP_DEBUG(cond_adv, COND_ADV))
+ vty_out(vty,
+ " BGP conditional advertisement debugging is on\n");
+
return CMD_SUCCESS;
}
@@ -2373,6 +2407,11 @@ static int bgp_config_write_debug(struct vty *vty)
write++;
}
+ if (CONF_BGP_DEBUG(cond_adv, COND_ADV)) {
+ vty_out(vty, "debug bgp conditional-advertisement\n");
+ write++;
+ }
+
return write;
}
@@ -2501,6 +2540,10 @@ void bgp_debug_init(void)
/* debug bgp bfd */
install_element(ENABLE_NODE, &debug_bgp_bfd_cmd);
install_element(CONFIG_NODE, &debug_bgp_bfd_cmd);
+
+ /* debug bgp conditional advertisement */
+ install_element(ENABLE_NODE, &debug_bgp_cond_adv_cmd);
+ install_element(CONFIG_NODE, &debug_bgp_cond_adv_cmd);
}
/* Return true if this prefix is on the per_prefix_list of prefixes to debug
@@ -2662,7 +2705,6 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
struct bgp_route_evpn *overlay_index,
char *str, int size)
{
- char rd_buf[RD_ADDRSTRLEN];
char tag_buf[30];
char overlay_index_buf[INET6_ADDRSTRLEN + 14];
const struct prefix_evpn *evp;
@@ -2720,8 +2762,7 @@ const char *bgp_debug_rdpfxpath2str(afi_t afi, safi_t safi,
}
if (prd)
- snprintfrr(str, size, "RD %s %pFX%s%s%s %s %s",
- prefix_rd2str(prd, rd_buf, sizeof(rd_buf)), pu.p,
+ snprintfrr(str, size, "RD %pRD %pFX%s%s%s %s %s", prd, pu.p,
overlay_index_buf, tag_buf, pathid_buf, afi2str(afi),
safi2str(safi));
else if (safi == SAFI_FLOWSPEC) {
diff --git a/bgpd/bgp_debug.h b/bgpd/bgp_debug.h
index 62f5340dfd..be5ed0afdc 100644
--- a/bgpd/bgp_debug.h
+++ b/bgpd/bgp_debug.h
@@ -80,6 +80,7 @@ extern unsigned long conf_bgp_debug_pbr;
extern unsigned long conf_bgp_debug_graceful_restart;
extern unsigned long conf_bgp_debug_evpn_mh;
extern unsigned long conf_bgp_debug_bfd;
+extern unsigned long conf_bgp_debug_cond_adv;
extern unsigned long term_bgp_debug_as4;
extern unsigned long term_bgp_debug_neighbor_events;
@@ -98,6 +99,7 @@ extern unsigned long term_bgp_debug_pbr;
extern unsigned long term_bgp_debug_graceful_restart;
extern unsigned long term_bgp_debug_evpn_mh;
extern unsigned long term_bgp_debug_bfd;
+extern unsigned long term_bgp_debug_cond_adv;
extern struct list *bgp_debug_neighbor_events_peers;
extern struct list *bgp_debug_keepalive_peers;
@@ -143,6 +145,7 @@ struct bgp_debug_filter {
#define BGP_DEBUG_GRACEFUL_RESTART 0x01
#define BGP_DEBUG_BFD_LIB 0x01
+#define BGP_DEBUG_COND_ADV 0x01
#define CONF_DEBUG_ON(a, b) (conf_bgp_debug_ ## a |= (BGP_DEBUG_ ## b))
#define CONF_DEBUG_OFF(a, b) (conf_bgp_debug_ ## a &= ~(BGP_DEBUG_ ## b))
diff --git a/bgpd/bgp_dump.c b/bgpd/bgp_dump.c
index 720925b20f..11e84f00b4 100644
--- a/bgpd/bgp_dump.c
+++ b/bgpd/bgp_dump.c
@@ -122,7 +122,7 @@ static FILE *bgp_dump_open_file(struct bgp_dump *bgp_dump)
ret = strftime(realpath, MAXPATHLEN, bgp_dump->filename, &tm);
if (ret == 0) {
- flog_warn(EC_BGP_DUMP, "bgp_dump_open_file: strftime error");
+ flog_warn(EC_BGP_DUMP, "%s: strftime error", __func__);
return NULL;
}
@@ -134,7 +134,7 @@ static FILE *bgp_dump_open_file(struct bgp_dump *bgp_dump)
bgp_dump->fp = fopen(realpath, "w");
if (bgp_dump->fp == NULL) {
- flog_warn(EC_BGP_DUMP, "bgp_dump_open_file: %s: %s", realpath,
+ flog_warn(EC_BGP_DUMP, "%s: %s: %s", __func__, realpath,
strerror(errno));
umask(oldumask);
return NULL;
@@ -367,7 +367,7 @@ bgp_dump_route_node_record(int afi, struct bgp_dest *dest,
stream_putw(obuf, path->peer->table_dump_index);
/* Originated */
- stream_putl(obuf, time(NULL) - (bgp_clock() - path->uptime));
+ stream_putl(obuf, time(NULL) - (monotime(NULL) - path->uptime));
/*Path Identifier*/
if (addpath_capable) {
diff --git a/bgpd/bgp_ecommunity.c b/bgpd/bgp_ecommunity.c
index 4120524e63..589d9af1e5 100644
--- a/bgpd/bgp_ecommunity.c
+++ b/bgpd/bgp_ecommunity.c
@@ -394,6 +394,44 @@ enum ecommunity_token {
ecommunity_token_val6,
};
+static const char *ecommunity_origin_validation_state2str(
+ enum ecommunity_origin_validation_states state)
+{
+ switch (state) {
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
+ return "valid";
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
+ return "not-found";
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
+ return "invalid";
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
+ return "not-used";
+ }
+
+ return "ERROR";
+}
+
+static void ecommunity_origin_validation_state_str(char *buf, size_t bufsz,
+ uint8_t *ptr)
+{
+ /* Origin Validation State is encoded in the last octet
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | 0x43 | 0x00 | Reserved |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | Reserved |validationstate|
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ */
+ uint8_t state = *(ptr + ECOMMUNITY_SIZE - 3);
+
+ snprintf(buf, bufsz, "OVS:%s",
+ ecommunity_origin_validation_state2str(state));
+
+ (void)ptr; /* consume value */
+}
+
static int ecommunity_encode_internal(uint8_t type, uint8_t sub_type,
int trans, as_t as,
struct in_addr *ip,
@@ -1172,6 +1210,13 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
ecom->disable_ieee_floating);
else
unk_ecom = 1;
+ } else if (type == ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS) {
+ sub_type = *pnt++;
+ if (sub_type == ECOMMUNITY_ORIGIN_VALIDATION_STATE)
+ ecommunity_origin_validation_state_str(
+ encbuf, sizeof(encbuf), pnt);
+ else
+ unk_ecom = 1;
} else {
sub_type = *pnt++;
unk_ecom = 1;
@@ -1188,6 +1233,23 @@ char *ecommunity_ecom2str(struct ecommunity *ecom, int format, int filter)
return str_buf;
}
+bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2)
+{
+ uint32_t i, j;
+
+ if (!e1 || !e2)
+ return false;
+ for (i = 0; i < e1->size; ++i) {
+ for (j = 0; j < e2->size; ++j) {
+ if (!memcmp(e1->val + (i * e1->unit_size),
+ e2->val + (j * e2->unit_size),
+ e1->unit_size))
+ return true;
+ }
+ }
+ return false;
+}
+
bool ecommunity_match(const struct ecommunity *ecom1,
const struct ecommunity *ecom2)
{
@@ -1321,7 +1383,7 @@ bool ecommunity_del_val(struct ecommunity *ecom, struct ecommunity_val *eval)
XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
ecom->val = p;
} else
- ecom->val = NULL;
+ XFREE(MTYPE_ECOMMUNITY_VAL, ecom->val);
return true;
}
@@ -1524,6 +1586,31 @@ void bgp_remove_ecomm_from_aggregate_hash(struct bgp_aggregate *aggregate,
}
}
+struct ecommunity *
+ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
+ struct ecommunity *old)
+{
+ struct ecommunity *new = NULL;
+ struct ecommunity ovs_ecomm = {0};
+ struct ecommunity_val ovs_eval;
+
+ encode_origin_validation_state(rpki_state, &ovs_eval);
+
+ if (old) {
+ new = ecommunity_dup(old);
+ ecommunity_add_val(new, &ovs_eval, true, true);
+ if (!old->refcnt)
+ ecommunity_free(&old);
+ } else {
+ ovs_ecomm.size = 1;
+ ovs_ecomm.unit_size = ECOMMUNITY_SIZE;
+ ovs_ecomm.val = (uint8_t *)&ovs_eval.val;
+ new = ecommunity_dup(&ovs_ecomm);
+ }
+
+ return new;
+}
+
/*
* return the BGP link bandwidth extended community, if present;
* the actual bandwidth is returned via param
diff --git a/bgpd/bgp_ecommunity.h b/bgpd/bgp_ecommunity.h
index f22855c329..4d7d4234a2 100644
--- a/bgpd/bgp_ecommunity.h
+++ b/bgpd/bgp_ecommunity.h
@@ -22,6 +22,7 @@
#define _QUAGGA_BGP_ECOMMUNITY_H
#include "bgpd/bgp_route.h"
+#include "bgpd/bgp_rpki.h"
#include "bgpd/bgpd.h"
/* Refer to rfc7153 for the IANA registry definitions. These are
@@ -51,6 +52,7 @@
/* Note: This really depends on the high-order octet. This means that
* multiple definitions for the same value are possible.
*/
+#define ECOMMUNITY_ORIGIN_VALIDATION_STATE 0x00
#define ECOMMUNITY_ROUTE_TARGET 0x02
#define ECOMMUNITY_SITE_ORIGIN 0x03
#define ECOMMUNITY_LINK_BANDWIDTH 0x04
@@ -100,6 +102,14 @@
#define ECOMMUNITY_SIZE 8
#define IPV6_ECOMMUNITY_SIZE 20
+/* Extended Community Origin Validation State */
+enum ecommunity_origin_validation_states {
+ ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID,
+ ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND,
+ ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID,
+ ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED
+};
+
/* Extended Communities type flag. */
#define ECOMMUNITY_FLAG_NON_TRANSITIVE 0x40
@@ -236,6 +246,32 @@ static inline void encode_lb_extcomm(as_t as, uint32_t bw, bool non_trans,
eval->val[7] = bandwidth & 0xff;
}
+static inline void encode_origin_validation_state(enum rpki_states state,
+ struct ecommunity_val *eval)
+{
+ enum ecommunity_origin_validation_states ovs_state =
+ ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED;
+
+ switch (state) {
+ case RPKI_VALID:
+ ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID;
+ break;
+ case RPKI_NOTFOUND:
+ ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND;
+ break;
+ case RPKI_INVALID:
+ ovs_state = ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID;
+ break;
+ case RPKI_NOT_BEING_USED:
+ break;
+ }
+
+ memset(eval, 0, sizeof(*eval));
+ eval->val[0] = ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS;
+ eval->val[1] = ECOMMUNITY_ORIGIN_VALIDATION_STATE;
+ eval->val[7] = ovs_state;
+}
+
extern void ecommunity_init(void);
extern void ecommunity_finish(void);
extern void ecommunity_free(struct ecommunity **);
@@ -257,6 +293,7 @@ extern struct ecommunity *ecommunity_str2com_ipv6(const char *str, int type,
int keyword_included);
extern char *ecommunity_ecom2str(struct ecommunity *, int, int);
extern void ecommunity_strfree(char **s);
+extern bool ecommunity_include(struct ecommunity *e1, struct ecommunity *e2);
extern bool ecommunity_match(const struct ecommunity *,
const struct ecommunity *);
extern char *ecommunity_str(struct ecommunity *);
@@ -313,4 +350,7 @@ static inline void ecommunity_strip_rts(struct ecommunity *ecom)
ecommunity_strip(ecom, ECOMMUNITY_ENCODE_IP, subtype);
ecommunity_strip(ecom, ECOMMUNITY_ENCODE_AS4, subtype);
}
+extern struct ecommunity *
+ecommunity_add_origin_validation_state(enum rpki_states rpki_state,
+ struct ecommunity *ecom);
#endif /* _QUAGGA_BGP_ECOMMUNITY_H */
diff --git a/bgpd/bgp_evpn.c b/bgpd/bgp_evpn.c
index 395111e1d2..58f5e9a226 100644
--- a/bgpd/bgp_evpn.c
+++ b/bgpd/bgp_evpn.c
@@ -191,6 +191,11 @@ static void vrf_import_rt_free(struct vrf_irt_node *irt)
XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt);
}
+static void hash_vrf_import_rt_free(struct vrf_irt_node *irt)
+{
+ XFREE(MTYPE_BGP_EVPN_VRF_IMPORT_RT, irt);
+}
+
/*
* Function to lookup Import RT node - used to map a RT to set of
* VNIs importing routes with that RT.
@@ -281,6 +286,11 @@ static void import_rt_free(struct bgp *bgp, struct irt_node *irt)
XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt);
}
+static void hash_import_rt_free(struct irt_node *irt)
+{
+ XFREE(MTYPE_BGP_EVPN_IMPORT_RT, irt);
+}
+
/*
* Function to lookup Import RT node - used to map a RT to set of
* VNIs importing routes with that RT.
@@ -1263,7 +1273,7 @@ static int update_evpn_type5_route_entry(struct bgp *bgp_evpn,
/* Unintern existing, set to new. */
bgp_attr_unintern(&tmp_pi->attr);
tmp_pi->attr = attr_new;
- tmp_pi->uptime = bgp_clock();
+ tmp_pi->uptime = monotime(NULL);
}
}
return 0;
@@ -1626,7 +1636,7 @@ static int update_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/* Unintern existing, set to new. */
bgp_attr_unintern(&tmp_pi->attr);
tmp_pi->attr = attr_new;
- tmp_pi->uptime = bgp_clock();
+ tmp_pi->uptime = monotime(NULL);
}
}
@@ -2448,8 +2458,10 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
if (attr.evpn_overlay.type != OVERLAY_INDEX_GATEWAY_IP) {
if (afi == AFI_IP6)
evpn_convert_nexthop_to_ipv6(&attr);
- else
+ else {
+ attr.nexthop = attr.mp_nexthop_global_in;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP);
+ }
} else {
/*
@@ -2518,7 +2530,7 @@ static int install_evpn_route_entry_in_vrf(struct bgp *bgp_vrf,
/* Unintern existing, set to new. */
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
- pi->uptime = bgp_clock();
+ pi->uptime = monotime(NULL);
}
/* Gateway IP nexthop should be resolved */
@@ -2641,7 +2653,7 @@ static int install_evpn_route_entry(struct bgp *bgp, struct bgpevpn *vpn,
/* Unintern existing, set to new. */
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
- pi->uptime = bgp_clock();
+ pi->uptime = monotime(NULL);
}
/* Add this route to remote IP hashtable */
@@ -3619,8 +3631,10 @@ static int update_advertise_vni_routes(struct bgp *bgp, struct bgpevpn *vpn)
pi->type == ZEBRA_ROUTE_BGP
&& pi->sub_type == BGP_ROUTE_STATIC)
break;
- if (!pi) /* unexpected */
+ if (!pi) {
+ bgp_dest_unlock_node(dest);
return 0;
+ }
attr = pi->attr;
global_dest = bgp_global_evpn_node_get(bgp->rib[afi][safi],
@@ -5353,6 +5367,11 @@ void bgp_evpn_free(struct bgp *bgp, struct bgpevpn *vpn)
XFREE(MTYPE_BGP_EVPN, vpn);
}
+static void hash_evpn_free(struct bgpevpn *vpn)
+{
+ XFREE(MTYPE_BGP_EVPN, vpn);
+}
+
/*
* Import evpn route from global table to VNI/VRF/ESI.
*/
@@ -5961,12 +5980,16 @@ void bgp_evpn_cleanup(struct bgp *bgp)
(void (*)(struct hash_bucket *, void *))free_vni_entry,
bgp);
+ hash_clean(bgp->import_rt_hash, (void (*)(void *))hash_import_rt_free);
hash_free(bgp->import_rt_hash);
bgp->import_rt_hash = NULL;
+ hash_clean(bgp->vrf_import_rt_hash,
+ (void (*)(void *))hash_vrf_import_rt_free);
hash_free(bgp->vrf_import_rt_hash);
bgp->vrf_import_rt_hash = NULL;
+ hash_clean(bgp->vni_svi_hash, (void (*)(void *))hash_evpn_free);
hash_free(bgp->vni_svi_hash);
bgp->vni_svi_hash = NULL;
hash_free(bgp->vnihash);
@@ -6237,9 +6260,6 @@ static void bgp_evpn_remote_ip_hash_iterate(struct bgpevpn *vpn,
static void show_remote_ip_entry(struct hash_bucket *bucket, void *args)
{
char buf[INET6_ADDRSTRLEN];
- char buf2[EVPN_ROUTE_STRLEN];
- struct prefix_evpn *evp;
-
struct listnode *node = NULL;
struct bgp_path_info *pi = NULL;
struct vty *vty = (struct vty *)args;
@@ -6248,11 +6268,8 @@ static void show_remote_ip_entry(struct hash_bucket *bucket, void *args)
vty_out(vty, " Remote IP: %s\n",
ipaddr2str(&ip->addr, buf, sizeof(buf)));
vty_out(vty, " Linked MAC/IP routes:\n");
- for (ALL_LIST_ELEMENTS_RO(ip->macip_path_list, node, pi)) {
- evp = (struct prefix_evpn *)&pi->net->p;
- prefix2str(evp, buf2, sizeof(buf2));
- vty_out(vty, " %s\n", buf2);
- }
+ for (ALL_LIST_ELEMENTS_RO(ip->macip_path_list, node, pi))
+ vty_out(vty, " %pFX\n", &pi->net->p);
}
void bgp_evpn_show_remote_ip_hash(struct hash_bucket *bucket, void *args)
@@ -6436,14 +6453,11 @@ static void bgp_evpn_remote_ip_process_nexthops(struct bgpevpn *vpn,
if (!bnc->nexthop || bnc->nexthop->ifindex != vpn->svi_ifindex)
return;
- if (BGP_DEBUG(nht, NHT)) {
- char buf[PREFIX2STR_BUFFER];
-
- prefix2str(&bnc->prefix, buf, sizeof(buf));
- zlog_debug("%s(%u): vni %u mac/ip %s for NH %s",
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("%s(%u): vni %u mac/ip %s for NH %pFX",
vpn->bgp_vrf->name_pretty, vpn->tenant_vrf_id,
- vpn->vni, (resolve ? "add" : "delete"), buf);
- }
+ vpn->vni, (resolve ? "add" : "delete"),
+ &bnc->prefix);
/*
* MAC/IP route or SVI or tenant vrf being added to EVI.
diff --git a/bgpd/bgp_evpn_mh.c b/bgpd/bgp_evpn_mh.c
index 3f801f7ea0..1d40664aeb 100644
--- a/bgpd/bgp_evpn_mh.c
+++ b/bgpd/bgp_evpn_mh.c
@@ -233,7 +233,7 @@ static int bgp_evpn_es_route_install(struct bgp *bgp,
/* Unintern existing, set to new. */
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
- pi->uptime = bgp_clock();
+ pi->uptime = monotime(NULL);
}
/* Perform route selection and update zebra, if required. */
@@ -432,7 +432,7 @@ int bgp_evpn_mh_route_update(struct bgp *bgp, struct bgp_evpn_es *es,
/* Unintern existing, set to new. */
bgp_attr_unintern(&tmp_pi->attr);
tmp_pi->attr = attr_new;
- tmp_pi->uptime = bgp_clock();
+ tmp_pi->uptime = monotime(NULL);
}
}
@@ -2402,16 +2402,13 @@ static void bgp_evpn_es_json_frag_fill(json_object *json_frags,
struct bgp_evpn_es *es)
{
json_object *json_frag;
- char buf1[RD_ADDRSTRLEN];
struct listnode *node;
struct bgp_evpn_es_frag *es_frag;
for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
json_frag = json_object_new_object();
- json_object_string_add(
- json_frag, "rd",
- prefix_rd2str(&es_frag->prd, buf1, sizeof(buf1)));
+ json_object_string_addf(json_frag, "rd", "%pRD", &es_frag->prd);
json_object_int_add(json_frag, "eviCount",
listcount(es_frag->es_evi_frag_list));
@@ -2423,12 +2420,10 @@ static void bgp_evpn_es_frag_show_detail(struct vty *vty,
struct bgp_evpn_es *es)
{
struct listnode *node;
- char buf1[RD_ADDRSTRLEN];
struct bgp_evpn_es_frag *es_frag;
for (ALL_LIST_ELEMENTS_RO(es->es_frag_list, node, es_frag)) {
- vty_out(vty, " %s EVIs: %d\n",
- prefix_rd2str(&es_frag->prd, buf1, sizeof(buf1)),
+ vty_out(vty, " %pRD EVIs: %d\n", &es_frag->prd,
listcount(es_frag->es_evi_frag_list));
}
}
@@ -2533,7 +2528,6 @@ static void bgp_evpn_es_vteps_show_detail(struct vty *vty,
static void bgp_evpn_es_show_entry(struct vty *vty,
struct bgp_evpn_es *es, json_object *json)
{
- char buf1[RD_ADDRSTRLEN];
struct listnode *node;
struct bgp_evpn_es_vtep *es_vtep;
@@ -2543,10 +2537,8 @@ static void bgp_evpn_es_show_entry(struct vty *vty,
json_object_string_add(json, "esi", es->esi_str);
if (es->es_base_frag)
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&es->es_base_frag->prd, buf1,
- sizeof(buf1)));
+ json_object_string_addf(json, "rd", "%pRD",
+ &es->es_base_frag->prd);
if (es->flags & (BGP_EVPNES_LOCAL | BGP_EVPNES_REMOTE)) {
json_types = json_object_new_array();
@@ -2583,15 +2575,9 @@ static void bgp_evpn_es_show_entry(struct vty *vty,
bgp_evpn_es_vteps_str(vtep_str, es, sizeof(vtep_str));
- if (es->es_base_frag)
- prefix_rd2str(&es->es_base_frag->prd, buf1,
- sizeof(buf1));
- else
- strlcpy(buf1, "-", sizeof(buf1));
-
- vty_out(vty, "%-30s %-5s %-21s %-8d %s\n",
- es->esi_str, type_str, buf1,
- listcount(es->es_evi_list), vtep_str);
+ vty_out(vty, "%-30s %-5s %-21pRD %-8d %s\n", es->esi_str,
+ type_str, &es->es_base_frag->prd,
+ listcount(es->es_evi_list), vtep_str);
}
}
@@ -2657,7 +2643,6 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
} else {
char incons_str[BGP_EVPNES_INCONS_STR_SZ];
char type_str[4];
- char buf1[RD_ADDRSTRLEN];
type_str[0] = '\0';
if (es->flags & BGP_EVPNES_LOCAL)
@@ -2665,15 +2650,9 @@ static void bgp_evpn_es_show_entry_detail(struct vty *vty,
if (es->flags & BGP_EVPNES_REMOTE)
strlcat(type_str, "R", sizeof(type_str));
- if (es->es_base_frag)
- prefix_rd2str(&es->es_base_frag->prd, buf1,
- sizeof(buf1));
- else
- strlcpy(buf1, "-", sizeof(buf1));
-
vty_out(vty, "ESI: %s\n", es->esi_str);
vty_out(vty, " Type: %s\n", type_str);
- vty_out(vty, " RD: %s\n", buf1);
+ vty_out(vty, " RD: %pRD\n", &es->es_base_frag->prd);
vty_out(vty, " Originator-IP: %pI4\n", &es->originator_ip);
if (es->flags & BGP_EVPNES_LOCAL)
vty_out(vty, " Local ES DF preference: %u\n",
@@ -4032,18 +4011,14 @@ static void bgp_evpn_es_evi_show_entry(struct vty *vty,
static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
struct bgp_evpn_es_evi *es_evi, json_object *json)
{
- char buf1[RD_ADDRSTRLEN];
-
if (json) {
json_object *json_flags;
/* Add the "brief" info first */
bgp_evpn_es_evi_show_entry(vty, es_evi, json);
if (es_evi->es_frag)
- json_object_string_add(
- json, "esFragmentRd",
- prefix_rd2str(&es_evi->es_frag->prd, buf1,
- sizeof(buf1)));
+ json_object_string_addf(json, "esFragmentRd", "%pRD",
+ &es_evi->es_frag->prd);
if (es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) {
json_flags = json_object_new_array();
json_array_string_add(json_flags, "es-vtep-mismatch");
@@ -4067,9 +4042,8 @@ static void bgp_evpn_es_evi_show_entry_detail(struct vty *vty,
es_evi->vpn->vni, es_evi->es->esi_str);
vty_out(vty, " Type: %s\n", type_str);
if (es_evi->es_frag)
- vty_out(vty, " ES fragment RD: %s\n",
- prefix_rd2str(&es_evi->es_frag->prd, buf1,
- sizeof(buf1)));
+ vty_out(vty, " ES fragment RD: %pRD\n",
+ &es_evi->es_frag->prd);
vty_out(vty, " Inconsistencies: %s\n",
(es_evi->flags & BGP_EVPNES_EVI_INCONS_VTEP_LIST) ?
"es-vtep-mismatch":"-");
@@ -4548,6 +4522,11 @@ static void bgp_evpn_nh_del(struct bgp_evpn_nh *n)
XFREE(MTYPE_BGP_EVPN_NH, tmp_n);
}
+static void hash_evpn_nh_free(struct bgp_evpn_nh *ben)
+{
+ XFREE(MTYPE_BGP_EVPN_NH, ben);
+}
+
static unsigned int bgp_evpn_nh_hash_keymake(const void *p)
{
const struct bgp_evpn_nh *n = p;
@@ -4612,6 +4591,7 @@ void bgp_evpn_nh_finish(struct bgp *bgp_vrf)
bgp_vrf->evpn_nh_table,
(void (*)(struct hash_bucket *, void *))bgp_evpn_nh_flush_cb,
NULL);
+ hash_clean(bgp_vrf->evpn_nh_table, (void (*)(void *))hash_evpn_nh_free);
hash_free(bgp_vrf->evpn_nh_table);
bgp_vrf->evpn_nh_table = NULL;
}
diff --git a/bgpd/bgp_evpn_vty.c b/bgpd/bgp_evpn_vty.c
index a94ff5ef64..5ad5cf8bff 100644
--- a/bgpd/bgp_evpn_vty.c
+++ b/bgpd/bgp_evpn_vty.c
@@ -386,9 +386,7 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
json_object_int_add(json, "vni", bgp_vrf->l3vni);
json_object_string_add(json, "type", "L3");
json_object_string_add(json, "inKernel", "True");
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "rd", "%pRD", &bgp_vrf->vrf_prd);
json_object_string_addf(json, "originatorIp", "%pI4",
&bgp_vrf->originator_ip);
json_object_string_add(json, "advertiseGatewayMacip", "n/a");
@@ -412,8 +410,7 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
vty_out(vty, " Type: %s\n", "L3");
vty_out(vty, " Tenant VRF: %s\n",
vrf_id_to_name(bgp_vrf->vrf_id));
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&bgp_vrf->vrf_prd, buf1, RD_ADDRSTRLEN));
+ vty_out(vty, " RD: %pRD\n", &bgp_vrf->vrf_prd);
vty_out(vty, " Originator IP: %pI4\n",
&bgp_vrf->originator_ip);
vty_out(vty, " Advertise-gw-macip : %s\n", "n/a");
@@ -471,7 +468,6 @@ static void display_l3vni(struct vty *vty, struct bgp *bgp_vrf,
static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
{
- char buf1[RD_ADDRSTRLEN];
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
@@ -488,9 +484,7 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
json_object_string_add(json, "type", "L2");
json_object_string_add(json, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ json_object_string_addf(json, "rd", "%pRD", &vpn->prd);
json_object_string_addf(json, "originatorIp", "%pI4",
&vpn->originator_ip);
json_object_string_addf(json, "mcastGroup", "%pI4",
@@ -531,8 +525,7 @@ static void display_vni(struct vty *vty, struct bgpevpn *vpn, json_object *json)
vty_out(vty, " Type: %s\n", "L2");
vty_out(vty, " Tenant-Vrf: %s\n",
vrf_id_to_name(vpn->tenant_vrf_id));
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ vty_out(vty, " RD: %pRD\n", &vpn->prd);
vty_out(vty, " Originator IP: %pI4\n", &vpn->originator_ip);
vty_out(vty, " Mcast group: %pI4\n", &vpn->mcast_grp);
if (!vpn->advertise_gw_macip &&
@@ -614,14 +607,10 @@ static void show_esi_routes(struct bgp *bgp,
for (dest = bgp_table_top(es->route_table); dest;
dest = bgp_route_next(dest)) {
int add_prefix_to_json = 0;
- char prefix_str[BUFSIZ];
json_object *json_paths = NULL;
json_object *json_prefix = NULL;
const struct prefix *p = bgp_dest_get_prefix(dest);
- prefix2str((struct prefix_evpn *)p, prefix_str,
- sizeof(prefix_str));
-
if (json)
json_prefix = json_object_new_object();
@@ -661,14 +650,14 @@ static void show_esi_routes(struct bgp *bgp,
if (json) {
if (add_prefix_to_json) {
- json_object_string_add(json_prefix, "prefix",
- prefix_str);
+ json_object_string_addf(json_prefix, "prefix",
+ "%pFX", p);
json_object_int_add(json_prefix, "prefixLen",
p->prefixlen);
json_object_object_add(json_prefix, "paths",
json_paths);
- json_object_object_add(json, prefix_str,
- json_prefix);
+ json_object_object_addf(json, json_prefix,
+ "%pFX", p);
} else {
json_object_free(json_paths);
json_object_free(json_prefix);
@@ -800,14 +789,10 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
const struct prefix_evpn *evp =
(const struct prefix_evpn *)bgp_dest_get_prefix(dest);
int add_prefix_to_json = 0;
- char prefix_str[BUFSIZ];
json_object *json_paths = NULL;
json_object *json_prefix = NULL;
const struct prefix *p = bgp_dest_get_prefix(dest);
- prefix2str((struct prefix_evpn *)bgp_dest_get_prefix(dest),
- prefix_str, sizeof(prefix_str));
-
if (type && evp->prefix.route_type != type)
continue;
@@ -861,14 +846,14 @@ static void show_vni_routes(struct bgp *bgp, struct bgpevpn *vpn, int type,
if (json) {
if (add_prefix_to_json) {
- json_object_string_add(json_prefix, "prefix",
- prefix_str);
+ json_object_string_addf(json_prefix, "prefix",
+ "%pFX", p);
json_object_int_add(json_prefix, "prefixLen",
p->prefixlen);
json_object_object_add(json_prefix, "paths",
json_paths);
- json_object_object_add(json, prefix_str,
- json_prefix);
+ json_object_object_addf(json, json_prefix,
+ "%pFX", p);
} else {
json_object_free(json_paths);
json_object_free(json_prefix);
@@ -949,9 +934,7 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
json_object_string_add(json_vni, "inKernel", "True");
json_object_string_addf(json_vni, "originatorIp", "%pI4",
&bgp->originator_ip);
- json_object_string_add(
- json_vni, "rd",
- prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
+ json_object_string_addf(json_vni, "rd", "%pRD", &bgp->vrf_prd);
json_object_string_add(json_vni, "advertiseGatewayMacip",
"n/a");
json_object_string_add(json_vni, "advertiseSviMacIp", "n/a");
@@ -967,8 +950,8 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
json_vni, "rmac",
prefix_mac2str(&bgp->rmac, buf2, sizeof(buf2)));
} else {
- vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, bgp->l3vni, "L3",
- prefix_rd2str(&bgp->vrf_prd, buf2, RD_ADDRSTRLEN));
+ vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, bgp->l3vni, "L3",
+ &bgp->vrf_prd);
}
for (ALL_LIST_ELEMENTS(bgp->vrf_import_rtl, node, nnode, ecom)) {
@@ -1020,13 +1003,12 @@ static void show_l3vni_entry(struct vty *vty, struct bgp *bgp,
/* If there are multiple export RTs we break here and show only
* one */
- if (!json)
+ if (!json) {
+ vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
break;
+ }
}
- if (!json)
- vty_out(vty, "%-37s", vrf_id_to_name(bgp->vrf_id));
-
if (json) {
char vni_str[VNI_STR_LEN];
@@ -1047,7 +1029,6 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
json_object *json_export_rtl = NULL;
struct bgpevpn *vpn = (struct bgpevpn *)bucket->data;
char buf1[10];
- char buf2[RD_ADDRSTRLEN];
char rt_buf[25];
char *ecom_str;
struct listnode *node, *nnode;
@@ -1074,9 +1055,7 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
json_object_string_add(json_vni, "type", "L2");
json_object_string_add(json_vni, "inKernel",
is_vni_live(vpn) ? "True" : "False");
- json_object_string_add(
- json_vni, "rd",
- prefix_rd2str(&vpn->prd, buf2, sizeof(buf2)));
+ json_object_string_addf(json_vni, "rd", "%pRD", &vpn->prd);
json_object_string_addf(json_vni, "originatorIp", "%pI4",
&vpn->originator_ip);
json_object_string_addf(json_vni, "mcastGroup", "%pI4",
@@ -1106,8 +1085,8 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
json_object_string_add(json_vni, "advertiseSviMacIp",
"Disabled");
} else {
- vty_out(vty, "%-1s %-10u %-4s %-21s", buf1, vpn->vni, "L2",
- prefix_rd2str(&vpn->prd, buf2, RD_ADDRSTRLEN));
+ vty_out(vty, "%-1s %-10u %-4s %-21pRD", buf1, vpn->vni, "L2",
+ &vpn->prd);
}
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode, ecom)) {
@@ -1159,13 +1138,13 @@ static void show_vni_entry(struct hash_bucket *bucket, void *args[])
/* If there are multiple export RTs we break here and show only
* one */
- if (!json)
+ if (!json) {
+ vty_out(vty, "%-37s",
+ vrf_id_to_name(vpn->tenant_vrf_id));
break;
+ }
}
- if (!json)
- vty_out(vty, "%-37s", vrf_id_to_name(vpn->tenant_vrf_id));
-
if (json) {
char vni_str[VNI_STR_LEN];
@@ -1190,7 +1169,6 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
int rd_header;
int header = 1;
char rd_str[RD_ADDRSTRLEN];
- char buf[BUFSIZ];
int no_display;
unsigned long output_count = 0;
@@ -1353,20 +1331,17 @@ static int bgp_show_ethernet_vpn(struct vty *vty, struct prefix_rd *prd,
json_prefix_info = json_object_new_object();
- prefix2str((struct prefix_evpn *)p, buf,
- BUFSIZ);
-
- json_object_string_addf(
- json_prefix_info, "prefix", "%pFX",
- (struct prefix_evpn *)p);
+ json_object_string_addf(json_prefix_info,
+ "prefix", "%pFX", p);
json_object_int_add(json_prefix_info,
"prefixLen", p->prefixlen);
json_object_object_add(json_prefix_info,
"paths", json_array);
- json_object_object_add(json_nroute, buf,
- json_prefix_info);
+ json_object_object_addf(json_nroute,
+ json_prefix_info,
+ "%pFX", p);
json_array = NULL;
}
}
@@ -2574,7 +2549,6 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
safi_t safi;
uint32_t path_cnt = 0;
json_object *json_paths = NULL;
- char prefix_str[BUFSIZ];
afi = AFI_L2VPN;
safi = SAFI_EVPN;
@@ -2593,8 +2567,6 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
return;
}
- prefix2str(&p, prefix_str, sizeof(prefix_str));
-
/* Prefix and num paths displayed once per prefix. */
route_vty_out_detail_header(vty, bgp, dest, prd, afi, safi, json);
@@ -2619,7 +2591,7 @@ static void evpn_show_route_rd_macip(struct vty *vty, struct bgp *bgp,
if (json && path_cnt) {
if (path_cnt)
- json_object_object_add(json, prefix_str, json_paths);
+ json_object_object_addf(json, json_paths, "%pFX", &p);
json_object_int_add(json, "numPaths", path_cnt);
} else {
vty_out(vty, "\nDisplayed %u paths for requested prefix\n",
@@ -2645,7 +2617,6 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
afi_t afi;
safi_t safi;
uint32_t prefix_cnt, path_cnt;
- char rd_str[RD_ADDRSTRLEN];
json_object *json_rd = NULL;
int add_rd_to_json = 0;
@@ -2653,8 +2624,6 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
safi = SAFI_EVPN;
prefix_cnt = path_cnt = 0;
- prefix_rd2str(prd, rd_str, sizeof(rd_str));
-
rd_dest = bgp_node_lookup(bgp->rib[afi][safi], (struct prefix *)prd);
if (!rd_dest)
return;
@@ -2667,7 +2636,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
if (json) {
json_rd = json_object_new_object();
- json_object_string_add(json_rd, "rd", rd_str);
+ json_object_string_addf(json_rd, "rd", "%pRD", prd);
}
bgp_dest_unlock_node(rd_dest);
@@ -2678,12 +2647,8 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
(const struct prefix_evpn *)bgp_dest_get_prefix(dest);
json_object *json_prefix = NULL;
json_object *json_paths = NULL;
- char prefix_str[BUFSIZ];
int add_prefix_to_json = 0;
- prefix2str((struct prefix_evpn *)evp, prefix_str,
- sizeof(prefix_str));
-
if (type && evp->prefix.route_type != type)
continue;
@@ -2739,8 +2704,8 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
if (add_prefix_to_json) {
json_object_object_add(json_prefix, "paths",
json_paths);
- json_object_object_add(json_rd, prefix_str,
- json_prefix);
+ json_object_object_addf(json_rd, json_prefix,
+ "%pFX", evp);
} else {
json_object_free(json_paths);
json_object_free(json_prefix);
@@ -2752,7 +2717,7 @@ static void evpn_show_route_rd(struct vty *vty, struct bgp *bgp,
if (json) {
if (add_rd_to_json)
- json_object_object_add(json, rd_str, json_rd);
+ json_object_object_addf(json, json_rd, "%pRD", prd);
else {
json_object_free(json_rd);
json_rd = NULL;
@@ -2798,7 +2763,6 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
json_object *json_prefix = NULL; /* prefix within an RD */
json_object *json_rd = NULL; /* holds all prefixes for RD */
char rd_str[RD_ADDRSTRLEN];
- char prefix_str[BUFSIZ];
int add_rd_to_json = 0;
struct prefix_evpn ep;
const struct prefix *rd_destp = bgp_dest_get_prefix(rd_dest);
@@ -2825,8 +2789,6 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
const struct prefix *p = bgp_dest_get_prefix(dest);
- prefix2str(p, prefix_str, sizeof(prefix_str));
-
pi = bgp_dest_get_bgp_path_info(dest);
if (pi) {
/* RD header - per RD. */
@@ -2838,8 +2800,8 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
if (json) {
json_prefix = json_object_new_object();
json_paths = json_object_new_array();
- json_object_string_add(json_prefix, "prefix",
- prefix_str);
+ json_object_string_addf(json_prefix, "prefix", "%pFX",
+ p);
json_object_int_add(json_prefix, "prefixLen",
p->prefixlen);
} else
@@ -2873,8 +2835,8 @@ static void evpn_show_route_rd_all_macip(struct vty *vty, struct bgp *bgp,
if (json) {
json_object_object_add(json_prefix, "paths",
json_paths);
- json_object_object_add(json_rd, prefix_str,
- json_prefix);
+ json_object_object_addf(json_rd, json_prefix, "%pFX",
+ p);
if (add_rd_to_json)
json_object_object_add(json, rd_str, json_rd);
else {
@@ -2954,13 +2916,9 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
const struct prefix_evpn *evp =
(const struct prefix_evpn *)bgp_dest_get_prefix(
dest);
- char prefix_str[BUFSIZ];
int add_prefix_to_json = 0;
const struct prefix *p = bgp_dest_get_prefix(dest);
- prefix2str((struct prefix_evpn *)p, prefix_str,
- sizeof(prefix_str));
-
if (type && evp->prefix.route_type != type)
continue;
@@ -2992,8 +2950,8 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
if (json) {
json_prefix = json_object_new_object();
json_paths = json_object_new_array();
- json_object_string_add(json_prefix, "prefix",
- prefix_str);
+ json_object_string_addf(json_prefix, "prefix",
+ "%pFX", p);
json_object_int_add(json_prefix, "prefixLen",
p->prefixlen);
}
@@ -3038,9 +2996,9 @@ static void evpn_show_all_routes(struct vty *vty, struct bgp *bgp, int type,
json_object_object_add(json_prefix,
"paths",
json_paths);
- json_object_object_add(json_rd,
- prefix_str,
- json_prefix);
+ json_object_object_addf(json_rd,
+ json_prefix,
+ "%pFX", p);
} else {
json_object_free(json_prefix);
json_object_free(json_paths);
@@ -3334,7 +3292,6 @@ static void evpn_unset_advertise_autort_rfc8365(struct bgp *bgp)
static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
{
- char buf1[RD_ADDRSTRLEN];
char *ecom_str;
struct listnode *node, *nnode;
struct ecommunity *ecom;
@@ -3342,8 +3299,7 @@ static void write_vni_config(struct vty *vty, struct bgpevpn *vpn)
if (is_vni_configured(vpn)) {
vty_out(vty, " vni %d\n", vpn->vni);
if (is_rd_configured(vpn))
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&vpn->prd, buf1, sizeof(buf1)));
+ vty_out(vty, " rd %pRD\n", &vpn->prd);
if (is_import_rt_configured(vpn)) {
for (ALL_LIST_ELEMENTS(vpn->import_rtl, node, nnode,
@@ -4036,6 +3992,9 @@ DEFUN (no_bgp_evpn_advertise_type5,
afi_t afi = 0;
safi_t safi = 0;
+ if (!bgp_vrf)
+ return CMD_WARNING;
+
argv_find_and_parse_afi(argv, argc, &idx_afi, &afi);
argv_find_and_parse_safi(argv, argc, &idx_safi, &safi);
@@ -4344,10 +4303,16 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
: "Disabled");
json_object_string_add(
json, "flooding",
- bgp_evpn->vxlan_flood_ctrl
- == VXLAN_FLOOD_HEAD_END_REPL
+ bgp_evpn->vxlan_flood_ctrl ==
+ VXLAN_FLOOD_HEAD_END_REPL
? "Head-end replication"
: "Disabled");
+ json_object_string_add(
+ json, "vxlanFlooding",
+ bgp_evpn->vxlan_flood_ctrl ==
+ VXLAN_FLOOD_HEAD_END_REPL
+ ? "Enabled"
+ : "Disabled");
json_object_int_add(json, "numVnis", num_vnis);
json_object_int_add(json, "numL2Vnis", num_l2vnis);
json_object_int_add(json, "numL3Vnis", num_l3vnis);
@@ -4361,10 +4326,15 @@ DEFUN(show_bgp_l2vpn_evpn_vni,
vty_out(vty, "Advertise All VNI flag: %s\n",
is_evpn_enabled() ? "Enabled" : "Disabled");
vty_out(vty, "BUM flooding: %s\n",
- bgp_evpn->vxlan_flood_ctrl
- == VXLAN_FLOOD_HEAD_END_REPL
+ bgp_evpn->vxlan_flood_ctrl ==
+ VXLAN_FLOOD_HEAD_END_REPL
? "Head-end replication"
: "Disabled");
+ vty_out(vty, "VXLAN flooding: %s\n",
+ bgp_evpn->vxlan_flood_ctrl ==
+ VXLAN_FLOOD_HEAD_END_REPL
+ ? "Enabled"
+ : "Disabled");
vty_out(vty, "Number of L2 VNIs: %u\n", num_l2vnis);
vty_out(vty, "Number of L3 VNIs: %u\n", num_l3vnis);
}
@@ -4700,7 +4670,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd,
if (uj)
json = json_object_new_object();
- if (argv_find(argv, argc, "all", &rd_all)) {
+ if (!argv_find(argv, argc, "all", &rd_all)) {
/* get the RD */
if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
&idx_ext_community)) {
@@ -4772,7 +4742,7 @@ DEFUN(show_bgp_l2vpn_evpn_route_rd_macip,
json = json_object_new_object();
/* get the prd */
- if (argv_find(argv, argc, "all", &rd_all)) {
+ if (!argv_find(argv, argc, "all", &rd_all)) {
if (argv_find(argv, argc, "ASN:NN_OR_IP-ADDRESS:NN",
&idx_ext_community)) {
ret = str2prefix_rd(argv[idx_ext_community]->arg, &prd);
@@ -5710,7 +5680,6 @@ DEFUN (show_bgp_vrf_l3vni_info,
JSON_STR)
{
char buf[ETHER_ADDR_STRLEN];
- char buf1[INET6_ADDRSTRLEN];
int idx_vrf = 3;
const char *name = NULL;
struct bgp *bgp = NULL;
@@ -5774,8 +5743,7 @@ DEFUN (show_bgp_vrf_l3vni_info,
for (ALL_LIST_ELEMENTS_RO(bgp->vrf_import_rtl, node, ecom))
vty_out(vty, "%s ", ecommunity_str(ecom));
vty_out(vty, "\n");
- vty_out(vty, " RD: %s\n",
- prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
+ vty_out(vty, " RD: %pRD\n", &bgp->vrf_prd);
} else {
json_object_string_add(json, "vrf", name);
json_object_string_addf(json, "local-ip", "%pI4",
@@ -5809,9 +5777,7 @@ DEFUN (show_bgp_vrf_l3vni_info,
json_import_rts,
json_object_new_string(ecommunity_str(ecom)));
json_object_object_add(json, "import-rts", json_import_rts);
- json_object_string_add(
- json, "rd",
- prefix_rd2str(&bgp->vrf_prd, buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "rd", "%pRD", &bgp->vrf_prd);
}
if (uj)
@@ -6044,6 +6010,7 @@ DEFUN(no_bgp_evpn_ead_es_rt, no_bgp_evpn_ead_es_rt_cmd,
if (!bgp_evpn_rt_matches_existing(bgp_mh_info->ead_es_export_rtl,
ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match EAD-ES RT configuration\n");
return CMD_WARNING;
@@ -6178,6 +6145,7 @@ DEFUN (no_bgp_evpn_vni_rt,
if (rt_type == RT_TYPE_IMPORT) {
if (!bgp_evpn_rt_matches_existing(vpn->import_rtl, ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
@@ -6185,6 +6153,7 @@ DEFUN (no_bgp_evpn_vni_rt,
evpn_unconfigure_import_rt(bgp, vpn, ecomdel);
} else if (rt_type == RT_TYPE_EXPORT) {
if (!bgp_evpn_rt_matches_existing(vpn->export_rtl, ecomdel)) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
@@ -6204,6 +6173,7 @@ DEFUN (no_bgp_evpn_vni_rt,
}
if (!found_ecomdel) {
+ ecommunity_free(&ecomdel);
vty_out(vty,
"%% RT specified does not match configuration for this VNI\n");
return CMD_WARNING;
@@ -6280,7 +6250,6 @@ static int vni_cmp(const void **a, const void **b)
void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
safi_t safi)
{
- char buf1[RD_ADDRSTRLEN];
char buf2[INET6_ADDRSTRLEN];
if (bgp->advertise_all_vni)
@@ -6446,8 +6415,7 @@ void bgp_config_write_evpn_info(struct vty *vty, struct bgp *bgp, afi_t afi,
}
}
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_RD_CFGD))
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&bgp->vrf_prd, buf1, sizeof(buf1)));
+ vty_out(vty, " rd %pRD\n", &bgp->vrf_prd);
/* import route-target */
if (CHECK_FLAG(bgp->vrf_flags, BGP_VRF_IMPORT_RT_CFGD)) {
diff --git a/bgpd/bgp_fsm.c b/bgpd/bgp_fsm.c
index b570c84d8b..ddda100774 100644
--- a/bgpd/bgp_fsm.c
+++ b/bgpd/bgp_fsm.c
@@ -574,7 +574,7 @@ void bgp_routeadv_timer(struct thread *thread)
zlog_debug("%s [FSM] Timer (routeadv timer expire)",
peer->host);
- peer->synctime = bgp_clock();
+ peer->synctime = monotime(NULL);
thread_add_timer_msec(bm->master, bgp_generate_updgrp_packets, peer, 0,
&peer->t_generate_updgrp_packets);
@@ -953,7 +953,7 @@ void bgp_start_routeadv(struct bgp *bgp)
struct listnode *node, *nnode;
struct peer *peer;
- zlog_info("bgp_start_routeadv(), update hold status %d",
+ zlog_info("%s, update hold status %d", __func__,
bgp->main_peers_update_hold);
if (bgp->main_peers_update_hold)
@@ -975,7 +975,7 @@ void bgp_start_routeadv(struct bgp *bgp)
*/
void bgp_adjust_routeadv(struct peer *peer)
{
- time_t nowtime = bgp_clock();
+ time_t nowtime = monotime(NULL);
double diff;
unsigned long remain;
@@ -987,7 +987,7 @@ void bgp_adjust_routeadv(struct peer *peer)
*/
THREAD_OFF(peer->t_routeadv);
- peer->synctime = bgp_clock();
+ peer->synctime = monotime(NULL);
/* If suppress fib pending is enabled, route is advertised to
* peers when the status is received from the FIB. The delay
* is added to update group packet generate which will allow
@@ -1464,6 +1464,11 @@ int bgp_stop(struct peer *peer)
/* There is no pending EOR message */
if (gr_info->eor_required == 0) {
+ if (gr_info->t_select_deferral) {
+ void *info = THREAD_ARG(
+ gr_info->t_select_deferral);
+ XFREE(MTYPE_TMP, info);
+ }
THREAD_OFF(gr_info->t_select_deferral);
gr_info->eor_received = 0;
}
@@ -1471,7 +1476,7 @@ int bgp_stop(struct peer *peer)
}
/* set last reset time */
- peer->resettime = peer->uptime = bgp_clock();
+ peer->resettime = peer->uptime = monotime(NULL);
if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
zlog_debug("%s remove from all update group",
@@ -1687,9 +1692,8 @@ static void bgp_connect_check(struct thread *thread)
static int bgp_connect_success(struct peer *peer)
{
if (peer->fd < 0) {
- flog_err(EC_BGP_CONNECT,
- "bgp_connect_success peer's fd is negative value %d",
- peer->fd);
+ flog_err(EC_BGP_CONNECT, "%s peer's fd is negative value %d",
+ __func__, peer->fd);
bgp_stop(peer);
return -1;
}
@@ -1910,7 +1914,7 @@ int bgp_start(struct peer *peer)
peer->host, peer->fd);
if (peer->fd < 0) {
flog_err(EC_BGP_FSM,
- "bgp_start peer's fd is negative value %d",
+ "%s peer's fd is negative value %d", __func__,
peer->fd);
return -1;
}
@@ -2220,7 +2224,7 @@ static int bgp_establish(struct peer *peer)
if (!peer->v_holdtime)
bgp_keepalives_on(peer);
- peer->uptime = bgp_clock();
+ peer->uptime = monotime(NULL);
/* Send route-refresh when ORF is enabled.
* Stop Long-lived Graceful Restart timers.
diff --git a/bgpd/bgp_io.c b/bgpd/bgp_io.c
index aba28fa504..f9bb8d518d 100644
--- a/bgpd/bgp_io.c
+++ b/bgpd/bgp_io.c
@@ -37,7 +37,7 @@
#include "bgpd/bgp_debug.h" // for bgp_debug_neighbor_events, bgp_type_str
#include "bgpd/bgp_errors.h" // for expanded error reference information
#include "bgpd/bgp_fsm.h" // for BGP_EVENT_ADD, bgp_event
-#include "bgpd/bgp_packet.h" // for bgp_notify_send_with_data, bgp_notify...
+#include "bgpd/bgp_packet.h" // for bgp_notify_io_invalid...
#include "bgpd/bgp_trace.h" // for frrtraces
#include "bgpd/bgpd.h" // for peer, BGP_MARKER_SIZE, bgp_master, bm
/* clang-format on */
@@ -431,7 +431,7 @@ static uint16_t bgp_write(struct peer *peer)
}
done : {
- now = bgp_clock();
+ now = monotime(NULL);
/*
* Update last_update if UPDATEs were written.
* Note: that these are only updated at end,
@@ -526,8 +526,8 @@ static bool validate_header(struct peer *peer)
return false;
if (memcmp(m_correct, m_rx, BGP_MARKER_SIZE) != 0) {
- bgp_notify_send(peer, BGP_NOTIFY_HEADER_ERR,
- BGP_NOTIFY_HEADER_NOT_SYNC);
+ bgp_notify_io_invalid(peer, BGP_NOTIFY_HEADER_ERR,
+ BGP_NOTIFY_HEADER_NOT_SYNC, NULL, 0);
return false;
}
@@ -547,9 +547,8 @@ static bool validate_header(struct peer *peer)
zlog_debug("%s unknown message type 0x%02x", peer->host,
type);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_HEADER_ERR,
- BGP_NOTIFY_HEADER_BAD_MESTYPE, &type,
- 1);
+ bgp_notify_io_invalid(peer, BGP_NOTIFY_HEADER_ERR,
+ BGP_NOTIFY_HEADER_BAD_MESTYPE, &type, 1);
return false;
}
@@ -574,9 +573,9 @@ static bool validate_header(struct peer *peer)
uint16_t nsize = htons(size);
- bgp_notify_send_with_data(peer, BGP_NOTIFY_HEADER_ERR,
- BGP_NOTIFY_HEADER_BAD_MESLEN,
- (unsigned char *)&nsize, 2);
+ bgp_notify_io_invalid(peer, BGP_NOTIFY_HEADER_ERR,
+ BGP_NOTIFY_HEADER_BAD_MESLEN,
+ (unsigned char *)&nsize, 2);
return false;
}
diff --git a/bgpd/bgp_keepalives.c b/bgpd/bgp_keepalives.c
index 158f163358..604d6c9509 100644
--- a/bgpd/bgp_keepalives.c
+++ b/bgpd/bgp_keepalives.c
@@ -175,6 +175,15 @@ void *bgp_keepalives_start(void *arg)
struct timeval next_update = {0, 0};
struct timespec next_update_ts = {0, 0};
+ /*
+ * The RCU mechanism for each pthread is initialized in a "locked"
+ * state. That's ok for pthreads using the frr_pthread,
+ * thread_fetch event loop, because that event loop unlocks regularly.
+ * For foreign pthreads, the lock needs to be unlocked so that the
+ * background rcu pthread can run.
+ */
+ rcu_read_unlock();
+
peerhash_mtx = XCALLOC(MTYPE_TMP, sizeof(pthread_mutex_t));
peerhash_cond = XCALLOC(MTYPE_TMP, sizeof(pthread_cond_t));
diff --git a/bgpd/bgp_labelpool.c b/bgpd/bgp_labelpool.c
index 8772afd736..c227a5e41c 100644
--- a/bgpd/bgp_labelpool.c
+++ b/bgpd/bgp_labelpool.c
@@ -37,18 +37,41 @@
#include "bgpd/bgp_errors.h"
#include "bgpd/bgp_route.h"
+#define BGP_LABELPOOL_ENABLE_TESTS 0
+
+#ifndef VTYSH_EXTRACT_PL
+#include "bgpd/bgp_labelpool_clippy.c"
+#endif
+
+
/*
* Definitions and external declarations.
*/
extern struct zclient *zclient;
+#if BGP_LABELPOOL_ENABLE_TESTS
+static void lptest_init(void);
+static void lptest_finish(void);
+#endif
+
/*
* Remember where pool data are kept
*/
static struct labelpool *lp;
-/* request this many labels at a time from zebra */
-#define LP_CHUNK_SIZE 50
+/*
+ * Number of labels requested at a time from the zebra label manager.
+ * We start small but double the request size each time up to a
+ * maximum size.
+ *
+ * The label space is 20 bits which is shared with other FRR processes
+ * on this host, so to avoid greedily requesting a mostly wasted chunk,
+ * we limit the chunk size to 1/16 of the label space (that's the -4 bits
+ * in the definition below). This limit slightly increases our cost of
+ * finding free labels in our allocated chunks.
+ */
+#define LP_CHUNK_SIZE_MIN 128
+#define LP_CHUNK_SIZE_MAX (1 << (20 - 4))
DEFINE_MTYPE_STATIC(BGPD, BGP_LABEL_CHUNK, "BGP Label Chunk");
DEFINE_MTYPE_STATIC(BGPD, BGP_LABEL_FIFO, "BGP Label FIFO item");
@@ -58,6 +81,9 @@ DEFINE_MTYPE_STATIC(BGPD, BGP_LABEL_CBQ, "BGP Dynamic Label Callback");
struct lp_chunk {
uint32_t first;
uint32_t last;
+ uint32_t nfree; /* un-allocated count */
+ uint32_t idx_last_allocated; /* start looking here */
+ bitfield_t allocated_map;
};
/*
@@ -160,6 +186,9 @@ static void lp_lcb_free(void *goner)
static void lp_chunk_free(void *goner)
{
+ struct lp_chunk *chunk = (struct lp_chunk *)goner;
+
+ bf_free(chunk->allocated_map);
XFREE(MTYPE_BGP_LABEL_CHUNK, goner);
}
@@ -180,6 +209,12 @@ void bgp_lp_init(struct thread_master *master, struct labelpool *pool)
lp->callback_q->spec.workfunc = lp_cbq_docallback;
lp->callback_q->spec.del_item_data = lp_cbq_item_free;
lp->callback_q->spec.max_retries = 0;
+
+ lp->next_chunksize = LP_CHUNK_SIZE_MIN;
+
+#if BGP_LABELPOOL_ENABLE_TESTS
+ lptest_init();
+#endif
}
/* check if a label callback was for a BGP LU node, and if so, unlock it */
@@ -201,6 +236,9 @@ void bgp_lp_finish(void)
struct lp_fifo *lf;
struct work_queue_item *item, *titem;
+#if BGP_LABELPOOL_ENABLE_TESTS
+ lptest_finish();
+#endif
if (!lp)
return;
@@ -240,25 +278,53 @@ static mpls_label_t get_label_from_pool(void *labelid)
/*
* Find a free label
- * Linear search is not efficient but should be executed infrequently.
*/
for (ALL_LIST_ELEMENTS_RO(lp->chunks, node, chunk)) {
uintptr_t lbl;
+ unsigned int index;
if (debug)
zlog_debug("%s: chunk first=%u last=%u",
__func__, chunk->first, chunk->last);
- for (lbl = chunk->first; lbl <= chunk->last; ++lbl) {
- /* labelid is key to all-request "ledger" list */
- if (!skiplist_insert(lp->inuse, (void *)lbl, labelid)) {
- /*
- * Success
- */
- return lbl;
- }
+ /*
+ * don't look in chunks with no available labels
+ */
+ if (!chunk->nfree)
+ continue;
+
+ /*
+ * roll through bitfield starting where we stopped
+ * last time
+ */
+ index = bf_find_next_clear_bit_wrap(
+ &chunk->allocated_map, chunk->idx_last_allocated + 1,
+ 0);
+
+ /*
+ * since chunk->nfree is non-zero, we should always get
+ * a valid index
+ */
+ assert(index != WORD_MAX);
+
+ lbl = chunk->first + index;
+ if (skiplist_insert(lp->inuse, (void *)lbl, labelid)) {
+ /* something is very wrong */
+ zlog_err("%s: unable to insert inuse label %u (id %p)",
+ __func__, (uint32_t)lbl, labelid);
+ return MPLS_LABEL_NONE;
}
+
+ /*
+ * Success
+ */
+ bf_set_bit(chunk->allocated_map, index);
+ chunk->idx_last_allocated = index;
+ chunk->nfree -= 1;
+
+ return lbl;
}
+
return MPLS_LABEL_NONE;
}
@@ -299,10 +365,14 @@ static struct lp_lcb *lcb_alloc(
* When connection to zebra is reestablished, previous label assignments
* will be invalidated (via callbacks having the "allocated" parameter unset)
* and new labels will be automatically reassigned by this labelpool module
- * (that is, a requestor does not need to call lp_get() again if it is
+ * (that is, a requestor does not need to call bgp_lp_get() again if it is
* notified via callback that its label has been lost: it will eventually
* get another callback with a new label assignment).
*
+ * The callback function should return 0 to accept the allocation
+ * and non-zero to refuse it. The callback function return value is
+ * ignored for invalidations (i.e., when the "allocated" parameter is false)
+ *
* Prior requests for a given labelid are detected so that requests and
* assignments are not duplicated.
*/
@@ -392,10 +462,13 @@ void bgp_lp_get(
if (lp_fifo_count(&lp->requests) > lp->pending_count) {
if (!zclient || zclient->sock < 0)
return;
- if (zclient_send_get_label_chunk(zclient, 0, LP_CHUNK_SIZE,
- MPLS_LABEL_BASE_ANY)
- != ZCLIENT_SEND_FAILURE)
- lp->pending_count += LP_CHUNK_SIZE;
+ if (zclient_send_get_label_chunk(zclient, 0, lp->next_chunksize,
+ MPLS_LABEL_BASE_ANY) !=
+ ZCLIENT_SEND_FAILURE) {
+ lp->pending_count += lp->next_chunksize;
+ if ((lp->next_chunksize << 1) <= LP_CHUNK_SIZE_MAX)
+ lp->next_chunksize <<= 1;
+ }
}
}
@@ -408,13 +481,36 @@ void bgp_lp_release(
if (!skiplist_search(lp->ledger, labelid, (void **)&lcb)) {
if (label == lcb->label && type == lcb->type) {
+ struct listnode *node;
+ struct lp_chunk *chunk;
uintptr_t lbl = label;
+ bool deallocated = false;
/* no longer in use */
skiplist_delete(lp->inuse, (void *)lbl, NULL);
/* no longer requested */
skiplist_delete(lp->ledger, labelid, NULL);
+
+ /*
+ * Find the chunk this label belongs to and
+ * deallocate the label
+ */
+ for (ALL_LIST_ELEMENTS_RO(lp->chunks, node, chunk)) {
+ uint32_t index;
+
+ if ((label < chunk->first) ||
+ (label > chunk->last))
+ continue;
+
+ index = label - chunk->first;
+ assert(bf_test_index(chunk->allocated_map,
+ index));
+ bf_release_index(chunk->allocated_map, index);
+ chunk->nfree += 1;
+ deallocated = true;
+ }
+ assert(deallocated);
}
}
}
@@ -427,6 +523,7 @@ void bgp_lp_event_chunk(uint8_t keep, uint32_t first, uint32_t last)
struct lp_chunk *chunk;
int debug = BGP_DEBUG(labelpool, LABELPOOL);
struct lp_fifo *lf;
+ uint32_t labelcount;
if (last < first) {
flog_err(EC_BGP_LABEL,
@@ -437,19 +534,27 @@ void bgp_lp_event_chunk(uint8_t keep, uint32_t first, uint32_t last)
chunk = XCALLOC(MTYPE_BGP_LABEL_CHUNK, sizeof(struct lp_chunk));
+ labelcount = last - first + 1;
+
chunk->first = first;
chunk->last = last;
+ chunk->nfree = labelcount;
+ bf_init(chunk->allocated_map, labelcount);
- listnode_add(lp->chunks, chunk);
+ /*
+ * Optimize for allocation by adding the new (presumably larger)
+ * chunk at the head of the list so it is examined first.
+ */
+ listnode_add_head(lp->chunks, chunk);
- lp->pending_count -= (last - first + 1);
+ lp->pending_count -= labelcount;
if (debug) {
zlog_debug("%s: %zu pending requests", __func__,
lp_fifo_count(&lp->requests));
}
- while ((lf = lp_fifo_first(&lp->requests))) {
+ while (labelcount && (lf = lp_fifo_first(&lp->requests))) {
struct lp_lcb *lcb;
void *labelid = lf->lcb.labelid;
@@ -495,6 +600,8 @@ void bgp_lp_event_chunk(uint8_t keep, uint32_t first, uint32_t last)
break;
}
+ labelcount -= 1;
+
/*
* we filled the request from local pool.
* Enqueue response work item with new label.
@@ -535,8 +642,8 @@ void bgp_lp_event_zebra_down(void)
*/
void bgp_lp_event_zebra_up(void)
{
- int labels_needed;
- int chunks_needed;
+ unsigned int labels_needed;
+ unsigned int chunks_needed;
void *labelid;
struct lp_lcb *lcb;
int lm_init_ok;
@@ -548,9 +655,16 @@ void bgp_lp_event_zebra_up(void)
labels_needed = lp_fifo_count(&lp->requests) +
skiplist_count(lp->inuse);
+ if (labels_needed > lp->next_chunksize) {
+ while ((lp->next_chunksize < labels_needed) &&
+ (lp->next_chunksize << 1 <= LP_CHUNK_SIZE_MAX))
+
+ lp->next_chunksize <<= 1;
+ }
+
/* round up */
- chunks_needed = (labels_needed / LP_CHUNK_SIZE) + 1;
- labels_needed = chunks_needed * LP_CHUNK_SIZE;
+ chunks_needed = (labels_needed / lp->next_chunksize) + 1;
+ labels_needed = chunks_needed * lp->next_chunksize;
lm_init_ok = lm_label_manager_connect(zclient, 1) == 0;
@@ -719,16 +833,14 @@ DEFUN(show_bgp_labelpool_ledger, show_bgp_labelpool_ledger_cmd,
vty_out(vty, "%-18s %u\n",
"INVALID", lcb->label);
else {
- char buf[PREFIX2STR_BUFFER];
p = bgp_dest_get_prefix(dest);
- prefix2str(p, buf, sizeof(buf));
if (uj) {
- json_object_string_add(json_elem,
- "prefix", buf);
+ json_object_string_addf(
+ json_elem, "prefix", "%pFX", p);
json_object_int_add(json_elem, "label",
lcb->label);
} else
- vty_out(vty, "%-18s %u\n", buf,
+ vty_out(vty, "%-18pFX %u\n", p,
lcb->label);
}
break;
@@ -812,16 +924,14 @@ DEFUN(show_bgp_labelpool_inuse, show_bgp_labelpool_inuse_cmd,
vty_out(vty, "INVALID %u\n",
label);
else {
- char buf[PREFIX2STR_BUFFER];
p = bgp_dest_get_prefix(dest);
- prefix2str(p, buf, sizeof(buf));
if (uj) {
- json_object_string_add(json_elem,
- "prefix", buf);
+ json_object_string_addf(
+ json_elem, "prefix", "%pFX", p);
json_object_int_add(json_elem, "label",
label);
} else
- vty_out(vty, "%-18s %u\n", buf,
+ vty_out(vty, "%-18pFX %u\n", p,
label);
}
break;
@@ -851,7 +961,6 @@ DEFUN(show_bgp_labelpool_requests, show_bgp_labelpool_requests_cmd,
json_object *json = NULL, *json_elem = NULL;
struct bgp_dest *dest;
const struct prefix *p;
- char buf[PREFIX2STR_BUFFER];
struct lp_fifo *item, *next;
int count;
@@ -893,12 +1002,11 @@ DEFUN(show_bgp_labelpool_requests, show_bgp_labelpool_requests_cmd,
vty_out(vty, "INVALID\n");
} else {
p = bgp_dest_get_prefix(dest);
- prefix2str(p, buf, sizeof(buf));
if (uj)
- json_object_string_add(json_elem,
- "prefix", buf);
+ json_object_string_addf(
+ json_elem, "prefix", "%pFX", p);
else
- vty_out(vty, "%-18s\n", buf);
+ vty_out(vty, "%-18pFX\n", p);
}
break;
case LP_TYPE_VRF:
@@ -943,25 +1051,496 @@ DEFUN(show_bgp_labelpool_chunks, show_bgp_labelpool_chunks_cmd,
}
json = json_object_new_array();
} else {
- vty_out(vty, "First Last\n");
- vty_out(vty, "--------------\n");
+ vty_out(vty, "%10s %10s %10s %10s\n", "First", "Last", "Size",
+ "nfree");
+ vty_out(vty, "-------------------------------------------\n");
}
for (ALL_LIST_ELEMENTS_RO(lp->chunks, node, chunk)) {
+ uint32_t size;
+
+ size = chunk->last - chunk->first + 1;
+
if (uj) {
json_elem = json_object_new_object();
json_object_array_add(json, json_elem);
json_object_int_add(json_elem, "first", chunk->first);
json_object_int_add(json_elem, "last", chunk->last);
+ json_object_int_add(json_elem, "size", size);
+ json_object_int_add(json_elem, "numberFree",
+ chunk->nfree);
} else
- vty_out(vty, "%-10u %-10u\n", chunk->first,
- chunk->last);
+ vty_out(vty, "%10u %10u %10u %10u\n", chunk->first,
+ chunk->last, size, chunk->nfree);
}
if (uj)
vty_json(vty, json);
return CMD_SUCCESS;
}
+#if BGP_LABELPOOL_ENABLE_TESTS
+/*------------------------------------------------------------------------
+ * Testing code start
+ *------------------------------------------------------------------------*/
+
+DEFINE_MTYPE_STATIC(BGPD, LABELPOOL_TEST, "Label pool test");
+
+#define LPT_STAT_INSERT_FAIL 0
+#define LPT_STAT_DELETE_FAIL 1
+#define LPT_STAT_ALLOCATED 2
+#define LPT_STAT_DEALLOCATED 3
+#define LPT_STAT_MAX 4
+
+const char *lpt_counter_names[] = {
+ "sl insert failures",
+ "sl delete failures",
+ "labels allocated",
+ "labels deallocated",
+};
+
+static uint8_t lpt_generation;
+static bool lpt_inprogress;
+static struct skiplist *lp_tests;
+static unsigned int lpt_test_cb_tcb_lookup_fails;
+static unsigned int lpt_release_tcb_lookup_fails;
+static unsigned int lpt_test_event_tcb_lookup_fails;
+static unsigned int lpt_stop_tcb_lookup_fails;
+
+struct lp_test {
+ uint8_t generation;
+ unsigned int request_maximum;
+ unsigned int request_blocksize;
+ uintptr_t request_count; /* match type of labelid */
+ int label_type;
+ struct skiplist *labels;
+ struct timeval starttime;
+ struct skiplist *timestamps_alloc;
+ struct skiplist *timestamps_dealloc;
+ struct thread *event_thread;
+ unsigned int counter[LPT_STAT_MAX];
+};
+
+/* test parameters */
+#define LPT_MAX_COUNT 500000 /* get this many labels in all */
+#define LPT_BLKSIZE 10000 /* this many at a time, then yield */
+#define LPT_TS_INTERVAL 10000 /* timestamp every this many labels */
+
+
+static int test_cb(mpls_label_t label, void *labelid, bool allocated)
+{
+ uintptr_t generation;
+ struct lp_test *tcb;
+
+ generation = ((uintptr_t)labelid >> 24) & 0xff;
+
+ if (skiplist_search(lp_tests, (void *)generation, (void **)&tcb)) {
+
+ /* couldn't find current test in progress */
+ ++lpt_test_cb_tcb_lookup_fails;
+ return -1; /* reject allocation */
+ }
+
+ if (allocated) {
+ ++tcb->counter[LPT_STAT_ALLOCATED];
+ if (!(tcb->counter[LPT_STAT_ALLOCATED] % LPT_TS_INTERVAL)) {
+ uintptr_t time_ms;
+
+ time_ms = monotime_since(&tcb->starttime, NULL) / 1000;
+ skiplist_insert(tcb->timestamps_alloc,
+ (void *)(uintptr_t)tcb
+ ->counter[LPT_STAT_ALLOCATED],
+ (void *)time_ms);
+ }
+ if (skiplist_insert(tcb->labels, labelid,
+ (void *)(uintptr_t)label)) {
+ ++tcb->counter[LPT_STAT_INSERT_FAIL];
+ return -1;
+ }
+ } else {
+ ++tcb->counter[LPT_STAT_DEALLOCATED];
+ if (!(tcb->counter[LPT_STAT_DEALLOCATED] % LPT_TS_INTERVAL)) {
+ uintptr_t time_ms;
+
+ time_ms = monotime_since(&tcb->starttime, NULL) / 1000;
+ skiplist_insert(tcb->timestamps_dealloc,
+ (void *)(uintptr_t)tcb
+ ->counter[LPT_STAT_ALLOCATED],
+ (void *)time_ms);
+ }
+ if (skiplist_delete(tcb->labels, labelid, 0)) {
+ ++tcb->counter[LPT_STAT_DELETE_FAIL];
+ return -1;
+ }
+ }
+ return 0;
+}
+
+static void labelpool_test_event_handler(struct thread *thread)
+{
+ struct lp_test *tcb;
+
+ if (skiplist_search(lp_tests, (void *)(uintptr_t)(lpt_generation),
+ (void **)&tcb)) {
+
+ /* couldn't find current test in progress */
+ ++lpt_test_event_tcb_lookup_fails;
+ return;
+ }
+
+ /*
+ * request a bunch of labels
+ */
+ for (unsigned int i = 0; (i < tcb->request_blocksize) &&
+ (tcb->request_count < tcb->request_maximum);
+ ++i) {
+
+ uintptr_t id;
+
+ ++tcb->request_count;
+
+ /*
+ * construct 32-bit id from request_count and generation
+ */
+ id = ((uintptr_t)tcb->generation << 24) |
+ (tcb->request_count & 0x00ffffff);
+ bgp_lp_get(LP_TYPE_VRF, (void *)id, test_cb);
+ }
+
+ if (tcb->request_count < tcb->request_maximum)
+ thread_add_event(bm->master, labelpool_test_event_handler, NULL,
+ 0, &tcb->event_thread);
+}
+
+static void lptest_stop(void)
+{
+ struct lp_test *tcb;
+
+ if (!lpt_inprogress)
+ return;
+
+ if (skiplist_search(lp_tests, (void *)(uintptr_t)(lpt_generation),
+ (void **)&tcb)) {
+
+ /* couldn't find current test in progress */
+ ++lpt_stop_tcb_lookup_fails;
+ return;
+ }
+
+ if (tcb->event_thread)
+ thread_cancel(&tcb->event_thread);
+
+ lpt_inprogress = false;
+}
+
+static int lptest_start(struct vty *vty)
+{
+ struct lp_test *tcb;
+
+ if (lpt_inprogress) {
+ vty_out(vty, "test already in progress\n");
+ return -1;
+ }
+
+ if (skiplist_count(lp_tests) >=
+ (1 << (8 * sizeof(lpt_generation))) - 1) {
+ /*
+ * Too many test runs
+ */
+ vty_out(vty, "too many tests: clear first\n");
+ return -1;
+ }
+
+ /*
+ * We pack the generation and request number into the labelid;
+ * make sure they fit.
+ */
+ unsigned int n1 = LPT_MAX_COUNT;
+ unsigned int sh = 0;
+ unsigned int label_bits;
+
+ label_bits = 8 * (sizeof(tcb->request_count) - sizeof(lpt_generation));
+
+ /* n1 should be same type as tcb->request_maximum */
+ assert(sizeof(n1) == sizeof(tcb->request_maximum));
+
+ while (n1 >>= 1)
+ ++sh;
+ sh += 1; /* number of bits needed to hold LPT_MAX_COUNT */
+
+ if (sh > label_bits) {
+ vty_out(vty,
+ "Sorry, test iteration count too big on this platform (LPT_MAX_COUNT %u, need %u bits, but label_bits is only %u)\n",
+ LPT_MAX_COUNT, sh, label_bits);
+ return -1;
+ }
+
+ lpt_inprogress = true;
+ ++lpt_generation;
+
+ tcb = XCALLOC(MTYPE_LABELPOOL_TEST, sizeof(*tcb));
+
+ tcb->generation = lpt_generation;
+ tcb->label_type = LP_TYPE_VRF;
+ tcb->request_maximum = LPT_MAX_COUNT;
+ tcb->request_blocksize = LPT_BLKSIZE;
+ tcb->labels = skiplist_new(0, NULL, NULL);
+ tcb->timestamps_alloc = skiplist_new(0, NULL, NULL);
+ tcb->timestamps_dealloc = skiplist_new(0, NULL, NULL);
+ thread_add_event(bm->master, labelpool_test_event_handler, NULL, 0,
+ &tcb->event_thread);
+ monotime(&tcb->starttime);
+
+ skiplist_insert(lp_tests, (void *)(uintptr_t)tcb->generation, tcb);
+ return 0;
+}
+
+DEFPY(start_labelpool_perf_test, start_labelpool_perf_test_cmd,
+ "debug bgp lptest start",
+ DEBUG_STR BGP_STR
+ "label pool test\n"
+ "start\n")
+{
+ lptest_start(vty);
+ return CMD_SUCCESS;
+}
+
+static void lptest_print_stats(struct vty *vty, struct lp_test *tcb)
+{
+ unsigned int i;
+
+ vty_out(vty, "Global Lookup Failures in test_cb: %5u\n",
+ lpt_test_cb_tcb_lookup_fails);
+ vty_out(vty, "Global Lookup Failures in release: %5u\n",
+ lpt_release_tcb_lookup_fails);
+ vty_out(vty, "Global Lookup Failures in event: %5u\n",
+ lpt_test_event_tcb_lookup_fails);
+ vty_out(vty, "Global Lookup Failures in stop: %5u\n",
+ lpt_stop_tcb_lookup_fails);
+ vty_out(vty, "\n");
+
+ if (!tcb) {
+ if (skiplist_search(lp_tests, (void *)(uintptr_t)lpt_generation,
+ (void **)&tcb)) {
+ vty_out(vty, "Error: can't find test %u\n",
+ lpt_generation);
+ return;
+ }
+ }
+
+ vty_out(vty, "Test Generation %u:\n", tcb->generation);
+
+ vty_out(vty, "Counter Value\n");
+ for (i = 0; i < LPT_STAT_MAX; ++i) {
+ vty_out(vty, "%20s: %10u\n", lpt_counter_names[i],
+ tcb->counter[i]);
+ }
+ vty_out(vty, "\n");
+
+ if (tcb->timestamps_alloc) {
+ void *Key;
+ void *Value;
+ void *cursor;
+
+ float elapsed;
+
+ vty_out(vty, "%10s %10s\n", "Count", "Seconds");
+
+ cursor = NULL;
+ while (!skiplist_next(tcb->timestamps_alloc, &Key, &Value,
+ &cursor)) {
+
+ elapsed = ((float)(uintptr_t)Value) / 1000;
+
+ vty_out(vty, "%10llu %10.3f\n",
+ (unsigned long long)(uintptr_t)Key, elapsed);
+ }
+ vty_out(vty, "\n");
+ }
+}
+
+DEFPY(show_labelpool_perf_test, show_labelpool_perf_test_cmd,
+ "debug bgp lptest show",
+ DEBUG_STR BGP_STR
+ "label pool test\n"
+ "show\n")
+{
+
+ if (lp_tests) {
+ void *Key;
+ void *Value;
+ void *cursor;
+
+ cursor = NULL;
+ while (!skiplist_next(lp_tests, &Key, &Value, &cursor)) {
+ lptest_print_stats(vty, (struct lp_test *)Value);
+ }
+ } else {
+ vty_out(vty, "no test results\n");
+ }
+ return CMD_SUCCESS;
+}
+
+DEFPY(stop_labelpool_perf_test, stop_labelpool_perf_test_cmd,
+ "debug bgp lptest stop",
+ DEBUG_STR BGP_STR
+ "label pool test\n"
+ "stop\n")
+{
+
+ if (lpt_inprogress) {
+ lptest_stop();
+ lptest_print_stats(vty, NULL);
+ } else {
+ vty_out(vty, "no test in progress\n");
+ }
+ return CMD_SUCCESS;
+}
+
+DEFPY(clear_labelpool_perf_test, clear_labelpool_perf_test_cmd,
+ "debug bgp lptest clear",
+ DEBUG_STR BGP_STR
+ "label pool test\n"
+ "clear\n")
+{
+
+ if (lpt_inprogress) {
+ lptest_stop();
+ }
+ if (lp_tests) {
+ while (!skiplist_first(lp_tests, NULL, NULL))
+ /* del function of skiplist cleans up tcbs */
+ skiplist_delete_first(lp_tests);
+ }
+ return CMD_SUCCESS;
+}
+
+/*
+ * With the "release" command, we can release labels at intervals through
+ * the ID space. Thus we can to exercise the bitfield-wrapping behavior
+ * of the allocator in a subsequent test.
+ */
+/* clang-format off */
+DEFPY(release_labelpool_perf_test, release_labelpool_perf_test_cmd,
+ "debug bgp lptest release test GENERATION$generation every (1-5)$every_nth",
+ DEBUG_STR
+ BGP_STR
+ "label pool test\n"
+ "release labels\n"
+ "\"test\"\n"
+ "test number\n"
+ "\"every\"\n"
+ "label fraction denominator\n")
+{
+ /* clang-format on */
+
+ unsigned long testnum;
+ char *end;
+ struct lp_test *tcb;
+
+ testnum = strtoul(generation, &end, 0);
+ if (*end) {
+ vty_out(vty, "Invalid test number: \"%s\"\n", generation);
+ return CMD_SUCCESS;
+ }
+ if (lpt_inprogress && (testnum == lpt_generation)) {
+ vty_out(vty,
+ "Error: Test %lu is still in progress (stop first)\n",
+ testnum);
+ return CMD_SUCCESS;
+ }
+
+ if (skiplist_search(lp_tests, (void *)(uintptr_t)testnum,
+ (void **)&tcb)) {
+
+ /* couldn't find current test in progress */
+ vty_out(vty, "Error: Can't look up test number: \"%lu\"\n",
+ testnum);
+ ++lpt_release_tcb_lookup_fails;
+ return CMD_SUCCESS;
+ }
+
+ void *Key, *cKey;
+ void *Value, *cValue;
+ void *cursor;
+ unsigned int iteration;
+ int rc;
+
+ cursor = NULL;
+ iteration = 0;
+ rc = skiplist_next(tcb->labels, &Key, &Value, &cursor);
+
+ while (!rc) {
+ cKey = Key;
+ cValue = Value;
+
+ /* find next item before we delete this one */
+ rc = skiplist_next(tcb->labels, &Key, &Value, &cursor);
+
+ if (!(iteration % every_nth)) {
+ bgp_lp_release(tcb->label_type, cKey,
+ (mpls_label_t)(uintptr_t)cValue);
+ skiplist_delete(tcb->labels, cKey, NULL);
+ ++tcb->counter[LPT_STAT_DEALLOCATED];
+ }
+ ++iteration;
+ }
+
+ return CMD_SUCCESS;
+}
+
+static void lptest_delete(void *val)
+{
+ struct lp_test *tcb = (struct lp_test *)val;
+ void *Key;
+ void *Value;
+ void *cursor;
+
+ if (tcb->labels) {
+ cursor = NULL;
+ while (!skiplist_next(tcb->labels, &Key, &Value, &cursor))
+ bgp_lp_release(tcb->label_type, Key,
+ (mpls_label_t)(uintptr_t)Value);
+ skiplist_free(tcb->labels);
+ tcb->labels = NULL;
+ }
+ if (tcb->timestamps_alloc) {
+ cursor = NULL;
+ skiplist_free(tcb->timestamps_alloc);
+ tcb->timestamps_alloc = NULL;
+ }
+
+ if (tcb->timestamps_dealloc) {
+ cursor = NULL;
+ skiplist_free(tcb->timestamps_dealloc);
+ tcb->timestamps_dealloc = NULL;
+ }
+
+ if (tcb->event_thread)
+ thread_cancel(&tcb->event_thread);
+
+ memset(tcb, 0, sizeof(*tcb));
+
+ XFREE(MTYPE_LABELPOOL_TEST, tcb);
+}
+
+static void lptest_init(void)
+{
+ lp_tests = skiplist_new(0, NULL, lptest_delete);
+}
+
+static void lptest_finish(void)
+{
+ if (lp_tests) {
+ skiplist_free(lp_tests);
+ lp_tests = NULL;
+ }
+}
+
+/*------------------------------------------------------------------------
+ * Testing code end
+ *------------------------------------------------------------------------*/
+#endif /* BGP_LABELPOOL_ENABLE_TESTS */
+
void bgp_lp_vty_init(void)
{
install_element(VIEW_NODE, &show_bgp_labelpool_summary_cmd);
@@ -969,4 +1548,12 @@ void bgp_lp_vty_init(void)
install_element(VIEW_NODE, &show_bgp_labelpool_inuse_cmd);
install_element(VIEW_NODE, &show_bgp_labelpool_requests_cmd);
install_element(VIEW_NODE, &show_bgp_labelpool_chunks_cmd);
+
+#if BGP_LABELPOOL_ENABLE_TESTS
+ install_element(ENABLE_NODE, &start_labelpool_perf_test_cmd);
+ install_element(ENABLE_NODE, &show_labelpool_perf_test_cmd);
+ install_element(ENABLE_NODE, &stop_labelpool_perf_test_cmd);
+ install_element(ENABLE_NODE, &release_labelpool_perf_test_cmd);
+ install_element(ENABLE_NODE, &clear_labelpool_perf_test_cmd);
+#endif /* BGP_LABELPOOL_ENABLE_TESTS */
}
diff --git a/bgpd/bgp_labelpool.h b/bgpd/bgp_labelpool.h
index d6a8eec84d..2f3ffe437f 100644
--- a/bgpd/bgp_labelpool.h
+++ b/bgpd/bgp_labelpool.h
@@ -41,6 +41,7 @@ struct labelpool {
struct work_queue *callback_q;
uint32_t pending_count; /* requested from zebra */
uint32_t reconnect_count; /* zebra reconnections */
+ uint32_t next_chunksize; /* request this many labels */
};
extern void bgp_lp_init(struct thread_master *master, struct labelpool *pool);
diff --git a/bgpd/bgp_main.c b/bgpd/bgp_main.c
index d9b0fab518..90ae580bab 100644
--- a/bgpd/bgp_main.c
+++ b/bgpd/bgp_main.c
@@ -454,8 +454,7 @@ int main(int argc, char **argv)
}
case 'l':
listnode_add_sort_nodup(addresses, optarg);
- /* listenon implies -n */
- /* fallthru */
+ break;
case 'n':
no_fib_flag = 1;
break;
@@ -512,6 +511,8 @@ int main(int argc, char **argv)
", bgp@%s:%d", address, bm->port);
}
+ bgp_if_init();
+
frr_config_fork();
/* must be called after fork() */
bgp_gr_apply_running_config();
diff --git a/bgpd/bgp_memory.c b/bgpd/bgp_memory.c
index b9f1ba3971..850657d35e 100644
--- a/bgpd/bgp_memory.c
+++ b/bgpd/bgp_memory.c
@@ -131,14 +131,6 @@ DEFINE_MTYPE(BGPD, BGP_EVPN_ES_EVI, "BGP EVPN ES-per-EVI Information");
DEFINE_MTYPE(BGPD, BGP_EVPN_ES_VRF, "BGP EVPN ES-per-VRF Information");
DEFINE_MTYPE(BGPD, BGP_EVPN_IMPORT_RT, "BGP EVPN Import RT");
DEFINE_MTYPE(BGPD, BGP_EVPN_VRF_IMPORT_RT, "BGP EVPN VRF Import RT");
-DEFINE_MTYPE(BGPD, BGP_EVPN_MACIP, "BGP EVPN MAC IP");
-
-DEFINE_MTYPE(BGPD, BGP_FLOWSPEC, "BGP flowspec");
-DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_RULE, "BGP flowspec rule");
-DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_RULE_STR, "BGP flowspec rule str");
-DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_COMPILED, "BGP flowspec compiled");
-DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_NAME, "BGP flowspec name");
-DEFINE_MTYPE(BGPD, BGP_FLOWSPEC_INDEX, "BGP flowspec index");
DEFINE_MTYPE(BGPD, BGP_SRV6_L3VPN, "BGP prefix-sid srv6 l3vpn servcie");
DEFINE_MTYPE(BGPD, BGP_SRV6_VPN, "BGP prefix-sid srv6 vpn service");
diff --git a/bgpd/bgp_memory.h b/bgpd/bgp_memory.h
index d4d7b0cf88..510cfa21c9 100644
--- a/bgpd/bgp_memory.h
+++ b/bgpd/bgp_memory.h
@@ -128,14 +128,6 @@ DECLARE_MTYPE(BGP_EVPN_ES_EVI_VTEP);
DECLARE_MTYPE(BGP_EVPN);
DECLARE_MTYPE(BGP_EVPN_IMPORT_RT);
DECLARE_MTYPE(BGP_EVPN_VRF_IMPORT_RT);
-DECLARE_MTYPE(BGP_EVPN_MACIP);
-
-DECLARE_MTYPE(BGP_FLOWSPEC);
-DECLARE_MTYPE(BGP_FLOWSPEC_RULE);
-DECLARE_MTYPE(BGP_FLOWSPEC_RULE_STR);
-DECLARE_MTYPE(BGP_FLOWSPEC_COMPILED);
-DECLARE_MTYPE(BGP_FLOWSPEC_NAME);
-DECLARE_MTYPE(BGP_FLOWSPEC_INDEX);
DECLARE_MTYPE(BGP_SRV6_L3VPN);
DECLARE_MTYPE(BGP_SRV6_VPN);
diff --git a/bgpd/bgp_mplsvpn.c b/bgpd/bgp_mplsvpn.c
index 7b8f0df2e2..d7fd4bc77e 100644
--- a/bgpd/bgp_mplsvpn.c
+++ b/bgpd/bgp_mplsvpn.c
@@ -662,25 +662,6 @@ void transpose_sid(struct in6_addr *sid, uint32_t label, uint8_t offset,
}
}
-static bool ecom_intersect(struct ecommunity *e1, struct ecommunity *e2)
-{
- uint32_t i, j;
-
- if (!e1 || !e2)
- return false;
- for (i = 0; i < e1->size; ++i) {
- for (j = 0; j < e2->size; ++j) {
- if (!memcmp(e1->val + (i * e1->unit_size),
- e2->val + (j * e2->unit_size),
- e1->unit_size)) {
-
- return true;
- }
- }
- }
- return false;
-}
-
static bool labels_same(struct bgp_path_info *bpi, mpls_label_t *label,
uint32_t n)
{
@@ -925,7 +906,7 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
bgp_aggregate_decrement(to_bgp, p, bpi, afi, safi);
bgp_attr_unintern(&bpi->attr);
bpi->attr = new_attr;
- bpi->uptime = bgp_clock();
+ bpi->uptime = monotime(NULL);
/*
* rewrite labels
@@ -997,6 +978,11 @@ leak_update(struct bgp *to_bgp, struct bgp_dest *bn,
new = info_make(ZEBRA_ROUTE_BGP, BGP_ROUTE_IMPORTED, 0,
to_bgp->peer_self, new_attr, bn);
+ if (source_bpi->peer) {
+ extra = bgp_path_info_extra_get(new);
+ extra->peer_orig = peer_lock(source_bpi->peer);
+ }
+
if (nexthop_self_flag)
bgp_path_info_set_flag(bn, new, BGP_PATH_ANNC_NH_SELF);
@@ -1502,7 +1488,7 @@ vpn_leak_to_vrf_update_onevrf(struct bgp *to_bgp, /* to */
}
/* Check for intersection of route targets */
- if (!ecom_intersect(
+ if (!ecommunity_include(
to_bgp->vpn_policy[afi].rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
bgp_attr_get_ecommunity(path_vpn->attr))) {
if (debug)
@@ -1751,9 +1737,10 @@ void vpn_leak_to_vrf_withdraw(struct bgp *from_bgp, /* from */
}
/* Check for intersection of route targets */
- if (!ecom_intersect(bgp->vpn_policy[afi]
- .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
- bgp_attr_get_ecommunity(path_vpn->attr))) {
+ if (!ecommunity_include(
+ bgp->vpn_policy[afi]
+ .rtlist[BGP_VPN_POLICY_DIR_FROMVPN],
+ bgp_attr_get_ecommunity(path_vpn->attr))) {
continue;
}
@@ -2001,9 +1988,15 @@ void vpn_handle_router_id_update(struct bgp *bgp, bool withdraw,
bgp->vpn_policy[afi].tovpn_rd = bgp->vrf_prd_auto;
prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
sizeof(buf));
- bgp->vpn_policy[afi].rtlist[edir] =
- ecommunity_str2com(buf,
- ECOMMUNITY_ROUTE_TARGET, 0);
+
+ /* free up pre-existing memory if any and allocate
+ * the ecommunity attribute with new RD/RT
+ */
+ if (bgp->vpn_policy[afi].rtlist[edir])
+ ecommunity_free(
+ &bgp->vpn_policy[afi].rtlist[edir]);
+ bgp->vpn_policy[afi].rtlist[edir] = ecommunity_str2com(
+ buf, ECOMMUNITY_ROUTE_TARGET, 0);
/* Update import_vrf rt_list */
ecom = bgp->vpn_policy[afi].rtlist[edir];
@@ -2932,7 +2925,7 @@ vrf_id_t get_first_vrf_for_redirect_with_rt(struct ecommunity *eckey)
if (ec && eckey->unit_size != ec->unit_size)
continue;
- if (ecom_intersect(ec, eckey))
+ if (ecommunity_include(ec, eckey))
return bgp->vrf_id;
}
return VRF_UNKNOWN;
diff --git a/bgpd/bgp_nexthop.c b/bgpd/bgp_nexthop.c
index e1fcc743ec..075350cd2b 100644
--- a/bgpd/bgp_nexthop.c
+++ b/bgpd/bgp_nexthop.c
@@ -64,11 +64,6 @@ int bgp_nexthop_cache_compare(const struct bgp_nexthop_cache *a,
return prefix_cmp(&a->prefix, &b->prefix);
}
-const char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size)
-{
- return prefix2str(&bnc->prefix, buf, size);
-}
-
void bnc_nexthop_free(struct bgp_nexthop_cache *bnc)
{
nexthops_free(bnc->nexthop);
@@ -748,7 +743,6 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,
safi_t safi;
struct bgp_table *table;
struct bgp *bgp_path;
- char buf1[BUFSIZ];
vty_out(vty, " Paths:\n");
LIST_FOREACH (path, &(bnc->paths), nh_thread) {
@@ -759,12 +753,13 @@ static void bgp_show_nexthop_paths(struct vty *vty, struct bgp *bgp,
safi = table->safi;
bgp_path = table->bgp;
- if (dest->pdest) {
- prefix_rd2str((struct prefix_rd *)bgp_dest_get_prefix(dest->pdest),
- buf1, sizeof(buf1));
- vty_out(vty, " %d/%d %pBD RD %s %s flags 0x%x\n",
- afi, safi, dest, buf1, bgp_path->name_pretty, path->flags);
- } else
+ if (dest->pdest)
+ vty_out(vty, " %d/%d %pBD RD %pRD %s flags 0x%x\n",
+ afi, safi, dest,
+ (struct prefix_rd *)bgp_dest_get_prefix(
+ dest->pdest),
+ bgp_path->name_pretty, path->flags);
+ else
vty_out(vty, " %d/%d %pBD %s flags 0x%x\n",
afi, safi, dest, bgp_path->name_pretty, path->flags);
}
@@ -868,9 +863,8 @@ static void bgp_show_nexthop(struct vty *vty, struct bgp *bgp,
if (!CHECK_FLAG(bnc->flags, BGP_NEXTHOP_REGISTERED))
vty_out(vty, " Is not Registered\n");
}
- tbuf = time(NULL) - (bgp_clock() - bnc->last_update);
+ tbuf = time(NULL) - (monotime(NULL) - bnc->last_update);
vty_out(vty, " Last update: %s", ctime(&tbuf));
- vty_out(vty, "\n");
/* show paths dependent on nexthop, if needed. */
if (specific)
@@ -917,6 +911,7 @@ static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
struct prefix nhop;
struct bgp_nexthop_cache_head (*tree)[AFI_MAX];
struct bgp_nexthop_cache *bnc;
+ bool found = false;
if (!str2prefix(nhopip_str, &nhop)) {
vty_out(vty, "nexthop address is malformed\n");
@@ -924,12 +919,16 @@ static int show_ip_bgp_nexthop_table(struct vty *vty, const char *name,
}
tree = import_table ? &bgp->import_check_table
: &bgp->nexthop_cache_table;
- bnc = bnc_find(tree[family2afi(nhop.family)], &nhop, 0, 0);
- if (!bnc) {
- vty_out(vty, "specified nexthop does not have entry\n");
- return CMD_SUCCESS;
+ frr_each (bgp_nexthop_cache, &(*tree)[family2afi(nhop.family)],
+ bnc) {
+ if (prefix_cmp(&bnc->prefix, &nhop))
+ continue;
+ bgp_show_nexthop(vty, bgp, bnc, true);
+ found = true;
}
- bgp_show_nexthop(vty, bgp, bnc, true);
+ if (!found)
+ vty_out(vty, "nexthop %s does not have entry\n",
+ nhopip_str);
} else
bgp_show_nexthops(vty, bgp, import_table);
diff --git a/bgpd/bgp_nexthop.h b/bgpd/bgp_nexthop.h
index 9d653ef4dc..efad906d0a 100644
--- a/bgpd/bgp_nexthop.h
+++ b/bgpd/bgp_nexthop.h
@@ -161,7 +161,6 @@ extern struct bgp_nexthop_cache *bnc_find(struct bgp_nexthop_cache_head *tree,
uint32_t srte_color,
ifindex_t ifindex);
extern void bnc_nexthop_free(struct bgp_nexthop_cache *bnc);
-extern const char *bnc_str(struct bgp_nexthop_cache *bnc, char *buf, int size);
extern void bgp_scan_init(struct bgp *bgp);
extern void bgp_scan_finish(struct bgp *bgp);
extern void bgp_scan_vty_init(void);
diff --git a/bgpd/bgp_nht.c b/bgpd/bgp_nht.c
index e03e83db2c..7274bcdb21 100644
--- a/bgpd/bgp_nht.c
+++ b/bgpd/bgp_nht.c
@@ -61,34 +61,97 @@ static int bgp_isvalid_nexthop(struct bgp_nexthop_cache *bnc)
&& bnc->nexthop_num > 0));
}
-static int bgp_isvalid_labeled_nexthop(struct bgp_nexthop_cache *bnc)
+static int bgp_isvalid_nexthop_for_ebgp(struct bgp_nexthop_cache *bnc,
+ struct bgp_path_info *path)
+{
+ struct interface *ifp = NULL;
+ struct nexthop *nexthop;
+ struct bgp_interface *iifp;
+ struct peer *peer;
+
+ if (!path->extra || !path->extra->peer_orig)
+ return false;
+
+ peer = path->extra->peer_orig;
+
+ /* only connected ebgp peers are valid */
+ if (peer->sort != BGP_PEER_EBGP || peer->ttl != BGP_DEFAULT_TTL ||
+ CHECK_FLAG(peer->flags, PEER_FLAG_DISABLE_CONNECTED_CHECK) ||
+ CHECK_FLAG(peer->bgp->flags, BGP_FLAG_DISABLE_NH_CONNECTED_CHK))
+ return false;
+
+ for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
+ if (nexthop->type == NEXTHOP_TYPE_IFINDEX ||
+ nexthop->type == NEXTHOP_TYPE_IPV4_IFINDEX ||
+ nexthop->type == NEXTHOP_TYPE_IPV6_IFINDEX) {
+ ifp = if_lookup_by_index(
+ bnc->ifindex ? bnc->ifindex : nexthop->ifindex,
+ bnc->bgp->vrf_id);
+ }
+ if (!ifp)
+ continue;
+ iifp = ifp->info;
+ if (CHECK_FLAG(iifp->flags, BGP_INTERFACE_MPLS_BGP_FORWARDING))
+ return true;
+ }
+ return false;
+}
+
+static int bgp_isvalid_nexthop_for_mplsovergre(struct bgp_nexthop_cache *bnc,
+ struct bgp_path_info *path)
+{
+ struct interface *ifp = NULL;
+ struct nexthop *nexthop;
+
+ for (nexthop = bnc->nexthop; nexthop; nexthop = nexthop->next) {
+ if (nexthop->type != NEXTHOP_TYPE_BLACKHOLE) {
+ ifp = if_lookup_by_index(
+ bnc->ifindex ? bnc->ifindex : nexthop->ifindex,
+ bnc->bgp->vrf_id);
+ if (ifp && (ifp->ll_type == ZEBRA_LLT_IPGRE ||
+ ifp->ll_type == ZEBRA_LLT_IP6GRE))
+ break;
+ }
+ }
+ if (!ifp)
+ return false;
+
+ if (CHECK_FLAG(path->attr->rmap_change_flags,
+ BATTR_RMAP_L3VPN_ACCEPT_GRE))
+ return true;
+
+ return false;
+}
+
+static int bgp_isvalid_nexthop_for_mpls(struct bgp_nexthop_cache *bnc,
+ struct bgp_path_info *path)
{
/*
- * In the case of MPLS-VPN, the label is learned from LDP or other
+ * - In the case of MPLS-VPN, the label is learned from LDP or other
* protocols, and nexthop tracking is enabled for the label.
* The value is recorded as BGP_NEXTHOP_LABELED_VALID.
- * In the case of SRv6-VPN, we need to track the reachability to the
+ * - In the case of SRv6-VPN, we need to track the reachability to the
* SID (in other words, IPv6 address). As in MPLS, we need to record
* the value as BGP_NEXTHOP_SID_VALID. However, this function is
* currently not implemented, and this function assumes that all
* Transit routes for SRv6-VPN are valid.
+ * - Otherwise check for mpls-gre acceptance
*/
- return (bgp_zebra_num_connects() == 0
- || (bnc && bnc->nexthop_num > 0
- && (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID)
- || bnc->bgp->srv6_enabled)));
+ return (bgp_zebra_num_connects() == 0 ||
+ (bnc && (bnc->nexthop_num > 0 &&
+ (CHECK_FLAG(bnc->flags, BGP_NEXTHOP_LABELED_VALID) ||
+ bnc->bgp->srv6_enabled ||
+ bgp_isvalid_nexthop_for_ebgp(bnc, path) ||
+ bgp_isvalid_nexthop_for_mplsovergre(bnc, path)))));
}
static void bgp_unlink_nexthop_check(struct bgp_nexthop_cache *bnc)
{
if (LIST_EMPTY(&(bnc->paths)) && !bnc->nht_info) {
- if (BGP_DEBUG(nht, NHT)) {
- char buf[PREFIX2STR_BUFFER];
- zlog_debug("%s: freeing bnc %s(%d)(%u)(%s)", __func__,
- bnc_str(bnc, buf, PREFIX2STR_BUFFER),
- bnc->ifindex, bnc->srte_color,
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("%s: freeing bnc %pFX(%d)(%u)(%s)", __func__,
+ &bnc->prefix, bnc->ifindex, bnc->srte_color,
bnc->bgp->name_pretty);
- }
/* only unregister if this is the last nh for this prefix*/
if (!bnc_existing_for_prefix(bnc))
unregister_zebra_rnh(bnc);
@@ -199,8 +262,8 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
to derive
address-family from the next-hop. */
if (!is_bgp_static_route)
- afi = BGP_ATTR_NEXTHOP_AFI_IP6(pi->attr) ? AFI_IP6
- : AFI_IP;
+ afi = BGP_ATTR_MP_NEXTHOP_LEN_IP6(pi->attr) ? AFI_IP6
+ : AFI_IP;
/* Validation for the ipv4 mapped ipv6 nexthop. */
if (IS_MAPPED_IPV6(&pi->attr->mp_nexthop_global)) {
@@ -261,24 +324,17 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
if (!bnc) {
bnc = bnc_new(tree, &p, srte_color, ifindex);
bnc->bgp = bgp_nexthop;
- if (BGP_DEBUG(nht, NHT)) {
- char buf[PREFIX2STR_BUFFER];
-
- zlog_debug("Allocated bnc %s(%d)(%u)(%s) peer %p",
- bnc_str(bnc, buf, PREFIX2STR_BUFFER),
- bnc->ifindex, bnc->srte_color,
+ if (BGP_DEBUG(nht, NHT))
+ zlog_debug("Allocated bnc %pFX(%d)(%u)(%s) peer %p",
+ &bnc->prefix, bnc->ifindex, bnc->srte_color,
bnc->bgp->name_pretty, peer);
- }
} else {
- if (BGP_DEBUG(nht, NHT)) {
- char buf[PREFIX2STR_BUFFER];
-
+ if (BGP_DEBUG(nht, NHT))
zlog_debug(
- "Found existing bnc %s(%d)(%s) flags 0x%x ifindex %d #paths %d peer %p",
- bnc_str(bnc, buf, PREFIX2STR_BUFFER),
- bnc->ifindex, bnc->bgp->name_pretty, bnc->flags,
- bnc->ifindex, bnc->path_count, bnc->nht_info);
- }
+ "Found existing bnc %pFX(%d)(%s) flags 0x%x ifindex %d #paths %d peer %p",
+ &bnc->prefix, bnc->ifindex,
+ bnc->bgp->name_pretty, bnc->flags, bnc->ifindex,
+ bnc->path_count, bnc->nht_info);
}
if (pi && is_route_parent_evpn(pi))
@@ -369,11 +425,11 @@ int bgp_find_or_add_nexthop(struct bgp *bgp_route, struct bgp *bgp_nexthop,
*/
if (bgp_route->inst_type == BGP_INSTANCE_TYPE_VIEW)
return 1;
- else if (safi == SAFI_UNICAST && pi
- && pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra
- && pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop) {
- return bgp_isvalid_labeled_nexthop(bnc);
- } else
+ else if (safi == SAFI_UNICAST && pi &&
+ pi->sub_type == BGP_ROUTE_IMPORTED && pi->extra &&
+ pi->extra->num_labels && !bnc->is_evpn_gwip_nexthop)
+ return bgp_isvalid_nexthop_for_mpls(bnc, pi);
+ else
return (bgp_isvalid_nexthop(bnc));
}
@@ -436,7 +492,7 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
int i;
bool evpn_resolved = false;
- bnc->last_update = bgp_clock();
+ bnc->last_update = monotime(NULL);
bnc->change_flags = 0;
/* debug print the input */
@@ -563,16 +619,12 @@ static void bgp_process_nexthop_update(struct bgp_nexthop_cache *bnc,
if (bnc->is_evpn_gwip_nexthop) {
evpn_resolved = bgp_evpn_is_gateway_ip_resolved(bnc);
- if (BGP_DEBUG(nht, NHT)) {
- char buf2[PREFIX2STR_BUFFER];
-
- prefix2str(&bnc->prefix, buf2, sizeof(buf2));
+ if (BGP_DEBUG(nht, NHT))
zlog_debug(
- "EVPN gateway IP %s recursive MAC/IP lookup %s",
- buf2,
+ "EVPN gateway IP %pFX recursive MAC/IP lookup %s",
+ &bnc->prefix,
(evpn_resolved ? "successful"
: "failed"));
- }
if (evpn_resolved) {
bnc->flags |= BGP_NEXTHOP_VALID;
@@ -609,7 +661,7 @@ static void bgp_nht_ifp_table_handle(struct bgp *bgp,
if (bnc->ifindex != ifp->ifindex)
continue;
- bnc->last_update = bgp_clock();
+ bnc->last_update = monotime(NULL);
bnc->change_flags = 0;
/*
@@ -847,7 +899,11 @@ static int make_prefix(int afi, struct bgp_path_info *pi, struct prefix *p)
p->u.prefix4 = ipv4;
p->prefixlen = IPV4_MAX_BITLEN;
} else {
- p->u.prefix4 = pi->attr->nexthop;
+ if (p_orig->family == AF_EVPN)
+ p->u.prefix4 =
+ pi->attr->mp_nexthop_global_in;
+ else
+ p->u.prefix4 = pi->attr->nexthop;
p->prefixlen = IPV4_MAX_BITLEN;
}
}
@@ -1019,14 +1075,12 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
const struct prefix *p;
if (BGP_DEBUG(nht, NHT)) {
- char buf[PREFIX2STR_BUFFER];
char bnc_buf[BNC_FLAG_DUMP_SIZE];
char chg_buf[BNC_FLAG_DUMP_SIZE];
- bnc_str(bnc, buf, PREFIX2STR_BUFFER);
zlog_debug(
- "NH update for %s(%d)(%u)(%s) - flags %s chgflags %s- evaluate paths",
- buf, bnc->ifindex, bnc->srte_color,
+ "NH update for %pFX(%d)(%u)(%s) - flags %s chgflags %s- evaluate paths",
+ &bnc->prefix, bnc->ifindex, bnc->srte_color,
bnc->bgp->name_pretty,
bgp_nexthop_dump_bnc_flags(bnc, bnc_buf,
sizeof(bnc_buf)),
@@ -1075,7 +1129,8 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
&& (path->attr->evpn_overlay.type
!= OVERLAY_INDEX_GATEWAY_IP)) {
bnc_is_valid_nexthop =
- bgp_isvalid_labeled_nexthop(bnc) ? true : false;
+ bgp_isvalid_nexthop_for_mpls(bnc, path) ? true
+ : false;
} else {
if (bgp_update_martian_nexthop(
bnc->bgp, afi, safi, path->type,
@@ -1090,16 +1145,14 @@ void evaluate_paths(struct bgp_nexthop_cache *bnc)
}
if (BGP_DEBUG(nht, NHT)) {
- char buf1[RD_ADDRSTRLEN];
-
- if (dest->pdest) {
- prefix_rd2str((struct prefix_rd *)bgp_dest_get_prefix(dest->pdest),
- buf1, sizeof(buf1));
+ if (dest->pdest)
zlog_debug(
- "... eval path %d/%d %pBD RD %s %s flags 0x%x",
- afi, safi, dest, buf1,
+ "... eval path %d/%d %pBD RD %pRD %s flags 0x%x",
+ afi, safi, dest,
+ (struct prefix_rd *)bgp_dest_get_prefix(
+ dest->pdest),
bgp_path->name_pretty, path->flags);
- } else
+ else
zlog_debug(
"... eval path %d/%d %pBD %s flags 0x%x",
afi, safi, dest, bgp_path->name_pretty,
diff --git a/bgpd/bgp_open.c b/bgpd/bgp_open.c
index 7248f034a5..d1667fac26 100644
--- a/bgpd/bgp_open.c
+++ b/bgpd/bgp_open.c
@@ -1185,15 +1185,30 @@ as_t peek_for_as4_capability(struct peer *peer, uint16_t length)
uint8_t opt_type;
uint16_t opt_length;
- /* Check the length. */
- if (stream_get_getp(s) + 2 > end)
+ /* Ensure we can read the option type */
+ if (stream_get_getp(s) + 1 > end)
goto end;
- /* Fetch option type and length. */
+ /* Fetch the option type */
opt_type = stream_getc(s);
- opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
- ? stream_getw(s)
- : stream_getc(s);
+
+ /*
+ * Check the length and fetch the opt_length
+ * If the peer is BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
+ * then we do a getw which is 2 bytes. So we need to
+ * ensure that we can read that as well
+ */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
+ if (stream_get_getp(s) + 2 > end)
+ goto end;
+
+ opt_length = stream_getw(s);
+ } else {
+ if (stream_get_getp(s) + 1 > end)
+ goto end;
+
+ opt_length = stream_getc(s);
+ }
/* Option length check. */
if (stream_get_getp(s) + opt_length > end)
@@ -1263,19 +1278,40 @@ int bgp_open_option_parse(struct peer *peer, uint16_t length,
uint8_t opt_type;
uint16_t opt_length;
- /* Must have at least an OPEN option header */
- if (STREAM_READABLE(s) < 2) {
+ /*
+ * Check that we can read the opt_type and fetch it
+ */
+ if (STREAM_READABLE(s) < 1) {
zlog_info("%s Option length error", peer->host);
bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
BGP_NOTIFY_OPEN_MALFORMED_ATTR);
return -1;
}
-
- /* Fetch option type and length. */
opt_type = stream_getc(s);
- opt_length = BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)
- ? stream_getw(s)
- : stream_getc(s);
+
+ /*
+ * Check the length of the stream to ensure that
+ * FRR can properly read the opt_length. Then read it
+ */
+ if (BGP_OPEN_EXT_OPT_PARAMS_CAPABLE(peer)) {
+ if (STREAM_READABLE(s) < 2) {
+ zlog_info("%s Option length error", peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+ return -1;
+ }
+
+ opt_length = stream_getw(s);
+ } else {
+ if (STREAM_READABLE(s) < 1) {
+ zlog_info("%s Option length error", peer->host);
+ bgp_notify_send(peer, BGP_NOTIFY_OPEN_ERR,
+ BGP_NOTIFY_OPEN_MALFORMED_ATTR);
+ return -1;
+ }
+
+ opt_length = stream_getc(s);
+ }
/* Option length check. */
if (STREAM_READABLE(s) < opt_length) {
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 45752a8ab6..8ae31bf2e6 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -131,11 +131,11 @@ static void bgp_packet_add(struct peer *peer, struct stream *s)
* after it'll get confused
*/
if (!stream_fifo_count_safe(peer->obuf))
- peer->last_sendq_ok = bgp_clock();
+ peer->last_sendq_ok = monotime(NULL);
stream_fifo_push(peer->obuf, s);
- delta = bgp_clock() - peer->last_sendq_ok;
+ delta = monotime(NULL) - peer->last_sendq_ok;
holdtime = atomic_load_explicit(&peer->holdtime,
memory_order_relaxed);
@@ -156,12 +156,12 @@ static void bgp_packet_add(struct peer *peer, struct stream *s)
peer->host);
BGP_EVENT_ADD(peer, TCP_fatal_error);
} else if (delta > (intmax_t)holdtime &&
- bgp_clock() - peer->last_sendq_warn > 5) {
+ monotime(NULL) - peer->last_sendq_warn > 5) {
flog_warn(
EC_BGP_SENDQ_STUCK_WARN,
"%s has not made any SendQ progress for 1 holdtime, peer overloaded?",
peer->host);
- peer->last_sendq_warn = bgp_clock();
+ peer->last_sendq_warn = monotime(NULL);
}
}
}
@@ -360,6 +360,31 @@ int bgp_nlri_parse(struct peer *peer, struct attr *attr,
return BGP_NLRI_PARSE_ERROR;
}
+
+/*
+ * Check if route-refresh request from peer is pending (received before EoR),
+ * and process it now.
+ */
+static void bgp_process_pending_refresh(struct peer *peer, afi_t afi,
+ safi_t safi)
+{
+ if (CHECK_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_REFRESH_PENDING)) {
+ UNSET_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_REFRESH_PENDING);
+ bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
+ BGP_ROUTE_REFRESH_BORR);
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP sending route-refresh (BoRR) for %s/%s (for pending REQUEST)",
+ peer, afi2str(afi), safi2str(safi));
+
+ SET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_BORR_SEND);
+ UNSET_FLAG(peer->af_sflags[afi][safi], PEER_STATUS_EORR_SEND);
+ bgp_announce_route(peer, afi, safi, true);
+ }
+}
+
/*
* Checks a variety of conditions to determine whether the peer needs to be
* rescheduled for packet generation again, and does so if necessary.
@@ -558,6 +583,9 @@ void bgp_generate_updgrp_packets(struct thread *thread)
BGP_UPDATE_EOR_PKT(
peer, afi, safi,
s);
+ bgp_process_pending_refresh(
+ peer, afi,
+ safi);
}
}
}
@@ -871,8 +899,9 @@ bool bgp_notify_received_hard_reset(struct peer *peer, uint8_t code,
* @param data Data portion
* @param datalen length of data portion
*/
-void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
- uint8_t sub_code, uint8_t *data, size_t datalen)
+static void bgp_notify_send_internal(struct peer *peer, uint8_t code,
+ uint8_t sub_code, uint8_t *data,
+ size_t datalen, bool use_curr)
{
struct stream *s;
bool hard_reset = bgp_notify_send_hard_reset(peer, code, sub_code);
@@ -917,8 +946,11 @@ void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
* If possible, store last packet for debugging purposes. This check is
* in place because we are sometimes called with a doppelganger peer,
* who tends to have a plethora of fields nulled out.
+ *
+ * Some callers should not attempt this - the io pthread for example
+ * should not touch internals of the peer struct.
*/
- if (peer->curr) {
+ if (use_curr && peer->curr) {
size_t packetsize = stream_get_endp(peer->curr);
assert(packetsize <= peer->max_packet_size);
memcpy(peer->last_reset_cause, peer->curr->data, packetsize);
@@ -1001,7 +1033,27 @@ void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
*/
void bgp_notify_send(struct peer *peer, uint8_t code, uint8_t sub_code)
{
- bgp_notify_send_with_data(peer, code, sub_code, NULL, 0);
+ bgp_notify_send_internal(peer, code, sub_code, NULL, 0, true);
+}
+
+/*
+ * Enqueue notification; called from the main pthread, peer object access is ok.
+ */
+void bgp_notify_send_with_data(struct peer *peer, uint8_t code,
+ uint8_t sub_code, uint8_t *data, size_t datalen)
+{
+ bgp_notify_send_internal(peer, code, sub_code, data, datalen, true);
+}
+
+/*
+ * For use by the io pthread, queueing a notification but avoiding access to
+ * the peer object.
+ */
+void bgp_notify_io_invalid(struct peer *peer, uint8_t code, uint8_t sub_code,
+ uint8_t *data, size_t datalen)
+{
+ /* Avoid touching the peer object */
+ bgp_notify_send_internal(peer, code, sub_code, data, datalen, false);
}
/*
@@ -2002,14 +2054,17 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
gr_info->eor_required,
"EOR RCV",
gr_info->eor_received);
+ if (gr_info->t_select_deferral) {
+ void *info = THREAD_ARG(
+ gr_info->t_select_deferral);
+ XFREE(MTYPE_TMP, info);
+ }
THREAD_OFF(gr_info->t_select_deferral);
gr_info->eor_required = 0;
gr_info->eor_received = 0;
/* Best path selection */
- if (bgp_best_path_select_defer(
- peer->bgp, afi, safi)
- < 0)
- return BGP_Stop;
+ bgp_best_path_select_defer(peer->bgp,
+ afi, safi);
}
}
@@ -2028,7 +2083,7 @@ static int bgp_update_receive(struct peer *peer, bgp_size_t size)
interned in bgp_attr_parse(). */
bgp_attr_unintern_sub(&attr);
- peer->update_time = bgp_clock();
+ peer->update_time = monotime(NULL);
/* Notify BGP Conditional advertisement scanner process */
peer->advmap_table_change = true;
@@ -2285,17 +2340,26 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
peer, orf_type, orf_len);
}
+ /* ORF prefix-list name */
+ snprintf(name, sizeof(name), "%s.%d.%d",
+ peer->host, afi, safi);
+
/* we're going to read at least 1 byte of common
* ORF header,
* and 7 bytes of ORF Address-filter entry from
* the stream
*/
- if (orf_len < 7)
+ if (*p_pnt & ORF_COMMON_PART_REMOVE_ALL) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP rcvd Remove-All pfxlist ORF request",
+ peer);
+ prefix_bgp_orf_remove_all(afi, name);
break;
+ }
- /* ORF prefix-list name */
- snprintf(name, sizeof(name), "%s.%d.%d",
- peer->host, afi, safi);
+ if (orf_len < 7)
+ break;
while (p_pnt < p_end) {
/* If the ORF entry is malformed, want
@@ -2308,17 +2372,6 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
memset(&orfp, 0, sizeof(orfp));
common = *p_pnt++;
/* after ++: p_pnt <= p_end */
- if (common
- & ORF_COMMON_PART_REMOVE_ALL) {
- if (bgp_debug_neighbor_events(
- peer))
- zlog_debug(
- "%pBP rcvd Remove-All pfxlist ORF request",
- peer);
- prefix_bgp_orf_remove_all(afi,
- name);
- break;
- }
ok = ((uint32_t)(p_end - p_pnt)
>= sizeof(uint32_t));
if (ok) {
@@ -2544,6 +2597,9 @@ static int bgp_route_refresh_receive(struct peer *peer, bgp_size_t size)
"%pBP rcvd route-refresh (REQUEST) for %s/%s before EoR",
peer, afi2str(afi),
safi2str(safi));
+ /* Can't send BoRR now, postpone after EoR */
+ SET_FLAG(peer->af_sflags[afi][safi],
+ PEER_STATUS_REFRESH_PENDING);
return BGP_PACKET_NOOP;
}
diff --git a/bgpd/bgp_packet.h b/bgpd/bgp_packet.h
index a0eb579db7..9f6d772bc0 100644
--- a/bgpd/bgp_packet.h
+++ b/bgpd/bgp_packet.h
@@ -62,6 +62,8 @@ extern void bgp_open_send(struct peer *);
extern void bgp_notify_send(struct peer *, uint8_t, uint8_t);
extern void bgp_notify_send_with_data(struct peer *, uint8_t, uint8_t,
uint8_t *, size_t);
+void bgp_notify_io_invalid(struct peer *peer, uint8_t code, uint8_t sub_code,
+ uint8_t *data, size_t datalen);
extern void bgp_route_refresh_send(struct peer *peer, afi_t afi, safi_t safi,
uint8_t orf_type, uint8_t when_to_refresh,
int remove, uint8_t subtype);
diff --git a/bgpd/bgp_rd.c b/bgpd/bgp_rd.c
index 9ab48aedc6..b4bcbdb804 100644
--- a/bgpd/bgp_rd.c
+++ b/bgpd/bgp_rd.c
@@ -211,3 +211,17 @@ void form_auto_rd(struct in_addr router_id,
snprintfrr(buf, sizeof(buf), "%pI4:%hu", &router_id, rd_id);
(void)str2prefix_rd(buf, prd);
}
+
+printfrr_ext_autoreg_p("RD", printfrr_prd);
+static ssize_t printfrr_prd(struct fbuf *buf, struct printfrr_eargs *ea,
+ const void *ptr)
+{
+ char rd_buf[RD_ADDRSTRLEN];
+
+ if (!ptr)
+ return bputs(buf, "(null)");
+
+ prefix_rd2str(ptr, rd_buf, sizeof(rd_buf));
+
+ return bputs(buf, rd_buf);
+}
diff --git a/bgpd/bgp_route.c b/bgpd/bgp_route.c
index 26341a5ce3..3324eb73de 100644
--- a/bgpd/bgp_route.c
+++ b/bgpd/bgp_route.c
@@ -255,6 +255,9 @@ void bgp_path_info_extra_free(struct bgp_path_info_extra **extra)
if (e->bgp_orig)
bgp_unlock(e->bgp_orig);
+ if (e->peer_orig)
+ peer_unlock(e->peer_orig);
+
if (e->aggr_suppressors)
list_delete(&e->aggr_suppressors);
@@ -1773,11 +1776,19 @@ static void bgp_peer_remove_private_as(struct bgp *bgp, afi_t afi, safi_t safi,
static void bgp_peer_as_override(struct bgp *bgp, afi_t afi, safi_t safi,
struct peer *peer, struct attr *attr)
{
- if (peer->sort == BGP_PEER_EBGP
- && peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
- if (aspath_single_asn_check(attr->aspath, peer->as))
- attr->aspath = aspath_replace_specific_asn(
- attr->aspath, peer->as, bgp->as);
+ struct aspath *aspath;
+
+ if (peer->sort == BGP_PEER_EBGP &&
+ peer_af_flag_check(peer, afi, safi, PEER_FLAG_AS_OVERRIDE)) {
+ if (attr->aspath->refcnt)
+ aspath = aspath_dup(attr->aspath);
+ else
+ aspath = attr->aspath;
+
+ attr->aspath = aspath_intern(
+ aspath_replace_specific_asn(aspath, peer->as, bgp->as));
+
+ aspath_free(aspath);
}
}
@@ -2027,8 +2038,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
&& (IPV4_ADDR_SAME(&onlypeer->remote_id, &piattr->originator_id))) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
- "%s [Update:SEND] %pFX originator-id is same as remote router-id",
- onlypeer->host, p);
+ "%pBP [Update:SEND] %pFX originator-id is same as remote router-id",
+ onlypeer, p);
return false;
}
@@ -2043,8 +2054,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
if (bgp_debug_update(NULL, p,
subgrp->update_group, 0))
zlog_debug(
- "%s [Update:SEND] %pFX is filtered via ORF",
- peer->host, p);
+ "%pBP [Update:SEND] %pFX is filtered via ORF",
+ peer, p);
return false;
}
}
@@ -2052,8 +2063,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
/* Output filter check. */
if (bgp_output_filter(peer, p, piattr, afi, safi) == FILTER_DENY) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
- zlog_debug("%s [Update:SEND] %pFX is filtered",
- peer->host, p);
+ zlog_debug("%pBP [Update:SEND] %pFX is filtered", peer,
+ p);
return false;
}
@@ -2062,8 +2073,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
&& aspath_loop_check(piattr->aspath, onlypeer->as)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
- "%s [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
- onlypeer->host, onlypeer->as);
+ "%pBP [Update:SEND] suppress announcement to peer AS %u that is part of AS path.",
+ onlypeer, onlypeer->as);
return false;
}
@@ -2072,8 +2083,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
if (aspath_loop_check(piattr->aspath, bgp->confed_id)) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
- "%s [Update:SEND] suppress announcement to peer AS %u is AS path.",
- peer->host, bgp->confed_id);
+ "%pBP [Update:SEND] suppress announcement to peer AS %u is AS path.",
+ peer, bgp->confed_id);
return false;
}
}
@@ -2214,6 +2225,32 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
bgp_peer_remove_private_as(bgp, afi, safi, peer, attr);
bgp_peer_as_override(bgp, afi, safi, peer, attr);
+ if (filter->advmap.update_type == UPDATE_TYPE_WITHDRAW &&
+ filter->advmap.aname &&
+ route_map_lookup_by_name(filter->advmap.aname)) {
+ struct bgp_path_info rmap_path = {0};
+ struct bgp_path_info_extra dummy_rmap_path_extra = {0};
+ struct attr dummy_attr = *attr;
+
+ /* Fill temp path_info */
+ prep_for_rmap_apply(&rmap_path, &dummy_rmap_path_extra, dest,
+ pi, peer, &dummy_attr);
+
+ struct route_map *amap =
+ route_map_lookup_by_name(filter->advmap.aname);
+
+ ret = route_map_apply(amap, p, &rmap_path);
+
+ bgp_attr_flush(&dummy_attr);
+
+ /*
+ * The conditional advertisement mode is Withdraw and this
+ * prefix is a conditional prefix. Don't advertise it
+ */
+ if (ret == RMAP_PERMITMATCH)
+ return false;
+ }
+
/* Route map & unsuppress-map apply. */
if (!post_attr &&
(ROUTE_MAP_OUT_NAME(filter) || bgp_path_suppressed(pi))) {
@@ -2254,9 +2291,8 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
if (ret == RMAP_DENYMATCH) {
if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
zlog_debug(
- "%s [Update:SEND] %pFX is filtered by route-map '%s'",
- peer->host, p,
- ROUTE_MAP_OUT_NAME(filter));
+ "%pBP [Update:SEND] %pFX is filtered by route-map '%s'",
+ peer, p, ROUTE_MAP_OUT_NAME(filter));
bgp_attr_flush(rmap_path.attr);
return false;
}
@@ -2293,6 +2329,29 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
if (aspath_check_as_sets(attr->aspath))
return false;
+ /* If neighbor sso is configured, then check if the route has
+ * SoO extended community and validate against the configured
+ * one. If they match, do not announce, to prevent routing
+ * loops.
+ */
+ if ((attr->flag & ATTR_FLAG_BIT(BGP_ATTR_EXT_COMMUNITIES)) &&
+ peer->soo[afi][safi]) {
+ struct ecommunity *ecomm_soo = peer->soo[afi][safi];
+ struct ecommunity *ecomm = bgp_attr_get_ecommunity(attr);
+
+ if ((ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS,
+ ECOMMUNITY_SITE_ORIGIN) ||
+ ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_AS4,
+ ECOMMUNITY_SITE_ORIGIN)) &&
+ ecommunity_include(ecomm, ecomm_soo)) {
+ if (bgp_debug_update(NULL, p, subgrp->update_group, 0))
+ zlog_debug(
+ "%pBP [Update:SEND] %pFX is filtered by SoO extcommunity '%s'",
+ peer, p, ecommunity_str(ecomm_soo));
+ return false;
+ }
+ }
+
/* Codification of AS 0 Processing */
if (aspath_check_as_zero(attr->aspath))
return false;
@@ -2427,6 +2486,21 @@ bool subgroup_announce_check(struct bgp_dest *dest, struct bgp_path_info *pi,
}
}
+ /* If this is an iBGP, send Origin Validation State (OVS)
+ * extended community (rfc8097).
+ */
+ if (peer->sort == BGP_PEER_IBGP) {
+ enum rpki_states rpki_state = RPKI_NOT_BEING_USED;
+
+ rpki_state = hook_call(bgp_rpki_prefix_status, peer, attr, p);
+
+ if (rpki_state != RPKI_NOT_BEING_USED)
+ bgp_attr_set_ecommunity(
+ attr, ecommunity_add_origin_validation_state(
+ rpki_state,
+ bgp_attr_get_ecommunity(attr)));
+ }
+
/*
* When the next hop is set to ourselves, if all multipaths have
* link-bandwidth announce the cumulative bandwidth as that makes
@@ -3193,7 +3267,7 @@ static void bgp_process_main_one(struct bgp *bgp, struct bgp_dest *dest,
}
/* Process the routes with the flag BGP_NODE_SELECT_DEFER set */
-int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
+void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct bgp_dest *dest;
int cnt = 0;
@@ -3240,7 +3314,7 @@ int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
/* Send route processing complete message to RIB */
bgp_zebra_update(afi, safi, bgp->vrf_id,
ZEBRA_CLIENT_ROUTE_UPDATE_COMPLETE);
- return 0;
+ return;
}
thread_info = XMALLOC(MTYPE_TMP, sizeof(struct afi_safi_info));
@@ -3255,7 +3329,6 @@ int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi)
thread_add_timer(bm->master, bgp_route_select_timer_expire, thread_info,
BGP_ROUTE_SELECT_DELAY,
&bgp->gr_info[afi][safi].t_route_select);
- return 0;
}
static wq_item_status bgp_process_wq(struct work_queue *wq, void *data)
@@ -3649,7 +3722,7 @@ struct bgp_path_info *info_make(int type, int sub_type, unsigned short instance,
new->sub_type = sub_type;
new->peer = peer;
new->attr = attr;
- new->uptime = bgp_clock();
+ new->uptime = monotime(NULL);
new->net = dest;
return new;
}
@@ -3781,8 +3854,6 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
int do_loop_check = 1;
int has_valid_label = 0;
afi_t nh_afi;
- uint8_t pi_type = 0;
- uint8_t pi_sub_type = 0;
bool force_evpn_import = false;
safi_t orig_safi = safi;
bool leak_success = true;
@@ -3986,15 +4057,10 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
bgp_attr_add_gshut_community(&new_attr);
}
- if (pi) {
- pi_type = pi->type;
- pi_sub_type = pi->sub_type;
- }
-
/* next hop check. */
- if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD)
- && bgp_update_martian_nexthop(bgp, afi, safi, pi_type, pi_sub_type,
- &new_attr, dest)) {
+ if (!CHECK_FLAG(peer->flags, PEER_FLAG_IS_RFAPI_HD) &&
+ bgp_update_martian_nexthop(bgp, afi, safi, type, sub_type,
+ &new_attr, dest)) {
peer->stat_pfx_nh_invalid++;
reason = "martian or self next-hop;";
bgp_attr_flush(&new_attr);
@@ -4035,11 +4101,35 @@ int bgp_update(struct peer *peer, const struct prefix *p, uint32_t addpath_id,
return -1;
}
+ /* If neighbor soo is configured, tag all incoming routes with
+ * this SoO tag and then filter out advertisements in
+ * subgroup_announce_check() if it matches the configured SoO
+ * on the other peer.
+ */
+ if (peer->soo[afi][safi]) {
+ struct ecommunity *old_ecomm =
+ bgp_attr_get_ecommunity(&new_attr);
+ struct ecommunity *ecomm_soo = peer->soo[afi][safi];
+ struct ecommunity *new_ecomm;
+
+ if (old_ecomm) {
+ new_ecomm = ecommunity_merge(ecommunity_dup(old_ecomm),
+ ecomm_soo);
+
+ if (!old_ecomm->refcnt)
+ ecommunity_free(&old_ecomm);
+ } else {
+ new_ecomm = ecommunity_dup(ecomm_soo);
+ }
+
+ bgp_attr_set_ecommunity(&new_attr, new_ecomm);
+ }
+
attr_new = bgp_attr_intern(&new_attr);
/* If the update is implicit withdraw. */
if (pi) {
- pi->uptime = bgp_clock();
+ pi->uptime = monotime(NULL);
same_attr = attrhash_cmp(pi->attr, attr_new);
hook_call(bgp_process, bgp, afi, safi, dest, peer, true);
@@ -5523,8 +5613,8 @@ void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
if (bgp_debug_neighbor_events(
peer))
zlog_debug(
- "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
- peer->host,
+ "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
+ peer,
afi2str(afi),
safi2str(safi),
bgp_dest_get_prefix(
@@ -5552,9 +5642,8 @@ void bgp_set_stale_route(struct peer *peer, afi_t afi, safi_t safi)
BGP_PATH_UNUSEABLE)) {
if (bgp_debug_neighbor_events(peer))
zlog_debug(
- "%s: route-refresh for %s/%s, marking prefix %pFX as stale",
- peer->host,
- afi2str(afi),
+ "%pBP route-refresh for %s/%s, marking prefix %pFX as stale",
+ peer, afi2str(afi),
safi2str(safi),
bgp_dest_get_prefix(
dest));
@@ -5884,6 +5973,9 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
attr.med = bgp_static->igpmetric;
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_MULTI_EXIT_DISC);
+ if (afi == AFI_IP)
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+
if (bgp_static->atomic)
attr.flag |= ATTR_FLAG_BIT(BGP_ATTR_ATOMIC_AGGREGATE);
@@ -5914,6 +6006,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
/* Unintern original. */
aspath_unintern(&attr.aspath);
bgp_static_withdraw(bgp, p, afi, safi);
+ bgp_dest_unlock_node(dest);
return;
}
@@ -5969,7 +6062,7 @@ void bgp_static_update(struct bgp *bgp, const struct prefix *p,
#endif
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
- pi->uptime = bgp_clock();
+ pi->uptime = monotime(NULL);
#ifdef ENABLE_BGP_VNC
if ((afi == AFI_IP || afi == AFI_IP6)
&& (safi == SAFI_UNICAST)) {
@@ -6240,6 +6333,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
aspath_unintern(&attr.aspath);
bgp_static_withdraw_safi(bgp, p, afi, safi,
&bgp_static->prd);
+ bgp_dest_unlock_node(dest);
return;
}
@@ -6271,7 +6365,7 @@ static void bgp_static_update_safi(struct bgp *bgp, const struct prefix *p,
bgp_aggregate_decrement(bgp, p, pi, afi, safi);
bgp_attr_unintern(&pi->attr);
pi->attr = attr_new;
- pi->uptime = bgp_clock();
+ pi->uptime = monotime(NULL);
#ifdef ENABLE_BGP_VNC
if (pi->extra)
label = decode_label(&pi->extra->label[0]);
@@ -6407,6 +6501,7 @@ static int bgp_static_set(struct vty *vty, const char *negate,
/* Label index cannot be changed. */
if (bgp_static->label_index != label_index) {
vty_out(vty, "%% cannot change label-index\n");
+ bgp_dest_unlock_node(dest);
return CMD_WARNING_CONFIG_FAILED;
}
@@ -7191,6 +7286,7 @@ static void bgp_aggregate_install(
aggregate, atomic_aggregate, p);
if (!attr) {
+ bgp_dest_unlock_node(dest);
bgp_aggregate_delete(bgp, p, afi, safi, aggregate);
if (BGP_DEBUG(update_groups, UPDATE_GROUPS))
zlog_debug("%s: %pFX null attribute", __func__,
@@ -7351,31 +7447,21 @@ void bgp_aggregate_toggle_suppressed(struct bgp_aggregate *aggregate,
static void bgp_aggregate_med_update(struct bgp_aggregate *aggregate,
struct bgp *bgp, const struct prefix *p,
afi_t afi, safi_t safi,
- struct bgp_path_info *pi, bool is_adding)
+ struct bgp_path_info *pi)
{
/* MED matching disabled. */
if (!aggregate->match_med)
return;
- /* Aggregation with different MED, nothing to do. */
- if (aggregate->med_mismatched)
- return;
-
- /*
- * Test the current entry:
- *
- * is_adding == true: if the new entry doesn't match then we must
- * install all suppressed routes.
- *
- * is_adding == false: if the entry being removed was the last
- * unmatching entry then we can suppress all routes.
+ /* Aggregation with different MED, recheck if we have got equal MEDs
+ * now.
*/
- if (!is_adding) {
- if (bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi)
- && aggregate->summary_only)
- bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi,
- safi, true);
- } else
+ if (aggregate->med_mismatched &&
+ bgp_aggregate_test_all_med(aggregate, bgp, p, afi, safi) &&
+ aggregate->summary_only)
+ bgp_aggregate_toggle_suppressed(aggregate, bgp, p, afi, safi,
+ true);
+ else
bgp_aggregate_med_match(aggregate, bgp, pi);
/* No mismatches, just quit. */
@@ -7741,7 +7827,7 @@ static void bgp_add_route_to_aggregate(struct bgp *bgp,
*/
if (aggregate->match_med)
bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi,
- pinew, true);
+ pinew);
if (aggregate->summary_only && AGGREGATE_MED_VALID(aggregate))
aggr_suppress_path(aggregate, pinew);
@@ -7864,8 +7950,7 @@ static void bgp_remove_route_from_aggregate(struct bgp *bgp, afi_t afi,
* "unsuppressing" twice.
*/
if (aggregate->match_med)
- bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi,
- true);
+ bgp_aggregate_med_update(aggregate, bgp, aggr_p, afi, safi, pi);
if (aggregate->count > 0)
aggregate->count--;
@@ -8390,10 +8475,22 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
switch (nhtype) {
case NEXTHOP_TYPE_IFINDEX:
+ switch (p->family) {
+ case AF_INET:
+ attr.nexthop.s_addr = INADDR_ANY;
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
+ break;
+ case AF_INET6:
+ memset(&attr.mp_nexthop_global, 0,
+ sizeof(attr.mp_nexthop_global));
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV6_GLOBAL;
+ break;
+ }
break;
case NEXTHOP_TYPE_IPV4:
case NEXTHOP_TYPE_IPV4_IFINDEX:
attr.nexthop = nexthop->ipv4;
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
break;
case NEXTHOP_TYPE_IPV6:
case NEXTHOP_TYPE_IPV6_IFINDEX:
@@ -8404,6 +8501,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
switch (p->family) {
case AF_INET:
attr.nexthop.s_addr = INADDR_ANY;
+ attr.mp_nexthop_len = BGP_ATTR_NHLEN_IPV4;
break;
case AF_INET6:
memset(&attr.mp_nexthop_global, 0,
@@ -8493,7 +8591,7 @@ void bgp_redistribute_add(struct bgp *bgp, struct prefix *p,
bgp, p, bpi, afi, SAFI_UNICAST);
bgp_attr_unintern(&bpi->attr);
bpi->attr = new_attr;
- bpi->uptime = bgp_clock();
+ bpi->uptime = monotime(NULL);
/* Process change. */
bgp_aggregate_increment(bgp, p, bpi, afi,
@@ -8954,7 +9052,8 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
json_nexthop_global = json_object_new_object();
json_object_string_addf(json_nexthop_global, "ip",
- "%pI4", &attr->nexthop);
+ "%pI4",
+ &attr->mp_nexthop_global_in);
if (path->peer->hostname)
json_object_string_add(json_nexthop_global,
@@ -8967,10 +9066,12 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
"used");
} else {
if (nexthop_hostname)
- len = vty_out(vty, "%pI4(%s)%s", &attr->nexthop,
+ len = vty_out(vty, "%pI4(%s)%s",
+ &attr->mp_nexthop_global_in,
nexthop_hostname, vrf_id_str);
else
- len = vty_out(vty, "%pI4%s", &attr->nexthop,
+ len = vty_out(vty, "%pI4%s",
+ &attr->mp_nexthop_global_in,
vrf_id_str);
len = wide ? (41 - len) : (16 - len);
@@ -9016,7 +9117,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
vty_out(vty, "%*s", len, " ");
}
}
- } else if (p->family == AF_INET && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
+ } else if (p->family == AF_INET && !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
@@ -9049,7 +9150,7 @@ void route_vty_out(struct vty *vty, const struct prefix *p,
}
/* IPv6 Next Hop */
- else if (p->family == AF_INET6 || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
+ else if (p->family == AF_INET6 || BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
if (json_paths) {
json_nexthop_global = json_object_new_object();
json_object_string_addf(json_nexthop_global, "ip",
@@ -9324,9 +9425,9 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
/* Print attribute */
if (attr) {
if (use_json) {
- if (p->family == AF_INET
- && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
- || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+ if (p->family == AF_INET &&
+ (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
+ !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)
json_object_string_addf(
json_net, "nextHop", "%pI4",
@@ -9335,13 +9436,13 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
json_object_string_addf(
json_net, "nextHop", "%pI4",
&attr->nexthop);
- } else if (p->family == AF_INET6
- || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
+ } else if (p->family == AF_INET6 ||
+ BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
json_object_string_addf(
json_net, "nextHopGlobal", "%pI6",
&attr->mp_nexthop_global);
- } else if (p->family == AF_EVPN
- && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
+ } else if (p->family == AF_EVPN &&
+ !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
json_object_string_addf(
json_net, "nextHop", "%pI4",
&attr->mp_nexthop_global_in);
@@ -9367,10 +9468,10 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
json_object_string_add(json_net, "bgpOriginCode",
bgp_origin_str[attr->origin]);
} else {
- if (p->family == AF_INET
- && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
- || safi == SAFI_EVPN
- || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+ if (p->family == AF_INET &&
+ (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP ||
+ safi == SAFI_EVPN ||
+ !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN)
vty_out(vty, "%-16pI4",
@@ -9379,8 +9480,8 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
vty_out(vty, "%-41pI4", &attr->nexthop);
else
vty_out(vty, "%-16pI4", &attr->nexthop);
- } else if (p->family == AF_INET6
- || BGP_ATTR_NEXTHOP_AFI_IP6(attr)) {
+ } else if (p->family == AF_INET6 ||
+ BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) {
char buf[BUFSIZ];
len = vty_out(
@@ -9425,9 +9526,7 @@ void route_vty_out_tmp(struct vty *vty, struct bgp_dest *dest,
json_object_boolean_true_add(json_status, ">");
json_object_object_add(json_net, "appliedStatusSymbols",
json_status);
-
- prefix2str(p, buff, PREFIX_STRLEN);
- json_object_object_add(json_ar, buff, json_net);
+ json_object_object_addf(json_ar, json_net, "%pFX", p);
} else
vty_out(vty, "\n");
}
@@ -9459,10 +9558,10 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
/* Print attribute */
attr = path->attr;
- if (((p->family == AF_INET)
- && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
- || (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))
- || (!BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+ if (((p->family == AF_INET) &&
+ ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
+ (safi == SAFI_EVPN && !BGP_ATTR_NEXTHOP_AFI_IP6(attr)) ||
+ (!BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN) {
if (json)
@@ -9479,10 +9578,10 @@ void route_vty_out_tag(struct vty *vty, const struct prefix *p,
else
vty_out(vty, "%-16pI4", &attr->nexthop);
}
- } else if (((p->family == AF_INET6)
- && ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP)))
- || (safi == SAFI_EVPN && BGP_ATTR_NEXTHOP_AFI_IP6(attr))
- || (BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+ } else if (((p->family == AF_INET6) &&
+ ((safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP))) ||
+ (safi == SAFI_EVPN && BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr)) ||
+ (BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
char buf_a[512];
if (attr->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL) {
@@ -9976,14 +10075,12 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
dest = parent_ri->net;
if (dest && dest->pdest) {
pdest = dest->pdest;
- prefix_rd2str(
- (struct prefix_rd *)bgp_dest_get_prefix(
- pdest),
- buf1, sizeof(buf1));
if (is_pi_family_evpn(parent_ri)) {
vty_out(vty,
- " Imported from %s:%pFX, VNI %s",
- buf1,
+ " Imported from %pRD:%pFX, VNI %s",
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest),
(struct prefix_evpn *)
bgp_dest_get_prefix(
dest),
@@ -9998,8 +10095,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
} else
vty_out(vty,
- " Imported from %s:%pFX\n",
- buf1,
+ " Imported from %pRD:%pFX\n",
+ (struct prefix_rd *)
+ bgp_dest_get_prefix(
+ pdest),
(struct prefix_evpn *)
bgp_dest_get_prefix(
dest));
@@ -10021,7 +10120,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
vty_out(vty, " Gateway IP %s", gwip_buf);
}
- if (safi == SAFI_EVPN)
+ if (safi == SAFI_EVPN && !json_path)
vty_out(vty, "\n");
/* Line1 display AS-path, Aggregator */
@@ -10105,10 +10204,10 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* Display the nexthop */
const struct prefix *bn_p = bgp_dest_get_prefix(bn);
- if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET
- || bn_p->family == AF_EVPN)
- && (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN
- || !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+ if ((bn_p->family == AF_INET || bn_p->family == AF_ETHERNET ||
+ bn_p->family == AF_EVPN) &&
+ (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP || safi == SAFI_EVPN ||
+ !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
if (safi == SAFI_MPLS_VPN || safi == SAFI_ENCAP
|| safi == SAFI_EVPN) {
if (json_paths) {
@@ -10181,11 +10280,17 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* Display the IGP cost or 'inaccessible' */
if (!CHECK_FLAG(path->flags, BGP_PATH_VALID)) {
- if (json_paths)
+ bool import = CHECK_FLAG(bgp->flags, BGP_FLAG_IMPORT_CHECK);
+
+ if (json_paths) {
json_object_boolean_false_add(json_nexthop_global,
"accessible");
- else
- vty_out(vty, " (inaccessible)");
+ json_object_boolean_add(json_nexthop_global,
+ "importCheckEnabled", import);
+ } else {
+ vty_out(vty, " (inaccessible%s)",
+ import ? ", import-check enabled" : "");
+ }
} else {
if (path->extra && path->extra->igpmetric) {
if (json_paths)
@@ -10213,9 +10318,8 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
/* This path was originated locally */
if (path->peer == bgp->peer_self) {
- if (safi == SAFI_EVPN
- || (bn_p->family == AF_INET
- && !BGP_ATTR_NEXTHOP_AFI_IP6(attr))) {
+ if (safi == SAFI_EVPN || (bn_p->family == AF_INET &&
+ !BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))) {
if (json_paths)
json_object_string_add(json_peer, "peerId",
"0.0.0.0");
@@ -10778,7 +10882,7 @@ void route_vty_out_detail(struct vty *vty, struct bgp *bgp, struct bgp_dest *bn,
}
/* Line 9 display Uptime */
- tbuf = time(NULL) - (bgp_clock() - path->uptime);
+ tbuf = time(NULL) - (monotime(NULL) - path->uptime);
if (json_paths) {
json_last_update = json_object_new_object();
json_object_int_add(json_last_update, "epoch", tbuf);
@@ -11054,6 +11158,13 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
!= PREFIX_PERMIT)
continue;
}
+ if (type == bgp_show_type_access_list) {
+ struct access_list *alist = output_arg;
+
+ if (access_list_apply(alist, dest_p) !=
+ FILTER_PERMIT)
+ continue;
+ }
if (type == bgp_show_type_filter_list) {
struct as_list *as_list = output_arg;
@@ -11064,13 +11175,14 @@ static int bgp_show_table(struct vty *vty, struct bgp *bgp, safi_t safi,
if (type == bgp_show_type_route_map) {
struct route_map *rmap = output_arg;
struct bgp_path_info path;
- struct attr dummy_attr;
+ struct bgp_path_info_extra extra;
+ struct attr dummy_attr = {};
route_map_result_t ret;
dummy_attr = *pi->attr;
- path.peer = pi->peer;
- path.attr = &dummy_attr;
+ prep_for_rmap_apply(&path, &extra, dest, pi,
+ pi->peer, &dummy_attr);
ret = route_map_apply(rmap, dest_p, &path);
bgp_attr_flush(&dummy_attr);
@@ -11508,7 +11620,6 @@ void route_vty_out_detail_header(struct vty *vty, struct bgp *bgp,
has_valid_label = bgp_is_valid_label(&label);
if (safi == SAFI_EVPN) {
-
if (!json) {
vty_out(vty, "BGP routing table entry for %s%s%pFX\n",
prd ? prefix_rd2str(prd, buf1, sizeof(buf1))
@@ -11687,7 +11798,6 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
{
struct bgp_path_info *pi;
int header = 1;
- char rdbuf[RD_ADDRSTRLEN];
json_object *json_header = NULL;
json_object *json_paths = NULL;
const struct prefix *p = bgp_dest_get_prefix(bgp_node);
@@ -11706,10 +11816,9 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
if (json && !json_paths) {
/* Instantiate json_paths only if path is valid */
json_paths = json_object_new_array();
- if (pfx_rd) {
- prefix_rd2str(pfx_rd, rdbuf, sizeof(rdbuf));
+ if (pfx_rd)
json_header = json_object_new_object();
- } else
+ else
json_header = json;
}
@@ -11735,7 +11844,8 @@ static void bgp_show_path_info(const struct prefix_rd *pfx_rd,
json_object_object_add(json_header, "paths", json_paths);
if (pfx_rd)
- json_object_object_add(json, rdbuf, json_header);
+ json_object_object_addf(json, json_header, "%pRD",
+ pfx_rd);
}
}
@@ -12287,6 +12397,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
|community-list <(1-500)|COMMUNITY_LIST_NAME> [exact-match]\
|filter-list AS_PATH_FILTER_NAME\
|prefix-list WORD\
+ |access-list ACCESSLIST_NAME\
|route-map RMAP_NAME\
|rpki <invalid|valid|notfound>\
|version (1-4294967295)\
@@ -12325,6 +12436,8 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
"Regular expression access list name\n"
"Display routes conforming to the prefix-list\n"
"Prefix-list name\n"
+ "Display routes conforming to the access-list\n"
+ "Access-list name\n"
"Display routes matching the route-map\n"
"A route-map to match on\n"
"RPKI route types\n"
@@ -12424,8 +12537,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
list = community_list_lookup(bgp_clist, clist_number_or_name, 0,
COMMUNITY_LIST_MASTER);
if (list == NULL) {
- vty_out(vty,
- "%% %s is not a valid community-list name\n",
+ vty_out(vty, "%% %s community-list not found\n",
clist_number_or_name);
return CMD_WARNING;
}
@@ -12443,8 +12555,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
as_list = as_list_lookup(filter);
if (as_list == NULL) {
- vty_out(vty,
- "%% %s is not a valid AS-path access-list name\n",
+ vty_out(vty, "%% %s AS-path access-list not found\n",
filter);
return CMD_WARNING;
}
@@ -12459,7 +12570,7 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
plist = prefix_list_lookup(afi, prefix_list_str);
if (plist == NULL) {
- vty_out(vty, "%% %s is not a valid prefix-list name\n",
+ vty_out(vty, "%% %s prefix-list not found\n",
prefix_list_str);
return CMD_WARNING;
}
@@ -12468,14 +12579,28 @@ DEFPY(show_ip_bgp, show_ip_bgp_cmd,
output_arg = plist;
}
+ if (argv_find(argv, argc, "access-list", &idx)) {
+ const char *access_list_str = argv[++idx]->arg;
+ struct access_list *alist;
+
+ alist = access_list_lookup(afi, access_list_str);
+ if (!alist) {
+ vty_out(vty, "%% %s access-list not found\n",
+ access_list_str);
+ return CMD_WARNING;
+ }
+
+ sh_type = bgp_show_type_access_list;
+ output_arg = alist;
+ }
+
if (argv_find(argv, argc, "route-map", &idx)) {
const char *rmap_str = argv[++idx]->arg;
struct route_map *rmap;
rmap = route_map_lookup_by_name(rmap_str);
if (!rmap) {
- vty_out(vty, "%% %s is not a valid route-map name\n",
- rmap_str);
+ vty_out(vty, "%% %s route-map not found\n", rmap_str);
return CMD_WARNING;
}
@@ -15069,7 +15194,6 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
const struct prefix_rd *prd;
struct bgp_static *bgp_static;
mpls_label_t label;
- char rdbuf[RD_ADDRSTRLEN];
/* Network configuration. */
for (pdest = bgp_table_top(bgp->route[afi][safi]); pdest;
@@ -15089,10 +15213,9 @@ static void bgp_config_write_network_vpn(struct vty *vty, struct bgp *bgp,
pdest);
/* "network" configuration display. */
- prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
label = decode_label(&bgp_static->label);
- vty_out(vty, " network %pFX rd %s", p, rdbuf);
+ vty_out(vty, " network %pFX rd %pRD", p, prd);
if (safi == SAFI_MPLS_VPN)
vty_out(vty, " label %u", label);
@@ -15119,7 +15242,6 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
struct bgp_static *bgp_static;
char buf[PREFIX_STRLEN * 2];
char buf2[SU_ADDRSTRLEN];
- char rdbuf[RD_ADDRSTRLEN];
char esi_buf[ESI_STR_LEN];
/* Network configuration. */
@@ -15147,7 +15269,6 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
prd = (struct prefix_rd *)bgp_dest_get_prefix(pdest);
/* "network" configuration display. */
- prefix_rd2str(prd, rdbuf, sizeof(rdbuf));
if (p->u.prefix_evpn.route_type == 5) {
char local_buf[PREFIX_STRLEN];
uint8_t family = is_evpn_prefix_ipaddr_v4((
@@ -15170,9 +15291,8 @@ static void bgp_config_write_network_evpn(struct vty *vty, struct bgp *bgp,
&bgp_static->gatewayIp.u.prefix, buf2,
sizeof(buf2));
vty_out(vty,
- " network %s rd %s ethtag %u label %u esi %s gwip %s routermac %s\n",
- buf, rdbuf,
- p->u.prefix_evpn.prefix_addr.eth_tag,
+ " network %s rd %pRD ethtag %u label %u esi %s gwip %s routermac %s\n",
+ buf, prd, p->u.prefix_evpn.prefix_addr.eth_tag,
decode_label(&bgp_static->label), esi_buf, buf2,
macrouter);
diff --git a/bgpd/bgp_route.h b/bgpd/bgp_route.h
index 743b369bfa..ddef4ca1bb 100644
--- a/bgpd/bgp_route.h
+++ b/bgpd/bgp_route.h
@@ -37,6 +37,7 @@ enum bgp_show_type {
bgp_show_type_normal,
bgp_show_type_regexp,
bgp_show_type_prefix_list,
+ bgp_show_type_access_list,
bgp_show_type_filter_list,
bgp_show_type_route_map,
bgp_show_type_neighbor,
@@ -235,6 +236,12 @@ struct bgp_path_info_extra {
struct bgp *bgp_orig;
/*
+ * Original bgp session to know if the session is a
+ * connected EBGP session or not
+ */
+ struct peer *peer_orig;
+
+ /*
* Nexthop in context of original bgp instance. Needed
* for label resolution of core mpls routes exported to a vrf.
* Set nexthop_orig.family to 0 if not valid.
@@ -468,12 +475,16 @@ struct bgp_aggregate {
? 0 \
: ((nhlen) < IPV6_MAX_BYTELEN ? AFI_IP : AFI_IP6))
+#define BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr) \
+ ((attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL || \
+ (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL || \
+ (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL || \
+ (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL)
+
#define BGP_ATTR_NEXTHOP_AFI_IP6(attr) \
- (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) \
- && ((attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL \
- || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_IPV6_GLOBAL_AND_LL \
- || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL \
- || (attr)->mp_nexthop_len == BGP_ATTR_NHLEN_VPNV6_GLOBAL_AND_LL))
+ (!CHECK_FLAG(attr->flag, ATTR_FLAG_BIT(BGP_ATTR_NEXT_HOP)) && \
+ BGP_ATTR_MP_NEXTHOP_LEN_IP6(attr))
+
#define BGP_PATH_COUNTABLE(BI) \
(!CHECK_FLAG((BI)->flags, BGP_PATH_HISTORY) \
&& !CHECK_FLAG((BI)->flags, BGP_PATH_REMOVED))
@@ -827,7 +838,7 @@ extern int bgp_show_table_rd(struct vty *vty, struct bgp *bgp, safi_t safi,
struct bgp_table *table, struct prefix_rd *prd,
enum bgp_show_type type, void *output_arg,
bool use_json);
-extern int bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi);
+extern void bgp_best_path_select_defer(struct bgp *bgp, afi_t afi, safi_t safi);
extern bool bgp_update_martian_nexthop(struct bgp *bgp, afi_t afi, safi_t safi,
uint8_t type, uint8_t stype,
struct attr *attr, struct bgp_dest *dest);
diff --git a/bgpd/bgp_routemap.c b/bgpd/bgp_routemap.c
index e94b633b3b..ded47028a6 100644
--- a/bgpd/bgp_routemap.c
+++ b/bgpd/bgp_routemap.c
@@ -1953,6 +1953,57 @@ static const struct route_map_rule_cmd route_set_ip_nexthop_cmd = {
route_set_ip_nexthop_free
};
+/* `set l3vpn next-hop encapsulation l3vpn gre' */
+
+/* Set nexthop to object */
+struct rmap_l3vpn_nexthop_encapsulation_set {
+ uint8_t protocol;
+};
+
+static enum route_map_cmd_result_t
+route_set_l3vpn_nexthop_encapsulation(void *rule, const struct prefix *prefix,
+ void *object)
+{
+ struct rmap_l3vpn_nexthop_encapsulation_set *rins = rule;
+ struct bgp_path_info *path;
+
+ path = object;
+
+ if (rins->protocol != IPPROTO_GRE)
+ return RMAP_OKAY;
+
+ SET_FLAG(path->attr->rmap_change_flags, BATTR_RMAP_L3VPN_ACCEPT_GRE);
+ return RMAP_OKAY;
+}
+
+/* Route map `l3vpn nexthop encapsulation' compile function. */
+static void *route_set_l3vpn_nexthop_encapsulation_compile(const char *arg)
+{
+ struct rmap_l3vpn_nexthop_encapsulation_set *rins;
+
+ rins = XCALLOC(MTYPE_ROUTE_MAP_COMPILED,
+ sizeof(struct rmap_l3vpn_nexthop_encapsulation_set));
+
+ /* XXX ALL GRE modes are accepted for now: gre or ip6gre */
+ rins->protocol = IPPROTO_GRE;
+
+ return rins;
+}
+
+/* Free route map's compiled `ip nexthop' value. */
+static void route_set_l3vpn_nexthop_encapsulation_free(void *rule)
+{
+ XFREE(MTYPE_ROUTE_MAP_COMPILED, rule);
+}
+
+/* Route map commands for l3vpn next-hop encapsulation set. */
+static const struct route_map_rule_cmd
+ route_set_l3vpn_nexthop_encapsulation_cmd = {
+ "l3vpn next-hop encapsulation",
+ route_set_l3vpn_nexthop_encapsulation,
+ route_set_l3vpn_nexthop_encapsulation_compile,
+ route_set_l3vpn_nexthop_encapsulation_free};
+
/* `set local-preference LOCAL_PREF' */
/* Set local preference. */
@@ -2219,6 +2270,8 @@ route_set_aspath_replace(void *rule, const struct prefix *dummy, void *object)
aspath_new, replace_asn, own_asn);
}
+ aspath_free(aspath_new);
+
return RMAP_OKAY;
}
@@ -3738,6 +3791,73 @@ static const struct route_map_rule_cmd route_set_originator_id_cmd = {
route_set_originator_id_free,
};
+static enum route_map_cmd_result_t
+route_match_rpki_extcommunity(void *rule, const struct prefix *prefix,
+ void *object)
+{
+ struct bgp_path_info *path;
+ struct ecommunity *ecomm;
+ struct ecommunity_val *ecomm_val;
+ enum rpki_states *rpki_status = rule;
+ enum rpki_states ecomm_rpki_status = RPKI_NOT_BEING_USED;
+
+ path = object;
+
+ ecomm = bgp_attr_get_ecommunity(path->attr);
+ if (!ecomm)
+ return RMAP_NOMATCH;
+
+ ecomm_val = ecommunity_lookup(ecomm, ECOMMUNITY_ENCODE_OPAQUE_NON_TRANS,
+ ECOMMUNITY_ORIGIN_VALIDATION_STATE);
+ if (!ecomm_val)
+ return RMAP_NOMATCH;
+
+ /* The Origin Validation State is encoded in the last octet of
+ * the extended community.
+ */
+ switch (ecomm_val->val[7]) {
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_VALID:
+ ecomm_rpki_status = RPKI_VALID;
+ break;
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTFOUND:
+ ecomm_rpki_status = RPKI_NOTFOUND;
+ break;
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_INVALID:
+ ecomm_rpki_status = RPKI_INVALID;
+ break;
+ case ECOMMUNITY_ORIGIN_VALIDATION_STATE_NOTUSED:
+ break;
+ }
+
+ if (ecomm_rpki_status == *rpki_status)
+ return RMAP_MATCH;
+
+ return RMAP_NOMATCH;
+}
+
+static void *route_match_extcommunity_compile(const char *arg)
+{
+ int *rpki_status;
+
+ rpki_status = XMALLOC(MTYPE_ROUTE_MAP_COMPILED, sizeof(int));
+
+ if (strcmp(arg, "valid") == 0)
+ *rpki_status = RPKI_VALID;
+ else if (strcmp(arg, "invalid") == 0)
+ *rpki_status = RPKI_INVALID;
+ else
+ *rpki_status = RPKI_NOTFOUND;
+
+ return rpki_status;
+}
+
+static const struct route_map_rule_cmd route_match_rpki_extcommunity_cmd = {
+ "rpki-extcommunity",
+ route_match_rpki_extcommunity,
+ route_match_extcommunity_compile,
+ route_value_free
+};
+
/*
* This is the workhorse routine for processing in/out routemap
* modifications.
@@ -3867,7 +3987,7 @@ static void bgp_route_map_update_peer_group(const char *rmap_name,
* network statements, etc looking to see if they use this route-map.
*/
static void bgp_route_map_process_update(struct bgp *bgp, const char *rmap_name,
- int route_update)
+ bool route_update)
{
int i;
bool matched;
@@ -4080,7 +4200,7 @@ static void bgp_route_map_process_update_cb(char *rmap_name)
struct bgp *bgp;
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
- bgp_route_map_process_update(bgp, rmap_name, 1);
+ bgp_route_map_process_update(bgp, rmap_name, true);
#ifdef ENABLE_BGP_VNC
vnc_routemap_update(bgp, __func__);
@@ -4092,8 +4212,6 @@ static void bgp_route_map_process_update_cb(char *rmap_name)
void bgp_route_map_update_timer(struct thread *thread)
{
- bm->t_rmap_update = NULL;
-
route_map_walk_update_list(bgp_route_map_process_update_cb);
}
@@ -4116,12 +4234,11 @@ static void bgp_route_map_mark_update(const char *rmap_name)
/* Signal the groups that a route-map update event has
* started */
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp))
- update_group_policy_update(bgp,
- BGP_POLICY_ROUTE_MAP,
- rmap_name, 1, 1);
+ update_group_policy_update(bgp, BGP_POLICY_ROUTE_MAP,
+ rmap_name, true, 1);
} else {
for (ALL_LIST_ELEMENTS(bm->bgp, node, nnode, bgp)) {
- bgp_route_map_process_update(bgp, rmap_name, 0);
+ bgp_route_map_process_update(bgp, rmap_name, false);
#ifdef ENABLE_BGP_VNC
vnc_routemap_update(bgp, __func__);
#endif
@@ -5291,6 +5408,34 @@ DEFUN_YANG (no_set_distance,
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG(set_l3vpn_nexthop_encapsulation, set_l3vpn_nexthop_encapsulation_cmd,
+ "[no] set l3vpn next-hop encapsulation gre",
+ NO_STR SET_STR
+ "L3VPN operations\n"
+ "Next hop Information\n"
+ "Encapsulation options (for BGP only)\n"
+ "Accept L3VPN traffic over GRE encapsulation\n")
+{
+ const char *xpath =
+ "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']";
+ const char *xpath_value =
+ "./set-action[action='frr-bgp-route-map:set-l3vpn-nexthop-encapsulation']/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation";
+ enum nb_operation operation;
+
+ if (no)
+ operation = NB_OP_DESTROY;
+ else
+ operation = NB_OP_CREATE;
+
+ nb_cli_enqueue_change(vty, xpath, operation, NULL);
+ if (operation == NB_OP_DESTROY)
+ return nb_cli_apply_changes(vty, NULL);
+
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY, "gre");
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
DEFUN_YANG (set_local_pref,
set_local_pref_cmd,
"set local-preference WORD",
@@ -6714,6 +6859,34 @@ DEFUN_YANG (no_set_originator_id,
return nb_cli_apply_changes(vty, NULL);
}
+DEFPY_YANG (match_rpki_extcommunity,
+ match_rpki_extcommunity_cmd,
+ "[no$no] match rpki-extcommunity <valid|invalid|notfound>",
+ NO_STR
+ MATCH_STR
+ "BGP RPKI (Origin Validation State) extended community attribute\n"
+ "Valid prefix\n"
+ "Invalid prefix\n"
+ "Prefix not found\n")
+{
+ const char *xpath =
+ "./match-condition[condition='frr-bgp-route-map:rpki-extcommunity']";
+ char xpath_value[XPATH_MAXLEN];
+
+ nb_cli_enqueue_change(vty, xpath, NB_OP_CREATE, NULL);
+
+ if (!no) {
+ snprintf(
+ xpath_value, sizeof(xpath_value),
+ "%s/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
+ xpath);
+ nb_cli_enqueue_change(vty, xpath_value, NB_OP_MODIFY,
+ argv[2]->arg);
+ }
+
+ return nb_cli_apply_changes(vty, NULL);
+}
+
/* Initialization of route map. */
void bgp_route_map_init(void)
{
@@ -6836,6 +7009,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ecommunity_none_cmd);
route_map_install_set(&route_set_tag_cmd);
route_map_install_set(&route_set_label_index_cmd);
+ route_map_install_set(&route_set_l3vpn_nexthop_encapsulation_cmd);
install_element(RMAP_NODE, &match_peer_cmd);
install_element(RMAP_NODE, &match_peer_local_cmd);
@@ -6938,6 +7112,7 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &no_set_ipx_vpn_nexthop_cmd);
install_element(RMAP_NODE, &set_originator_id_cmd);
install_element(RMAP_NODE, &no_set_originator_id_cmd);
+ install_element(RMAP_NODE, &set_l3vpn_nexthop_encapsulation_cmd);
route_map_install_match(&route_match_ipv6_address_cmd);
route_map_install_match(&route_match_ipv6_next_hop_cmd);
@@ -6950,6 +7125,7 @@ void bgp_route_map_init(void)
route_map_install_set(&route_set_ipv6_nexthop_prefer_global_cmd);
route_map_install_set(&route_set_ipv6_nexthop_local_cmd);
route_map_install_set(&route_set_ipv6_nexthop_peer_cmd);
+ route_map_install_match(&route_match_rpki_extcommunity_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_cmd);
install_element(RMAP_NODE, &match_ipv6_next_hop_address_cmd);
@@ -6967,6 +7143,7 @@ void bgp_route_map_init(void)
install_element(RMAP_NODE, &no_set_ipv6_nexthop_prefer_global_cmd);
install_element(RMAP_NODE, &set_ipv6_nexthop_peer_cmd);
install_element(RMAP_NODE, &no_set_ipv6_nexthop_peer_cmd);
+ install_element(RMAP_NODE, &match_rpki_extcommunity_cmd);
#ifdef HAVE_SCRIPTING
install_element(RMAP_NODE, &match_script_cmd);
#endif
diff --git a/bgpd/bgp_routemap_nb.c b/bgpd/bgp_routemap_nb.c
index 585596e1aa..c47c37dc66 100644
--- a/bgpd/bgp_routemap_nb.c
+++ b/bgpd/bgp_routemap_nb.c
@@ -67,6 +67,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
}
},
{
+ .xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity",
+ .cbs = {
+ .modify = lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_modify,
+ .destroy = lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_destroy,
+ }
+ },
+ {
.xpath = "/frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:probability",
.cbs = {
.modify = lib_route_map_entry_match_condition_rmap_match_condition_probability_modify,
@@ -407,6 +414,13 @@ const struct frr_yang_module_info frr_bgp_route_map_info = {
}
},
{
+ .xpath = "/frr-route-map:lib/route-map/entry/set-action/rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation",
+ .cbs = {
+ .modify = lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_modify,
+ .destroy = lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_destroy,
+ }
+ },
+ {
.xpath = NULL,
},
}
diff --git a/bgpd/bgp_routemap_nb.h b/bgpd/bgp_routemap_nb.h
index a01adf7d5d..163e3b55cc 100644
--- a/bgpd/bgp_routemap_nb.h
+++ b/bgpd/bgp_routemap_nb.h
@@ -39,6 +39,10 @@ int lib_route_map_entry_match_condition_rmap_match_condition_origin_modify(struc
int lib_route_map_entry_match_condition_rmap_match_condition_origin_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_rpki_destroy(struct nb_cb_destroy_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_destroy(
+ struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_probability_modify(struct nb_cb_modify_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_probability_destroy(struct nb_cb_destroy_args *args);
int lib_route_map_entry_match_condition_rmap_match_condition_source_vrf_modify(struct nb_cb_modify_args *args);
@@ -150,6 +154,10 @@ int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_modify(
struct nb_cb_modify_args *args);
int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy(
struct nb_cb_destroy_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_modify(
+ struct nb_cb_modify_args *args);
+int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_destroy(
+ struct nb_cb_destroy_args *args);
#ifdef __cplusplus
}
diff --git a/bgpd/bgp_routemap_nb_config.c b/bgpd/bgp_routemap_nb_config.c
index b87877b1e0..b18cf9d4dd 100644
--- a/bgpd/bgp_routemap_nb_config.c
+++ b/bgpd/bgp_routemap_nb_config.c
@@ -381,6 +381,60 @@ lib_route_map_entry_match_condition_rmap_match_condition_rpki_destroy(
}
/*
+ * XPath:
+ * /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:rpki-extcommunity
+ */
+int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *rpki;
+ enum rmap_compile_rets ret;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ rpki = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_mhook = bgp_route_match_delete;
+ rhc->rhc_rule = "rpki-extcommunity";
+ rhc->rhc_event = RMAP_EVENT_MATCH_DELETED;
+
+ ret = bgp_route_match_add(rhc->rhc_rmi, "rpki-extcommunity",
+ rpki, RMAP_EVENT_MATCH_ADDED,
+ args->errmsg, args->errmsg_len);
+
+ if (ret != RMAP_COMPILE_SUCCESS) {
+ rhc->rhc_mhook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_match_condition_rmap_match_condition_rpki_extcommunity_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_match_destroy(args);
+ }
+
+ return NB_OK;
+}
+
+/*
* XPath: /frr-route-map:lib/route-map/entry/match-condition/rmap-match-condition/frr-bgp-route-map:probability
*/
int
@@ -2922,3 +2976,56 @@ int lib_route_map_entry_set_action_rmap_set_action_evpn_gateway_ip_ipv6_destroy(
return NB_OK;
}
+
+/*
+ * XPath:
+ * /frr-route-map:lib/route-map/entry/set-action/rmap-set-action/l3vpn-nexthop-encapsulation
+ */
+int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_modify(
+ struct nb_cb_modify_args *args)
+{
+ struct routemap_hook_context *rhc;
+ const char *type;
+ int rv;
+
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ /* Add configuration. */
+ rhc = nb_running_get_entry(args->dnode, NULL, true);
+ type = yang_dnode_get_string(args->dnode, NULL);
+
+ /* Set destroy information. */
+ rhc->rhc_shook = generic_set_delete;
+ rhc->rhc_rule = "l3vpn next-hop encapsulation";
+ rhc->rhc_event = RMAP_EVENT_SET_DELETED;
+
+ rv = generic_set_add(rhc->rhc_rmi,
+ "l3vpn next-hop encapsulation", type,
+ args->errmsg, args->errmsg_len);
+ if (rv != CMD_SUCCESS) {
+ rhc->rhc_shook = NULL;
+ return NB_ERR_INCONSISTENCY;
+ }
+ }
+
+ return NB_OK;
+}
+
+int lib_route_map_entry_set_action_rmap_set_action_l3vpn_nexthop_encapsulation_destroy(
+ struct nb_cb_destroy_args *args)
+{
+ switch (args->event) {
+ case NB_EV_VALIDATE:
+ case NB_EV_PREPARE:
+ case NB_EV_ABORT:
+ break;
+ case NB_EV_APPLY:
+ return lib_route_map_entry_set_destroy(args);
+ }
+
+ return NB_OK;
+}
diff --git a/bgpd/bgp_rpki.c b/bgpd/bgp_rpki.c
index de1c559641..e03853d187 100644
--- a/bgpd/bgp_rpki.c
+++ b/bgpd/bgp_rpki.c
@@ -428,14 +428,15 @@ static void bgpd_sync_callback(struct thread *thread)
safi_t safi;
for (safi = SAFI_UNICAST; safi < SAFI_MAX; safi++) {
- if (!bgp->rib[afi][safi])
+ struct bgp_table *table = bgp->rib[afi][safi];
+
+ if (!table)
continue;
struct bgp_dest *match;
struct bgp_dest *node;
- match = bgp_table_subtree_lookup(bgp->rib[afi][safi],
- prefix);
+ match = bgp_table_subtree_lookup(table, prefix);
node = match;
while (node) {
@@ -445,6 +446,9 @@ static void bgpd_sync_callback(struct thread *thread)
node = bgp_route_next_until(node, match);
}
+
+ if (match)
+ bgp_dest_unlock_node(match);
}
}
@@ -588,7 +592,7 @@ static int bgp_rpki_module_init(void)
hook_register(bgp_rpki_prefix_status, rpki_validate_prefix);
hook_register(frr_late_init, bgp_rpki_init);
- hook_register(frr_early_fini, &bgp_rpki_fini);
+ hook_register(frr_early_fini, bgp_rpki_fini);
return 0;
}
diff --git a/bgpd/bgp_snmp.c b/bgpd/bgp_snmp.c
index e25d8d90db..6bc313464a 100644
--- a/bgpd/bgp_snmp.c
+++ b/bgpd/bgp_snmp.c
@@ -588,7 +588,7 @@ static uint8_t *bgpPeerTable(struct variable *v, oid name[], size_t *length,
if (peer->uptime == 0)
return SNMP_INTEGER(0);
else
- return SNMP_INTEGER(bgp_clock() - peer->uptime);
+ return SNMP_INTEGER(monotime(NULL) - peer->uptime);
case BGPPEERCONNECTRETRYINTERVAL:
*write_method = write_bgpPeerTable;
return SNMP_INTEGER(peer->v_connect);
@@ -615,7 +615,7 @@ static uint8_t *bgpPeerTable(struct variable *v, oid name[], size_t *length,
if (peer->update_time == 0)
return SNMP_INTEGER(0);
else
- return SNMP_INTEGER(bgp_clock() - peer->update_time);
+ return SNMP_INTEGER(monotime(NULL) - peer->update_time);
default:
return NULL;
}
diff --git a/bgpd/bgp_table.h b/bgpd/bgp_table.h
index d832383ab4..86cd4f3da1 100644
--- a/bgpd/bgp_table.h
+++ b/bgpd/bgp_table.h
@@ -256,28 +256,6 @@ static inline struct bgp_dest *bgp_node_match(const struct bgp_table *table,
return bgp_dest_from_rnode(rn);
}
-/*
- * bgp_node_match_ipv4
- */
-static inline struct bgp_dest *
-bgp_node_match_ipv4(const struct bgp_table *table, struct in_addr *addr)
-{
- struct route_node *rn = route_node_match_ipv4(table->route_table, addr);
-
- return bgp_dest_from_rnode(rn);
-}
-
-/*
- * bgp_node_match_ipv6
- */
-static inline struct bgp_dest *
-bgp_node_match_ipv6(const struct bgp_table *table, struct in6_addr *addr)
-{
- struct route_node *rn = route_node_match_ipv6(table->route_table, addr);
-
- return bgp_dest_from_rnode(rn);
-}
-
static inline unsigned long bgp_table_count(const struct bgp_table *const table)
{
return route_table_count(table->route_table);
@@ -292,59 +270,6 @@ static inline struct bgp_dest *bgp_table_get_next(const struct bgp_table *table,
return bgp_dest_from_rnode(route_table_get_next(table->route_table, p));
}
-/*
- * bgp_table_iter_init
- */
-static inline void bgp_table_iter_init(bgp_table_iter_t *iter,
- struct bgp_table *table)
-{
- bgp_table_lock(table);
- iter->table = table;
- route_table_iter_init(&iter->rt_iter, table->route_table);
-}
-
-/*
- * bgp_table_iter_next
- */
-static inline struct bgp_dest *bgp_table_iter_next(bgp_table_iter_t *iter)
-{
- return bgp_dest_from_rnode(route_table_iter_next(&iter->rt_iter));
-}
-
-/*
- * bgp_table_iter_cleanup
- */
-static inline void bgp_table_iter_cleanup(bgp_table_iter_t *iter)
-{
- route_table_iter_cleanup(&iter->rt_iter);
- bgp_table_unlock(iter->table);
- iter->table = NULL;
-}
-
-/*
- * bgp_table_iter_pause
- */
-static inline void bgp_table_iter_pause(bgp_table_iter_t *iter)
-{
- route_table_iter_pause(&iter->rt_iter);
-}
-
-/*
- * bgp_table_iter_is_done
- */
-static inline int bgp_table_iter_is_done(bgp_table_iter_t *iter)
-{
- return route_table_iter_is_done(&iter->rt_iter);
-}
-
-/*
- * bgp_table_iter_started
- */
-static inline int bgp_table_iter_started(bgp_table_iter_t *iter)
-{
- return route_table_iter_started(&iter->rt_iter);
-}
-
/* This would benefit from a real atomic operation...
* until then. */
static inline uint64_t bgp_table_next_version(struct bgp_table *table)
diff --git a/bgpd/bgp_updgrp.c b/bgpd/bgp_updgrp.c
index 405dd8f6ec..0219535b0d 100644
--- a/bgpd/bgp_updgrp.c
+++ b/bgpd/bgp_updgrp.c
@@ -70,14 +70,14 @@
static void update_group_checkin(struct update_group *updgrp)
{
updgrp->id = ++bm->updgrp_idspace;
- updgrp->uptime = bgp_clock();
+ updgrp->uptime = monotime(NULL);
}
static void update_subgroup_checkin(struct update_subgroup *subgrp,
struct update_group *updgrp)
{
subgrp->id = ++bm->subgrp_idspace;
- subgrp->uptime = bgp_clock();
+ subgrp->uptime = monotime(NULL);
}
static void sync_init(struct update_subgroup *subgrp,
@@ -164,6 +164,12 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
dst->change_local_as = src->change_local_as;
dst->shared_network = src->shared_network;
dst->local_role = src->local_role;
+
+ if (src->soo[afi][safi]) {
+ ecommunity_free(&dst->soo[afi][safi]);
+ dst->soo[afi][safi] = ecommunity_dup(src->soo[afi][safi]);
+ }
+
memcpy(&(dst->nexthop), &(src->nexthop), sizeof(struct bgp_nexthop));
dst->group = src->group;
@@ -218,6 +224,8 @@ static void conf_copy(struct peer *dst, struct peer *src, afi_t afi,
MTYPE_BGP_FILTER_NAME, CONDITION_MAP_NAME(srcfilter));
CONDITION_MAP(dstfilter) = CONDITION_MAP(srcfilter);
}
+
+ dstfilter->advmap.update_type = srcfilter->advmap.update_type;
}
/**
@@ -246,6 +254,8 @@ static void conf_release(struct peer *src, afi_t afi, safi_t safi)
XFREE(MTYPE_BGP_FILTER_NAME, srcfilter->advmap.cname);
XFREE(MTYPE_BGP_PEER_HOST, src->host);
+
+ ecommunity_free(&src->soo[afi][safi]);
}
static void peer2_updgrp_copy(struct update_group *updgrp, struct peer_af *paf)
@@ -389,6 +399,9 @@ static unsigned int updgrp_hash_key_make(const void *p)
strlen(filter->advmap.aname), SEED1),
key);
+ if (filter->advmap.update_type)
+ key = jhash_1word(filter->advmap.update_type, key);
+
if (peer->default_rmap[afi][safi].name)
key = jhash_1word(
jhash(peer->default_rmap[afi][safi].name,
@@ -423,17 +436,24 @@ static unsigned int updgrp_hash_key_make(const void *p)
*/
key = jhash_1word(peer->local_role, key);
+ if (peer->soo[afi][safi]) {
+ char *soo_str = ecommunity_str(peer->soo[afi][safi]);
+
+ key = jhash_1word(jhash(soo_str, strlen(soo_str), SEED1), key);
+ }
+
if (bgp_debug_neighbor_events(peer)) {
zlog_debug(
- "%pBP Update Group Hash: sort: %d UpdGrpFlags: %ju UpdGrpAFFlags: %u",
+ "%pBP Update Group Hash: sort: %d UpdGrpFlags: %ju UpdGrpAFFlags: %ju",
peer, peer->sort,
- (intmax_t)(peer->flags & PEER_UPDGRP_FLAGS),
- flags & PEER_UPDGRP_AF_FLAGS);
+ (intmax_t)CHECK_FLAG(peer->flags, PEER_UPDGRP_FLAGS),
+ (intmax_t)CHECK_FLAG(flags, PEER_UPDGRP_AF_FLAGS));
zlog_debug(
"%pBP Update Group Hash: addpath: %u UpdGrpCapFlag: %u UpdGrpCapAFFlag: %u route_adv: %u change local as: %u",
peer, (uint32_t)peer->addpath_type[afi][safi],
- peer->cap & PEER_UPDGRP_CAP_FLAGS,
- peer->af_cap[afi][safi] & PEER_UPDGRP_AF_CAP_FLAGS,
+ CHECK_FLAG(peer->cap, PEER_UPDGRP_CAP_FLAGS),
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_UPDGRP_AF_CAP_FLAGS),
peer->v_routeadv, peer->change_local_as);
zlog_debug(
"%pBP Update Group Hash: max packet size: %u pmax_out: %u Peer Group: %s rmap out: %s",
@@ -467,14 +487,14 @@ static unsigned int updgrp_hash_key_make(const void *p)
peer->shared_network &&
peer_afi_active_nego(peer, AFI_IP6));
zlog_debug(
- "%pBP Update Group Hash: Lonesoul: %d ORF prefix: %u ORF old: %u max prefix out: %u",
+ "%pBP Update Group Hash: Lonesoul: %d ORF prefix: %u ORF old: %u max prefix out: %ju",
peer, !!CHECK_FLAG(peer->flags, PEER_FLAG_LONESOUL),
CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ORF_PREFIX_SM_RCV),
CHECK_FLAG(peer->af_cap[afi][safi],
PEER_CAP_ORF_PREFIX_SM_OLD_RCV),
- CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_MAX_PREFIX_OUT));
+ (intmax_t)CHECK_FLAG(peer->af_flags[afi][safi],
+ PEER_FLAG_MAX_PREFIX_OUT));
zlog_debug("%pBP Update Group Hash key: %u", peer, key);
}
return key;
@@ -588,6 +608,9 @@ static bool updgrp_hash_cmp(const void *p1, const void *p2)
&& strcmp(fl1->advmap.aname, fl2->advmap.aname)))
return false;
+ if (fl1->advmap.update_type != fl2->advmap.update_type)
+ return false;
+
if ((pe1->default_rmap[afi][safi].name
&& !pe2->default_rmap[afi][safi].name)
|| (!pe1->default_rmap[afi][safi].name
@@ -1547,7 +1570,7 @@ static int update_group_periodic_merge_walkcb(struct update_group *updgrp,
* update groups.
*/
void update_group_policy_update(struct bgp *bgp, enum bgp_policy_type ptype,
- const char *pname, int route_update,
+ const char *pname, bool route_update,
int start_event)
{
struct updwalk_context ctx;
diff --git a/bgpd/bgp_updgrp.h b/bgpd/bgp_updgrp.h
index 473017c809..56289d399d 100644
--- a/bgpd/bgp_updgrp.h
+++ b/bgpd/bgp_updgrp.h
@@ -298,7 +298,7 @@ struct updwalk_context {
enum bgp_policy_type policy_type;
const char *policy_name;
int policy_event_start_flag;
- int policy_route_update;
+ bool policy_route_update;
updgrp_walkcb cb;
void *context;
uint8_t flags;
@@ -377,7 +377,7 @@ extern bool update_subgroup_trigger_merge_check(struct update_subgroup *,
int force);
extern void update_group_policy_update(struct bgp *bgp,
enum bgp_policy_type ptype,
- const char *pname, int route_update,
+ const char *pname, bool route_update,
int start_event);
extern void update_group_af_walk(struct bgp *bgp, afi_t afi, safi_t safi,
updgrp_walkcb cb, void *ctx);
diff --git a/bgpd/bgp_vty.c b/bgpd/bgp_vty.c
index 029a6a0f8c..de810aa195 100644
--- a/bgpd/bgp_vty.c
+++ b/bgpd/bgp_vty.c
@@ -53,6 +53,7 @@
#include "bgpd/bgp_debug.h"
#include "bgpd/bgp_errors.h"
#include "bgpd/bgp_fsm.h"
+#include "bgpd/bgp_nht.h"
#include "bgpd/bgp_nexthop.h"
#include "bgpd/bgp_network.h"
#include "bgpd/bgp_open.h"
@@ -306,12 +307,16 @@ static int bgp_srv6_locator_unset(struct bgp *bgp)
return -1;
/* refresh chunks */
- for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk))
+ for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk)) {
listnode_delete(bgp->srv6_locator_chunks, chunk);
+ srv6_locator_chunk_free(chunk);
+ }
/* refresh functions */
- for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func))
+ for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func)) {
listnode_delete(bgp->srv6_functions, func);
+ XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+ }
/* refresh tovpn_sid */
for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
@@ -334,6 +339,20 @@ static int bgp_srv6_locator_unset(struct bgp *bgp)
/* update vpn bgp processes */
vpn_leak_postchange_all();
+ /* refresh tovpn_sid_locator */
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
+ if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ /* refresh vpnv4 tovpn_sid_locator */
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator);
+
+ /* refresh vpnv6 tovpn_sid_locator */
+ XFREE(MTYPE_BGP_SRV6_SID,
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator);
+ }
+
/* clear locator name */
memset(bgp->srv6_locator_name, 0, sizeof(bgp->srv6_locator_name));
@@ -854,9 +873,6 @@ int bgp_vty_return(struct vty *vty, enum bgp_create_error_code ret)
case BGP_ERR_REMOVE_PRIVATE_AS:
str = "remove-private-AS cannot be configured for IBGP peers";
break;
- case BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP:
- str = "Local-AS allowed only for EBGP peers";
- break;
case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS:
str = "Cannot have local-as same as BGP AS number";
break;
@@ -917,9 +933,6 @@ int bgp_vty_return(struct vty *vty, enum bgp_create_error_code ret)
case BGP_ERR_AF_UNCONFIGURED:
str = "AFI/SAFI specified is not currently configured.";
break;
- case BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS:
- str = "AS specified for local as is the same as the remote as and this is not allowed.";
- break;
case BGP_ERR_INVALID_AS:
str = "Confederation AS specified is the same AS as our AS.";
break;
@@ -3896,11 +3909,17 @@ DEFPY(bgp_default_afi_safi, bgp_default_afi_safi_cmd,
afi_t afi = bgp_vty_afi_from_str(afi_str);
safi_t safi;
+ /*
+ * Impossible situation but making coverity happy
+ */
+ assert(afi != AFI_MAX);
+
if (strmatch(safi_str, "labeled"))
safi = bgp_vty_safi_from_str("labeled-unicast");
else
safi = bgp_vty_safi_from_str(safi_str);
+ assert(safi != SAFI_MAX);
if (no)
bgp->default_af[afi][safi] = false;
else {
@@ -8263,6 +8282,63 @@ ALIAS_HIDDEN(
"Only give warning message when limit is exceeded\n"
"Force checking all received routes not only accepted\n")
+/* "neighbor soo" */
+DEFPY (neighbor_soo,
+ neighbor_soo_cmd,
+ "neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor soo ASN:NN_OR_IP-ADDRESS:NN$soo",
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set the Site-of-Origin (SoO) extended community\n"
+ "VPN extended community\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+ struct ecommunity *ecomm_soo;
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ecomm_soo = ecommunity_str2com(soo, ECOMMUNITY_SITE_ORIGIN, 0);
+ if (!ecomm_soo) {
+ vty_out(vty, "%% Malformed SoO extended community\n");
+ return CMD_WARNING;
+ }
+ ecommunity_str(ecomm_soo);
+
+ if (!ecommunity_match(peer->soo[afi][safi], ecomm_soo)) {
+ ecommunity_free(&peer->soo[afi][safi]);
+ peer->soo[afi][safi] = ecomm_soo;
+ peer_af_flag_unset(peer, afi, safi, PEER_FLAG_SOO);
+ }
+
+ return bgp_vty_return(vty,
+ peer_af_flag_set(peer, afi, safi, PEER_FLAG_SOO));
+}
+
+DEFPY (no_neighbor_soo,
+ no_neighbor_soo_cmd,
+ "no neighbor <A.B.C.D|X:X::X:X|WORD>$neighbor soo [ASN:NN_OR_IP-ADDRESS:NN$soo]",
+ NO_STR
+ NEIGHBOR_STR
+ NEIGHBOR_ADDR_STR2
+ "Set the Site-of-Origin (SoO) extended community\n"
+ "VPN extended community\n")
+{
+ struct peer *peer;
+ afi_t afi = bgp_node_afi(vty);
+ safi_t safi = bgp_node_safi(vty);
+
+ peer = peer_and_group_lookup_vty(vty, neighbor);
+ if (!peer)
+ return CMD_WARNING_CONFIG_FAILED;
+
+ ecommunity_free(&peer->soo[afi][safi]);
+
+ return bgp_vty_return(
+ vty, peer_af_flag_unset(peer, afi, safi, PEER_FLAG_SOO));
+}
/* "neighbor allowas-in" */
DEFUN (neighbor_allowas_in,
@@ -9596,11 +9672,7 @@ DEFPY (show_bgp_srv6,
struct listnode *node;
struct srv6_locator_chunk *chunk;
struct bgp_srv6_function *func;
- struct in6_addr *tovpn4_sid;
- struct in6_addr *tovpn6_sid;
char buf[256];
- char buf_tovpn4_sid[256];
- char buf_tovpn6_sid[256];
bgp = bgp_get_default();
if (!bgp)
@@ -9608,10 +9680,8 @@ DEFPY (show_bgp_srv6,
vty_out(vty, "locator_name: %s\n", bgp->srv6_locator_name);
vty_out(vty, "locator_chunks:\n");
- for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk)) {
- prefix2str(&chunk->prefix, buf, sizeof(buf));
- vty_out(vty, "- %s\n", buf);
- }
+ for (ALL_LIST_ELEMENTS_RO(bgp->srv6_locator_chunks, node, chunk))
+ vty_out(vty, "- %pFX\n", &chunk->prefix);
vty_out(vty, "functions:\n");
for (ALL_LIST_ELEMENTS_RO(bgp->srv6_functions, node, func)) {
@@ -9625,19 +9695,10 @@ DEFPY (show_bgp_srv6,
vty_out(vty, "- name: %s\n",
bgp->name ? bgp->name : "default");
- tovpn4_sid = bgp->vpn_policy[AFI_IP].tovpn_sid;
- tovpn6_sid = bgp->vpn_policy[AFI_IP6].tovpn_sid;
- if (tovpn4_sid)
- inet_ntop(AF_INET6, tovpn4_sid, buf_tovpn4_sid,
- sizeof(buf_tovpn4_sid));
- if (tovpn6_sid)
- inet_ntop(AF_INET6, tovpn6_sid, buf_tovpn6_sid,
- sizeof(buf_tovpn6_sid));
-
- vty_out(vty, " vpn_policy[AFI_IP].tovpn_sid: %s\n",
- tovpn4_sid ? buf_tovpn4_sid : "none");
- vty_out(vty, " vpn_policy[AFI_IP6].tovpn_sid: %s\n",
- tovpn6_sid ? buf_tovpn6_sid : "none");
+ vty_out(vty, " vpn_policy[AFI_IP].tovpn_sid: %pI6\n",
+ bgp->vpn_policy[AFI_IP].tovpn_sid);
+ vty_out(vty, " vpn_policy[AFI_IP6].tovpn_sid: %pI6\n",
+ bgp->vpn_policy[AFI_IP6].tovpn_sid);
}
return CMD_SUCCESS;
@@ -12758,7 +12819,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
if (peer_established(p)) {
time_t uptime;
- uptime = bgp_clock();
+ uptime = monotime(NULL);
uptime -= p->uptime;
epoch_tbuf = time(NULL) - uptime;
@@ -12786,7 +12847,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
time_t uptime;
struct tm tm;
- uptime = bgp_clock();
+ uptime = monotime(NULL);
uptime -= p->readtime;
gmtime_r(&uptime, &tm);
@@ -12794,7 +12855,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
(tm.tm_sec * 1000) + (tm.tm_min * 60000)
+ (tm.tm_hour * 3600000));
- uptime = bgp_clock();
+ uptime = monotime(NULL);
uptime -= p->last_write;
gmtime_r(&uptime, &tm);
@@ -12802,7 +12863,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
(tm.tm_sec * 1000) + (tm.tm_min * 60000)
+ (tm.tm_hour * 3600000));
- uptime = bgp_clock();
+ uptime = monotime(NULL);
uptime -= p->update_time;
gmtime_r(&uptime, &tm);
@@ -14074,7 +14135,7 @@ static void bgp_show_peer(struct vty *vty, struct peer *p, bool use_json,
time_t uptime;
struct tm tm;
- uptime = bgp_clock();
+ uptime = monotime(NULL);
uptime -= p->resettime;
gmtime_r(&uptime, &tm);
@@ -14696,7 +14757,7 @@ static int bgp_show_neighbor_vty(struct vty *vty, const char *name,
/* "show [ip] bgp neighbors graceful-restart" commands. */
-DEFUN (show_ip_bgp_neighbors_gracrful_restart,
+DEFUN (show_ip_bgp_neighbors_graceful_restart,
show_ip_bgp_neighbors_graceful_restart_cmd,
"show bgp [<ipv4|ipv6>] neighbors [<A.B.C.D|X:X::X:X|WORD>] graceful-restart [json]",
SHOW_STR
@@ -14954,7 +15015,6 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
struct bgp *bgp;
struct listnode *node;
char *vname;
- char buf1[INET6_ADDRSTRLEN];
char *ecom_str;
enum vpn_policy_direction dir;
@@ -15019,9 +15079,9 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
json_object_new_string(vname));
json_object_object_add(json, "exportToVrfs",
json_export_vrfs);
- json_object_string_add(json, "routeDistinguisher",
- prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
- buf1, RD_ADDRSTRLEN));
+ json_object_string_addf(json, "routeDistinguisher",
+ "%pRD",
+ &bgp->vpn_policy[afi].tovpn_rd);
dir = BGP_VPN_POLICY_DIR_TOVPN;
if (bgp->vpn_policy[afi].rtlist[dir]) {
@@ -15090,9 +15150,8 @@ static int bgp_show_route_leak_vty(struct vty *vty, const char *name,
node, vname))
vty_out(vty, " %s\n", vname);
- vty_out(vty, "RD: %s\n",
- prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd,
- buf1, RD_ADDRSTRLEN));
+ vty_out(vty, "RD: %pRD\n",
+ &bgp->vpn_policy[afi].tovpn_rd);
dir = BGP_VPN_POLICY_DIR_TOVPN;
if (bgp->vpn_policy[afi].rtlist[dir]) {
@@ -16469,7 +16528,7 @@ static bool peergroup_flag_check(struct peer *peer, uint64_t flag)
}
static bool peergroup_af_flag_check(struct peer *peer, afi_t afi, safi_t safi,
- uint32_t flag)
+ uint64_t flag)
{
if (!peer_group_active(peer)) {
if (CHECK_FLAG(peer->af_flags_invert[afi][safi], flag))
@@ -16582,13 +16641,10 @@ static void bgp_vpn_policy_config_write_afi(struct vty *vty, struct bgp *bgp,
tovpn_sid_index);
}
- if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
- BGP_VPN_POLICY_TOVPN_RD_SET)) {
- char buf[RD_ADDRSTRLEN];
- vty_out(vty, "%*srd vpn export %s\n", indent, "",
- prefix_rd2str(&bgp->vpn_policy[afi].tovpn_rd, buf,
- sizeof(buf)));
- }
+ if (CHECK_FLAG(bgp->vpn_policy[afi].flags, BGP_VPN_POLICY_TOVPN_RD_SET))
+ vty_out(vty, "%*srd vpn export %pRD\n", indent, "",
+ &bgp->vpn_policy[afi].tovpn_rd);
+
if (CHECK_FLAG(bgp->vpn_policy[afi].flags,
BGP_VPN_POLICY_TOVPN_NEXTHOP_SET)) {
@@ -17256,6 +17312,15 @@ static void bgp_config_write_peer_af(struct vty *vty, struct bgp *bgp,
}
}
+ /* soo */
+ if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_SOO)) {
+ char *soo_str = ecommunity_ecom2str(
+ peer->soo[afi][safi], ECOMMUNITY_FORMAT_ROUTE_MAP, 0);
+
+ vty_out(vty, " neighbor %s soo %s\n", addr, soo_str);
+ XFREE(MTYPE_ECOMMUNITY_STR, soo_str);
+ }
+
/* weight */
if (peergroup_af_flag_check(peer, afi, safi, PEER_FLAG_WEIGHT))
vty_out(vty, " neighbor %s weight %lu\n", addr,
@@ -18080,6 +18145,84 @@ static void bgp_config_end(void)
bgp_post_config_delay, &t_bgp_cfg);
}
+static int config_write_interface_one(struct vty *vty, struct vrf *vrf)
+{
+ int write = 0;
+ struct interface *ifp;
+ struct bgp_interface *iifp;
+
+ FOR_ALL_INTERFACES (vrf, ifp) {
+ iifp = ifp->info;
+ if (!iifp)
+ continue;
+
+ if_vty_config_start(vty, ifp);
+
+ if (CHECK_FLAG(iifp->flags,
+ BGP_INTERFACE_MPLS_BGP_FORWARDING)) {
+ vty_out(vty, " mpls bgp forwarding\n");
+ write++;
+ }
+
+ if_vty_config_end(vty);
+ }
+
+ return write;
+}
+
+/* Configuration write function for bgpd. */
+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_interface_one(vty, vrf);
+ }
+
+ return write;
+}
+
+DEFPY(mpls_bgp_forwarding, mpls_bgp_forwarding_cmd,
+ "[no$no] mpls bgp forwarding",
+ NO_STR MPLS_STR BGP_STR
+ "Enable MPLS forwarding for eBGP directly connected peers\n")
+{
+ bool check;
+ struct bgp_interface *iifp;
+
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ iifp = ifp->info;
+ if (!iifp) {
+ vty_out(vty, "Interface %s not available\n", ifp->name);
+ return CMD_WARNING_CONFIG_FAILED;
+ }
+ check = CHECK_FLAG(iifp->flags, BGP_INTERFACE_MPLS_BGP_FORWARDING);
+ if (check != !no) {
+ if (no)
+ UNSET_FLAG(iifp->flags,
+ BGP_INTERFACE_MPLS_BGP_FORWARDING);
+ else
+ SET_FLAG(iifp->flags,
+ BGP_INTERFACE_MPLS_BGP_FORWARDING);
+ /* trigger a nht update on eBGP sessions */
+ if (if_is_operative(ifp))
+ bgp_nht_ifp_up(ifp);
+ }
+ return CMD_SUCCESS;
+}
+
+/* Initialization of BGP interface. */
+static void bgp_vty_if_init(void)
+{
+ /* Install interface node. */
+ if_cmd_init(config_write_interface);
+
+ /* "mpls bgp forwarding" commands. */
+ install_element(INTERFACE_NODE, &mpls_bgp_forwarding_cmd);
+}
+
void bgp_vty_init(void)
{
cmd_variable_handler_register(bgp_var_neighbor);
@@ -19343,6 +19486,26 @@ void bgp_vty_init(void)
install_element(BGP_EVPN_NODE, &neighbor_allowas_in_cmd);
install_element(BGP_EVPN_NODE, &no_neighbor_allowas_in_cmd);
+ /* "neighbor soo" */
+ install_element(BGP_IPV4_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV4_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV4M_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV4M_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV4L_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV4L_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV6_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV6_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV6M_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV6M_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_IPV6L_NODE, &neighbor_soo_cmd);
+ install_element(BGP_IPV6L_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_VPNV4_NODE, &neighbor_soo_cmd);
+ install_element(BGP_VPNV4_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_VPNV6_NODE, &neighbor_soo_cmd);
+ install_element(BGP_VPNV6_NODE, &no_neighbor_soo_cmd);
+ install_element(BGP_EVPN_NODE, &neighbor_soo_cmd);
+ install_element(BGP_EVPN_NODE, &no_neighbor_soo_cmd);
+
/* address-family commands. */
install_element(BGP_NODE, &address_family_ipv4_safi_cmd);
install_element(BGP_NODE, &address_family_ipv6_safi_cmd);
@@ -19521,6 +19684,8 @@ void bgp_vty_init(void)
install_element(BGP_SRV6_NODE, &no_bgp_srv6_locator_cmd);
install_element(BGP_IPV4_NODE, &af_sid_vpn_export_cmd);
install_element(BGP_IPV6_NODE, &af_sid_vpn_export_cmd);
+
+ bgp_vty_if_init();
}
#include "memory.h"
diff --git a/bgpd/bgp_zebra.c b/bgpd/bgp_zebra.c
index 2151d0a613..57a859c61d 100644
--- a/bgpd/bgp_zebra.c
+++ b/bgpd/bgp_zebra.c
@@ -75,6 +75,8 @@ struct zclient *zclient = NULL;
DEFINE_HOOK(bgp_vrf_status_changed, (struct bgp *bgp, struct interface *ifp),
(bgp, ifp));
+DEFINE_MTYPE_STATIC(BGPD, BGP_IF_INFO, "BGP interface context");
+
/* Can we install into zebra? */
static inline bool bgp_install_info_to_zebra(struct bgp *bgp)
{
@@ -305,6 +307,11 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
{
struct connected *ifc;
struct bgp *bgp;
+ struct peer *peer;
+ struct prefix *addr;
+ struct listnode *node, *nnode;
+ afi_t afi;
+ safi_t safi;
bgp = bgp_lookup_by_vrf_id(vrf_id);
@@ -330,6 +337,48 @@ static int bgp_interface_address_add(ZAPI_CALLBACK_ARGS)
if (IN6_IS_ADDR_LINKLOCAL(&ifc->address->u.prefix6)
&& !list_isempty(ifc->ifp->nbr_connected))
bgp_start_interface_nbrs(bgp, ifc->ifp);
+ else {
+ addr = ifc->address;
+
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (addr->family == AF_INET)
+ continue;
+
+ /*
+ * If the Peer's interface name matches the
+ * interface name for which BGP received the
+ * update and if the received interface address
+ * is a globalV6 and if the peer is currently
+ * using a v4-mapped-v6 addr or a link local
+ * address, then copy the Rxed global v6 addr
+ * into peer's v6_global and send updates out
+ * with new nexthop addr.
+ */
+ if ((peer->conf_if &&
+ (strcmp(peer->conf_if, ifc->ifp->name) ==
+ 0)) &&
+ !IN6_IS_ADDR_LINKLOCAL(&addr->u.prefix6) &&
+ ((IS_MAPPED_IPV6(
+ &peer->nexthop.v6_global)) ||
+ IN6_IS_ADDR_LINKLOCAL(
+ &peer->nexthop.v6_global))) {
+
+ if (bgp_debug_zebra(ifc->address)) {
+ zlog_debug(
+ "Update peer %pBP's current intf addr %pI6 and send updates",
+ peer,
+ &peer->nexthop
+ .v6_global);
+ }
+ memcpy(&peer->nexthop.v6_global,
+ &addr->u.prefix6,
+ IPV6_MAX_BYTELEN);
+ FOREACH_AFI_SAFI (afi, safi)
+ bgp_announce_route(peer, afi,
+ safi, true);
+ }
+ }
+ }
}
return 0;
@@ -456,7 +505,7 @@ static int bgp_interface_vrf_update(ZAPI_CALLBACK_ARGS)
if (!ifp)
return 0;
- if (BGP_DEBUG(zebra, ZEBRA) && ifp)
+ if (BGP_DEBUG(zebra, ZEBRA))
zlog_debug("Rx Intf VRF change VRF %u IF %s NewVRF %u", vrf_id,
ifp->name, new_vrf_id);
@@ -1000,19 +1049,13 @@ static bool bgp_table_map_apply(struct route_map *map, const struct prefix *p,
p, &path->attr->nexthop);
}
if (p->family == AF_INET6) {
- char buf[2][INET6_ADDRSTRLEN];
ifindex_t ifindex;
struct in6_addr *nexthop;
nexthop = bgp_path_info_to_ipv6_nexthop(path, &ifindex);
zlog_debug(
- "Zebra rmap deny: IPv6 route %pFX nexthop %s",
- p,
- nexthop ? inet_ntop(AF_INET6, nexthop, buf[1],
- sizeof(buf[1]))
- : inet_ntop(AF_INET,
- &path->attr->nexthop,
- buf[1], sizeof(buf[1])));
+ "Zebra rmap deny: IPv6 route %pFX nexthop %pI6",
+ p, nexthop);
}
}
return false;
@@ -1369,12 +1412,12 @@ void bgp_zebra_announce(struct bgp_dest *dest, const struct prefix *p,
nh_weight = 0;
/* Get nexthop address-family */
- if (p->family == AF_INET
- && !BGP_ATTR_NEXTHOP_AFI_IP6(mpinfo_cp->attr))
+ if (p->family == AF_INET &&
+ !BGP_ATTR_MP_NEXTHOP_LEN_IP6(mpinfo_cp->attr))
nh_family = AF_INET;
- else if (p->family == AF_INET6
- || (p->family == AF_INET
- && BGP_ATTR_NEXTHOP_AFI_IP6(mpinfo_cp->attr)))
+ else if (p->family == AF_INET6 ||
+ (p->family == AF_INET &&
+ BGP_ATTR_MP_NEXTHOP_LEN_IP6(mpinfo_cp->attr)))
nh_family = AF_INET6;
else
continue;
@@ -3215,7 +3258,7 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
struct srv6_locator_chunk *chunk;
struct bgp_srv6_function *func;
struct bgp *bgp_vrf;
- struct in6_addr *tovpn_sid;
+ struct in6_addr *tovpn_sid, *tovpn_sid_locator;
struct prefix_ipv6 tmp_prefi;
if (zapi_srv6_locator_decode(zclient->ibuf, &loc) < 0)
@@ -3224,8 +3267,10 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
// refresh chunks
for (ALL_LIST_ELEMENTS(bgp->srv6_locator_chunks, node, nnode, chunk))
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&chunk->prefix))
+ (struct prefix *)&chunk->prefix)) {
listnode_delete(bgp->srv6_locator_chunks, chunk);
+ srv6_locator_chunk_free(chunk);
+ }
// refresh functions
for (ALL_LIST_ELEMENTS(bgp->srv6_functions, node, nnode, func)) {
@@ -3233,8 +3278,10 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
tmp_prefi.prefixlen = 128;
tmp_prefi.prefix = func->sid;
if (prefix_match((struct prefix *)&loc.prefix,
- (struct prefix *)&tmp_prefi))
+ (struct prefix *)&tmp_prefi)) {
listnode_delete(bgp->srv6_functions, func);
+ XFREE(MTYPE_BGP_SRV6_FUNCTION, func);
+ }
}
// refresh tovpn_sid
@@ -3268,6 +3315,37 @@ static int bgp_zebra_process_srv6_locator_delete(ZAPI_CALLBACK_ARGS)
}
vpn_leak_postchange_all();
+
+ /* refresh tovpn_sid_locator */
+ for (ALL_LIST_ELEMENTS_RO(bm->bgp, node, bgp_vrf)) {
+ if (bgp_vrf->inst_type != BGP_INSTANCE_TYPE_VRF)
+ continue;
+
+ /* refresh vpnv4 tovpn_sid_locator */
+ tovpn_sid_locator =
+ bgp_vrf->vpn_policy[AFI_IP].tovpn_sid_locator;
+ if (tovpn_sid_locator) {
+ tmp_prefi.family = AF_INET6;
+ tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
+ tmp_prefi.prefix = *tovpn_sid_locator;
+ if (prefix_match((struct prefix *)&loc.prefix,
+ (struct prefix *)&tmp_prefi))
+ XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid_locator);
+ }
+
+ /* refresh vpnv6 tovpn_sid_locator */
+ tovpn_sid_locator =
+ bgp_vrf->vpn_policy[AFI_IP6].tovpn_sid_locator;
+ if (tovpn_sid_locator) {
+ tmp_prefi.family = AF_INET6;
+ tmp_prefi.prefixlen = IPV6_MAX_BITLEN;
+ tmp_prefi.prefix = *tovpn_sid_locator;
+ if (prefix_match((struct prefix *)&loc.prefix,
+ (struct prefix *)&tmp_prefi))
+ XFREE(MTYPE_BGP_SRV6_SID, tovpn_sid_locator);
+ }
+ }
+
return 0;
}
@@ -3306,6 +3384,31 @@ static zclient_handler *const bgp_handlers[] = {
bgp_zebra_process_srv6_locator_chunk,
};
+static int bgp_if_new_hook(struct interface *ifp)
+{
+ struct bgp_interface *iifp;
+
+ if (ifp->info)
+ return 0;
+ iifp = XCALLOC(MTYPE_BGP_IF_INFO, sizeof(struct bgp_interface));
+ ifp->info = iifp;
+
+ return 0;
+}
+
+static int bgp_if_delete_hook(struct interface *ifp)
+{
+ XFREE(MTYPE_BGP_IF_INFO, ifp->info);
+ return 0;
+}
+
+void bgp_if_init(void)
+{
+ /* Initialize Zebra interface data structure. */
+ hook_register_prio(if_add, 0, bgp_if_new_hook);
+ hook_register_prio(if_del, 0, bgp_if_delete_hook);
+}
+
void bgp_zebra_init(struct thread_master *master, unsigned short instance)
{
zclient_num_connects = 0;
diff --git a/bgpd/bgp_zebra.h b/bgpd/bgp_zebra.h
index 17f46e49cc..0a41069411 100644
--- a/bgpd/bgp_zebra.h
+++ b/bgpd/bgp_zebra.h
@@ -35,6 +35,7 @@
extern void bgp_zebra_init(struct thread_master *master,
unsigned short instance);
+extern void bgp_if_init(void);
extern void bgp_zebra_init_tm_connect(struct bgp *bgp);
extern uint32_t bgp_zebra_tm_get_id(void);
extern bool bgp_zebra_tm_chunk_obtained(void);
diff --git a/bgpd/bgpd.c b/bgpd/bgpd.c
index 15b4d7c5a9..1bcd714407 100644
--- a/bgpd/bgpd.c
+++ b/bgpd/bgpd.c
@@ -482,14 +482,14 @@ void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set)
}
/* BGP's cluster-id control. */
-int bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
+void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
{
struct peer *peer;
struct listnode *node, *nnode;
if (bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID)
&& IPV4_ADDR_SAME(&bgp->cluster_id, cluster_id))
- return 0;
+ return;
IPV4_ADDR_COPY(&bgp->cluster_id, cluster_id);
bgp_config_set(bgp, BGP_CONFIG_CLUSTER_ID);
@@ -505,16 +505,15 @@ int bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
}
- return 0;
}
-int bgp_cluster_id_unset(struct bgp *bgp)
+void bgp_cluster_id_unset(struct bgp *bgp)
{
struct peer *peer;
struct listnode *node, *nnode;
if (!bgp_config_check(bgp, BGP_CONFIG_CLUSTER_ID))
- return 0;
+ return;
bgp->cluster_id.s_addr = 0;
bgp_config_unset(bgp, BGP_CONFIG_CLUSTER_ID);
@@ -530,18 +529,6 @@ int bgp_cluster_id_unset(struct bgp *bgp)
BGP_NOTIFY_CEASE_CONFIG_CHANGE);
}
}
- return 0;
-}
-
-/* time_t value that is monotonicly increasing
- * and uneffected by adjustments to system clock
- */
-time_t bgp_clock(void)
-{
- struct timeval tv;
-
- monotime(&tv);
- return tv.tv_sec;
}
/* BGP timer configuration. */
@@ -638,7 +625,7 @@ void bgp_confederation_id_set(struct bgp *bgp, as_t as)
return;
}
-int bgp_confederation_id_unset(struct bgp *bgp)
+void bgp_confederation_id_unset(struct bgp *bgp)
{
struct peer *peer;
struct listnode *node, *nnode;
@@ -660,7 +647,6 @@ int bgp_confederation_id_unset(struct bgp *bgp)
bgp_session_reset_safe(peer, &nnode);
}
}
- return 0;
}
/* Is an AS part of the confed or not? */
@@ -679,16 +665,16 @@ bool bgp_confederation_peers_check(struct bgp *bgp, as_t as)
}
/* Add an AS to the confederation set. */
-int bgp_confederation_peers_add(struct bgp *bgp, as_t as)
+void bgp_confederation_peers_add(struct bgp *bgp, as_t as)
{
struct peer *peer;
struct listnode *node, *nnode;
if (bgp->as == as)
- return BGP_ERR_INVALID_AS;
+ return;
if (bgp_confederation_peers_check(bgp, as))
- return -1;
+ return;
bgp->confed_peers =
XREALLOC(MTYPE_BGP_CONFED_LIST, bgp->confed_peers,
@@ -714,11 +700,10 @@ int bgp_confederation_peers_add(struct bgp *bgp, as_t as)
}
}
}
- return 0;
}
/* Delete an AS from the confederation set. */
-int bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
+void bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
{
int i;
int j;
@@ -726,10 +711,10 @@ int bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
struct listnode *node, *nnode;
if (!bgp)
- return -1;
+ return;
if (!bgp_confederation_peers_check(bgp, as))
- return -1;
+ return;
for (i = 0; i < bgp->confed_peers_cnt; i++)
if (bgp->confed_peers[i] == as)
@@ -766,71 +751,58 @@ int bgp_confederation_peers_remove(struct bgp *bgp, as_t as)
}
}
}
-
- return 0;
}
/* Local preference configuration. */
-int bgp_default_local_preference_set(struct bgp *bgp, uint32_t local_pref)
+void bgp_default_local_preference_set(struct bgp *bgp, uint32_t local_pref)
{
if (!bgp)
- return -1;
+ return;
bgp->default_local_pref = local_pref;
-
- return 0;
}
-int bgp_default_local_preference_unset(struct bgp *bgp)
+void bgp_default_local_preference_unset(struct bgp *bgp)
{
if (!bgp)
- return -1;
+ return;
bgp->default_local_pref = BGP_DEFAULT_LOCAL_PREF;
-
- return 0;
}
/* Local preference configuration. */
-int bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp, uint32_t queue_size)
+void bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp,
+ uint32_t queue_size)
{
if (!bgp)
- return -1;
+ return;
bgp->default_subgroup_pkt_queue_max = queue_size;
-
- return 0;
}
-int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp)
+void bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp)
{
if (!bgp)
- return -1;
+ return;
bgp->default_subgroup_pkt_queue_max =
BGP_DEFAULT_SUBGROUP_PKT_QUEUE_MAX;
-
- return 0;
}
/* Listen limit configuration. */
-int bgp_listen_limit_set(struct bgp *bgp, int listen_limit)
+void bgp_listen_limit_set(struct bgp *bgp, int listen_limit)
{
if (!bgp)
- return -1;
+ return;
bgp->dynamic_neighbors_limit = listen_limit;
-
- return 0;
}
-int bgp_listen_limit_unset(struct bgp *bgp)
+void bgp_listen_limit_unset(struct bgp *bgp)
{
if (!bgp)
- return -1;
+ return;
bgp->dynamic_neighbors_limit = BGP_DYNAMIC_NEIGHBORS_LIMIT_DEFAULT;
-
- return 0;
}
int bgp_map_afi_safi_iana2int(iana_afi_t pkt_afi, iana_safi_t pkt_safi,
@@ -1012,7 +984,7 @@ int peer_af_flag_check(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
}
void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
- uint32_t flag)
+ uint64_t flag)
{
bool group_val;
@@ -1040,9 +1012,15 @@ void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
{
struct bgp *bgp;
+ as_t local_as;
bgp = peer->bgp;
+ if (peer->change_local_as)
+ local_as = peer->change_local_as;
+ else
+ local_as = peer->local_as;
+
/* Peer-group */
if (CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
if (peer->as_type == AS_INTERNAL)
@@ -1053,8 +1031,8 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
else if (peer->as_type == AS_SPECIFIED && peer->as) {
assert(bgp);
- return (bgp->as == peer->as ? BGP_PEER_IBGP
- : BGP_PEER_EBGP);
+ return (local_as == peer->as ? BGP_PEER_IBGP
+ : BGP_PEER_EBGP);
}
else {
@@ -1071,17 +1049,17 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
/* Normal peer */
if (bgp && CHECK_FLAG(bgp->config, BGP_CONFIG_CONFEDERATION)) {
- if (peer->local_as == 0)
+ if (local_as == 0)
return BGP_PEER_INTERNAL;
- if (peer->local_as == peer->as) {
+ if (local_as == peer->as) {
if (bgp->as == bgp->confed_id) {
- if (peer->local_as == bgp->as)
+ if (local_as == bgp->as)
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
} else {
- if (peer->local_as == bgp->confed_id)
+ if (local_as == bgp->confed_id)
return BGP_PEER_EBGP;
else
return BGP_PEER_IBGP;
@@ -1099,8 +1077,7 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
&& (peer->group->conf->as_type != AS_UNSPECIFIED)) {
if (peer->group->conf->as_type
== AS_SPECIFIED) {
- if (peer->local_as
- == peer->group->conf->as)
+ if (local_as == peer->group->conf->as)
return BGP_PEER_IBGP;
else
return BGP_PEER_EBGP;
@@ -1116,9 +1093,8 @@ static inline enum bgp_peer_sort peer_calc_sort(struct peer *peer)
return (peer->as_type == AS_INTERNAL ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
- return (peer->local_as == 0
- ? BGP_PEER_INTERNAL
- : peer->local_as == peer->as ? BGP_PEER_IBGP
+ return (local_as == 0 ? BGP_PEER_INTERNAL
+ : local_as == peer->as ? BGP_PEER_IBGP
: BGP_PEER_EBGP);
}
}
@@ -1409,6 +1385,7 @@ struct peer *peer_new(struct bgp *bgp)
SET_FLAG(peer->af_flags_invert[afi][safi],
PEER_FLAG_SEND_LARGE_COMMUNITY);
peer->addpath_type[afi][safi] = BGP_ADDPATH_NONE;
+ peer->soo[afi][safi] = NULL;
}
/* set nexthop-unchanged for l2vpn evpn by default */
@@ -1792,7 +1769,7 @@ struct peer *peer_create(union sockunion *su, const char *conf_if,
}
/* Last read and reset time set */
- peer->readtime = peer->resettime = bgp_clock();
+ peer->readtime = peer->resettime = monotime(NULL);
/* Default TTL set. */
peer->ttl = (peer->sort == BGP_PEER_IBGP) ? MAXTTL : BGP_DEFAULT_TTL;
@@ -1843,7 +1820,7 @@ struct peer *peer_create_accept(struct bgp *bgp)
/*
* Return true if we have a peer configured to use this afi/safi
*/
-int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
+bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
{
struct listnode *node;
struct peer *peer;
@@ -1853,10 +1830,10 @@ int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi)
continue;
if (peer->afc[afi][safi])
- return 1;
+ return true;
}
- return 0;
+ return false;
}
/* Change peer's AS number. */
@@ -1927,14 +1904,6 @@ void peer_as_change(struct peer *peer, as_t as, int as_specified)
UNSET_FLAG(peer->af_flags[AFI_L2VPN][SAFI_EVPN],
PEER_FLAG_REFLECTOR_CLIENT);
}
-
- /* local-as reset */
- if (newtype != BGP_PEER_EBGP) {
- peer->change_local_as = 0;
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS);
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_NO_PREPEND);
- peer_flag_unset(peer, PEER_FLAG_LOCAL_AS_REPLACE_AS);
- }
}
/* If peer does not exist, create new one. If peer already exists,
@@ -2039,8 +2008,8 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
{
int in = FILTER_IN;
int out = FILTER_OUT;
- uint32_t flags_tmp;
- uint32_t pflags_ovrd;
+ uint64_t flags_tmp;
+ uint64_t pflags_ovrd;
uint8_t *pfilter_ovrd;
struct peer *conf;
@@ -2074,6 +2043,10 @@ static void peer_group2peer_config_copy_af(struct peer_group *group,
if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_ALLOWAS_IN))
PEER_ATTR_INHERIT(peer, group, allowas_in[afi][safi]);
+ /* soo */
+ if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_SOO))
+ PEER_ATTR_INHERIT(peer, group, soo[afi][safi]);
+
/* weight */
if (!CHECK_FLAG(pflags_ovrd, PEER_FLAG_WEIGHT))
PEER_ATTR_INHERIT(peer, group, weight[afi][safi]);
@@ -2412,8 +2385,10 @@ void peer_nsf_stop(struct peer *peer)
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_WAIT);
UNSET_FLAG(peer->sflags, PEER_STATUS_NSF_MODE);
- FOREACH_AFI_SAFI_NSF (afi, safi)
+ FOREACH_AFI_SAFI_NSF (afi, safi) {
peer->nsf[afi][safi] = 0;
+ THREAD_OFF(peer->t_llgr_stale[afi][safi]);
+ }
if (peer->t_gr_restart) {
THREAD_OFF(peer->t_gr_restart);
@@ -2580,6 +2555,7 @@ int peer_delete(struct peer *peer)
XFREE(MTYPE_BGP_FILTER_NAME, filter->usmap.name);
XFREE(MTYPE_ROUTE_MAP_NAME, peer->default_rmap[afi][safi].name);
+ ecommunity_free(&peer->soo[afi][safi]);
}
FOREACH_AFI_SAFI (afi, safi)
@@ -2795,6 +2771,21 @@ void peer_notify_unconfig(struct peer *peer)
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
}
+static void peer_notify_shutdown(struct peer *peer)
+{
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP configured Graceful-Restart, skipping shutdown notification",
+ peer);
+ return;
+ }
+
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
+ bgp_notify_send(peer, BGP_NOTIFY_CEASE,
+ BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
+}
+
void peer_group_notify_unconfig(struct peer_group *group)
{
struct peer *peer, *other;
@@ -3053,17 +3044,6 @@ int peer_group_bind(struct bgp *bgp, union sockunion *su, struct peer *peer,
/* ebgp-multihop reset */
if (gtype == BGP_PEER_IBGP)
group->conf->ttl = MAXTTL;
-
- /* local-as reset */
- if (gtype != BGP_PEER_EBGP) {
- group->conf->change_local_as = 0;
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS);
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS_NO_PREPEND);
- peer_flag_unset(group->conf,
- PEER_FLAG_LOCAL_AS_REPLACE_AS);
- }
}
SET_FLAG(peer->flags, PEER_FLAG_CONFIG_NODE);
@@ -3653,6 +3633,7 @@ int bgp_delete(struct bgp *bgp)
hook_call(bgp_inst_delete, bgp);
+ THREAD_OFF(bgp->t_condition_check);
THREAD_OFF(bgp->t_startup);
THREAD_OFF(bgp->t_maxmed_onstartup);
THREAD_OFF(bgp->t_update_delay);
@@ -3668,7 +3649,12 @@ int bgp_delete(struct bgp *bgp)
gr_info = &bgp->gr_info[afi][safi];
if (!gr_info)
continue;
+ t = gr_info->t_select_deferral;
+ if (t) {
+ void *info = THREAD_ARG(t);
+ XFREE(MTYPE_TMP, info);
+ }
THREAD_OFF(gr_info->t_select_deferral);
t = gr_info->t_route_select;
@@ -3706,11 +3692,8 @@ int bgp_delete(struct bgp *bgp)
}
/* Inform peers we're going down. */
- for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer)) {
- if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
- bgp_notify_send(peer, BGP_NOTIFY_CEASE,
- BGP_NOTIFY_CEASE_ADMIN_SHUTDOWN);
- }
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, next, peer))
+ peer_notify_shutdown(peer);
/* Delete static routes (networks). */
bgp_static_delete(bgp);
@@ -3751,6 +3734,17 @@ int bgp_delete(struct bgp *bgp)
bgp->vpn_policy[afi].import_redirect_rtlist = NULL;
}
+ /* Free any memory allocated to holding routemap references */
+ for (afi = 0; afi < AFI_MAX; ++afi) {
+ for (enum vpn_policy_direction dir = 0;
+ dir < BGP_VPN_POLICY_DIR_MAX; ++dir) {
+ if (bgp->vpn_policy[afi].rmap_name[dir])
+ XFREE(MTYPE_ROUTE_MAP_NAME,
+ bgp->vpn_policy[afi].rmap_name[dir]);
+ bgp->vpn_policy[afi].rmap[dir] = NULL;
+ }
+ }
+
/* Deregister from Zebra, if needed */
if (IS_BGP_INST_KNOWN_TO_ZEBRA(bgp)) {
if (BGP_DEBUG(zebra, ZEBRA))
@@ -4050,7 +4044,6 @@ struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
struct prefix prefix;
struct prefix *listen_range;
int dncount;
- char buf[PREFIX2STR_BUFFER];
if (!sockunion2hostprefix(su, &prefix))
return NULL;
@@ -4067,21 +4060,19 @@ struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
if (!gbgp)
return NULL;
- prefix2str(&prefix, buf, sizeof(buf));
-
if (bgp_debug_neighbor_events(NULL))
zlog_debug(
- "Dynamic Neighbor %s matches group %s listen range %pFX",
- buf, group->name, listen_range);
+ "Dynamic Neighbor %pFX matches group %s listen range %pFX",
+ &prefix, group->name, listen_range);
/* Are we within the listen limit? */
dncount = gbgp->dynamic_neighbors_count;
if (dncount >= gbgp->dynamic_neighbors_limit) {
if (bgp_debug_neighbor_events(NULL))
- zlog_debug("Dynamic Neighbor %s rejected - at limit %d",
- inet_sutop(su, buf),
- gbgp->dynamic_neighbors_limit);
+ zlog_debug(
+ "Dynamic Neighbor %pFX rejected - at limit %d",
+ &prefix, gbgp->dynamic_neighbors_limit);
return NULL;
}
@@ -4089,8 +4080,8 @@ struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
if (CHECK_FLAG(group->conf->flags, PEER_FLAG_SHUTDOWN)) {
if (bgp_debug_neighbor_events(NULL))
zlog_debug(
- "Dynamic Neighbor %s rejected - group %s disabled",
- buf, group->name);
+ "Dynamic Neighbor %pFX rejected - group %s disabled",
+ &prefix, group->name);
return NULL;
}
@@ -4098,8 +4089,8 @@ struct peer *peer_lookup_dynamic_neighbor(struct bgp *bgp, union sockunion *su)
if (!peer_group_af_configured(group)) {
if (bgp_debug_neighbor_events(NULL))
zlog_debug(
- "Dynamic Neighbor %s rejected - no AF activated for group %s",
- buf, group->name);
+ "Dynamic Neighbor %pFX rejected - no AF activated for group %s",
+ &prefix, group->name);
return NULL;
}
@@ -4311,6 +4302,7 @@ static const struct peer_flag_action peer_af_flag_action_list[] = {
{PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE, 1, peer_change_reset_out},
{PEER_FLAG_WEIGHT, 0, peer_change_reset_in},
{PEER_FLAG_DISABLE_ADDPATH_RX, 0, peer_change_reset},
+ {PEER_FLAG_SOO, 0, peer_change_reset},
{0, 0, 0}};
/* Proper action set. */
@@ -4614,7 +4606,7 @@ int peer_flag_unset(struct peer *peer, uint64_t flag)
}
static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
- uint32_t flag, bool set)
+ uint64_t flag, bool set)
{
int found;
int size;
@@ -4797,12 +4789,12 @@ static int peer_af_flag_modify(struct peer *peer, afi_t afi, safi_t safi,
return 0;
}
-int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
+int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi, uint64_t flag)
{
return peer_af_flag_modify(peer, afi, safi, flag, 1);
}
-int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, uint32_t flag)
+int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi, uint64_t flag)
{
return peer_af_flag_modify(peer, afi, safi, flag, 0);
}
@@ -5143,7 +5135,7 @@ int peer_update_source_if_set(struct peer *peer, const char *ifname)
return 0;
}
-int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
+void peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
{
struct peer *member;
struct listnode *node, *nnode;
@@ -5152,7 +5144,7 @@ int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
peer_flag_set(peer, PEER_FLAG_UPDATE_SOURCE);
if (peer->update_source) {
if (sockunion_cmp(peer->update_source, su) == 0)
- return 0;
+ return;
sockunion_free(peer->update_source);
}
peer->update_source = sockunion_dup(su);
@@ -5173,7 +5165,7 @@ int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
bgp_peer_bfd_update_source(peer);
/* Skip peer-group mechanics for regular peers. */
- return 0;
+ return;
}
/*
@@ -5209,17 +5201,15 @@ int peer_update_source_addr_set(struct peer *peer, const union sockunion *su)
if (member->bfd_config)
bgp_peer_bfd_update_source(member);
}
-
- return 0;
}
-int peer_update_source_unset(struct peer *peer)
+void peer_update_source_unset(struct peer *peer)
{
struct peer *member;
struct listnode *node, *nnode;
if (!CHECK_FLAG(peer->flags, PEER_FLAG_UPDATE_SOURCE))
- return 0;
+ return;
/* Inherit configuration from peer-group if peer is member. */
if (peer_group_active(peer)) {
@@ -5250,7 +5240,7 @@ int peer_update_source_unset(struct peer *peer)
bgp_peer_bfd_update_source(peer);
/* Skip peer-group mechanics for regular peers. */
- return 0;
+ return;
}
/*
@@ -5285,8 +5275,6 @@ int peer_update_source_unset(struct peer *peer)
if (member->bfd_config)
bgp_peer_bfd_update_source(member);
}
-
- return 0;
}
int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
@@ -5501,8 +5489,8 @@ void peer_tcp_mss_unset(struct peer *peer)
* being used by a peer has changed (AF specific). Automatically
* initiates inbound or outbound processing as needed.
*/
-static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
- int outbound)
+void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
+ int outbound)
{
if (outbound) {
update_group_adjust_peer(peer_af_find(peer, afi, safi));
@@ -5513,12 +5501,23 @@ static void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
return;
if (CHECK_FLAG(peer->af_flags[afi][safi],
- PEER_FLAG_SOFT_RECONFIG))
+ PEER_FLAG_SOFT_RECONFIG)) {
bgp_soft_reconfig_in(peer, afi, safi);
- else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV)
- || CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV))
- bgp_route_refresh_send(peer, afi, safi, 0, 0, 0,
- BGP_ROUTE_REFRESH_NORMAL);
+ } else if (CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_OLD_RCV) ||
+ CHECK_FLAG(peer->cap, PEER_CAP_REFRESH_NEW_RCV)) {
+ if (CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_SM_ADV) &&
+ (CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_RCV) ||
+ CHECK_FLAG(peer->af_cap[afi][safi],
+ PEER_CAP_ORF_PREFIX_RM_OLD_RCV)))
+ peer_clear_soft(peer, afi, safi,
+ BGP_CLEAR_SOFT_IN_ORF_PREFIX);
+ else
+ bgp_route_refresh_send(
+ peer, afi, safi, 0, 0, 0,
+ BGP_ROUTE_REFRESH_NORMAL);
+ }
}
}
@@ -6123,17 +6122,10 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
struct bgp *bgp = peer->bgp;
struct peer *member;
struct listnode *node, *nnode;
- enum bgp_peer_sort ptype = peer_sort(peer);
-
- if (ptype != BGP_PEER_EBGP && ptype != BGP_PEER_INTERNAL)
- return BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP;
if (bgp->as == as)
return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS;
- if (peer->as == as)
- return BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS;
-
/* Save previous flag states. */
old_no_prepend =
!!CHECK_FLAG(peer->flags, PEER_FLAG_LOCAL_AS_NO_PREPEND);
@@ -6149,6 +6141,7 @@ int peer_local_as_set(struct peer *peer, as_t as, bool no_prepend,
&& old_replace_as == replace_as)
return 0;
peer->change_local_as = as;
+ (void)peer_sort(peer);
/* Check if handling a regular peer. */
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
@@ -6562,7 +6555,7 @@ static void peer_distribute_update(struct access_list *access)
if (access->name)
update_group_policy_update(bgp,
BGP_POLICY_DISTRIBUTE_LIST,
- access->name, 0, 0);
+ access->name, true, 0);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
FOREACH_AFI_SAFI (afi, safi) {
filter = &peer->filter[afi][safi];
@@ -6751,7 +6744,7 @@ static void peer_prefix_list_update(struct prefix_list *plist)
*/
update_group_policy_update(
bgp, BGP_POLICY_PREFIX_LIST,
- plist ? prefix_list_name(plist) : NULL, 0, 0);
+ plist ? prefix_list_name(plist) : NULL, true, 0);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
FOREACH_AFI_SAFI (afi, safi) {
@@ -6769,6 +6762,14 @@ static void peer_prefix_list_update(struct prefix_list *plist)
filter->plist[direct].plist =
NULL;
}
+
+ /* If we touch prefix-list, we need to process
+ * new updates. This is important for ORF to
+ * work correctly as well.
+ */
+ if (peer->afc_nego[afi][safi])
+ peer_on_policy_change(peer, afi, safi,
+ 0);
}
}
for (ALL_LIST_ELEMENTS(bgp->group, node, nnode, group)) {
@@ -6928,7 +6929,7 @@ static void peer_aslist_update(const char *aslist_name)
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
update_group_policy_update(bgp, BGP_POLICY_FILTER_LIST,
- aslist_name, 0, 0);
+ aslist_name, true, 0);
for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
FOREACH_AFI_SAFI (afi, safi) {
@@ -7225,166 +7226,6 @@ int peer_unsuppress_map_unset(struct peer *peer, afi_t afi, safi_t safi)
return 0;
}
-static void peer_advertise_map_filter_update(struct peer *peer, afi_t afi,
- safi_t safi, const char *amap_name,
- struct route_map *amap,
- const char *cmap_name,
- struct route_map *cmap,
- bool condition, bool set)
-{
- struct bgp_filter *filter;
- bool filter_exists = false;
-
- filter = &peer->filter[afi][safi];
-
- /* advertise-map is already configured. */
- if (filter->advmap.aname) {
- filter_exists = true;
- XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.aname);
- XFREE(MTYPE_BGP_FILTER_NAME, filter->advmap.cname);
- }
-
- route_map_counter_decrement(filter->advmap.amap);
-
- /* Removed advertise-map configuration */
- if (!set) {
- memset(&filter->advmap, 0, sizeof(filter->advmap));
-
- /* decrement condition_filter_count delete timer if
- * this is the last advertise-map to be removed.
- */
- if (filter_exists)
- bgp_conditional_adv_disable(peer, afi, safi);
-
- return;
- }
-
- /* Update filter data with newly configured values. */
- filter->advmap.aname = XSTRDUP(MTYPE_BGP_FILTER_NAME, amap_name);
- filter->advmap.cname = XSTRDUP(MTYPE_BGP_FILTER_NAME, cmap_name);
- filter->advmap.amap = amap;
- filter->advmap.cmap = cmap;
- filter->advmap.condition = condition;
- route_map_counter_increment(filter->advmap.amap);
- peer->advmap_config_change[afi][safi] = true;
-
- /* Increment condition_filter_count and/or create timer. */
- if (!filter_exists) {
- filter->advmap.update_type = UPDATE_TYPE_ADVERTISE;
- bgp_conditional_adv_enable(peer, afi, safi);
- }
-
- /* Process peer route updates. */
- peer_on_policy_change(peer, afi, safi, 1);
-}
-
-/* Set advertise-map to the peer. */
-int peer_advertise_map_set(struct peer *peer, afi_t afi, safi_t safi,
- const char *advertise_name,
- struct route_map *advertise_map,
- const char *condition_name,
- struct route_map *condition_map, bool condition)
-{
- struct peer *member;
- struct listnode *node, *nnode;
-
- /* Set configuration on peer. */
- peer_advertise_map_filter_update(peer, afi, safi, advertise_name,
- advertise_map, condition_name,
- condition_map, condition, true);
-
- /* Check if handling a regular peer & Skip peer-group mechanics. */
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- /* Set override-flag and process peer route updates. */
- SET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP);
- return 0;
- }
-
- /*
- * Set configuration on all peer-group members, unless they are
- * explicitly overriding peer-group configuration.
- */
- for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
- /* Skip peers with overridden configuration. */
- if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP))
- continue;
-
- /* Set configuration on peer-group member. */
- peer_advertise_map_filter_update(
- member, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, true);
- }
-
- return 0;
-}
-
-/* Unset advertise-map from the peer. */
-int peer_advertise_map_unset(struct peer *peer, afi_t afi, safi_t safi,
- const char *advertise_name,
- struct route_map *advertise_map,
- const char *condition_name,
- struct route_map *condition_map, bool condition)
-{
- struct peer *member;
- struct listnode *node, *nnode;
-
- /* advertise-map is not configured */
- if (!peer->filter[afi][safi].advmap.aname)
- return 0;
-
- /* Unset override-flag unconditionally. */
- UNSET_FLAG(peer->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP);
-
- /* Inherit configuration from peer-group if peer is member. */
- if (peer_group_active(peer)) {
- PEER_STR_ATTR_INHERIT(peer, peer->group,
- filter[afi][safi].advmap.aname,
- MTYPE_BGP_FILTER_NAME);
- PEER_ATTR_INHERIT(peer, peer->group,
- filter[afi][safi].advmap.amap);
- } else
- peer_advertise_map_filter_update(
- peer, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, false);
-
- /* Check if handling a regular peer and skip peer-group mechanics. */
- if (!CHECK_FLAG(peer->sflags, PEER_STATUS_GROUP)) {
- /* Process peer route updates. */
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Send normal update to %s for %s",
- __func__, peer->host,
- get_afi_safi_str(afi, safi, false));
-
- return 0;
- }
-
- /*
- * Remove configuration on all peer-group members, unless they are
- * explicitly overriding peer-group configuration.
- */
- for (ALL_LIST_ELEMENTS(peer->group->peer, node, nnode, member)) {
- /* Skip peers with overridden configuration. */
- if (CHECK_FLAG(member->filter_override[afi][safi][RMAP_OUT],
- PEER_FT_ADVERTISE_MAP))
- continue;
- /* Remove configuration on peer-group member. */
- peer_advertise_map_filter_update(
- member, afi, safi, advertise_name, advertise_map,
- condition_name, condition_map, condition, false);
-
- /* Process peer route updates. */
- if (BGP_DEBUG(update, UPDATE_OUT))
- zlog_debug("%s: Send normal update to %s for %s ",
- __func__, member->host,
- get_afi_safi_str(afi, safi, false));
- }
-
- return 0;
-}
-
static bool peer_maximum_prefix_clear_overflow(struct peer *peer)
{
if (!CHECK_FLAG(peer->sflags, PEER_STATUS_PREFIX_OVERFLOW))
@@ -7978,7 +7819,7 @@ char *peer_uptime(time_t uptime2, char *buf, size_t len, bool use_json,
}
/* Get current time. */
- uptime1 = bgp_clock();
+ uptime1 = monotime(NULL);
uptime1 -= uptime2;
gmtime_r(&uptime1, &tm);
@@ -8020,7 +7861,7 @@ void bgp_master_init(struct thread_master *master, const int buffer_size,
bm->port = BGP_PORT_DEFAULT;
bm->addresses = addresses;
bm->master = master;
- bm->start_time = bgp_clock();
+ bm->start_time = monotime(NULL);
bm->t_rmap_update = NULL;
bm->rmap_update_timer = RMAP_DEFAULT_UPDATE_TIMER;
bm->v_update_delay = BGP_UPDATE_DELAY_DEF;
@@ -8254,11 +8095,18 @@ void bgp_terminate(void)
/* reverse bgp_master_init */
for (ALL_LIST_ELEMENTS(bm->bgp, mnode, mnnode, bgp)) {
bgp_close_vrf_socket(bgp);
- for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer))
- if (peer_established(peer) || peer->status == OpenSent
- || peer->status == OpenConfirm)
+ for (ALL_LIST_ELEMENTS(bgp->peer, node, nnode, peer)) {
+ if (BGP_PEER_GRACEFUL_RESTART_CAPABLE(peer)) {
+ if (bgp_debug_neighbor_events(peer))
+ zlog_debug(
+ "%pBP configured Graceful-Restart, skipping unconfig notification",
+ peer);
+ continue;
+ }
+ if (BGP_IS_VALID_STATE_FOR_NOTIF(peer->status))
bgp_notify_send(peer, BGP_NOTIFY_CEASE,
BGP_NOTIFY_CEASE_PEER_UNCONFIG);
+ }
}
if (bm->listen_sockets)
diff --git a/bgpd/bgpd.conf.sample2 b/bgpd/bgpd.conf.sample2
deleted file mode 100644
index d376ad25bc..0000000000
--- a/bgpd/bgpd.conf.sample2
+++ /dev/null
@@ -1,77 +0,0 @@
-!
-! Zebra configuration saved from vty
-! 2002/07/01 03:16:33
-!
-hostname bgpd
-password zebra
-log file bgpd.log
-log stdout
-!
-router bgp 7675
- no bgp default ipv4-unicast
- neighbor 3ffe:506:1000::2 remote-as 7675
- neighbor fe80::200:c0ff:fe30:9be3 remote-as 9377
- neighbor fe80::200:c0ff:fe30:9be3 interface sit3
- neighbor fe80::210:5aff:fe6b:3cee remote-as 7675
- neighbor fe80::210:5aff:fe6b:3cee interface eth0
- neighbor fe80::290:27ff:fe51:84c7 remote-as 4691
- neighbor fe80::290:27ff:fe51:84c7 description DTI
- neighbor fe80::290:27ff:fe51:84c7 interface sit7
- neighbor fe80::2a0:c9ff:fec8:82ec remote-as 7530
- neighbor fe80::2a0:c9ff:fec8:82ec description IRI
- neighbor fe80::2a0:c9ff:fec8:82ec interface sit8
- neighbor fe80::2e0:18ff:fe98:2725 remote-as 2500
- neighbor fe80::2e0:18ff:fe98:2725 description WIDE
- neighbor fe80::2e0:18ff:fe98:2725 interface sit5
- neighbor fe80::2e0:18ff:fea8:bf5 remote-as 65000
- neighbor fe80::2e0:18ff:fea8:bf5 interface sit6
-!
- address-family ipv6
- network 3ffe:506::/33
- network 3ffe:1800:e800::/40
- aggregate-address 3ffe:506::/32
- redistribute connected
- neighbor 3ffe:506:1000::2 activate
- neighbor fe80::200:c0ff:fe30:9be3 activate
- neighbor fe80::200:c0ff:fe30:9be3 route-map set-nexthop out
- neighbor fe80::210:5aff:fe6b:3cee activate
- neighbor fe80::290:27ff:fe51:84c7 activate
- neighbor fe80::290:27ff:fe51:84c7 route-map set-nexthop out
- neighbor fe80::2a0:c9ff:fec8:82ec activate
- neighbor fe80::2a0:c9ff:fec8:82ec route-map set-nexthop out
- neighbor fe80::2e0:18ff:fe98:2725 activate
- neighbor fe80::2e0:18ff:fe98:2725 distribute-list nla1 out
- neighbor fe80::2e0:18ff:fe98:2725 route-map set-nexthop out
- neighbor fe80::2e0:18ff:fea8:bf5 activate
- neighbor fe80::2e0:18ff:fea8:bf5 route-map set-nexthop out
- exit-address-family
-!
-ipv6 access-list all permit any
-ipv6 access-list nla1 deny 3ffe:506::/33
-ipv6 access-list nla1 permit 3ffe:506::/32
-ipv6 access-list nla1 deny any
-ipv6 access-list ntt-nla1 permit 3ffe:1800:0:ffff::c/127
-ipv6 access-list ntt-nla1 deny 3ffe:1800:e800::/41
-ipv6 access-list ntt-nla1 permit 3ffe:1800:e800::/40
-ipv6 access-list ntt-nla1 deny any
-!
-ipv6 prefix-list 6bone-filter seq 5 permit 3ffe::/17 ge 24 le 24
-ipv6 prefix-list 6bone-filter seq 10 permit 3ffe:8000::/17 ge 28 le 28
-ipv6 prefix-list 6bone-filter seq 12 deny 3ffe::/16
-ipv6 prefix-list 6bone-filter seq 15 permit 2000::/3 ge 16 le 16
-ipv6 prefix-list 6bone-filter seq 20 permit 2001::/16 ge 35 le 35
-!
-route-map set-nexthop permit 10
- match ipv6 address all
- set ipv6 next-hop global 3ffe:506::1
- set ipv6 next-hop local fe80::cbb5:591a
- set ip next-hop 203.181.89.26
- set community 7675:0
-!
-route-map set-link-local permit 10
- match ipv6 address all
- set ipv6 next-hop local fe80::cbb5:591a
- set ipv6 next-hop global 3ffe:1800:0:ffff::d
-!
-line vty
-!
diff --git a/bgpd/bgpd.h b/bgpd/bgpd.h
index 2d6b78d509..af46550650 100644
--- a/bgpd/bgpd.h
+++ b/bgpd/bgpd.h
@@ -783,6 +783,11 @@ struct bgp {
};
DECLARE_QOBJ_TYPE(bgp);
+struct bgp_interface {
+#define BGP_INTERFACE_MPLS_BGP_FORWARDING (1 << 0)
+ uint32_t flags;
+};
+
DECLARE_HOOK(bgp_inst_delete, (struct bgp *bgp), (bgp));
DECLARE_HOOK(bgp_inst_config_write,
(struct bgp *bgp, struct vty *vty),
@@ -1385,37 +1390,38 @@ struct peer {
* specific attributes are being treated the exact same way as global
* peer attributes.
*/
- uint32_t af_flags_override[AFI_MAX][SAFI_MAX];
- uint32_t af_flags_invert[AFI_MAX][SAFI_MAX];
- uint32_t af_flags[AFI_MAX][SAFI_MAX];
-#define PEER_FLAG_SEND_COMMUNITY (1U << 0) /* send-community */
-#define PEER_FLAG_SEND_EXT_COMMUNITY (1U << 1) /* send-community ext. */
-#define PEER_FLAG_NEXTHOP_SELF (1U << 2) /* next-hop-self */
-#define PEER_FLAG_REFLECTOR_CLIENT (1U << 3) /* reflector-client */
-#define PEER_FLAG_RSERVER_CLIENT (1U << 4) /* route-server-client */
-#define PEER_FLAG_SOFT_RECONFIG (1U << 5) /* soft-reconfiguration */
-#define PEER_FLAG_AS_PATH_UNCHANGED (1U << 6) /* transparent-as */
-#define PEER_FLAG_NEXTHOP_UNCHANGED (1U << 7) /* transparent-next-hop */
-#define PEER_FLAG_MED_UNCHANGED (1U << 8) /* transparent-next-hop */
-#define PEER_FLAG_DEFAULT_ORIGINATE (1U << 9) /* default-originate */
-#define PEER_FLAG_REMOVE_PRIVATE_AS (1U << 10) /* remove-private-as */
-#define PEER_FLAG_ALLOWAS_IN (1U << 11) /* set allowas-in */
-#define PEER_FLAG_ORF_PREFIX_SM (1U << 12) /* orf capability send-mode */
-#define PEER_FLAG_ORF_PREFIX_RM (1U << 13) /* orf capability receive-mode */
-#define PEER_FLAG_MAX_PREFIX (1U << 14) /* maximum prefix */
-#define PEER_FLAG_MAX_PREFIX_WARNING (1U << 15) /* maximum prefix warning-only */
-#define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1U << 16) /* leave link-local nexthop unchanged */
-#define PEER_FLAG_FORCE_NEXTHOP_SELF (1U << 17) /* next-hop-self force */
-#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL (1U << 18) /* remove-private-as all */
-#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1U << 19) /* remove-private-as replace-as */
-#define PEER_FLAG_AS_OVERRIDE (1U << 20) /* as-override */
-#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE (1U << 21) /* remove-private-as all replace-as */
-#define PEER_FLAG_WEIGHT (1U << 24) /* weight */
-#define PEER_FLAG_ALLOWAS_IN_ORIGIN (1U << 25) /* allowas-in origin */
-#define PEER_FLAG_SEND_LARGE_COMMUNITY (1U << 26) /* Send large Communities */
-#define PEER_FLAG_MAX_PREFIX_OUT (1U << 27) /* outgoing maximum prefix */
-#define PEER_FLAG_MAX_PREFIX_FORCE (1U << 28) /* maximum-prefix <num> force */
-#define PEER_FLAG_DISABLE_ADDPATH_RX (1U << 29) /* disable-addpath-rx */
+ uint64_t af_flags_override[AFI_MAX][SAFI_MAX];
+ uint64_t af_flags_invert[AFI_MAX][SAFI_MAX];
+ uint64_t af_flags[AFI_MAX][SAFI_MAX];
+#define PEER_FLAG_SEND_COMMUNITY (1ULL << 0)
+#define PEER_FLAG_SEND_EXT_COMMUNITY (1ULL << 1)
+#define PEER_FLAG_NEXTHOP_SELF (1ULL << 2)
+#define PEER_FLAG_REFLECTOR_CLIENT (1ULL << 3)
+#define PEER_FLAG_RSERVER_CLIENT (1ULL << 4)
+#define PEER_FLAG_SOFT_RECONFIG (1ULL << 5)
+#define PEER_FLAG_AS_PATH_UNCHANGED (1ULL << 6)
+#define PEER_FLAG_NEXTHOP_UNCHANGED (1ULL << 7)
+#define PEER_FLAG_MED_UNCHANGED (1ULL << 8)
+#define PEER_FLAG_DEFAULT_ORIGINATE (1ULL << 9)
+#define PEER_FLAG_REMOVE_PRIVATE_AS (1ULL << 10)
+#define PEER_FLAG_ALLOWAS_IN (1ULL << 11)
+#define PEER_FLAG_ORF_PREFIX_SM (1ULL << 12)
+#define PEER_FLAG_ORF_PREFIX_RM (1ULL << 13)
+#define PEER_FLAG_MAX_PREFIX (1ULL << 14)
+#define PEER_FLAG_MAX_PREFIX_WARNING (1ULL << 15)
+#define PEER_FLAG_NEXTHOP_LOCAL_UNCHANGED (1ULL << 16)
+#define PEER_FLAG_FORCE_NEXTHOP_SELF (1ULL << 17)
+#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL (1ULL << 18)
+#define PEER_FLAG_REMOVE_PRIVATE_AS_REPLACE (1ULL << 19)
+#define PEER_FLAG_AS_OVERRIDE (1ULL << 20)
+#define PEER_FLAG_REMOVE_PRIVATE_AS_ALL_REPLACE (1ULL << 21)
+#define PEER_FLAG_WEIGHT (1ULL << 24)
+#define PEER_FLAG_ALLOWAS_IN_ORIGIN (1ULL << 25)
+#define PEER_FLAG_SEND_LARGE_COMMUNITY (1ULL << 26)
+#define PEER_FLAG_MAX_PREFIX_OUT (1ULL << 27)
+#define PEER_FLAG_MAX_PREFIX_FORCE (1ULL << 28)
+#define PEER_FLAG_DISABLE_ADDPATH_RX (1ULL << 29)
+#define PEER_FLAG_SOO (1ULL << 30)
enum bgp_addpath_strat addpath_type[AFI_MAX][SAFI_MAX];
@@ -1455,6 +1461,7 @@ struct peer {
#define PEER_STATUS_EORR_RECEIVED (1U << 10) /* EoRR received from peer */
/* LLGR aware peer */
#define PEER_STATUS_LLGR_WAIT (1U << 11)
+#define PEER_STATUS_REFRESH_PENDING (1U << 12) /* refresh request from peer */
/* Configured timer values. */
_Atomic uint32_t holdtime;
@@ -1625,6 +1632,9 @@ struct peer {
/* allowas-in. */
char allowas_in[AFI_MAX][SAFI_MAX];
+ /* soo */
+ struct ecommunity *soo[AFI_MAX][SAFI_MAX];
+
/* weight */
unsigned long weight[AFI_MAX][SAFI_MAX];
@@ -1999,13 +2009,11 @@ enum bgp_create_error_code {
BGP_ERR_AF_UNCONFIGURED = -15,
BGP_ERR_SOFT_RECONFIG_UNCONFIGURED = -16,
BGP_ERR_INSTANCE_MISMATCH = -17,
- BGP_ERR_LOCAL_AS_ALLOWED_ONLY_FOR_EBGP = -18,
BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS = -19,
BGP_ERR_TCPSIG_FAILED = -20,
BGP_ERR_NO_EBGP_MULTIHOP_WITH_TTLHACK = -21,
BGP_ERR_NO_IBGP_WITH_TTLHACK = -22,
BGP_ERR_NO_INTERFACE_CONFIG = -23,
- BGP_ERR_CANNOT_HAVE_LOCAL_AS_SAME_AS_REMOTE_AS = -24,
BGP_ERR_AS_OVERRIDE = -25,
BGP_ERR_INVALID_DYNAMIC_NEIGHBORS_LIMIT = -26,
BGP_ERR_DYNAMIC_NEIGHBORS_RANGE_EXISTS = -27,
@@ -2048,7 +2056,6 @@ extern unsigned int multipath_num;
/* Prototypes. */
extern void bgp_terminate(void);
extern void bgp_reset(void);
-extern time_t bgp_clock(void);
extern void bgp_zclient_reset(void);
extern struct bgp *bgp_get_default(void);
extern struct bgp *bgp_lookup(as_t, const char *);
@@ -2133,32 +2140,34 @@ extern void bgp_router_id_static_set(struct bgp *, struct in_addr);
extern void bm_wait_for_fib_set(bool set);
extern void bgp_suppress_fib_pending_set(struct bgp *bgp, bool set);
-extern int bgp_cluster_id_set(struct bgp *, struct in_addr *);
-extern int bgp_cluster_id_unset(struct bgp *);
+extern void bgp_cluster_id_set(struct bgp *bgp, struct in_addr *cluster_id);
+extern void bgp_cluster_id_unset(struct bgp *bgp);
-extern void bgp_confederation_id_set(struct bgp *, as_t);
-extern int bgp_confederation_id_unset(struct bgp *);
+extern void bgp_confederation_id_set(struct bgp *bgp, as_t as);
+extern void bgp_confederation_id_unset(struct bgp *bgp);
extern bool bgp_confederation_peers_check(struct bgp *, as_t);
-extern int bgp_confederation_peers_add(struct bgp *, as_t);
-extern int bgp_confederation_peers_remove(struct bgp *, as_t);
+extern void bgp_confederation_peers_add(struct bgp *bgp, as_t as);
+extern void bgp_confederation_peers_remove(struct bgp *bgp, as_t as);
extern void bgp_timers_set(struct bgp *, uint32_t keepalive, uint32_t holdtime,
uint32_t connect_retry, uint32_t delayopen);
extern void bgp_timers_unset(struct bgp *);
-extern int bgp_default_local_preference_set(struct bgp *, uint32_t);
-extern int bgp_default_local_preference_unset(struct bgp *);
+extern void bgp_default_local_preference_set(struct bgp *bgp,
+ uint32_t local_pref);
+extern void bgp_default_local_preference_unset(struct bgp *bgp);
-extern int bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp, uint32_t);
-extern int bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp);
+extern void bgp_default_subgroup_pkt_queue_max_set(struct bgp *bgp,
+ uint32_t queue_size);
+extern void bgp_default_subgroup_pkt_queue_max_unset(struct bgp *bgp);
-extern int bgp_listen_limit_set(struct bgp *, int);
-extern int bgp_listen_limit_unset(struct bgp *);
+extern void bgp_listen_limit_set(struct bgp *bgp, int listen_limit);
+extern void bgp_listen_limit_unset(struct bgp *bgp);
extern bool bgp_update_delay_active(struct bgp *);
extern bool bgp_update_delay_configured(struct bgp *);
-extern int bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi);
+extern bool bgp_afi_safi_peer_exists(struct bgp *bgp, afi_t afi, safi_t safi);
extern void peer_as_change(struct peer *, as_t, int);
extern int peer_remote_as(struct bgp *, union sockunion *, const char *, as_t *,
int);
@@ -2180,11 +2189,13 @@ extern int peer_flag_set(struct peer *peer, uint64_t flag);
extern int peer_flag_unset(struct peer *peer, uint64_t flag);
extern void peer_flag_inherit(struct peer *peer, uint64_t flag);
-extern int peer_af_flag_set(struct peer *, afi_t, safi_t, uint32_t);
-extern int peer_af_flag_unset(struct peer *, afi_t, safi_t, uint32_t);
+extern int peer_af_flag_set(struct peer *peer, afi_t afi, safi_t safi,
+ uint64_t flag);
+extern int peer_af_flag_unset(struct peer *peer, afi_t afi, safi_t safi,
+ uint64_t flag);
extern int peer_af_flag_check(struct peer *, afi_t, safi_t, uint32_t);
extern void peer_af_flag_inherit(struct peer *peer, afi_t afi, safi_t safi,
- uint32_t flag);
+ uint64_t flag);
extern void peer_change_action(struct peer *peer, afi_t afi, safi_t safi,
enum peer_change_type type);
@@ -2199,8 +2210,9 @@ extern void peer_description_set(struct peer *, const char *);
extern void peer_description_unset(struct peer *);
extern int peer_update_source_if_set(struct peer *, const char *);
-extern int peer_update_source_addr_set(struct peer *, const union sockunion *);
-extern int peer_update_source_unset(struct peer *);
+extern void peer_update_source_addr_set(struct peer *peer,
+ const union sockunion *su);
+extern void peer_update_source_unset(struct peer *peer);
extern int peer_default_originate_set(struct peer *peer, afi_t afi, safi_t safi,
const char *rmap,
@@ -2454,7 +2466,7 @@ static inline int peer_group_af_configured(struct peer_group *group)
static inline char *timestamp_string(time_t ts)
{
time_t tbuf;
- tbuf = time(NULL) - (bgp_clock() - ts);
+ tbuf = time(NULL) - (monotime(NULL) - ts);
return ctime(&tbuf);
}
@@ -2570,7 +2582,8 @@ void peer_tcp_mss_unset(struct peer *peer);
extern void bgp_recalculate_afi_safi_bestpaths(struct bgp *bgp, afi_t afi,
safi_t safi);
-
+extern void peer_on_policy_change(struct peer *peer, afi_t afi, safi_t safi,
+ int outbound);
#ifdef _FRR_ATTRIBUTE_PRINTFRR
/* clang-format off */
#pragma FRR printfrr_ext "%pBP" (struct peer *)
diff --git a/bgpd/rfapi/bgp_rfapi_cfg.c b/bgpd/rfapi/bgp_rfapi_cfg.c
index 2437bd8cfe..eae9859ba1 100644
--- a/bgpd/rfapi/bgp_rfapi_cfg.c
+++ b/bgpd/rfapi/bgp_rfapi_cfg.c
@@ -94,7 +94,7 @@ DEFINE_QOBJ_TYPE(rfapi_l2_group_cfg);
*/
time_t rfapi_time(time_t *t)
{
- time_t clock = bgp_clock();
+ time_t clock = monotime(NULL);
if (t)
*t = clock;
return clock;
@@ -3913,8 +3913,6 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
}
if (rfg->rd.prefixlen) {
- char buf[RD_ADDRSTRLEN];
-
if (AF_UNIX == rfg->rd.family) {
uint16_t value = 0;
@@ -3927,9 +3925,7 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
value);
} else
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&rfg->rd, buf,
- sizeof(buf)));
+ vty_out(vty, " rd %pRD\n", &rfg->rd);
}
if (rfg->rt_import_list && rfg->rt_export_list
@@ -4137,8 +4133,6 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
vty_out(vty, " vnc defaults\n");
if (hc->default_rd.prefixlen) {
- char buf[RD_ADDRSTRLEN];
-
if (AF_UNIX == hc->default_rd.family) {
uint16_t value = 0;
@@ -4151,10 +4145,8 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
value);
} else
- vty_out(vty, " rd %s\n",
- prefix_rd2str(&hc->default_rd,
- buf,
- sizeof(buf)));
+ vty_out(vty, " rd %pRD\n",
+ &hc->default_rd);
}
if (hc->default_response_lifetime
!= BGP_VNC_DEFAULT_RESPONSE_LIFETIME_DEFAULT) {
@@ -4219,8 +4211,6 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
if (rfg->rd.prefixlen) {
- char buf[RD_ADDRSTRLEN];
-
if (AF_UNIX == rfg->rd.family) {
uint16_t value = 0;
@@ -4235,10 +4225,8 @@ int bgp_rfapi_cfg_write(struct vty *vty, struct bgp *bgp)
value);
} else
- vty_out(vty, " rd %s\n",
- prefix_rd2str(
- &rfg->rd, buf,
- sizeof(buf)));
+ vty_out(vty, " rd %pRD\n",
+ &rfg->rd);
}
if (rfg->flags & RFAPI_RFG_RESPONSE_LIFETIME) {
vty_out(vty, " response-lifetime ");
diff --git a/bgpd/rfapi/rfapi.c b/bgpd/rfapi/rfapi.c
index 382886e0bd..ed0714ce2d 100644
--- a/bgpd/rfapi/rfapi.c
+++ b/bgpd/rfapi/rfapi.c
@@ -362,7 +362,6 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
afi_t afi; /* of the VN address */
struct bgp_dest *bn;
struct bgp_path_info *bpi;
- char buf2[RD_ADDRSTRLEN];
struct prefix_rd prd0;
afi = family2afi(p->family);
@@ -377,9 +376,9 @@ void del_vnc_route(struct rfapi_descriptor *rfd,
bn = bgp_afi_node_get(bgp->rib[afi][safi], afi, safi, p, prd);
vnc_zlog_debug_verbose(
- "%s: peer=%p, prefix=%pFX, prd=%s afi=%d, safi=%d bn=%p, bn->info=%p",
- __func__, peer, p, prefix_rd2str(prd, buf2, sizeof(buf2)), afi,
- safi, bn, (bn ? bgp_dest_get_bgp_path_info(bn) : NULL));
+ "%s: peer=%p, prefix=%pFX, prd=%pRD afi=%d, safi=%d bn=%p, bn->info=%p",
+ __func__, peer, p, prd, afi, safi, bn,
+ (bn ? bgp_dest_get_bgp_path_info(bn) : NULL));
for (bpi = (bn ? bgp_dest_get_bgp_path_info(bn) : NULL); bpi;
bpi = bpi->next) {
@@ -577,7 +576,6 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
struct bgp_attr_encap_subtlv *encaptlv;
char buf[PREFIX_STRLEN];
- char buf2[RD_ADDRSTRLEN];
struct rfapi_nexthop *lnh = NULL; /* local nexthop */
struct rfapi_vn_option *vo;
@@ -616,8 +614,6 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
else
label_val = MPLS_LABEL_IMPLICIT_NULL;
- prefix_rd2str(prd, buf2, sizeof(buf2));
-
afi = family2afi(p->family);
assert(afi == AFI_IP || afi == AFI_IP6);
@@ -1006,7 +1002,7 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
bgp_aggregate_decrement(bgp, p, bpi, afi, safi);
bgp_attr_unintern(&bpi->attr);
bpi->attr = new_attr;
- bpi->uptime = bgp_clock();
+ bpi->uptime = monotime(NULL);
if (safi == SAFI_MPLS_VPN) {
@@ -1070,8 +1066,8 @@ void add_vnc_route(struct rfapi_descriptor *rfd, /* cookie, VPN UN addr, peer */
bgp_process(bgp, bn, afi, safi);
vnc_zlog_debug_any(
- "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%s)",
- __func__, safi2str(safi), buf, bn, buf2);
+ "%s: Added route (safi=%s) at prefix %s (bn=%p, prd=%pRD)",
+ __func__, safi2str(safi), buf, bn, prd);
done:
/* Loop back to import tables */
@@ -1351,8 +1347,7 @@ int rfapi_init_and_open(struct bgp *bgp, struct rfapi_descriptor *rfd,
struct prefix pfx_un;
struct agg_node *rn;
-
- rfapi_time(&rfd->open_time);
+ rfd->open_time = monotime(NULL);
if (rfg->type == RFAPI_GROUP_CFG_VRF)
SET_FLAG(rfd->flags, RFAPI_HD_FLAG_IS_VRF);
@@ -1521,10 +1516,10 @@ rfapi_query_inner(void *handle, struct rfapi_ip_addr *target,
}
rfd->rsp_counter++; /* dedup: identify this generation */
- rfd->rsp_time = rfapi_time(NULL); /* response content dedup */
+ rfd->rsp_time = monotime(NULL); /* response content dedup */
rfd->ftd_last_allowed_time =
- bgp_clock()
- - bgp->rfapi_cfg->rfp_cfg.ftd_advertisement_interval;
+ monotime(NULL) -
+ bgp->rfapi_cfg->rfp_cfg.ftd_advertisement_interval;
if (l2o) {
if (!memcmp(l2o->macaddr.octet, rfapi_ethaddr0.octet,
@@ -3725,12 +3720,7 @@ int rfapi_set_autord_from_vn(struct prefix_rd *rd, struct rfapi_ip_addr *vn)
memcpy(rd->val + 2, &vn->addr.v6.s6_addr32[3],
4); /* low order 4 bytes */
}
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose("%s: auto-RD is set to %s", __func__,
- prefix_rd2str(rd, buf, sizeof(buf)));
- }
+ vnc_zlog_debug_verbose("%s: auto-RD is set to %pRD", __func__, rd);
return 0;
}
diff --git a/bgpd/rfapi/rfapi_import.c b/bgpd/rfapi/rfapi_import.c
index 1d42702769..1dd623d3f3 100644
--- a/bgpd/rfapi/rfapi_import.c
+++ b/bgpd/rfapi/rfapi_import.c
@@ -489,7 +489,7 @@ static struct bgp_path_info *rfapiBgpInfoCreate(struct attr *attr,
bgp_path_info_extra_get(new);
if (prd) {
new->extra->vnc.import.rd = *prd;
- rfapi_time(&new->extra->vnc.import.create_time);
+ new->extra->vnc.import.create_time = monotime(NULL);
}
if (label)
encode_label(*label, &new->extra->label[0]);
@@ -2091,14 +2091,8 @@ static void rfapiItBiIndexAdd(struct agg_node *rn, /* Import table VPN node */
assert(bpi);
assert(bpi->extra);
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %s", __func__,
- bpi, bpi->peer,
- prefix_rd2str(&bpi->extra->vnc.import.rd,
- buf, sizeof(buf)));
- }
+ vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi,
+ bpi->peer, &bpi->extra->vnc.import.rd);
sl = RFAPI_RDINDEX_W_ALLOC(rn);
if (!sl) {
@@ -2164,7 +2158,6 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
#ifdef DEBUG_BI_SEARCH
{
- char buf[RD_ADDRSTRLEN];
char buf_aux_pfx[PREFIX_STRLEN];
if (aux_prefix) {
@@ -2173,10 +2166,9 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
} else
strlcpy(buf_aux_pfx, "(nil)", sizeof(buf_aux_pfx));
- vnc_zlog_debug_verbose("%s want prd=%s, peer=%p, aux_prefix=%s",
- __func__,
- prefix_rd2str(prd, buf, sizeof(buf)),
- peer, buf_aux_pfx);
+ vnc_zlog_debug_verbose(
+ "%s want prd=%pRD, peer=%p, aux_prefix=%s", __func__,
+ prd, peer, buf_aux_pfx);
rfapiItBiIndexDump(rn);
}
#endif
@@ -2190,16 +2182,10 @@ static struct bgp_path_info *rfapiItBiIndexSearch(
for (bpi_result = rn->info; bpi_result;
bpi_result = bpi_result->next) {
#ifdef DEBUG_BI_SEARCH
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose(
- "%s: bpi has prd=%s, peer=%p", __func__,
- prefix_rd2str(&bpi_result->extra->vnc
- .import.rd,
- buf, sizeof(buf)),
- bpi_result->peer);
- }
+ vnc_zlog_debug_verbose(
+ "%s: bpi has prd=%pRD, peer=%p", __func__,
+ &bpi_result->extra->vnc.import.rd,
+ bpi_result->peer);
#endif
if (peer == bpi_result->peer
&& !prefix_cmp((struct prefix *)&bpi_result->extra
@@ -2261,14 +2247,8 @@ static void rfapiItBiIndexDel(struct agg_node *rn, /* Import table VPN node */
struct skiplist *sl;
int rc;
- {
- char buf[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %s", __func__,
- bpi, bpi->peer,
- prefix_rd2str(&bpi->extra->vnc.import.rd,
- buf, sizeof(buf)));
- }
+ vnc_zlog_debug_verbose("%s: bpi %p, peer %p, rd %pRD", __func__, bpi,
+ bpi->peer, &bpi->extra->vnc.import.rd);
sl = RFAPI_RDINDEX(rn);
assert(sl);
@@ -3750,7 +3730,7 @@ void rfapiBgpInfoFilteredImportVPN(
remote_peer_match = 1;
}
- if (!un_match & !remote_peer_match)
+ if (!un_match && !remote_peer_match)
continue;
vnc_zlog_debug_verbose(
diff --git a/bgpd/rfapi/rfapi_private.h b/bgpd/rfapi/rfapi_private.h
index bc0e192ae2..8c76e1dd0b 100644
--- a/bgpd/rfapi/rfapi_private.h
+++ b/bgpd/rfapi/rfapi_private.h
@@ -364,6 +364,11 @@ extern int rfapi_extract_l2o(
* compaitibility to old quagga_time call
* time_t value in terms of stabilised absolute time.
* replacement for POSIX time()
+ *
+ * Please do not use this. This is kept only for
+ * Lou's CI in that that CI compiles against some
+ * private bgp code and it will just fail to compile
+ * without this. Use monotime()
*/
extern time_t rfapi_time(time_t *t);
diff --git a/bgpd/rfapi/rfapi_rib.c b/bgpd/rfapi/rfapi_rib.c
index 9d61ada7db..50a10c3b1d 100644
--- a/bgpd/rfapi/rfapi_rib.c
+++ b/bgpd/rfapi/rfapi_rib.c
@@ -784,7 +784,7 @@ int rfapiRibPreloadBi(
skiplist_insert(slRibPt, &ori->rk, ori);
}
- ori->last_sent_time = rfapi_time(NULL);
+ ori->last_sent_time = monotime(NULL);
/*
* poke timer
@@ -797,7 +797,7 @@ int rfapiRibPreloadBi(
* Update last sent time for prefix
*/
trn = agg_node_get(rfd->rsp_times[afi], p); /* locks trn */
- trn->info = (void *)(uintptr_t)bgp_clock();
+ trn->info = (void *)(uintptr_t)monotime(NULL);
if (agg_node_get_lock_count(trn) > 1)
agg_unlock_node(trn);
@@ -1089,7 +1089,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
rfapiFreeBgpTeaOptionChain(ori->tea_options);
ori->tea_options =
rfapiOptionsDup(ri->tea_options);
- ori->last_sent_time = rfapi_time(NULL);
+ ori->last_sent_time = monotime(NULL);
rfapiFreeRfapiVnOptionChain(ori->vn_options);
ori->vn_options =
@@ -1104,9 +1104,6 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
__func__, ri);
} else {
-
- char buf_rd[RD_ADDRSTRLEN];
-
/* not found: add new route to RIB */
ori = rfapi_info_new();
ori->rk = ri->rk;
@@ -1115,7 +1112,7 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
ori->lifetime = ri->lifetime;
ori->tea_options =
rfapiOptionsDup(ri->tea_options);
- ori->last_sent_time = rfapi_time(NULL);
+ ori->last_sent_time = monotime(NULL);
ori->vn_options =
rfapiVnOptionsDup(ri->vn_options);
ori->un_options =
@@ -1129,16 +1126,9 @@ static void process_pending_node(struct bgp *bgp, struct rfapi_descriptor *rfd,
}
skiplist_insert(slRibPt, &ori->rk, ori);
-#if DEBUG_RIB_SL_RD
- prefix_rd2str(&ori->rk.rd, buf_rd,
- sizeof(buf_rd));
-#else
- buf_rd[0] = 0;
-#endif
-
vnc_zlog_debug_verbose(
- "%s: nomatch lPendCost item %p in slRibPt, added (rd=%s)",
- __func__, ri, buf_rd);
+ "%s: nomatch lPendCost item %p in slRibPt, added (rd=%pRD)",
+ __func__, ri, &ori->rk.rd);
}
/*
@@ -1227,7 +1217,7 @@ callback:
*/
trn = agg_node_get(rfd->rsp_times[afi],
p); /* locks trn */
- trn->info = (void *)(uintptr_t)bgp_clock();
+ trn->info = (void *)(uintptr_t)monotime(NULL);
if (agg_node_get_lock_count(trn) > 1)
agg_unlock_node(trn);
@@ -1376,19 +1366,11 @@ callback:
rfapiRibStartTimer(rfd, ri, rn, 1);
RFAPI_RIB_CHECK_COUNTS(
0, delete_list->count);
- ri->last_sent_time = rfapi_time(NULL);
+ ri->last_sent_time = monotime(NULL);
#if DEBUG_RIB_SL_RD
- {
- char buf_rd[RD_ADDRSTRLEN];
-
- vnc_zlog_debug_verbose(
- "%s: move route to recently deleted list, rd=%s",
- __func__,
- prefix_rd2str(
- &ri->rk.rd,
- buf_rd,
- sizeof(buf_rd)));
- }
+ vnc_zlog_debug_verbose(
+ "%s: move route to recently deleted list, rd=%pRD",
+ __func__, &ri->rk.rd);
#endif
} else {
@@ -1400,7 +1382,7 @@ callback:
rfapiRibStartTimer(rfd, ri_del, rn, 1);
RFAPI_RIB_CHECK_COUNTS(
0, delete_list->count);
- ri->last_sent_time = rfapi_time(NULL);
+ ri->last_sent_time = monotime(NULL);
}
}
} else {
@@ -1849,7 +1831,7 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
vnc_zlog_debug_verbose("%s: loading response=%p, use_eth_resolution=%d",
__func__, response, use_eth_resolution);
- new_last_sent_time = rfapi_time(NULL);
+ new_last_sent_time = monotime(NULL);
for (nhp = response; nhp; nhp = nhp_next) {
@@ -2019,7 +2001,7 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
ri->lifetime = nhp->lifetime;
ri->vn_options = rfapiVnOptionsDup(nhp->vn_options);
ri->rsp_counter = rfd->rsp_counter;
- ri->last_sent_time = rfapi_time(NULL);
+ ri->last_sent_time = monotime(NULL);
if (need_insert) {
int rc;
@@ -2042,7 +2024,7 @@ rfapiRibPreload(struct bgp *bgp, struct rfapi_descriptor *rfd,
* update this NVE's timestamp for this prefix
*/
trn = agg_node_get(rfd->rsp_times[afi], &pfx); /* locks trn */
- trn->info = (void *)(uintptr_t)bgp_clock();
+ trn->info = (void *)(uintptr_t)monotime(NULL);
if (agg_node_get_lock_count(trn) > 1)
agg_unlock_node(trn);
@@ -2256,7 +2238,6 @@ static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,
char str_lifetime[BUFSIZ];
char str_age[BUFSIZ];
char *p;
- char str_rd[RD_ADDRSTRLEN];
++routes_displayed;
@@ -2275,7 +2256,7 @@ static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,
rfapiFormatAge(ri->last_sent_time, str_age, BUFSIZ);
#else
{
- time_t now = rfapi_time(NULL);
+ time_t now = monotime(NULL);
time_t expire =
ri->last_sent_time + (time_t)ri->lifetime;
/* allow for delayed/async removal */
@@ -2284,14 +2265,9 @@ static int print_rib_sl(int (*fp)(void *, const char *, ...), struct vty *vty,
}
#endif
- str_rd[0] = 0; /* start empty */
-#if DEBUG_RIB_SL_RD
- prefix_rd2str(&ri->rk.rd, str_rd, sizeof(str_rd));
-#endif
-
- fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %s\n",
+ fp(out, " %c %-20s %-15s %-15s %-4u %-8s %-8s %pRD\n",
deleted ? 'r' : ' ', *printedprefix ? "" : str_pfx, str_vn,
- str_un, ri->cost, str_lifetime, str_age, str_rd);
+ str_un, ri->cost, str_lifetime, str_age, &ri->rk.rd);
if (!*printedprefix)
*printedprefix = 1;
diff --git a/bgpd/rfapi/rfapi_vty.c b/bgpd/rfapi/rfapi_vty.c
index c8fdadcac9..23f43fa7d3 100644
--- a/bgpd/rfapi/rfapi_vty.c
+++ b/bgpd/rfapi/rfapi_vty.c
@@ -109,7 +109,7 @@ char *rfapiFormatAge(time_t age, char *buf, size_t len)
{
time_t now, age_adjusted;
- now = rfapi_time(NULL);
+ now = monotime(NULL);
age_adjusted = now - age;
return rfapiFormatSeconds(age_adjusted, buf, len);
@@ -1537,14 +1537,6 @@ void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p)
fp(out, "?/?:?");
}
-void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd)
-{
- char buf[RD_ADDRSTRLEN];
-
- prefix_rd2str(prd, buf, sizeof(buf));
- vty_out(vty, "%s", buf);
-}
-
void rfapiPrintAdvertisedInfo(struct vty *vty, struct rfapi_descriptor *rfd,
safi_t safi, struct prefix *p)
{
@@ -1615,7 +1607,7 @@ void rfapiPrintDescriptor(struct vty *vty, struct rfapi_descriptor *rfd)
vty_out(vty, " ");
rfapiPrintRfapiIpAddr(vty, &rfd->vn_addr);
vty_out(vty, " %p %p ", rfd->response_cb, rfd->cookie);
- rfapiPrintRd(vty, &rfd->rd);
+ vty_out(vty, "%pRD", &rfd->rd);
vty_out(vty, " %d", rfd->response_lifetime);
vty_out(vty, " %s", (rfd->rfg ? rfd->rfg->name : "<orphaned>"));
vty_out(vty, "%s", HVTYNL);
diff --git a/bgpd/rfapi/rfapi_vty.h b/bgpd/rfapi/rfapi_vty.h
index b5e1c38b0d..09e1b3c4c4 100644
--- a/bgpd/rfapi/rfapi_vty.h
+++ b/bgpd/rfapi/rfapi_vty.h
@@ -93,8 +93,6 @@ extern void rfapiPrintRfapiIpAddr(void *stream, struct rfapi_ip_addr *a);
extern void rfapiPrintRfapiIpPrefix(void *stream, struct rfapi_ip_prefix *p);
-void rfapiPrintRd(struct vty *vty, struct prefix_rd *prd);
-
extern void rfapiPrintAdvertisedInfo(struct vty *vty,
struct rfapi_descriptor *rfd, safi_t safi,
struct prefix *p);
diff --git a/bgpd/subdir.am b/bgpd/subdir.am
index 9e3a095529..b1eeb937e1 100644
--- a/bgpd/subdir.am
+++ b/bgpd/subdir.am
@@ -232,6 +232,7 @@ clippy_scan += \
bgpd/bgp_bmp.c \
bgpd/bgp_debug.c \
bgpd/bgp_evpn_vty.c \
+ bgpd/bgp_labelpool.c \
bgpd/bgp_route.c \
bgpd/bgp_routemap.c \
bgpd/bgp_rpki.c \
diff --git a/configure.ac b/configure.ac
index b7e17d3565..4e1080045e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -7,7 +7,7 @@
##
AC_PREREQ([2.69])
-AC_INIT([frr], [8.4-dev], [https://github.com/frrouting/frr/issues])
+AC_INIT([frr], [8.5-dev], [https://github.com/frrouting/frr/issues])
PACKAGE_URL="https://frrouting.org/"
AC_SUBST([PACKAGE_URL])
PACKAGE_FULLNAME="FRRouting"
@@ -1372,7 +1372,7 @@ case "${enable_vtysh}" in
AC_DEFINE([VTYSH], [1], [VTY shell])
prev_libs="$LIBS"
- AC_CHECK_LIB([readline], [main], [
+ AC_CHECK_LIB([readline], [readline], [
LIBREADLINE="-lreadline"
], [
dnl readline failed - it might be incorrectly linked and missing its
diff --git a/debian/changelog b/debian/changelog
index 9c14270b66..ad43f13e33 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,9 @@
+frr (8.5~dev-1) UNRELEASED; urgency=medium
+
+ * FRR Dev 8.5
+
+ -- Donatas Abraitis <donatas@opensourcerouting.org> Tue, 04 Oct 2022 16:00:00 +0500
+
frr (8.4~dev-1) UNRELEASED; urgency=medium
* FRR Dev 8.4
diff --git a/debian/control b/debian/control
index e8bf1a8ffa..06c16cc945 100644
--- a/debian/control
+++ b/debian/control
@@ -30,6 +30,7 @@ Build-Depends: bison,
python3-pytest <!nocheck>,
python3-sphinx,
texinfo (>= 4.7),
+ lua5.3 <pkg.frr.lua>,
liblua5.3-dev <pkg.frr.lua>
Standards-Version: 4.5.0.3
Homepage: https://www.frrouting.org/
diff --git a/debian/frr.logrotate b/debian/frr.logrotate
index 1e0e726cb4..735af6539b 100644
--- a/debian/frr.logrotate
+++ b/debian/frr.logrotate
@@ -17,7 +17,7 @@
# open, as well as the daemons, so always signal the daemons.
# It's safe, a NOP if (only) syslog is being used.
for i in babeld bgpd eigrpd isisd ldpd nhrpd ospf6d ospfd sharpd \
- pimd ripd ripngd zebra pathd pbrd staticd bfdd fabricd vrrpd; do
+ pimd pim6d ripd ripngd zebra pathd pbrd staticd bfdd fabricd vrrpd; do
if [ -e /var/run/frr/$i.pid ] ; then
pids="$pids $(cat /var/run/frr/$i.pid)"
fi
diff --git a/doc/developer/topotests.rst b/doc/developer/topotests.rst
index 6c1d9148d1..ada182d847 100644
--- a/doc/developer/topotests.rst
+++ b/doc/developer/topotests.rst
@@ -38,6 +38,12 @@ Installing Topotest Requirements
# To enable the gRPC topotest install:
python3 -m pip install grpcio grpcio-tools
+ # Install Socat tool to run PIMv6 tests,
+ # Socat code can be taken from below url,
+ # which has latest changes done for PIMv6,
+ # join and traffic:
+ https://github.com/opensourcerouting/socat/
+
Enable Coredumps
""""""""""""""""
diff --git a/doc/user/bfd.rst b/doc/user/bfd.rst
index c47ed04f63..0eb1064519 100644
--- a/doc/user/bfd.rst
+++ b/doc/user/bfd.rst
@@ -518,6 +518,10 @@ You can inspect the current BFD peer status with the following commands:
frr# show bfd peer 192.168.0.1 json
{"multihop":false,"peer":"192.168.0.1","id":1,"remote-id":1,"status":"up","uptime":161,"diagnostic":"ok","remote-diagnostic":"ok","receive-interval":300,"transmit-interval":300,"echo-receive-interval":50,"echo-transmit-interval":0,"detect-multiplier":3,"remote-receive-interval":300,"remote-transmit-interval":300,"remote-echo-receive-interval":50,"remote-detect-multiplier":3,"peer-type":"dynamic"}
+If you are running IPV4 BFD Echo, on a Linux platform, we also
+calculate round trip time for the packets. We display minimum,
+average and maximum time it took to receive the looped Echo packets
+in the RTT fields.
You can inspect the current BFD peer status in brief with the following commands:
diff --git a/doc/user/bgp.rst b/doc/user/bgp.rst
index 7993dd96c2..25d1cbfb6b 100644
--- a/doc/user/bgp.rst
+++ b/doc/user/bgp.rst
@@ -1672,7 +1672,7 @@ Configuring Peers
.. clicmd:: bgp fast-external-failover
- This command causes bgp to not take down ebgp peers immediately
+ This command causes bgp to take down ebgp peers immediately
when a link flaps. `bgp fast-external-failover` is the default
and will not be displayed as part of a `show run`. The no form
of the command turns off this ability.
@@ -1775,6 +1775,15 @@ Configuring Peers
default, the DelayOpenTimer is disabled. The timer interval may be set to a
duration of 1 to 240 seconds.
+.. clicmd:: neighbor PEER extended-optional-parameters
+
+ Force the extended optional parameters format for OPEN messages. By default,
+ optional parameters length is 255 octets. With more and more BGP capabilities
+ implemented on top of BGP, this is needed to extend this value.
+
+ This is turned off by default, but it's automatically enabled when this limit
+ is hit. You can force this new encoding to be enabled with this command.
+
.. clicmd:: bgp minimum-holdtime (1-65535)
This command allows user to prevent session establishment with BGP peers
@@ -2341,11 +2350,8 @@ setting BGP communities attribute to the updates.
exit-address-family
!
bgp community-list 70 permit 7675:70
- bgp community-list 70 deny
bgp community-list 80 permit 7675:80
- bgp community-list 80 deny
bgp community-list 90 permit 7675:90
- bgp community-list 90 deny
!
route-map RMAP permit 10
match community 70
@@ -2500,6 +2506,9 @@ Extended Community Lists
there is no matched entry, deny will be returned. When `extcommunity` is
empty it matches to any routes.
+ A special handling for ``internet`` community is applied. It matches
+ any community.
+
.. clicmd:: bgp extcommunity-list expanded NAME permit|deny LINE
This command defines a new expanded extcommunity-list. `line` is a string
@@ -2727,6 +2736,25 @@ are reached using *core* MPLS labels which are distributed using LDP or BGP
labeled unicast. *bgpd* also supports inter-VRF route leaking.
+L3VPN over GRE interfaces
+^^^^^^^^^^^^^^^^^^^^^^^^^
+
+In MPLS-VPN or SRv6-VPN, an L3VPN next-hop entry requires that the path
+chosen respectively contains a labelled path or a valid SID IPv6 address.
+Otherwise the L3VPN entry will not be installed. It is possible to ignore
+that check when the path chosen by the next-hop uses a GRE interface, and
+there is a route-map configured at inbound side of ipv4-vpn or ipv6-vpn
+address family with following syntax:
+
+.. clicmd:: set l3vpn next-hop encapsulation gre
+
+The incoming BGP L3VPN entry is accepted, provided that the next hop of the
+L3VPN entry uses a path that takes the GRE tunnel as outgoing interface. The
+remote endpoint should be configured just behind the GRE tunnel; remote
+device configuration may vary depending whether it acts at edge endpoint or
+not: in any case, the expectation is that incoming MPLS traffic received at
+this endpoint should be considered as a valid path for L3VPN.
+
.. _bgp-vrf-route-leaking:
VRF Route Leaking
@@ -2842,6 +2870,26 @@ of the global VPNv4/VPNv6 family. This command defaults to on and is not
displayed.
The `no bgp retain route-target all` form of the command is displayed.
+.. clicmd:: neighbor <A.B.C.D|X:X::X:X|WORD> soo EXTCOMMUNITY
+
+Without this command, SoO extended community attribute is configured using
+an inbound route map that sets the SoO value during the update process.
+With the introduction of the new BGP per-neighbor Site-of-Origin (SoO) feature,
+two new commands configured in sub-modes under router configuration mode
+simplify the SoO value configuration.
+
+If we configure SoO per neighbor at PEs, the SoO community is automatically
+added for all routes from the CPEs. Routes are validated and prevented from
+being sent back to the same CPE (e.g.: multi-site). This is especially needed
+when using ``as-override`` or ``allowas-in`` to prevent routing loops.
+
+.. clicmd:: mpls bgp forwarding
+
+It is possible to permit BGP install VPN prefixes without transport labels,
+by issuing the following command under the interface configuration context.
+This configuration will install VPN prefixes originated from an e-bgp session,
+and with the next-hop directly connected.
+
.. _bgp-l3vpn-srv6:
L3VPN SRv6
@@ -3456,6 +3504,10 @@ Debugging
library messages and BGP BFD integration messages that are mostly state
transitions and validation problems.
+.. clicmd:: debug bgp conditional-advertisement
+
+ Enable or disable debugging of BGP conditional advertisement.
+
.. clicmd:: debug bgp neighbor-events
Enable or disable debugging for neighbor events. This provides general
@@ -3816,6 +3868,10 @@ structure is extended with :clicmd:`show bgp [afi] [safi]`.
If the ``json`` option is specified, output is displayed in JSON format.
+.. clicmd:: show [ip] bgp [afi] [safi] [all] access-list WORD [wide|json]
+
+ Display routes that match the specified access-list.
+
.. clicmd:: show [ip] bgp [afi] [safi] [all] filter-list WORD [wide|json]
Display routes that match the specified AS-Path filter-list.
diff --git a/doc/user/ospfd.rst b/doc/user/ospfd.rst
index 26810bd883..3bb018548e 100644
--- a/doc/user/ospfd.rst
+++ b/doc/user/ospfd.rst
@@ -1060,78 +1060,83 @@ TI-LFA requires a proper Segment Routing configuration.
Debugging OSPF
==============
-.. clicmd:: debug ospf bfd
+.. clicmd:: debug ospf [(1-65535)] bfd
Enable or disable debugging for BFD events. This will show BFD integration
library messages and OSPF BFD integration messages that are mostly state
transitions and validation problems.
-.. clicmd:: debug ospf client-api
+.. clicmd:: debug ospf [(1-65535)] client-api
Show debug information for the OSPF opaque data client API.
-.. clicmd:: debug ospf packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
+.. clicmd:: debug ospf [(1-65535)] default-information
+ Show debug information of default information
- Dump Packet for debugging
+.. clicmd:: debug ospf [(1-65535)] packet (hello|dd|ls-request|ls-update|ls-ack|all) (send|recv) [detail]
-.. clicmd:: debug ospf ism
-.. clicmd:: debug ospf ism (status|events|timers)
+ Dump Packet for debugging
+.. clicmd:: debug ospf [(1-65535)] ism [status|events|timers]
- Show debug information of Interface State Machine
-.. clicmd:: debug ospf nsm
+ Show debug information of Interface State Machine
-.. clicmd:: debug ospf nsm (status|events|timers)
+.. clicmd:: debug ospf [(1-65535)] nsm [status|events|timers]
Show debug information of Network State Machine
-.. clicmd:: debug ospf event
+.. clicmd:: debug ospf [(1-65535)] event
Show debug information of OSPF event
-.. clicmd:: debug ospf nssa
+.. clicmd:: debug ospf [(1-65535)] nssa
Show debug information about Not So Stub Area
-.. clicmd:: debug ospf lsa
+.. clicmd:: debug ospf [(1-65535)] ldp-sync
+
+ Show debug information about LDP-Sync
-.. clicmd:: debug ospf lsa (generate|flooding|refresh)
+.. clicmd:: debug ospf [(1-65535)] lsa [aggregate|flooding|generate|install|refresh]
Show debug detail of Link State messages
-.. clicmd:: debug ospf te
+.. clicmd:: debug ospf [(1-65535)] sr
+
+ Show debug information about Segment Routing
+
+.. clicmd:: debug ospf [(1-65535)] te
Show debug information about Traffic Engineering LSA
-.. clicmd:: debug ospf zebra
+.. clicmd:: debug ospf [(1-65535)] ti-lfa
-.. clicmd:: debug ospf zebra (interface|redistribute)
+ Show debug information about SR TI-LFA
+
+.. clicmd:: debug ospf [(1-65535)] zebra [interface|redistribute]
Show debug information of ZEBRA API
-.. clicmd:: debug ospf graceful-restart helper
+.. clicmd:: debug ospf [(1-65535)] graceful-restart
Enable/disable debug information for OSPF Graceful Restart Helper
.. clicmd:: show debugging ospf
-.. clicmd:: debug ospf lsa aggregate
-
- Debug commnd to enable/disable external route summarisation specific debugs.
Sample Configuration
diff --git a/doc/user/overview.rst b/doc/user/overview.rst
index bf401825e0..4a24fa52be 100644
--- a/doc/user/overview.rst
+++ b/doc/user/overview.rst
@@ -258,7 +258,7 @@ feature you're interested in, it should be supported on your platform.
+-----------------------------------+----------------+--------------+------------+------------+
| **Multicast Routing** | | | | |
+-----------------------------------+----------------+--------------+------------+------------+
-| `pimd` (PIM) | :mark:`≥4.18` | :mark:`N` | :mark:`Y` | :mark:`Y` |
+| `pimd` (PIM) | :mark:`≥4.19` | :mark:`N` | :mark:`Y` | :mark:`Y` |
+-----------------------------------+----------------+--------------+------------+------------+
| SSM (Source Specific) | :mark:`Y` | :mark:`N` | :mark:`Y` | :mark:`Y` |
+-----------------------------------+----------------+--------------+------------+------------+
@@ -310,39 +310,64 @@ BGP
:t:`Autonomous System Confederations for BGP. P. Traina. June 1996.`
- :rfc:`1997`
:t:`BGP Communities Attribute. R. Chandra, P. Traina & T. Li. August 1996.`
+- :rfc:`1998`
+ :t:`An Application of the BGP Community Attribute in Multi-home Routing. E. Chen, T. Bates. August 1996.`
+- :rfc:`2385`
+ :t:`Protection of BGP Sessions via the TCP MD5 Signature Option. A. Heffernan. August 1998.`
- :rfc:`2439`
:t:`BGP Route Flap Damping. C. Villamizar, R. Chandra, R. Govindan. November 1998.`
- :rfc:`2545`
- :t:`Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing. P.
- Marques, F. Dupont. March 1999.`
+ :t:`Use of BGP-4 Multiprotocol Extensions for IPv6 Inter-Domain Routing. P. Marques, F. Dupont. March 1999.`
- :rfc:`2796`
:t:`BGP Route Reflection An alternative to full mesh IBGP. T. Bates & R. Chandrasekeran. June 1996.`
- :rfc:`2842`
:t:`Capabilities Advertisement with BGP-4. R. Chandra, J. Scudder. May 2000.`
- :rfc:`2858`
- :t:`Multiprotocol Extensions for BGP-4. T. Bates, Y. Rekhter, R. Chandra, D.`
+ :t:`Multiprotocol Extensions for BGP-4. T. Bates, Y. Rekhter, R. Chandra, D. Katz. June 2000.`
+- :rfc:`2918`
+ :t:`Route Refresh Capability for BGP-4. E. Chen, September 2000.`
- :rfc:`3107`
:t:`Carrying Label Information in BGP-4. Y. Rekhter & E. Rosen. May 2001.`
- :rfc:`3765`
- :t:`NOPEER Community for Border Gateway Protocol (BGP) Route Scope Control. G.Huston, April 2001.`
+ :t:`NOPEER Community for Border Gateway Protocol (BGP) Route Scope Control. G.Huston. April 2001.`
- :rfc:`4271`
:t:`A Border Gateway Protocol 4 (BGP-4). Updates RFC1771. Y. Rekhter, T. Li & S. Hares. January 2006.`
+- :rfc:`4360`
+ :t:`BGP Extended Communities Attribute. S. Sangli, D. Tappan, Y. Rekhter. February 2006.`
- :rfc:`4364`
- :t:`BGP/MPLS IP Virtual Private Networks (VPNs). Y. Rekhter. Feb 2006.`
+ :t:`BGP/MPLS IP Virtual Private Networks (VPNs). Y. Rekhter. February 2006.`
+- :rfc:`4456`
+ :t:`BGP Route Reflection An alternative to full mesh IBGP. T. Bates, E. Chen, R. Chandra. April 2006.`
- :rfc:`4486`
:t:`Subcodes for BGP Cease Notification Message. E. Chen, V. Gillet. April 2006.`
- :rfc:`4659`
:t:`BGP-MPLS IP Virtual Private Network (VPN) Extension for IPv6 VPN. J. De Clercq, D. Ooms, M. Carugi, F. Le Faucheur. September 2006.`
+- :rfc:`4724`
+ :t:`Graceful Restart Mechanism for BGP. S. Sangli, E. Chen, R. Fernando, J. Scudder, Y. Rekhter. January 2007.`
+- :rfc:`4760`
+ :t:`Multiprotocol Extensions for BGP-4. T. Bates, R. Chandra, D. Katz, Y. Rekhter. January 2007.`
- :rfc:`4893`
:t:`BGP Support for Four-octet AS Number Space. Q. Vohra, E. Chen May 2007.`
- :rfc:`5004`
:t:`Avoid BGP Best Path Transitions from One External to Another. E. Chen & S. Sangli. September 2007 (Partial support).`
+- :rfc:`5065`
+ :t:`Autonomous System Confederations for BGP. P. Traina, D. McPherson, J. Scudder. August 2007.`
- :rfc:`5082`
:t:`The Generalized TTL Security Mechanism (GTSM). V. Gill, J. Heasley, D. Meyer, P. Savola, C. Pingnataro. October 2007.`
+- :rfc:`5291`
+ :t:`Outbound Route Filtering Capability. E. Chen, Y. Rekhter. August 2008.`
+- :rfc:`5292`
+ :t:`Address-Prefix-Based Outbound Route Filter for BGP-4. E. Chen, S. Sangli. August 2008.`
+- :rfc:`5492`
+ :t:`Capabilities Advertisement with BGP-4. J. Scudder, R. Chandra. February 2009.`
- :rfc:`5575`
- :t:`Dissemination of Flow Specification Rules. P. Marques, N. Sheth, R. Raszuk, B. Greene, J. Mauch, D. McPherson. August 2009`
+ :t:`Dissemination of Flow Specification Rules. P. Marques, N. Sheth, R. Raszuk, B. Greene, J. Mauch, D. McPherson. August 2009.`
+- :rfc:`5668`
+ :t:`4-Octet AS Specific BGP Extended Community. Y. Rekhter, S. Sangli, D. Tappan October 2009.`
- :rfc:`6286`
- :t:`Autonomous-System-Wide Unique BGP Identifier for BGP-4. E. Chen, J. Yuan, June 2011.`
+ :t:`Autonomous-System-Wide Unique BGP Identifier for BGP-4. E. Chen, J. Yuan. June 2011.`
+- :rfc:`6472`
+ :t:`Recommendation for Not Using AS_SET and AS_CONFED_SET in BGP. W. Kumari, K. Sriram. December 2011.`
- :rfc:`6608`
:t:`Subcodes for BGP Finite State Machine Error. J. Dong, M. Chen, Huawei Technologies, A. Suryanarayana, Cisco Systems. May 2012.`
- :rfc:`6810`
@@ -351,6 +376,8 @@ BGP
:t:`BGP Prefix Origin Validation. P. Mohapatra, J. Scudder, D. Ward, R. Bush, R. Austein. January 2013.`
- :rfc:`6938`
:t:`Deprecation of BGP Path Attributes: DPA, ADVERTISER, and RCID_PATH / CLUSTER_ID. J. Scudder. May 2013.`
+- :rfc:`6996`
+ :t:`Autonomous System (AS) Reservation for Private Use. J. Mitchell. July 2013.`
- :rfc:`7196`
:t:`Making Route Flap Damping Usable. C. Pelsser, R. Bush, K. Patel, P. Mohapatra, O. Maennel. May 2014.`
- :rfc:`7300`
@@ -363,28 +390,40 @@ BGP
:t:`Codification of AS 0 Processing. W. Kumari, R. Bush, H. Schiller, K. Patel. August 2015.`
- :rfc:`7611`
:t:`BGP ACCEPT_OWN Community Attribute. J. Uttaro, P. Mohapatra, D. Smith, R. Raszuk, J. Scudder. August 2015.`
+- :rfc:`7911`
+ :t:`Advertisement of Multiple Paths in BGP. D. Walton, A. Retana, E. Chen, J. Scudder. July 2016.`
+- :rfc:`7947`
+ :t:`Internet Exchange BGP Route Server. E. Jasinska, N. Hilliard, R. Raszuk, N. Bakker. September 2016.`
- :rfc:`7999`
- :t:`BLACKHOLE Community. T. King, C. Dietzel, J. Snijders, G. Doering, G. Hankins. Oct 2016.`
+ :t:`BLACKHOLE Community. T. King, C. Dietzel, J. Snijders, G. Doering, G. Hankins. October 2016.`
+- :rfc:`8050`
+ :t:`Multi-Threaded Routing Toolkit (MRT) Routing Information Export Format with BGP Additional Path Extensions. C. Petrie, T. King. May 2017.`
- :rfc:`8092`
- :t:`BGP Large Communities Attribute. J. Heitz, Ed., J. Snijders, Ed, K. Patel, I. Bagdonas, N. Hilliard. February 2017`
+ :t:`BGP Large Communities Attribute. J. Heitz, Ed., J. Snijders, Ed, K. Patel, I. Bagdonas, N. Hilliard. February 2017.`
+- :rfc:`8093`
+ :t:`Deprecation of BGP Path Attribute Values 30, 31, 129, 241, 242, and 243. J. Snijders. February 2017.`
+- :rfc:`8097`
+ :t:`BGP Prefix Origin Validation State Extended Community. P. Mohapatra, K. Patel, J. Scudder, D. Ward, R. Bush. March 2017.`
- :rfc:`8195`
- :t:`Use of BGP Large Communities. J. Snijders, J. Heasley, M. Schmidt, June 2017`
+ :t:`Use of BGP Large Communities. J. Snijders, J. Heasley, M. Schmidt. June 2017.`
- :rfc:`8203`
:t:`BGP Administrative Shutdown Communication. J. Snijders, J. Heitz, J. Scudder. July 2017.`
- :rfc:`8212`
- :t:`Default External BGP (EBGP) Route Propagation Behavior without Policies. J. Mauch, J. Snijders, G. Hankins. July 2017`
+ :t:`Default External BGP (EBGP) Route Propagation Behavior without Policies. J. Mauch, J. Snijders, G. Hankins. July 2017.`
- :rfc:`8277`
- :t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017`
+ :t:`Using BGP to Bind MPLS Labels to Address Prefixes. E. Rosen. October 2017.`
- :rfc:`8538`
- :t:`Notification Message Support for BGP Graceful Restart. K. Patel, R. Fernando, J. Scudder, J. Haas. March 2019`
+ :t:`Notification Message Support for BGP Graceful Restart. K. Patel, R. Fernando, J. Scudder, J. Haas. March 2019.`
- :rfc:`8654`
- :t:`Extended Message Support for BGP. R. Bush, K. Patel, D. Ward. October 2019`
+ :t:`Extended Message Support for BGP. R. Bush, K. Patel, D. Ward. October 2019.`
- :rfc:`9003`
- :t:`Extended BGP Administrative Shutdown Communication. J. Snijders, J. Heitz, J. Scudder, A. Azimov. January 2021`
+ :t:`Extended BGP Administrative Shutdown Communication. J. Snijders, J. Heitz, J. Scudder, A. Azimov. January 2021.`
+- :rfc:`9012`
+ :t:`The BGP Tunnel Encapsulation Attribute. K. Patel, G. Van de Velde, S. Sangli, J. Scudder. April 2021.`
- :rfc:`9072`
- :t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021`
+ :t:`Extended Optional Parameters Length for BGP OPEN Message. E. Chen, J. Scudder. July 2021.`
- :rfc:`9234`
- :t:`Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages. A. Azimov, E. Bogomazov, R. Bush, K. Patel, K. Sriram. May 2022`
+ :t:`Route Leak Prevention and Detection Using Roles in UPDATE and OPEN Messages. A. Azimov, E. Bogomazov, R. Bush, K. Patel, K. Sriram. May 2022.`
OSPF
----
diff --git a/doc/user/pim.rst b/doc/user/pim.rst
index ae39f4220d..44ade916a2 100644
--- a/doc/user/pim.rst
+++ b/doc/user/pim.rst
@@ -13,7 +13,7 @@ network for optimizing forwarding of overlay BUM traffic.
.. note::
- On Linux for PIM-SM operation you *must* have kernel version 4.18 or greater.
+ On Linux for PIM-SM operation you *must* have kernel version 4.19 or greater.
To use PIM for EVPN BUM forwarding, kernels 5.0 or greater are required.
OpenBSD has no multicast support and FreeBSD, and NetBSD only
have support for SSM.
diff --git a/doc/user/pimv6.rst b/doc/user/pimv6.rst
index bda9eaec80..b242f4fe17 100644
--- a/doc/user/pimv6.rst
+++ b/doc/user/pimv6.rst
@@ -195,7 +195,7 @@ is in a vrf, enter the interface command with the vrf keyword at the end.
Set the MLD last member query count. The default value is 2. 'no' form of
this command is used to configure back to the default value.
-.. clicmd:: ipv6 MLD last-member-query-interval (1-65535)
+.. clicmd:: ipv6 mld last-member-query-interval (1-65535)
Set the MLD last member query interval in deciseconds. The default value is
10 deciseconds. 'no' form of this command is used to to configure back to the
@@ -325,6 +325,9 @@ MLD state
a MLDv2 querier. MLDv1 joins are recorded as "untracked" and shown in the
``NonTrkSeen`` output column.
+.. clicmd:: show ipv6 mld [vrf NAME] groups [json]
+
+ Display MLD group information.
General multicast routing state
-------------------------------
@@ -389,6 +392,11 @@ Clear commands reset various variables.
Reset PIMv6 interfaces.
+.. clicmd:: clear ipv6 pim [vrf NAME] interface traffic
+
+ When this command is issued, resets the information about the
+ number of PIM protocol packets sent/received on an interface.
+
.. clicmd:: clear ipv6 pim oil
Rescan PIMv6 OIL (output interface list).
@@ -408,6 +416,10 @@ configure CLI mode. If you specify debug commands in the configuration cli
mode, the debug commands can be persistent across restarts of the FRR pim6d if
the config was written out.
+.. clicmd:: debug mld
+
+ This turns on debugging for MLD protocol activity.
+
.. clicmd:: debug pimv6 events
This turns on debugging for PIMv6 system events. Especially timers.
@@ -440,3 +452,23 @@ the config was written out.
.. clicmd:: debug pimv6 zebra
This gathers data about events from zebra that come up through the ZAPI.
+
+.. clicmd:: debug mroute6
+
+ This turns on debugging for PIMv6 interaction with kernel MFC cache.
+
+.. clicmd:: debug mroute6 detail
+
+ This turns on detailed debugging for PIMv6 interaction with kernel MFC cache.
+
+.. clicmd:: debug mld events
+
+ This turns on debugging for MLD system events.
+
+.. clicmd:: debug mld packets
+
+ This turns on information about MLD protocol packets handling.
+
+.. clicmd:: debug mld trace [detail]
+
+ This traces mld code and how it is running.
diff --git a/doc/user/ripd.rst b/doc/user/ripd.rst
index 0a155bf489..66bdd26f1a 100644
--- a/doc/user/ripd.rst
+++ b/doc/user/ripd.rst
@@ -119,14 +119,14 @@ RIP Configuration
.. clicmd:: neighbor A.B.C.D
- Specify RIP neighbor. When a neighbor doesn't understand multicast, this
- command is used to specify neighbors. In some cases, not all routers will be
- able to understand multicasting, where packets are sent to a network or a
- group of addresses. In a situation where a neighbor cannot process multicast
- packets, it is necessary to establish a direct link between routers. The
- neighbor command allows the network administrator to specify a router as a
- RIP neighbor. The `no neighbor a.b.c.d` command will disable the RIP
- neighbor.
+ Specify a RIP neighbor to send updates to. This is required when a neighbor
+ is connected via a network that does not support multicast, or when it is
+ desired to statically define a neighbor. RIP updates will be sent via unicast
+ to each neighbour. Neighbour updates are in addition to any multicast updates
+ sent when an interface is not in passive mode (see the `passive-interface`
+ command). RIP will continue to process updates received from both the
+ neighbor and any received via multicast. The `no neighbor a.b.c.d` command
+ will disable the RIP neighbor.
Below is very simple RIP configuration. Interface `eth0` and interface which
address match to `10.0.0.0/8` are RIP enabled.
diff --git a/doc/user/routemap.rst b/doc/user/routemap.rst
index 05c9eeb755..5e222576ca 100644
--- a/doc/user/routemap.rst
+++ b/doc/user/routemap.rst
@@ -339,6 +339,9 @@ Route Map Set Command
Set the color of a SR-TE Policy to be applied to a learned route. The SR-TE
Policy is uniquely determined by the color and the BGP nexthop.
+.. clicmd:: set l3vpn next-hop encapsulation gre
+
+ Accept L3VPN traffic over GRE encapsulation.
.. _route-map-call-command:
diff --git a/doc/user/rpki.rst b/doc/user/rpki.rst
index cc0e7f70c6..4053536247 100644
--- a/doc/user/rpki.rst
+++ b/doc/user/rpki.rst
@@ -178,6 +178,12 @@ Validating BGP Updates
match rpki valid
set local-preference 500
+.. clicmd:: match rpki-extcommunity notfound|invalid|valid
+
+ Create a clause for a route map to match prefixes with the specified RPKI
+ state, that is derived from the Origin Validation State extended community
+ attribute (OVS). OVS extended community is non-transitive and is exchanged
+ only between iBGP peers.
.. _debugging:
diff --git a/doc/user/setup.rst b/doc/user/setup.rst
index 25934df9cb..dcc7607e48 100644
--- a/doc/user/setup.rst
+++ b/doc/user/setup.rst
@@ -111,7 +111,7 @@ reasons touched on in the VTYSH documentation and should generally be enabled.
This allows the operator to control the number of open file descriptors
each daemon is allowed to start with. The current assumed value on
most operating systems is 1024. If the operator plans to run bgp with
-several thousands of peers than this is where we would modify FRR to
+several thousands of peers then this is where we would modify FRR to
allow this to happen.
::
diff --git a/doc/user/vtysh.rst b/doc/user/vtysh.rst
index 97b3863ef5..1ab54f09ab 100644
--- a/doc/user/vtysh.rst
+++ b/doc/user/vtysh.rst
@@ -177,11 +177,7 @@ Writing the configuration can be triggered directly by invoking *vtysh -w*.
This may be useful for scripting. Note this command should be run as either the
superuser or the FRR user.
-We recommend you do not mix the use of the two types of files. Further, it is
-better not to use the integrated :file:`frr.conf` file, as any syntax error in
-it can lead to /all/ of your daemons being unable to start up. Per daemon files
-are more robust as impact of errors in configuration are limited to the daemon
-in whose file the error is made.
+We recommend you do not mix the use of the two types of files.
.. clicmd:: service integrated-vtysh-config
diff --git a/doc/user/zebra.rst b/doc/user/zebra.rst
index d96df0ce52..05990e2523 100644
--- a/doc/user/zebra.rst
+++ b/doc/user/zebra.rst
@@ -155,6 +155,13 @@ Standard Commands
Set description for the interface.
+.. clicmd:: mpls enable
+
+ Enable or disable mpls kernel processing on the interface, for linux. Interfaces
+ configured with mpls will not automatically turn on if mpls kernel modules do not
+ happen to be loaded. This command will fail on 3.X linux kernels and does not
+ work on non-linux systems at all.
+
.. clicmd:: multicast
diff --git a/docker/alpine/Dockerfile b/docker/alpine/Dockerfile
index 187b528524..b9278dbb88 100644
--- a/docker/alpine/Dockerfile
+++ b/docker/alpine/Dockerfile
@@ -12,16 +12,6 @@ RUN apk add \
&& echo 'builder ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers
RUN adduser -D -G abuild builder && su builder -c 'abuild-keygen -a -n'
-# This stage builds a libyang APK from source
-FROM alpine-builder as libyang-builder
-RUN mkdir -p /libyang && chown -R builder /pkgs /libyang
-# -- Not currently needed - libyang currently available in Alpine upstream
-# COPY docker/alpine/libyang/ /libyang
-# USER builder
-# RUN cd /libyang \
-# && abuild checksum \
-# && abuild -r -P /pkgs/apk
-
# This stage builds a dist tarball from the source
FROM alpine:3.15 as source-builder
@@ -36,14 +26,7 @@ RUN source /src/alpine/APKBUILD.in \
py-pip \
rtrlib \
&& pip install pytest
-
RUN mkdir -p /pkgs/apk
-# -- Not needed while libyang is not built
-# COPY --from=libyang-builder /pkgs/apk/ /pkgs/apk/
-# RUN apk add \
-# --no-cache \
-# --allow-untrusted /pkgs/apk/*/*.apk \
-
COPY . /src
ARG PKGVER
RUN cd /src \
@@ -54,12 +37,7 @@ RUN cd /src \
&& make dist
# This stage builds an APK from the dist tarball
-FROM alpine-builder as frr-apk-builder
-# -- Not needed while libyang is not built
-# COPY --from=libyang-builder /pkgs/apk/ /pkgs/apk/
-# RUN apk add \
-# --no-cache \
-# --allow-untrusted /pkgs/apk/*/*.apk
+FROM alpine-builder as alpine-apk-builder
COPY --from=source-builder /src/frr-*.tar.gz /src/alpine/* /dist/
RUN find /pkgs/apk -type f -name APKINDEX.tar.gz -delete
RUN chown -R builder /dist /pkgs
@@ -72,7 +50,7 @@ RUN cd /dist \
# This stage installs frr from the apk
FROM alpine:3.15
RUN mkdir -p /pkgs/apk
-COPY --from=frr-apk-builder /pkgs/apk/ /pkgs/apk/
+COPY --from=alpine-apk-builder /pkgs/apk/ /pkgs/apk/
RUN apk add \
--no-cache \
--update-cache \
diff --git a/docker/alpine/build.sh b/docker/alpine/build.sh
index 3132feb9f1..80ee81c821 100755
--- a/docker/alpine/build.sh
+++ b/docker/alpine/build.sh
@@ -25,7 +25,16 @@ docker build \
--target=alpine-builder \
.
-CONTAINER_ID="$(docker create "frr:alpine-builder-$GITREV")"
+# Keep .apk files for debugging purposes, docker image as well.
+docker build \
+ --pull \
+ --file=docker/alpine/Dockerfile \
+ --build-arg="PKGVER=$PKGVER" \
+ --tag="frr:alpine-apk-builder-$GITREV" \
+ --target=alpine-apk-builder \
+ .
+
+CONTAINER_ID="$(docker create "frr:alpine-apk-builder-$GITREV")"
docker cp "${CONTAINER_ID}:/pkgs/" docker/alpine
docker rm "${CONTAINER_ID}"
@@ -36,3 +45,4 @@ docker build \
.
docker rmi "frr:alpine-builder-$GITREV"
+docker rmi "frr:alpine-apk-builder-$GITREV"
diff --git a/eigrpd/eigrp_network.c b/eigrpd/eigrp_network.c
index 6b3a0afc12..13db38ce91 100644
--- a/eigrpd/eigrp_network.c
+++ b/eigrpd/eigrp_network.c
@@ -69,8 +69,8 @@ int eigrp_sock_init(struct vrf *vrf)
AF_INET, SOCK_RAW, IPPROTO_EIGRPIGP, vrf->vrf_id,
vrf->vrf_id != VRF_DEFAULT ? vrf->name : NULL);
if (eigrp_sock < 0) {
- zlog_err("eigrp_read_sock_init: socket: %s",
- safe_strerror(errno));
+ zlog_err("%s: socket: %s",
+ __func__, safe_strerror(errno));
exit(1);
}
diff --git a/eigrpd/eigrp_packet.c b/eigrpd/eigrp_packet.c
index dd5ba8a164..1ea6f9813b 100644
--- a/eigrpd/eigrp_packet.c
+++ b/eigrpd/eigrp_packet.c
@@ -727,8 +727,8 @@ static struct stream *eigrp_recv_packet(struct eigrp *eigrp,
if ((unsigned int)ret < sizeof(*iph)) /* ret must be > 0 now */
{
zlog_warn(
- "eigrp_recv_packet: discarding runt packet of length %d (ip header size is %u)",
- ret, (unsigned int)sizeof(*iph));
+ "%s: discarding runt packet of length %d (ip header size is %u)",
+ __func__, ret, (unsigned int)sizeof(*iph));
return NULL;
}
@@ -772,8 +772,8 @@ static struct stream *eigrp_recv_packet(struct eigrp *eigrp,
if (ret != ip_len) {
zlog_warn(
- "eigrp_recv_packet read length mismatch: ip_len is %d, but recvmsg returned %d",
- ip_len, ret);
+ "%s read length mismatch: ip_len is %d, but recvmsg returned %d",
+ __func__, ip_len, ret);
return NULL;
}
diff --git a/eigrpd/eigrpd.c b/eigrpd/eigrpd.c
index 7bc7be9706..0ec9574813 100644
--- a/eigrpd/eigrpd.c
+++ b/eigrpd/eigrpd.c
@@ -163,7 +163,8 @@ static struct eigrp *eigrp_new(uint16_t as, vrf_id_t vrf_id)
if (eigrp->fd < 0) {
flog_err_sys(
EC_LIB_SOCKET,
- "eigrp_new: fatal error: eigrp_sock_init was unable to open a socket");
+ "%s: fatal error: eigrp_sock_init was unable to open a socket",
+ __func__);
exit(1);
}
diff --git a/gdb/lib.txt b/gdb/lib.txt
index 913b455ed1..b44c237985 100644
--- a/gdb/lib.txt
+++ b/gdb/lib.txt
@@ -293,3 +293,25 @@ Arguments:
1st: A (struct route_node *) to the top of the route table.
2nd: The (struct route_node *) to walk up from
end
+
+define mq_walk
+ set $mg = (struct memgroup *)$arg0
+
+ while ($mg)
+ printf "showing active allocations in memory group %s\n", $mg->name
+ set $mt = (struct memtype *)$mg->types
+ while ($mt)
+ printf "memstats: %s:%zu\n", $mt->name, $mt->n_alloc
+ set $mt = $mt->next
+ end
+ set $mg = $mg->next
+ end
+
+document mg_walk
+Walk the memory data structures to show what is holding memory.
+
+Arguments:
+1st: A (struct memgroup *) where to start the walk. If you are not
+ sure where to start pass it mg_first, which is a global DS for
+ all memory allocated in FRR
+end
diff --git a/include/linux/pkt_cls.h b/include/linux/pkt_cls.h
new file mode 100644
index 0000000000..7ea59cfe1f
--- /dev/null
+++ b/include/linux/pkt_cls.h
@@ -0,0 +1,776 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_PKT_CLS_H
+#define __LINUX_PKT_CLS_H
+
+#include <linux/types.h>
+#include <linux/pkt_sched.h>
+
+#define TC_COOKIE_MAX_SIZE 16
+
+/* Action attributes */
+enum {
+ TCA_ACT_UNSPEC,
+ TCA_ACT_KIND,
+ TCA_ACT_OPTIONS,
+ TCA_ACT_INDEX,
+ TCA_ACT_STATS,
+ TCA_ACT_PAD,
+ TCA_ACT_COOKIE,
+ TCA_ACT_FLAGS,
+ TCA_ACT_HW_STATS,
+ TCA_ACT_USED_HW_STATS,
+ __TCA_ACT_MAX
+};
+
+#define TCA_ACT_FLAGS_NO_PERCPU_STATS 1 /* Don't use percpu allocator for
+ * actions stats.
+ */
+
+/* tca HW stats type
+ * When user does not pass the attribute, he does not care.
+ * It is the same as if he would pass the attribute with
+ * all supported bits set.
+ * In case no bits are set, user is not interested in getting any HW statistics.
+ */
+#define TCA_ACT_HW_STATS_IMMEDIATE (1 << 0) /* Means that in dump, user
+ * gets the current HW stats
+ * state from the device
+ * queried at the dump time.
+ */
+#define TCA_ACT_HW_STATS_DELAYED (1 << 1) /* Means that in dump, user gets
+ * HW stats that might be out of date
+ * for some time, maybe couple of
+ * seconds. This is the case when
+ * driver polls stats updates
+ * periodically or when it gets async
+ * stats update from the device.
+ */
+
+#define TCA_ACT_MAX __TCA_ACT_MAX
+#define TCA_OLD_COMPAT (TCA_ACT_MAX+1)
+#define TCA_ACT_MAX_PRIO 32
+#define TCA_ACT_BIND 1
+#define TCA_ACT_NOBIND 0
+#define TCA_ACT_UNBIND 1
+#define TCA_ACT_NOUNBIND 0
+#define TCA_ACT_REPLACE 1
+#define TCA_ACT_NOREPLACE 0
+
+#define TC_ACT_UNSPEC (-1)
+#define TC_ACT_OK 0
+#define TC_ACT_RECLASSIFY 1
+#define TC_ACT_SHOT 2
+#define TC_ACT_PIPE 3
+#define TC_ACT_STOLEN 4
+#define TC_ACT_QUEUED 5
+#define TC_ACT_REPEAT 6
+#define TC_ACT_REDIRECT 7
+#define TC_ACT_TRAP 8 /* For hw path, this means "trap to cpu"
+ * and don't further process the frame
+ * in hardware. For sw path, this is
+ * equivalent of TC_ACT_STOLEN - drop
+ * the skb and act like everything
+ * is alright.
+ */
+#define TC_ACT_VALUE_MAX TC_ACT_TRAP
+
+/* There is a special kind of actions called "extended actions",
+ * which need a value parameter. These have a local opcode located in
+ * the highest nibble, starting from 1. The rest of the bits
+ * are used to carry the value. These two parts together make
+ * a combined opcode.
+ */
+#define __TC_ACT_EXT_SHIFT 28
+#define __TC_ACT_EXT(local) ((local) << __TC_ACT_EXT_SHIFT)
+#define TC_ACT_EXT_VAL_MASK ((1 << __TC_ACT_EXT_SHIFT) - 1)
+#define TC_ACT_EXT_OPCODE(combined) ((combined) & (~TC_ACT_EXT_VAL_MASK))
+#define TC_ACT_EXT_CMP(combined, opcode) (TC_ACT_EXT_OPCODE(combined) == opcode)
+
+#define TC_ACT_JUMP __TC_ACT_EXT(1)
+#define TC_ACT_GOTO_CHAIN __TC_ACT_EXT(2)
+#define TC_ACT_EXT_OPCODE_MAX TC_ACT_GOTO_CHAIN
+
+/* These macros are put here for binary compatibility with userspace apps that
+ * make use of them. For kernel code and new userspace apps, use the TCA_ID_*
+ * versions.
+ */
+#define TCA_ACT_GACT 5
+#define TCA_ACT_IPT 6
+#define TCA_ACT_PEDIT 7
+#define TCA_ACT_MIRRED 8
+#define TCA_ACT_NAT 9
+#define TCA_ACT_XT 10
+#define TCA_ACT_SKBEDIT 11
+#define TCA_ACT_VLAN 12
+#define TCA_ACT_BPF 13
+#define TCA_ACT_CONNMARK 14
+#define TCA_ACT_SKBMOD 15
+#define TCA_ACT_CSUM 16
+#define TCA_ACT_TUNNEL_KEY 17
+#define TCA_ACT_SIMP 22
+#define TCA_ACT_IFE 25
+#define TCA_ACT_SAMPLE 26
+
+/* Action type identifiers*/
+enum tca_id {
+ TCA_ID_UNSPEC = 0,
+ TCA_ID_POLICE = 1,
+ TCA_ID_GACT = TCA_ACT_GACT,
+ TCA_ID_IPT = TCA_ACT_IPT,
+ TCA_ID_PEDIT = TCA_ACT_PEDIT,
+ TCA_ID_MIRRED = TCA_ACT_MIRRED,
+ TCA_ID_NAT = TCA_ACT_NAT,
+ TCA_ID_XT = TCA_ACT_XT,
+ TCA_ID_SKBEDIT = TCA_ACT_SKBEDIT,
+ TCA_ID_VLAN = TCA_ACT_VLAN,
+ TCA_ID_BPF = TCA_ACT_BPF,
+ TCA_ID_CONNMARK = TCA_ACT_CONNMARK,
+ TCA_ID_SKBMOD = TCA_ACT_SKBMOD,
+ TCA_ID_CSUM = TCA_ACT_CSUM,
+ TCA_ID_TUNNEL_KEY = TCA_ACT_TUNNEL_KEY,
+ TCA_ID_SIMP = TCA_ACT_SIMP,
+ TCA_ID_IFE = TCA_ACT_IFE,
+ TCA_ID_SAMPLE = TCA_ACT_SAMPLE,
+ TCA_ID_CTINFO,
+ TCA_ID_MPLS,
+ TCA_ID_CT,
+ TCA_ID_GATE,
+ /* other actions go here */
+ __TCA_ID_MAX = 255
+};
+
+#define TCA_ID_MAX __TCA_ID_MAX
+
+struct tc_police {
+ __u32 index;
+ int action;
+#define TC_POLICE_UNSPEC TC_ACT_UNSPEC
+#define TC_POLICE_OK TC_ACT_OK
+#define TC_POLICE_RECLASSIFY TC_ACT_RECLASSIFY
+#define TC_POLICE_SHOT TC_ACT_SHOT
+#define TC_POLICE_PIPE TC_ACT_PIPE
+
+ __u32 limit;
+ __u32 burst;
+ __u32 mtu;
+ struct tc_ratespec rate;
+ struct tc_ratespec peakrate;
+ int refcnt;
+ int bindcnt;
+ __u32 capab;
+};
+
+struct tcf_t {
+ __u64 install;
+ __u64 lastuse;
+ __u64 expires;
+ __u64 firstuse;
+};
+
+struct tc_cnt {
+ int refcnt;
+ int bindcnt;
+};
+
+#define tc_gen \
+ __u32 index; \
+ __u32 capab; \
+ int action; \
+ int refcnt; \
+ int bindcnt
+
+enum {
+ TCA_POLICE_UNSPEC,
+ TCA_POLICE_TBF,
+ TCA_POLICE_RATE,
+ TCA_POLICE_PEAKRATE,
+ TCA_POLICE_AVRATE,
+ TCA_POLICE_RESULT,
+ TCA_POLICE_TM,
+ TCA_POLICE_PAD,
+ TCA_POLICE_RATE64,
+ TCA_POLICE_PEAKRATE64,
+ __TCA_POLICE_MAX
+#define TCA_POLICE_RESULT TCA_POLICE_RESULT
+};
+
+#define TCA_POLICE_MAX (__TCA_POLICE_MAX - 1)
+
+/* tca flags definitions */
+#define TCA_CLS_FLAGS_SKIP_HW (1 << 0) /* don't offload filter to HW */
+#define TCA_CLS_FLAGS_SKIP_SW (1 << 1) /* don't use filter in SW */
+#define TCA_CLS_FLAGS_IN_HW (1 << 2) /* filter is offloaded to HW */
+#define TCA_CLS_FLAGS_NOT_IN_HW (1 << 3) /* filter isn't offloaded to HW */
+#define TCA_CLS_FLAGS_VERBOSE (1 << 4) /* verbose logging */
+
+/* U32 filters */
+
+#define TC_U32_HTID(h) ((h)&0xFFF00000)
+#define TC_U32_USERHTID(h) (TC_U32_HTID(h)>>20)
+#define TC_U32_HASH(h) (((h)>>12)&0xFF)
+#define TC_U32_NODE(h) ((h)&0xFFF)
+#define TC_U32_KEY(h) ((h)&0xFFFFF)
+#define TC_U32_UNSPEC 0
+#define TC_U32_ROOT (0xFFF00000)
+
+enum {
+ TCA_U32_UNSPEC,
+ TCA_U32_CLASSID,
+ TCA_U32_HASH,
+ TCA_U32_LINK,
+ TCA_U32_DIVISOR,
+ TCA_U32_SEL,
+ TCA_U32_POLICE,
+ TCA_U32_ACT,
+ TCA_U32_INDEV,
+ TCA_U32_PCNT,
+ TCA_U32_MARK,
+ TCA_U32_FLAGS,
+ TCA_U32_PAD,
+ __TCA_U32_MAX
+};
+
+#define TCA_U32_MAX (__TCA_U32_MAX - 1)
+
+struct tc_u32_key {
+ __be32 mask;
+ __be32 val;
+ int off;
+ int offmask;
+};
+
+struct tc_u32_sel {
+ unsigned char flags;
+ unsigned char offshift;
+ unsigned char nkeys;
+
+ __be16 offmask;
+ __u16 off;
+ short offoff;
+
+ short hoff;
+ __be32 hmask;
+ struct tc_u32_key keys[0];
+};
+
+struct tc_u32_mark {
+ __u32 val;
+ __u32 mask;
+ __u32 success;
+};
+
+struct tc_u32_pcnt {
+ __u64 rcnt;
+ __u64 rhit;
+ __u64 kcnts[0];
+};
+
+/* Flags */
+
+#define TC_U32_TERMINAL 1
+#define TC_U32_OFFSET 2
+#define TC_U32_VAROFFSET 4
+#define TC_U32_EAT 8
+
+#define TC_U32_MAXDEPTH 8
+
+
+/* RSVP filter */
+
+enum {
+ TCA_RSVP_UNSPEC,
+ TCA_RSVP_CLASSID,
+ TCA_RSVP_DST,
+ TCA_RSVP_SRC,
+ TCA_RSVP_PINFO,
+ TCA_RSVP_POLICE,
+ TCA_RSVP_ACT,
+ __TCA_RSVP_MAX
+};
+
+#define TCA_RSVP_MAX (__TCA_RSVP_MAX - 1 )
+
+struct tc_rsvp_gpi {
+ __u32 key;
+ __u32 mask;
+ int offset;
+};
+
+struct tc_rsvp_pinfo {
+ struct tc_rsvp_gpi dpi;
+ struct tc_rsvp_gpi spi;
+ __u8 protocol;
+ __u8 tunnelid;
+ __u8 tunnelhdr;
+ __u8 pad;
+};
+
+/* ROUTE filter */
+
+enum {
+ TCA_ROUTE4_UNSPEC,
+ TCA_ROUTE4_CLASSID,
+ TCA_ROUTE4_TO,
+ TCA_ROUTE4_FROM,
+ TCA_ROUTE4_IIF,
+ TCA_ROUTE4_POLICE,
+ TCA_ROUTE4_ACT,
+ __TCA_ROUTE4_MAX
+};
+
+#define TCA_ROUTE4_MAX (__TCA_ROUTE4_MAX - 1)
+
+
+/* FW filter */
+
+enum {
+ TCA_FW_UNSPEC,
+ TCA_FW_CLASSID,
+ TCA_FW_POLICE,
+ TCA_FW_INDEV,
+ TCA_FW_ACT, /* used by CONFIG_NET_CLS_ACT */
+ TCA_FW_MASK,
+ __TCA_FW_MAX
+};
+
+#define TCA_FW_MAX (__TCA_FW_MAX - 1)
+
+/* TC index filter */
+
+enum {
+ TCA_TCINDEX_UNSPEC,
+ TCA_TCINDEX_HASH,
+ TCA_TCINDEX_MASK,
+ TCA_TCINDEX_SHIFT,
+ TCA_TCINDEX_FALL_THROUGH,
+ TCA_TCINDEX_CLASSID,
+ TCA_TCINDEX_POLICE,
+ TCA_TCINDEX_ACT,
+ __TCA_TCINDEX_MAX
+};
+
+#define TCA_TCINDEX_MAX (__TCA_TCINDEX_MAX - 1)
+
+/* Flow filter */
+
+enum {
+ FLOW_KEY_SRC,
+ FLOW_KEY_DST,
+ FLOW_KEY_PROTO,
+ FLOW_KEY_PROTO_SRC,
+ FLOW_KEY_PROTO_DST,
+ FLOW_KEY_IIF,
+ FLOW_KEY_PRIORITY,
+ FLOW_KEY_MARK,
+ FLOW_KEY_NFCT,
+ FLOW_KEY_NFCT_SRC,
+ FLOW_KEY_NFCT_DST,
+ FLOW_KEY_NFCT_PROTO_SRC,
+ FLOW_KEY_NFCT_PROTO_DST,
+ FLOW_KEY_RTCLASSID,
+ FLOW_KEY_SKUID,
+ FLOW_KEY_SKGID,
+ FLOW_KEY_VLAN_TAG,
+ FLOW_KEY_RXHASH,
+ __FLOW_KEY_MAX,
+};
+
+#define FLOW_KEY_MAX (__FLOW_KEY_MAX - 1)
+
+enum {
+ FLOW_MODE_MAP,
+ FLOW_MODE_HASH,
+};
+
+enum {
+ TCA_FLOW_UNSPEC,
+ TCA_FLOW_KEYS,
+ TCA_FLOW_MODE,
+ TCA_FLOW_BASECLASS,
+ TCA_FLOW_RSHIFT,
+ TCA_FLOW_ADDEND,
+ TCA_FLOW_MASK,
+ TCA_FLOW_XOR,
+ TCA_FLOW_DIVISOR,
+ TCA_FLOW_ACT,
+ TCA_FLOW_POLICE,
+ TCA_FLOW_EMATCHES,
+ TCA_FLOW_PERTURB,
+ __TCA_FLOW_MAX
+};
+
+#define TCA_FLOW_MAX (__TCA_FLOW_MAX - 1)
+
+/* Basic filter */
+
+struct tc_basic_pcnt {
+ __u64 rcnt;
+ __u64 rhit;
+};
+
+enum {
+ TCA_BASIC_UNSPEC,
+ TCA_BASIC_CLASSID,
+ TCA_BASIC_EMATCHES,
+ TCA_BASIC_ACT,
+ TCA_BASIC_POLICE,
+ TCA_BASIC_PCNT,
+ TCA_BASIC_PAD,
+ __TCA_BASIC_MAX
+};
+
+#define TCA_BASIC_MAX (__TCA_BASIC_MAX - 1)
+
+
+/* Cgroup classifier */
+
+enum {
+ TCA_CGROUP_UNSPEC,
+ TCA_CGROUP_ACT,
+ TCA_CGROUP_POLICE,
+ TCA_CGROUP_EMATCHES,
+ __TCA_CGROUP_MAX,
+};
+
+#define TCA_CGROUP_MAX (__TCA_CGROUP_MAX - 1)
+
+/* BPF classifier */
+
+#define TCA_BPF_FLAG_ACT_DIRECT (1 << 0)
+
+enum {
+ TCA_BPF_UNSPEC,
+ TCA_BPF_ACT,
+ TCA_BPF_POLICE,
+ TCA_BPF_CLASSID,
+ TCA_BPF_OPS_LEN,
+ TCA_BPF_OPS,
+ TCA_BPF_FD,
+ TCA_BPF_NAME,
+ TCA_BPF_FLAGS,
+ TCA_BPF_FLAGS_GEN,
+ TCA_BPF_TAG,
+ TCA_BPF_ID,
+ __TCA_BPF_MAX,
+};
+
+#define TCA_BPF_MAX (__TCA_BPF_MAX - 1)
+
+/* Flower classifier */
+
+enum {
+ TCA_FLOWER_UNSPEC,
+ TCA_FLOWER_CLASSID,
+ TCA_FLOWER_INDEV,
+ TCA_FLOWER_ACT,
+ TCA_FLOWER_KEY_ETH_DST, /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_DST_MASK, /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_SRC, /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_SRC_MASK, /* ETH_ALEN */
+ TCA_FLOWER_KEY_ETH_TYPE, /* be16 */
+ TCA_FLOWER_KEY_IP_PROTO, /* u8 */
+ TCA_FLOWER_KEY_IPV4_SRC, /* be32 */
+ TCA_FLOWER_KEY_IPV4_SRC_MASK, /* be32 */
+ TCA_FLOWER_KEY_IPV4_DST, /* be32 */
+ TCA_FLOWER_KEY_IPV4_DST_MASK, /* be32 */
+ TCA_FLOWER_KEY_IPV6_SRC, /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_SRC_MASK, /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_DST, /* struct in6_addr */
+ TCA_FLOWER_KEY_IPV6_DST_MASK, /* struct in6_addr */
+ TCA_FLOWER_KEY_TCP_SRC, /* be16 */
+ TCA_FLOWER_KEY_TCP_DST, /* be16 */
+ TCA_FLOWER_KEY_UDP_SRC, /* be16 */
+ TCA_FLOWER_KEY_UDP_DST, /* be16 */
+
+ TCA_FLOWER_FLAGS,
+ TCA_FLOWER_KEY_VLAN_ID, /* be16 */
+ TCA_FLOWER_KEY_VLAN_PRIO, /* u8 */
+ TCA_FLOWER_KEY_VLAN_ETH_TYPE, /* be16 */
+
+ TCA_FLOWER_KEY_ENC_KEY_ID, /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_SRC, /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_SRC_MASK,/* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_DST, /* be32 */
+ TCA_FLOWER_KEY_ENC_IPV4_DST_MASK,/* be32 */
+ TCA_FLOWER_KEY_ENC_IPV6_SRC, /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_SRC_MASK,/* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_DST, /* struct in6_addr */
+ TCA_FLOWER_KEY_ENC_IPV6_DST_MASK,/* struct in6_addr */
+
+ TCA_FLOWER_KEY_TCP_SRC_MASK, /* be16 */
+ TCA_FLOWER_KEY_TCP_DST_MASK, /* be16 */
+ TCA_FLOWER_KEY_UDP_SRC_MASK, /* be16 */
+ TCA_FLOWER_KEY_UDP_DST_MASK, /* be16 */
+ TCA_FLOWER_KEY_SCTP_SRC_MASK, /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST_MASK, /* be16 */
+
+ TCA_FLOWER_KEY_SCTP_SRC, /* be16 */
+ TCA_FLOWER_KEY_SCTP_DST, /* be16 */
+
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT, /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_SRC_PORT_MASK, /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT, /* be16 */
+ TCA_FLOWER_KEY_ENC_UDP_DST_PORT_MASK, /* be16 */
+
+ TCA_FLOWER_KEY_FLAGS, /* be32 */
+ TCA_FLOWER_KEY_FLAGS_MASK, /* be32 */
+
+ TCA_FLOWER_KEY_ICMPV4_CODE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_CODE_MASK,/* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV4_TYPE_MASK,/* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_CODE_MASK,/* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE, /* u8 */
+ TCA_FLOWER_KEY_ICMPV6_TYPE_MASK,/* u8 */
+
+ TCA_FLOWER_KEY_ARP_SIP, /* be32 */
+ TCA_FLOWER_KEY_ARP_SIP_MASK, /* be32 */
+ TCA_FLOWER_KEY_ARP_TIP, /* be32 */
+ TCA_FLOWER_KEY_ARP_TIP_MASK, /* be32 */
+ TCA_FLOWER_KEY_ARP_OP, /* u8 */
+ TCA_FLOWER_KEY_ARP_OP_MASK, /* u8 */
+ TCA_FLOWER_KEY_ARP_SHA, /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_SHA_MASK, /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_THA, /* ETH_ALEN */
+ TCA_FLOWER_KEY_ARP_THA_MASK, /* ETH_ALEN */
+
+ TCA_FLOWER_KEY_MPLS_TTL, /* u8 - 8 bits */
+ TCA_FLOWER_KEY_MPLS_BOS, /* u8 - 1 bit */
+ TCA_FLOWER_KEY_MPLS_TC, /* u8 - 3 bits */
+ TCA_FLOWER_KEY_MPLS_LABEL, /* be32 - 20 bits */
+
+ TCA_FLOWER_KEY_TCP_FLAGS, /* be16 */
+ TCA_FLOWER_KEY_TCP_FLAGS_MASK, /* be16 */
+
+ TCA_FLOWER_KEY_IP_TOS, /* u8 */
+ TCA_FLOWER_KEY_IP_TOS_MASK, /* u8 */
+ TCA_FLOWER_KEY_IP_TTL, /* u8 */
+ TCA_FLOWER_KEY_IP_TTL_MASK, /* u8 */
+
+ TCA_FLOWER_KEY_CVLAN_ID, /* be16 */
+ TCA_FLOWER_KEY_CVLAN_PRIO, /* u8 */
+ TCA_FLOWER_KEY_CVLAN_ETH_TYPE, /* be16 */
+
+ TCA_FLOWER_KEY_ENC_IP_TOS, /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TOS_MASK, /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TTL, /* u8 */
+ TCA_FLOWER_KEY_ENC_IP_TTL_MASK, /* u8 */
+
+ TCA_FLOWER_KEY_ENC_OPTS,
+ TCA_FLOWER_KEY_ENC_OPTS_MASK,
+
+ TCA_FLOWER_IN_HW_COUNT,
+
+ TCA_FLOWER_KEY_PORT_SRC_MIN, /* be16 */
+ TCA_FLOWER_KEY_PORT_SRC_MAX, /* be16 */
+ TCA_FLOWER_KEY_PORT_DST_MIN, /* be16 */
+ TCA_FLOWER_KEY_PORT_DST_MAX, /* be16 */
+
+ TCA_FLOWER_KEY_CT_STATE, /* u16 */
+ TCA_FLOWER_KEY_CT_STATE_MASK, /* u16 */
+ TCA_FLOWER_KEY_CT_ZONE, /* u16 */
+ TCA_FLOWER_KEY_CT_ZONE_MASK, /* u16 */
+ TCA_FLOWER_KEY_CT_MARK, /* u32 */
+ TCA_FLOWER_KEY_CT_MARK_MASK, /* u32 */
+ TCA_FLOWER_KEY_CT_LABELS, /* u128 */
+ TCA_FLOWER_KEY_CT_LABELS_MASK, /* u128 */
+
+ TCA_FLOWER_KEY_MPLS_OPTS,
+
+ TCA_FLOWER_KEY_HASH, /* u32 */
+ TCA_FLOWER_KEY_HASH_MASK, /* u32 */
+
+ __TCA_FLOWER_MAX,
+};
+
+#define TCA_FLOWER_MAX (__TCA_FLOWER_MAX - 1)
+
+enum {
+ TCA_FLOWER_KEY_CT_FLAGS_NEW = 1 << 0, /* Beginning of a new connection. */
+ TCA_FLOWER_KEY_CT_FLAGS_ESTABLISHED = 1 << 1, /* Part of an existing connection. */
+ TCA_FLOWER_KEY_CT_FLAGS_RELATED = 1 << 2, /* Related to an established connection. */
+ TCA_FLOWER_KEY_CT_FLAGS_TRACKED = 1 << 3, /* Conntrack has occurred. */
+ TCA_FLOWER_KEY_CT_FLAGS_INVALID = 1 << 4, /* Conntrack is invalid. */
+ TCA_FLOWER_KEY_CT_FLAGS_REPLY = 1 << 5, /* Packet is in the reply direction. */
+ __TCA_FLOWER_KEY_CT_FLAGS_MAX,
+};
+
+enum {
+ TCA_FLOWER_KEY_ENC_OPTS_UNSPEC,
+ TCA_FLOWER_KEY_ENC_OPTS_GENEVE, /* Nested
+ * TCA_FLOWER_KEY_ENC_OPT_GENEVE_
+ * attributes
+ */
+ TCA_FLOWER_KEY_ENC_OPTS_VXLAN, /* Nested
+ * TCA_FLOWER_KEY_ENC_OPT_VXLAN_
+ * attributes
+ */
+ TCA_FLOWER_KEY_ENC_OPTS_ERSPAN, /* Nested
+ * TCA_FLOWER_KEY_ENC_OPT_ERSPAN_
+ * attributes
+ */
+ __TCA_FLOWER_KEY_ENC_OPTS_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPTS_MAX (__TCA_FLOWER_KEY_ENC_OPTS_MAX - 1)
+
+enum {
+ TCA_FLOWER_KEY_ENC_OPT_GENEVE_UNSPEC,
+ TCA_FLOWER_KEY_ENC_OPT_GENEVE_CLASS, /* u16 */
+ TCA_FLOWER_KEY_ENC_OPT_GENEVE_TYPE, /* u8 */
+ TCA_FLOWER_KEY_ENC_OPT_GENEVE_DATA, /* 4 to 128 bytes */
+
+ __TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX \
+ (__TCA_FLOWER_KEY_ENC_OPT_GENEVE_MAX - 1)
+
+enum {
+ TCA_FLOWER_KEY_ENC_OPT_VXLAN_UNSPEC,
+ TCA_FLOWER_KEY_ENC_OPT_VXLAN_GBP, /* u32 */
+ __TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX \
+ (__TCA_FLOWER_KEY_ENC_OPT_VXLAN_MAX - 1)
+
+enum {
+ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_UNSPEC,
+ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_VER, /* u8 */
+ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_INDEX, /* be32 */
+ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_DIR, /* u8 */
+ TCA_FLOWER_KEY_ENC_OPT_ERSPAN_HWID, /* u8 */
+ __TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX,
+};
+
+#define TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX \
+ (__TCA_FLOWER_KEY_ENC_OPT_ERSPAN_MAX - 1)
+
+enum {
+ TCA_FLOWER_KEY_MPLS_OPTS_UNSPEC,
+ TCA_FLOWER_KEY_MPLS_OPTS_LSE,
+ __TCA_FLOWER_KEY_MPLS_OPTS_MAX,
+};
+
+#define TCA_FLOWER_KEY_MPLS_OPTS_MAX (__TCA_FLOWER_KEY_MPLS_OPTS_MAX - 1)
+
+enum {
+ TCA_FLOWER_KEY_MPLS_OPT_LSE_UNSPEC,
+ TCA_FLOWER_KEY_MPLS_OPT_LSE_DEPTH,
+ TCA_FLOWER_KEY_MPLS_OPT_LSE_TTL,
+ TCA_FLOWER_KEY_MPLS_OPT_LSE_BOS,
+ TCA_FLOWER_KEY_MPLS_OPT_LSE_TC,
+ TCA_FLOWER_KEY_MPLS_OPT_LSE_LABEL,
+ __TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX,
+};
+
+#define TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX \
+ (__TCA_FLOWER_KEY_MPLS_OPT_LSE_MAX - 1)
+
+enum {
+ TCA_FLOWER_KEY_FLAGS_IS_FRAGMENT = (1 << 0),
+ TCA_FLOWER_KEY_FLAGS_FRAG_IS_FIRST = (1 << 1),
+};
+
+#define TCA_FLOWER_MASK_FLAGS_RANGE (1 << 0) /* Range-based match */
+
+/* Match-all classifier */
+
+struct tc_matchall_pcnt {
+ __u64 rhit;
+};
+
+enum {
+ TCA_MATCHALL_UNSPEC,
+ TCA_MATCHALL_CLASSID,
+ TCA_MATCHALL_ACT,
+ TCA_MATCHALL_FLAGS,
+ TCA_MATCHALL_PCNT,
+ TCA_MATCHALL_PAD,
+ __TCA_MATCHALL_MAX,
+};
+
+#define TCA_MATCHALL_MAX (__TCA_MATCHALL_MAX - 1)
+
+/* Extended Matches */
+
+struct tcf_ematch_tree_hdr {
+ __u16 nmatches;
+ __u16 progid;
+};
+
+enum {
+ TCA_EMATCH_TREE_UNSPEC,
+ TCA_EMATCH_TREE_HDR,
+ TCA_EMATCH_TREE_LIST,
+ __TCA_EMATCH_TREE_MAX
+};
+#define TCA_EMATCH_TREE_MAX (__TCA_EMATCH_TREE_MAX - 1)
+
+struct tcf_ematch_hdr {
+ __u16 matchid;
+ __u16 kind;
+ __u16 flags;
+ __u16 pad; /* currently unused */
+};
+
+/* 0 1
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5
+ * +-----------------------+-+-+---+
+ * | Unused |S|I| R |
+ * +-----------------------+-+-+---+
+ *
+ * R(2) ::= relation to next ematch
+ * where: 0 0 END (last ematch)
+ * 0 1 AND
+ * 1 0 OR
+ * 1 1 Unused (invalid)
+ * I(1) ::= invert result
+ * S(1) ::= simple payload
+ */
+#define TCF_EM_REL_END 0
+#define TCF_EM_REL_AND (1<<0)
+#define TCF_EM_REL_OR (1<<1)
+#define TCF_EM_INVERT (1<<2)
+#define TCF_EM_SIMPLE (1<<3)
+
+#define TCF_EM_REL_MASK 3
+#define TCF_EM_REL_VALID(v) (((v) & TCF_EM_REL_MASK) != TCF_EM_REL_MASK)
+
+enum {
+ TCF_LAYER_LINK,
+ TCF_LAYER_NETWORK,
+ TCF_LAYER_TRANSPORT,
+ __TCF_LAYER_MAX
+};
+#define TCF_LAYER_MAX (__TCF_LAYER_MAX - 1)
+
+/* Ematch type assignments
+ * 1..32767 Reserved for ematches inside kernel tree
+ * 32768..65535 Free to use, not reliable
+ */
+#define TCF_EM_CONTAINER 0
+#define TCF_EM_CMP 1
+#define TCF_EM_NBYTE 2
+#define TCF_EM_U32 3
+#define TCF_EM_META 4
+#define TCF_EM_TEXT 5
+#define TCF_EM_VLAN 6
+#define TCF_EM_CANID 7
+#define TCF_EM_IPSET 8
+#define TCF_EM_IPT 9
+#define TCF_EM_MAX 9
+
+enum {
+ TCF_EM_PROG_TC
+};
+
+enum {
+ TCF_EM_OPND_EQ,
+ TCF_EM_OPND_GT,
+ TCF_EM_OPND_LT
+};
+
+#endif
diff --git a/include/linux/rtnetlink.h b/include/linux/rtnetlink.h
index b15b72a262..71ad7bf69e 100644
--- a/include/linux/rtnetlink.h
+++ b/include/linux/rtnetlink.h
@@ -188,12 +188,12 @@ enum {
RTM_SETHWFLAGS = 119,
#define RTM_SETHWFLAGS RTM_SETHWFLAGS
- RTM_NEWTUNNEL = 120,
-#define RTM_NEWTUNNEL RTM_NEWTUNNEL
- RTM_DELTUNNEL,
-#define RTM_DELTUNNEL RTM_DELTUNNEL
- RTM_GETTUNNEL,
-#define RTM_GETTUNNEL RTM_GETTUNNEL
+ RTM_NEWTUNNEL = 120,
+#define RTM_NEWTUNNEL RTM_NEWTUNNEL
+ RTM_DELTUNNEL,
+#define RTM_DELTUNNEL RTM_DELTUNNEL
+ RTM_GETTUNNEL,
+#define RTM_GETTUNNEL RTM_GETTUNNEL
__RTM_MAX,
#define RTM_MAX (((__RTM_MAX + 3) & ~3) - 1)
diff --git a/isisd/fabricd.c b/isisd/fabricd.c
index a37cda1ce1..be035b623d 100644
--- a/isisd/fabricd.c
+++ b/isisd/fabricd.c
@@ -254,8 +254,10 @@ static void fabricd_initial_sync_timeout(struct thread *thread)
{
struct fabricd *f = THREAD_ARG(thread);
- zlog_info("OpenFabric: Initial synchronization on %s timed out!",
- f->initial_sync_circuit->interface->name);
+ if (IS_DEBUG_ADJ_PACKETS)
+ zlog_debug(
+ "OpenFabric: Initial synchronization on %s timed out!",
+ f->initial_sync_circuit->interface->name);
f->initial_sync_state = FABRICD_SYNC_PENDING;
f->initial_sync_circuit = NULL;
}
@@ -282,9 +284,11 @@ void fabricd_initial_sync_hello(struct isis_circuit *circuit)
timeout, &f->initial_sync_timeout);
f->initial_sync_start = monotime(NULL);
- zlog_info("OpenFabric: Started initial synchronization with %s on %s",
- sysid_print(circuit->u.p2p.neighbor->sysid),
- circuit->interface->name);
+ if (IS_DEBUG_ADJ_PACKETS)
+ zlog_debug(
+ "OpenFabric: Started initial synchronization with %s on %s",
+ sysid_print(circuit->u.p2p.neighbor->sysid),
+ circuit->interface->name);
}
bool fabricd_initial_sync_is_in_progress(struct isis_area *area)
diff --git a/isisd/isis_adjacency.c b/isisd/isis_adjacency.c
index eda39a844b..00763135e6 100644
--- a/isisd/isis_adjacency.c
+++ b/isisd/isis_adjacency.c
@@ -170,7 +170,7 @@ void isis_delete_adj(void *arg)
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->area_addresses);
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ipv4_addresses);
XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->ll_ipv6_addrs);
-
+ XFREE(MTYPE_ISIS_ADJACENCY_INFO, adj->global_ipv6_addrs);
adj_mt_finish(adj);
list_delete(&adj->adj_sids);
@@ -860,13 +860,13 @@ void isis_adj_build_neigh_list(struct list *adjdb, struct list *list)
struct listnode *node;
if (!list) {
- zlog_warn("isis_adj_build_neigh_list(): NULL list");
+ zlog_warn("%s: NULL list", __func__);
return;
}
for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) {
if (!adj) {
- zlog_warn("isis_adj_build_neigh_list(): NULL adj");
+ zlog_warn("%s: NULL adj", __func__);
return;
}
@@ -883,18 +883,18 @@ void isis_adj_build_up_list(struct list *adjdb, struct list *list)
struct listnode *node;
if (adjdb == NULL) {
- zlog_warn("isis_adj_build_up_list(): adjacency DB is empty");
+ zlog_warn("%s: adjacency DB is empty", __func__);
return;
}
if (!list) {
- zlog_warn("isis_adj_build_up_list(): NULL list");
+ zlog_warn("%s: NULL list", __func__);
return;
}
for (ALL_LIST_ELEMENTS_RO(adjdb, node, adj)) {
if (!adj) {
- zlog_warn("isis_adj_build_up_list(): NULL adj");
+ zlog_warn("%s: NULL adj", __func__);
return;
}
diff --git a/isisd/isis_bpf.c b/isisd/isis_bpf.c
index 5f3d70ed3a..11f43279ec 100644
--- a/isisd/isis_bpf.c
+++ b/isisd/isis_bpf.c
@@ -165,7 +165,7 @@ static int open_bpf_dev(struct isis_circuit *circuit)
bpf_prog.bf_len = 8;
bpf_prog.bf_insns = &(llcfilter[0]);
if (ioctl(fd, BIOCSETF, (caddr_t)&bpf_prog) < 0) {
- zlog_warn("open_bpf_dev(): failed to install filter: %s",
+ zlog_warn("%s: failed to install filter: %s", __func__,
safe_strerror(errno));
return ISIS_WARNING;
}
@@ -198,7 +198,7 @@ int isis_sock_init(struct isis_circuit *circuit)
circuit->tx = isis_send_pdu_bcast;
circuit->rx = isis_recv_pdu_bcast;
} else {
- zlog_warn("isis_sock_init(): unknown circuit type");
+ zlog_warn("%s: unknown circuit type", __func__);
retval = ISIS_WARNING;
break;
}
@@ -223,8 +223,8 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
bytesread = read(circuit->fd, readbuff, readblen);
}
if (bytesread < 0) {
- zlog_warn("isis_recv_pdu_bcast(): read() failed: %s",
- safe_strerror(errno));
+ zlog_warn("%s: read() failed: %s", __func__,
+ safe_strerror(errno));
return ISIS_WARNING;
}
@@ -267,8 +267,9 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN + ETHER_HDR_LEN;
if (buflen > sizeof(sock_buff)) {
zlog_warn(
- "isis_send_pdu_bcast: sock_buff size %zu is less than output pdu size %zu on circuit %s",
- sizeof(sock_buff), buflen, circuit->interface->name);
+ "%s: sock_buff size %zu is less than output pdu size %zu on circuit %s",
+ __func__, sizeof(sock_buff), buflen,
+ circuit->interface->name);
return ISIS_WARNING;
}
diff --git a/isisd/isis_circuit.c b/isisd/isis_circuit.c
index 9e97e48937..dcc4ed6e42 100644
--- a/isisd/isis_circuit.c
+++ b/isisd/isis_circuit.c
@@ -217,6 +217,11 @@ void isis_circuit_del(struct isis_circuit *circuit)
list_delete(&circuit->ipv6_link);
list_delete(&circuit->ipv6_non_link);
+ if (circuit->ext) {
+ isis_del_ext_subtlvs(circuit->ext);
+ circuit->ext = NULL;
+ }
+
XFREE(MTYPE_TMP, circuit->bfd_config.profile);
XFREE(MTYPE_ISIS_CIRCUIT, circuit->tag);
@@ -513,7 +518,7 @@ void isis_circuit_if_add(struct isis_circuit *circuit, struct interface *ifp)
} else {
/* It's normal in case of loopback etc. */
if (IS_DEBUG_EVENTS)
- zlog_debug("isis_circuit_if_add: unsupported media");
+ zlog_debug("%s: unsupported media", __func__);
circuit->circ_type = CIRCUIT_T_UNKNOWN;
}
@@ -678,10 +683,10 @@ int isis_circuit_up(struct isis_circuit *circuit)
}
#ifdef EXTREME_DEGUG
if (IS_DEBUG_EVENTS)
- zlog_debug(
- "isis_circuit_if_add: if_id %d, isomtu %d snpa %s",
- circuit->interface->ifindex, ISO_MTU(circuit),
- snpa_print(circuit->u.bc.snpa));
+ zlog_debug("%s: if_id %d, isomtu %d snpa %s", __func__,
+ circuit->interface->ifindex,
+ ISO_MTU(circuit),
+ snpa_print(circuit->u.bc.snpa));
#endif /* EXTREME_DEBUG */
circuit->u.bc.adjdb[0] = list_new();
diff --git a/isisd/isis_dlpi.c b/isisd/isis_dlpi.c
index bb8c542597..f6ea0aea60 100644
--- a/isisd/isis_dlpi.c
+++ b/isisd/isis_dlpi.c
@@ -336,9 +336,8 @@ static int open_dlpi_dev(struct isis_circuit *circuit)
/* Double check the DLPI style */
if (dia->dl_provider_style != DL_STYLE2) {
- zlog_warn(
- "open_dlpi_dev(): interface %s: %s is not style 2",
- circuit->interface->name, devpath);
+ zlog_warn("%s: interface %s: %s is not style 2",
+ __func__, circuit->interface->name, devpath);
close(fd);
return ISIS_WARNING;
}
@@ -355,9 +354,8 @@ static int open_dlpi_dev(struct isis_circuit *circuit)
} else {
/* Double check the DLPI style */
if (dia->dl_provider_style != DL_STYLE1) {
- zlog_warn(
- "open_dlpi_dev(): interface %s: %s is not style 1",
- circuit->interface->name, devpath);
+ zlog_warn("%s: interface %s: %s is not style 1",
+ __func__, circuit->interface->name, devpath);
close(fd);
return ISIS_WARNING;
}
@@ -404,9 +402,8 @@ static int open_dlpi_dev(struct isis_circuit *circuit)
* so we need to be careful and use DL_PHYS_ADDR_REQ instead.
*/
if (dlpiaddr(fd, circuit->u.bc.snpa) == -1) {
- zlog_warn(
- "open_dlpi_dev(): interface %s: unable to get MAC address",
- circuit->interface->name);
+ zlog_warn("%s: interface %s: unable to get MAC address",
+ __func__, circuit->interface->name);
close(fd);
return ISIS_WARNING;
}
@@ -479,7 +476,7 @@ int isis_sock_init(struct isis_circuit *circuit)
circuit->tx = isis_send_pdu_bcast;
circuit->rx = isis_recv_pdu_bcast;
} else {
- zlog_warn("isis_sock_init(): unknown circuit type");
+ zlog_warn("%s: unknown circuit type", __func__);
retval = ISIS_WARNING;
break;
}
@@ -511,7 +508,7 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
retv = getmsg(circuit->fd, &ctlbuf, &databuf, &flags);
if (retv < 0) {
- zlog_warn("isis_recv_pdu_bcast: getmsg failed: %s",
+ zlog_warn("%s: getmsg failed: %s", __func__,
safe_strerror(errno));
return ISIS_WARNING;
}
@@ -561,8 +558,9 @@ int isis_send_pdu_bcast(struct isis_circuit *circuit, int level)
buflen = stream_get_endp(circuit->snd_stream) + LLC_LEN;
if ((size_t)buflen > sizeof(sock_buff)) {
zlog_warn(
- "isis_send_pdu_bcast: sock_buff size %zu is less than output pdu size %d on circuit %s",
- sizeof(sock_buff), buflen, circuit->interface->name);
+ "%s: sock_buff size %zu is less than output pdu size %d on circuit %s",
+ __func__, sizeof(sock_buff), buflen,
+ circuit->interface->name);
return ISIS_WARNING;
}
diff --git a/isisd/isis_dr.c b/isisd/isis_dr.c
index b9bf49867d..400982f2fc 100644
--- a/isisd/isis_dr.c
+++ b/isisd/isis_dr.c
@@ -80,7 +80,8 @@ void isis_run_dr(struct thread *thread)
}
if (circuit->u.bc.run_dr_elect[level - 1])
- zlog_warn("isis_run_dr(): run_dr_elect already set for l%d", level);
+ zlog_warn("%s: run_dr_elect already set for l%d", __func__,
+ level);
circuit->u.bc.t_run_dr[level - 1] = NULL;
circuit->u.bc.run_dr_elect[level - 1] = 1;
@@ -126,7 +127,7 @@ int isis_dr_elect(struct isis_circuit *circuit, int level)
adjdb = circuit->u.bc.adjdb[level - 1];
if (!adjdb) {
- zlog_warn("isis_dr_elect() adjdb == NULL");
+ zlog_warn("%s adjdb == NULL", __func__);
list_delete(&list);
return ISIS_WARNING;
}
@@ -155,7 +156,8 @@ int isis_dr_elect(struct isis_circuit *circuit, int level)
}
if (cmp_res == 0)
zlog_warn(
- "isis_dr_elect(): multiple adjacencies with same SNPA");
+ "%s: multiple adjacencies with same SNPA",
+ __func__);
} else {
adj_dr = adj;
}
@@ -218,7 +220,7 @@ int isis_dr_resign(struct isis_circuit *circuit, int level)
uint8_t id[ISIS_SYS_ID_LEN + 2];
if (IS_DEBUG_EVENTS)
- zlog_debug("isis_dr_resign l%d", level);
+ zlog_debug("%s l%d", __func__, level);
circuit->u.bc.is_dr[level - 1] = 0;
circuit->u.bc.run_dr_elect[level - 1] = 0;
@@ -266,7 +268,7 @@ int isis_dr_commence(struct isis_circuit *circuit, int level)
uint8_t old_dr[ISIS_SYS_ID_LEN + 2];
if (IS_DEBUG_EVENTS)
- zlog_debug("isis_dr_commence l%d", level);
+ zlog_debug("%s l%d", __func__, level);
/* Lets keep a pause in DR election */
circuit->u.bc.run_dr_elect[level - 1] = 0;
diff --git a/isisd/isis_ldp_sync.c b/isisd/isis_ldp_sync.c
index fb605eb07a..3568543b4a 100644
--- a/isisd/isis_ldp_sync.c
+++ b/isisd/isis_ldp_sync.c
@@ -82,7 +82,7 @@ int isis_ldp_sync_state_update(struct ldp_igp_sync_if_state state)
return 0;
/* received ldp-sync interface state from LDP */
- ils_debug("ldp_sync: rcvd %s from LDP if %s",
+ ils_debug("%s: rcvd %s from LDP if %s", __func__,
state.sync_start ? "sync-start" : "sync-complete", ifp->name);
if (state.sync_start)
isis_ldp_sync_if_start(circuit, false);
@@ -106,7 +106,7 @@ int isis_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)
if (announce.proto != ZEBRA_ROUTE_LDP)
return 0;
- ils_debug("ldp_sync: rcvd announce from LDP");
+ ils_debug("%s: rcvd announce from LDP", __func__);
/* LDP just started up:
* set cost to LSInfinity
@@ -128,8 +128,7 @@ void isis_ldp_sync_state_req_msg(struct isis_circuit *circuit)
struct ldp_igp_sync_if_state_req request;
struct interface *ifp = circuit->interface;
- ils_debug("ldp_sync: send state request to LDP for %s",
- ifp->name);
+ ils_debug("%s: send state request to LDP for %s", __func__, ifp->name);
memset(&request, 0, sizeof(request));
strlcpy(request.name, ifp->name, sizeof(ifp->name));
@@ -159,7 +158,7 @@ void isis_ldp_sync_if_start(struct isis_circuit *circuit,
if (ldp_sync_info &&
ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
- ils_debug("ldp_sync: start on if %s state: %s",
+ ils_debug("%s: start on if %s state: %s", __func__,
circuit->interface->name, "Holding down until Sync");
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
isis_ldp_sync_set_if_metric(circuit, true);
@@ -246,7 +245,8 @@ static int isis_ldp_sync_adj_state_change(struct isis_adjacency *adj)
else
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
- ils_debug("ldp_sync: down on if %s", circuit->interface->name);
+ ils_debug("%s: down on if %s", __func__,
+ circuit->interface->name);
ldp_sync_if_down(circuit->ldp_sync_info);
}
@@ -362,8 +362,8 @@ static void isis_ldp_sync_holddown_timer(struct thread *thread)
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
ldp_sync_info->t_holddown = NULL;
- ils_debug("ldp_sync: holddown timer expired for %s state:sync achieved",
- circuit->interface->name);
+ ils_debug("%s: holddown timer expired for %s state:sync achieved",
+ __func__, circuit->interface->name);
isis_ldp_sync_set_if_metric(circuit, true);
}
@@ -383,7 +383,7 @@ void isis_ldp_sync_holddown_timer_add(struct isis_circuit *circuit)
ldp_sync_info->holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
return;
- ils_debug("ldp_sync: start holddown timer for %s time %d",
+ ils_debug("%s: start holddown timer for %s time %d", __func__,
circuit->interface->name, ldp_sync_info->holddown);
thread_add_timer(master, isis_ldp_sync_holddown_timer,
@@ -413,7 +413,7 @@ void isis_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
* set cost to LSInfinity
* send request to LDP for LDP-SYNC state for each interface
*/
- zlog_err("ldp_sync: LDP down");
+ zlog_err("%s: LDP down", __func__);
for (ALL_LIST_ELEMENTS_RO(isis->area_list, anode, area)) {
if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
@@ -488,7 +488,7 @@ void isis_if_ldp_sync_enable(struct isis_circuit *circuit)
if (circuit->interface->vrf->vrf_id != VRF_DEFAULT)
return;
- ils_debug("ldp_sync: enable if %s", circuit->interface->name);
+ ils_debug("%s: enable if %s", __func__, circuit->interface->name);
if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
return;
@@ -507,7 +507,7 @@ void isis_if_ldp_sync_enable(struct isis_circuit *circuit)
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",
+ ils_debug("%s: Sync only runs on P2P links %s", __func__,
circuit->interface->name);
}
}
@@ -525,7 +525,7 @@ void isis_if_ldp_sync_disable(struct isis_circuit *circuit)
if (if_is_loopback(circuit->interface))
return;
- ils_debug("ldp_sync: remove if %s", circuit->interface->name);
+ ils_debug("%s: remove if %s", __func__, circuit->interface->name);
if (!CHECK_FLAG(area->ldp_sync_cmd.flags, LDP_SYNC_FLAG_ENABLE))
return;
diff --git a/isisd/isis_nb_config.c b/isisd/isis_nb_config.c
index 79b167718b..e0decf48f2 100644
--- a/isisd/isis_nb_config.c
+++ b/isisd/isis_nb_config.c
@@ -54,9 +54,6 @@
#include "isisd/isis_dr.h"
#include "isisd/isis_zebra.h"
-DEFINE_MTYPE_STATIC(ISISD, ISIS_MPLS_TE, "ISIS MPLS_TE parameters");
-DEFINE_MTYPE_STATIC(ISISD, ISIS_PLIST_NAME, "ISIS prefix-list name");
-
/*
* XPath: /frr-isisd:isis/instance
*/
@@ -86,12 +83,17 @@ int isis_instance_create(struct nb_cb_create_args *args)
int isis_instance_destroy(struct nb_cb_destroy_args *args)
{
struct isis_area *area;
+ struct isis *isis;
if (args->event != NB_EV_APPLY)
return NB_OK;
area = nb_running_unset_entry(args->dnode);
-
+ isis = area->isis;
isis_area_destroy(area);
+
+ if (listcount(isis->area_list) == 0)
+ isis_finish(isis);
+
return NB_OK;
}
@@ -1787,45 +1789,13 @@ int isis_instance_log_adjacency_changes_modify(struct nb_cb_modify_args *args)
*/
int isis_instance_mpls_te_create(struct nb_cb_create_args *args)
{
- struct listnode *node;
struct isis_area *area;
- struct isis_circuit *circuit;
if (args->event != NB_EV_APPLY)
return NB_OK;
area = nb_running_get_entry(args->dnode, NULL, true);
- if (area->mta == NULL) {
-
- struct mpls_te_area *new;
-
- zlog_debug("ISIS-TE(%s): Initialize MPLS Traffic Engineering",
- area->area_tag);
-
- new = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_area));
-
- /* Initialize MPLS_TE structure */
- new->status = enable;
- new->level = 0;
- new->inter_as = off;
- new->interas_areaid.s_addr = 0;
- new->router_id.s_addr = 0;
- new->ted = ls_ted_new(1, "ISIS", 0);
- if (!new->ted)
- zlog_warn("Unable to create Link State Data Base");
-
- area->mta = new;
- } else {
- area->mta->status = enable;
- }
-
- /* Initialize Link State Database */
- if (area->mta->ted)
- isis_te_init_ted(area);
-
- /* Update Extended TLVs according to Interface link parameters */
- for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
- isis_link_params_update(circuit, circuit->interface);
+ isis_mpls_te_create(area);
/* Reoriginate STD_TE & GMPLS circuits */
lsp_regenerate_schedule(area, area->is_type, 0);
@@ -1835,35 +1805,16 @@ int isis_instance_mpls_te_create(struct nb_cb_create_args *args)
int isis_instance_mpls_te_destroy(struct nb_cb_destroy_args *args)
{
- struct listnode *node;
struct isis_area *area;
- struct isis_circuit *circuit;
if (args->event != NB_EV_APPLY)
return NB_OK;
area = nb_running_get_entry(args->dnode, NULL, true);
- if (IS_MPLS_TE(area->mta))
- area->mta->status = disable;
- else
- return NB_OK;
-
- /* Remove Link State Database */
- ls_ted_del_all(&area->mta->ted);
-
- /* Flush LSP if circuit engage */
- for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
- if (!IS_EXT_TE(circuit->ext))
- continue;
-
- /* disable MPLS_TE Circuit keeping SR one's */
- if (IS_SUBTLV(circuit->ext, EXT_ADJ_SID))
- circuit->ext->status = EXT_ADJ_SID;
- else if (IS_SUBTLV(circuit->ext, EXT_LAN_ADJ_SID))
- circuit->ext->status = EXT_LAN_ADJ_SID;
- else
- circuit->ext->status = 0;
- }
+ if (!IS_MPLS_TE(area->mta))
+ return NB_OK;
+
+ isis_mpls_te_disable(area);
/* Reoriginate STD_TE & GMPLS circuits */
lsp_regenerate_schedule(area, area->is_type, 0);
diff --git a/isisd/isis_pfpacket.c b/isisd/isis_pfpacket.c
index a448e0043c..84278f3f71 100644
--- a/isisd/isis_pfpacket.c
+++ b/isisd/isis_pfpacket.c
@@ -103,15 +103,15 @@ static int isis_multicast_join(int fd, int registerto, int if_num)
#ifdef EXTREME_DEBUG
if (IS_DEBUG_EVENTS)
zlog_debug(
- "isis_multicast_join(): fd=%d, reg_to=%d, if_num=%d, address = %02x:%02x:%02x:%02x:%02x:%02x",
- fd, registerto, if_num, mreq.mr_address[0],
+ "%s: fd=%d, reg_to=%d, if_num=%d, address = %02x:%02x:%02x:%02x:%02x:%02x",
+ __func__, fd, registerto, if_num, mreq.mr_address[0],
mreq.mr_address[1], mreq.mr_address[2],
mreq.mr_address[3], mreq.mr_address[4],
mreq.mr_address[5]);
#endif /* EXTREME_DEBUG */
if (setsockopt(fd, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &mreq,
sizeof(struct packet_mreq))) {
- zlog_warn("isis_multicast_join(): setsockopt(): %s",
+ zlog_warn("%s: setsockopt(): %s", __func__,
safe_strerror(errno));
return ISIS_WARNING;
}
@@ -131,13 +131,13 @@ static int open_packet_socket(struct isis_circuit *circuit)
vrf->name);
if (fd < 0) {
- zlog_warn("open_packet_socket(): socket() failed %s",
+ zlog_warn("%s: socket() failed %s", __func__,
safe_strerror(errno));
return ISIS_WARNING;
}
if (setsockopt(fd, SOL_SOCKET, SO_ATTACH_FILTER, &bpf, sizeof(bpf))) {
- zlog_warn("open_packet_socket(): SO_ATTACH_FILTER failed: %s",
+ zlog_warn("%s: SO_ATTACH_FILTER failed: %s", __func__,
safe_strerror(errno));
}
@@ -151,7 +151,7 @@ static int open_packet_socket(struct isis_circuit *circuit)
if (bind(fd, (struct sockaddr *)(&s_addr), sizeof(struct sockaddr_ll))
< 0) {
- zlog_warn("open_packet_socket(): bind() failed: %s",
+ zlog_warn("%s: bind() failed: %s", __func__,
safe_strerror(errno));
close(fd);
return ISIS_WARNING;
@@ -208,7 +208,7 @@ int isis_sock_init(struct isis_circuit *circuit)
circuit->tx = isis_send_pdu_p2p;
circuit->rx = isis_recv_pdu_p2p;
} else {
- zlog_warn("isis_sock_init(): unknown circuit type");
+ zlog_warn("%s: unknown circuit type", __func__);
retval = ISIS_WARNING;
break;
}
@@ -243,8 +243,8 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
|| (s_addr.sll_ifindex != (int)circuit->interface->ifindex)) {
if (bytesread < 0) {
zlog_warn(
- "isis_recv_packet_bcast(): ifname %s, fd %d, bytesread %d, recvfrom(): %s",
- circuit->interface->name, circuit->fd,
+ "%s: ifname %s, fd %d, bytesread %d, recvfrom(): %s",
+ __func__, circuit->interface->name, circuit->fd,
bytesread, safe_strerror(errno));
}
if (s_addr.sll_ifindex != (int)circuit->interface->ifindex) {
@@ -261,7 +261,7 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
(socklen_t *)&addr_len);
if (bytesread < 0)
- zlog_warn("isis_recv_pdu_bcast(): recvfrom() failed");
+ zlog_warn("%s: recvfrom() failed", __func__);
return ISIS_WARNING;
}
@@ -276,7 +276,7 @@ int isis_recv_pdu_bcast(struct isis_circuit *circuit, uint8_t *ssnpa)
(struct sockaddr *)&s_addr,
(socklen_t *)&addr_len);
if (bytesread < 0)
- zlog_warn("isis_recv_pdu_bcast(): recvfrom() failed");
+ zlog_warn("%s: recvfrom() failed", __func__);
return ISIS_WARNING;
}
@@ -321,7 +321,7 @@ int isis_recv_pdu_p2p(struct isis_circuit *circuit, uint8_t *ssnpa)
(struct sockaddr *)&s_addr,
(socklen_t *)&addr_len);
if (bytesread < 0)
- zlog_warn("isis_recv_pdu_p2p(): recvfrom() failed");
+ zlog_warn("%s: recvfrom() failed", __func__);
return ISIS_WARNING;
}
@@ -329,7 +329,7 @@ int isis_recv_pdu_p2p(struct isis_circuit *circuit, uint8_t *ssnpa)
* ISO over GRE we exit with pain :)
*/
if (ntohs(s_addr.sll_protocol) != 0x00FE) {
- zlog_warn("isis_recv_pdu_p2p(): protocol mismatch(): %X",
+ zlog_warn("%s: protocol mismatch(): %X", __func__,
ntohs(s_addr.sll_protocol));
return ISIS_WARNING;
}
diff --git a/isisd/isis_spf.c b/isisd/isis_spf.c
index 6be7c2d608..bdd323e1a7 100644
--- a/isisd/isis_spf.c
+++ b/isisd/isis_spf.c
@@ -844,8 +844,7 @@ static int isis_spf_process_lsp(struct isis_spftree *spftree,
lspfragloop:
if (lsp->hdr.seqno == 0) {
- zlog_warn(
- "isis_spf_process_lsp(): lsp with 0 seq_num - ignore");
+ zlog_warn("%s: lsp with 0 seq_num - ignore", __func__);
return ISIS_WARNING;
}
@@ -1780,7 +1779,8 @@ void isis_run_spf(struct isis_spftree *spftree)
break;
case SPFTREE_COUNT:
zlog_err(
- "isis_run_spf should never be called with SPFTREE_COUNT as argument!");
+ "%s should never be called with SPFTREE_COUNT as argument!",
+ __func__);
exit(1);
}
diff --git a/isisd/isis_sr.c b/isisd/isis_sr.c
index 259047ff66..f70840a637 100644
--- a/isisd/isis_sr.c
+++ b/isisd/isis_sr.c
@@ -1253,6 +1253,9 @@ void isis_sr_area_term(struct isis_area *area)
if (area->srdb.enabled)
isis_sr_stop(area);
+ /* Free Adjacency SID list */
+ list_delete(&srdb->adj_sids);
+
/* Clear Prefix-SID configuration. */
while (srdb_prefix_cfg_count(&srdb->config.prefix_sids) > 0) {
struct sr_prefix_cfg *pcfg;
diff --git a/isisd/isis_te.c b/isisd/isis_te.c
index 3faff1cc4d..0093279cde 100644
--- a/isisd/isis_te.c
+++ b/isisd/isis_te.c
@@ -64,10 +64,115 @@
#include "isisd/isis_te.h"
#include "isisd/isis_zebra.h"
+DEFINE_MTYPE_STATIC(ISISD, ISIS_MPLS_TE, "ISIS MPLS_TE parameters");
+
/*------------------------------------------------------------------------*
* Following are control functions for MPLS-TE parameters management.
*------------------------------------------------------------------------*/
+/**
+ * Create MPLS Traffic Engineering structure which belongs to given area.
+ *
+ * @param area IS-IS Area
+ */
+void isis_mpls_te_create(struct isis_area *area)
+{
+ struct listnode *node;
+ struct isis_circuit *circuit;
+
+ if (!area)
+ return;
+
+ if (area->mta == NULL) {
+
+ struct mpls_te_area *new;
+
+ zlog_debug("ISIS-TE(%s): Initialize MPLS Traffic Engineering",
+ area->area_tag);
+
+ new = XCALLOC(MTYPE_ISIS_MPLS_TE, sizeof(struct mpls_te_area));
+
+ /* Initialize MPLS_TE structure */
+ new->status = enable;
+ new->level = 0;
+ new->inter_as = off;
+ new->interas_areaid.s_addr = 0;
+ new->router_id.s_addr = 0;
+ new->ted = ls_ted_new(1, "ISIS", 0);
+ if (!new->ted)
+ zlog_warn("Unable to create Link State Data Base");
+
+ area->mta = new;
+ } else {
+ area->mta->status = enable;
+ }
+
+ /* Initialize Link State Database */
+ if (area->mta->ted)
+ isis_te_init_ted(area);
+
+ /* Update Extended TLVs according to Interface link parameters */
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit))
+ isis_link_params_update(circuit, circuit->interface);
+}
+
+/**
+ * Disable MPLS Traffic Engineering structure which belongs to given area.
+ *
+ * @param area IS-IS Area
+ */
+void isis_mpls_te_disable(struct isis_area *area)
+{
+ struct listnode *node;
+ struct isis_circuit *circuit;
+
+ if (!area->mta)
+ return;
+
+ area->mta->status = disable;
+
+ /* Remove Link State Database */
+ ls_ted_del_all(&area->mta->ted);
+
+ /* Disable Extended SubTLVs on all circuit */
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
+ if (!IS_EXT_TE(circuit->ext))
+ continue;
+
+ /* disable MPLS_TE Circuit keeping SR one's */
+ if (IS_SUBTLV(circuit->ext, EXT_ADJ_SID))
+ circuit->ext->status = EXT_ADJ_SID;
+ else if (IS_SUBTLV(circuit->ext, EXT_LAN_ADJ_SID))
+ circuit->ext->status = EXT_LAN_ADJ_SID;
+ else
+ circuit->ext->status = 0;
+ }
+}
+
+void isis_mpls_te_term(struct isis_area *area)
+{
+ struct listnode *node;
+ struct isis_circuit *circuit;
+
+ if (!area->mta)
+ return;
+
+ zlog_info("TE(%s): Terminate MPLS TE", __func__);
+ /* Remove Link State Database */
+ ls_ted_del_all(&area->mta->ted);
+
+ /* Remove Extended SubTLVs */
+ zlog_info(" |- Remove Extended SubTLVS for all circuit");
+ for (ALL_LIST_ELEMENTS_RO(area->circuit_list, node, circuit)) {
+ zlog_info(" |- Call isis_del_ext_subtlvs()");
+ isis_del_ext_subtlvs(circuit->ext);
+ circuit->ext = NULL;
+ }
+
+ zlog_info(" |- Free MTA structure at %p", area->mta);
+ XFREE(MTYPE_ISIS_MPLS_TE, area->mta);
+}
+
/* Main initialization / update function of the MPLS TE Circuit context */
/* Call when interface TE Link parameters are modified */
void isis_link_params_update(struct isis_circuit *circuit,
diff --git a/isisd/isis_te.h b/isisd/isis_te.h
index 56954073dd..03525962f5 100644
--- a/isisd/isis_te.h
+++ b/isisd/isis_te.h
@@ -123,6 +123,9 @@ enum lsp_event { LSP_UNKNOWN, LSP_ADD, LSP_UPD, LSP_DEL, LSP_INC, LSP_TICK };
/* Prototypes. */
void isis_mpls_te_init(void);
+void isis_mpls_te_create(struct isis_area *area);
+void isis_mpls_te_disable(struct isis_area *area);
+void isis_mpls_te_term(struct isis_area *area);
void isis_link_params_update(struct isis_circuit *, struct interface *);
int isis_mpls_te_update(struct interface *);
void isis_te_lsp_event(struct isis_lsp *lsp, enum lsp_event event);
diff --git a/isisd/isis_tlvs.c b/isisd/isis_tlvs.c
index b3c3fd4b0b..8907fa256b 100644
--- a/isisd/isis_tlvs.c
+++ b/isisd/isis_tlvs.c
@@ -139,6 +139,25 @@ struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void)
return ext;
}
+void isis_del_ext_subtlvs(struct isis_ext_subtlvs *ext)
+{
+ struct isis_item *item, *next_item;
+
+ if (!ext)
+ return;
+
+ /* First, free Adj SID and LAN Adj SID list if needed */
+ for (item = ext->adj_sid.head; item; item = next_item) {
+ next_item = item->next;
+ XFREE(MTYPE_ISIS_SUBTLV, item);
+ }
+ for (item = ext->lan_sid.head; item; item = next_item) {
+ next_item = item->next;
+ XFREE(MTYPE_ISIS_SUBTLV, item);
+ }
+ XFREE(MTYPE_ISIS_SUBTLV, ext);
+}
+
/*
* mtid parameter is used to determine if Adjacency is related to IPv4 or IPv6
* Multi-Topology. Special 4096 value i.e. first R flag set is used to indicate
@@ -648,18 +667,7 @@ static void format_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
static void free_item_ext_subtlvs(struct isis_ext_subtlvs *exts)
{
- struct isis_item *item, *next_item;
-
- /* First, free Adj SID and LAN Adj SID list if needed */
- for (item = exts->adj_sid.head; item; item = next_item) {
- next_item = item->next;
- XFREE(MTYPE_ISIS_SUBTLV, item);
- }
- for (item = exts->lan_sid.head; item; item = next_item) {
- next_item = item->next;
- XFREE(MTYPE_ISIS_SUBTLV, item);
- }
- XFREE(MTYPE_ISIS_SUBTLV, exts);
+ isis_del_ext_subtlvs(exts);
}
static int pack_item_ext_subtlvs(struct isis_ext_subtlvs *exts,
@@ -1059,6 +1067,7 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
log, indent,
"TLV size does not match expected size for Adjacency SID!\n");
stream_forward_getp(s, subtlv_len - 2);
+ XFREE(MTYPE_ISIS_SUBTLV, adj);
break;
}
@@ -1070,6 +1079,7 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
log, indent,
"TLV size does not match expected size for Adjacency SID!\n");
stream_forward_getp(s, subtlv_len - 2);
+ XFREE(MTYPE_ISIS_SUBTLV, adj);
break;
}
@@ -1114,6 +1124,7 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
stream_forward_getp(
s, subtlv_len - 2
- ISIS_SYS_ID_LEN);
+ XFREE(MTYPE_ISIS_SUBTLV, lan);
break;
}
@@ -1127,6 +1138,7 @@ static int unpack_item_ext_subtlvs(uint16_t mtid, uint8_t len, struct stream *s,
stream_forward_getp(
s, subtlv_len - 2
- ISIS_SYS_ID_LEN);
+ XFREE(MTYPE_ISIS_SUBTLV, lan);
break;
}
@@ -1892,6 +1904,7 @@ static void format_item_extended_reach(uint16_t mtid, struct isis_item *i,
static void free_item_extended_reach(struct isis_item *i)
{
struct isis_extended_reach *item = (struct isis_extended_reach *)i;
+
if (item->subtlvs != NULL)
free_item_ext_subtlvs(item->subtlvs);
XFREE(MTYPE_ISIS_TLV, item);
diff --git a/isisd/isis_tlvs.h b/isisd/isis_tlvs.h
index 157450dc6c..905032bda1 100644
--- a/isisd/isis_tlvs.h
+++ b/isisd/isis_tlvs.h
@@ -597,6 +597,7 @@ void isis_tlvs_add_ipv6_dstsrc_reach(struct isis_tlvs *tlvs, uint16_t mtid,
struct prefix_ipv6 *src,
uint32_t metric);
struct isis_ext_subtlvs *isis_alloc_ext_subtlvs(void);
+void isis_del_ext_subtlvs(struct isis_ext_subtlvs *ext);
void isis_tlvs_add_adj_sid(struct isis_ext_subtlvs *exts,
struct isis_adj_sid *adj);
void isis_tlvs_del_adj_sid(struct isis_ext_subtlvs *exts,
diff --git a/isisd/isisd.c b/isisd/isisd.c
index 3fd2476ad1..54e6be5970 100644
--- a/isisd/isisd.c
+++ b/isisd/isisd.c
@@ -90,6 +90,7 @@ DEFINE_MTYPE_STATIC(ISISD, ISIS_NAME, "ISIS process name");
DEFINE_MTYPE_STATIC(ISISD, ISIS_AREA, "ISIS area");
DEFINE_MTYPE(ISISD, ISIS_AREA_ADDR, "ISIS area address");
DEFINE_MTYPE(ISISD, ISIS_ACL_NAME, "ISIS access-list name");
+DEFINE_MTYPE(ISISD, ISIS_PLIST_NAME, "ISIS prefix-list name");
DEFINE_QOBJ_TYPE(isis_area);
@@ -224,6 +225,12 @@ struct isis *isis_new(const char *vrf_name)
void isis_finish(struct isis *isis)
{
+ struct isis_area *area;
+ struct listnode *node, *nnode;
+
+ for (ALL_LIST_ELEMENTS(isis->area_list, node, nnode, area))
+ isis_area_destroy(area);
+
struct vrf *vrf = NULL;
listnode_delete(im->isis, isis);
@@ -273,6 +280,13 @@ void isis_area_del_circuit(struct isis_area *area, struct isis_circuit *circuit)
isis_csm_state_change(ISIS_DISABLE, circuit, area);
}
+static void delete_area_addr(void *arg)
+{
+ struct area_addr *addr = (struct area_addr *)arg;
+
+ XFREE(MTYPE_ISIS_AREA_ADDR, addr);
+}
+
struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name)
{
struct isis_area *area;
@@ -318,6 +332,8 @@ struct isis_area *isis_area_create(const char *area_tag, const char *vrf_name)
area->circuit_list = list_new();
area->adjacency_list = list_new();
area->area_addrs = list_new();
+ area->area_addrs->del = delete_area_addr;
+
if (!CHECK_FLAG(im->options, F_ISIS_UNIT_TEST))
thread_add_timer(master, lsp_tick, area, 1, &area->t_tick);
flags_initialize(&area->flags);
@@ -481,17 +497,12 @@ void isis_area_destroy(struct isis_area *area)
{
struct listnode *node, *nnode;
struct isis_circuit *circuit;
- struct area_addr *addr;
QOBJ_UNREG(area);
if (fabricd)
fabricd_finish(area->fabricd);
- /* Disable MPLS if necessary before flooding LSP */
- if (IS_MPLS_TE(area->mta))
- area->mta->status = disable;
-
if (area->circuit_list) {
for (ALL_LIST_ELEMENTS(area->circuit_list, node, nnode,
circuit))
@@ -499,6 +510,9 @@ void isis_area_destroy(struct isis_area *area)
list_delete(&area->circuit_list);
}
+ if (area->flags.free_idcs)
+ list_delete(&area->flags.free_idcs);
+
list_delete(&area->adjacency_list);
lsp_db_fini(&area->lspdb[0]);
@@ -510,6 +524,8 @@ void isis_area_destroy(struct isis_area *area)
isis_sr_area_term(area);
+ isis_mpls_te_term(area);
+
spftree_area_del(area);
if (area->spf_timer[0])
@@ -525,11 +541,7 @@ void isis_area_destroy(struct isis_area *area)
if (!CHECK_FLAG(im->options, F_ISIS_UNIT_TEST))
isis_redist_area_finish(area);
- for (ALL_LIST_ELEMENTS(area->area_addrs, node, nnode, addr)) {
- list_delete_node(area->area_addrs, node);
- XFREE(MTYPE_ISIS_AREA_ADDR, addr);
- }
- area->area_addrs = NULL;
+ list_delete(&area->area_addrs);
for (int i = SPF_PREFIX_PRIO_CRITICAL; i <= SPF_PREFIX_PRIO_MEDIUM;
i++) {
@@ -554,9 +566,10 @@ void isis_area_destroy(struct isis_area *area)
area_mt_finish(area);
- if (listcount(area->isis->area_list) == 0) {
- isis_finish(area->isis);
- }
+ if (area->rlfa_plist_name[0])
+ XFREE(MTYPE_ISIS_PLIST_NAME, area->rlfa_plist_name[0]);
+ if (area->rlfa_plist_name[1])
+ XFREE(MTYPE_ISIS_PLIST_NAME, area->rlfa_plist_name[1]);
XFREE(MTYPE_ISIS_AREA, area);
diff --git a/isisd/isisd.h b/isisd/isisd.h
index c313fd9ef7..4951e5809b 100644
--- a/isisd/isisd.h
+++ b/isisd/isisd.h
@@ -251,6 +251,7 @@ DECLARE_QOBJ_TYPE(isis_area);
DECLARE_MTYPE(ISIS_ACL_NAME); /* isis_area->spf_prefix_prioritites */
DECLARE_MTYPE(ISIS_AREA_ADDR); /* isis_area->area_addrs */
+DECLARE_MTYPE(ISIS_PLIST_NAME);
DECLARE_HOOK(isis_area_overload_bit_update, (struct isis_area * area), (area));
diff --git a/ldpd/ldpe.c b/ldpd/ldpe.c
index 792dcb2f2a..1b5c0e90fb 100644
--- a/ldpd/ldpe.c
+++ b/ldpd/ldpe.c
@@ -616,8 +616,8 @@ static void ldpe_dispatch_main(struct thread *thread)
}
break;
default:
- log_debug("ldpe_dispatch_main: error handling imsg %d",
- imsg.hdr.type);
+ log_debug("%s: error handling imsg %d",
+ __func__, imsg.hdr.type);
break;
}
imsg_free(&imsg);
@@ -724,7 +724,7 @@ static void ldpe_dispatch_lde(struct thread *thread)
nbr = nbr_find_peerid(imsg.hdr.peerid);
if (nbr == NULL) {
- log_debug("ldpe_dispatch_lde: cannot find neighbor");
+ log_debug("%s: cannot find neighbor", __func__);
break;
}
if (nbr->state != NBR_STA_OPER)
@@ -744,7 +744,7 @@ static void ldpe_dispatch_lde(struct thread *thread)
case IMSG_NBR_SHUTDOWN:
nbr = nbr_find_peerid(imsg.hdr.peerid);
if (nbr == NULL) {
- log_debug("ldpe_dispatch_lde: cannot find neighbor");
+ log_debug("%s: cannot find neighbor", __func__);
break;
}
if (nbr->state != NBR_STA_OPER)
@@ -752,8 +752,8 @@ static void ldpe_dispatch_lde(struct thread *thread)
session_shutdown(nbr,S_SHUTDOWN,0,0);
break;
default:
- log_debug("ldpe_dispatch_lde: error handling imsg %d",
- imsg.hdr.type);
+ log_debug("%s: error handling imsg %d",
+ __func__, imsg.hdr.type);
break;
}
imsg_free(&imsg);
diff --git a/lib/bitfield.h b/lib/bitfield.h
index a3f361ed9d..9af4053daf 100644
--- a/lib/bitfield.h
+++ b/lib/bitfield.h
@@ -158,6 +158,75 @@ DECLARE_MTYPE(BITFIELD);
(b) += (w * WORD_SIZE); \
} while (0)
+/*
+ * Find a clear bit in v and return it
+ * Start looking in the word containing bit position start_index.
+ * If necessary, wrap around after bit position max_index.
+ */
+static inline unsigned int
+bf_find_next_clear_bit_wrap(bitfield_t *v, word_t start_index, word_t max_index)
+{
+ int start_bit;
+ unsigned long i, offset, scanbits, wordcount_max, index_max;
+
+ if (start_index > max_index)
+ start_index = 0;
+
+ start_bit = start_index & (WORD_SIZE - 1);
+ wordcount_max = bf_index(max_index) + 1;
+
+ scanbits = WORD_SIZE;
+ for (i = bf_index(start_index); i < v->m; ++i) {
+ if (v->data[i] == WORD_MAX) {
+ /* if the whole word is full move to the next */
+ start_bit = 0;
+ continue;
+ }
+ /* scan one word for clear bits */
+ if ((i == v->m - 1) && (v->m >= wordcount_max))
+ /* max index could be only part of word */
+ scanbits = (max_index % WORD_SIZE) + 1;
+ for (offset = start_bit; offset < scanbits; ++offset) {
+ if (!((v->data[i] >> offset) & 1))
+ return ((i * WORD_SIZE) + offset);
+ }
+ /* move to the next word */
+ start_bit = 0;
+ }
+
+ if (v->m < wordcount_max) {
+ /*
+ * We can expand bitfield, so no need to wrap.
+ * Return the index of the first bit of the next word.
+ * Assumption is that caller will call bf_set_bit which
+ * will allocate additional space.
+ */
+ v->m += 1;
+ v->data = (word_t *)realloc(v->data, v->m * sizeof(word_t));
+ v->data[v->m - 1] = 0;
+ return v->m * WORD_SIZE;
+ }
+
+ /*
+ * start looking for a clear bit at the start of the bitfield and
+ * stop when we reach start_index
+ */
+ scanbits = WORD_SIZE;
+ index_max = bf_index(start_index - 1);
+ for (i = 0; i <= index_max; ++i) {
+ if (i == index_max)
+ scanbits = ((start_index - 1) % WORD_SIZE) + 1;
+ for (offset = start_bit; offset < scanbits; ++offset) {
+ if (!((v->data[i] >> offset) & 1))
+ return ((i * WORD_SIZE) + offset);
+ }
+ /* move to the next word */
+ start_bit = 0;
+ }
+
+ return WORD_MAX;
+}
+
static inline unsigned int bf_find_next_set_bit(bitfield_t v,
word_t start_index)
{
diff --git a/lib/link_state.c b/lib/link_state.c
index 639a1d37d8..ab5a8515b5 100644
--- a/lib/link_state.c
+++ b/lib/link_state.c
@@ -1357,7 +1357,6 @@ struct ls_message *ls_parse_msg(struct stream *s)
/* Read LS Message header */
STREAM_GETC(s, msg->event);
STREAM_GETC(s, msg->type);
- STREAM_GET(&msg->remote_id, s, sizeof(struct ls_node_id));
/* Read Message Payload */
switch (msg->type) {
@@ -1365,6 +1364,7 @@ struct ls_message *ls_parse_msg(struct stream *s)
msg->data.node = ls_parse_node(s);
break;
case LS_MSG_TYPE_ATTRIBUTES:
+ STREAM_GET(&msg->remote_id, s, sizeof(struct ls_node_id));
msg->data.attr = ls_parse_attributes(s);
break;
case LS_MSG_TYPE_PREFIX:
@@ -1563,13 +1563,14 @@ static int ls_format_msg(struct stream *s, struct ls_message *msg)
/* Prepare Link State header */
stream_putc(s, msg->event);
stream_putc(s, msg->type);
- stream_put(s, &msg->remote_id, sizeof(struct ls_node_id));
/* Add Message Payload */
switch (msg->type) {
case LS_MSG_TYPE_NODE:
return ls_format_node(s, msg->data.node);
case LS_MSG_TYPE_ATTRIBUTES:
+ /* Add remote node first */
+ stream_put(s, &msg->remote_id, sizeof(struct ls_node_id));
return ls_format_attributes(s, msg->data.attr);
case LS_MSG_TYPE_PREFIX:
return ls_format_prefix(s, msg->data.prefix);
@@ -1625,7 +1626,6 @@ int ls_send_msg(struct zclient *zclient, struct ls_message *msg,
return zclient_send_message(zclient);
}
-
struct ls_message *ls_vertex2msg(struct ls_message *msg,
struct ls_vertex *vertex)
{
@@ -1791,9 +1791,10 @@ struct ls_edge *ls_msg2edge(struct ls_ted *ted, struct ls_message *msg,
case LS_MSG_EVENT_DELETE:
edge = ls_find_edge_by_source(ted, attr);
if (edge) {
- if (delete)
+ if (delete) {
ls_edge_del_all(ted, edge);
- else
+ edge = NULL;
+ } else
edge->status = DELETE;
}
break;
diff --git a/lib/link_state.h b/lib/link_state.h
index f46a2068a1..ed315452da 100644
--- a/lib/link_state.h
+++ b/lib/link_state.h
@@ -91,7 +91,7 @@ struct ls_node_id {
uint8_t level; /* ISIS Level */
uint8_t padding;
} iso;
- } id __attribute__((aligned(8)));
+ } id;
};
/**
diff --git a/lib/plist.c b/lib/plist.c
index d8ef9dcbd5..ff2a59ba2d 100644
--- a/lib/plist.c
+++ b/lib/plist.c
@@ -1570,7 +1570,6 @@ static void prefix_list_reset_afi(afi_t afi, int orf)
while ((plist = plist_first(&master->str))) {
prefix_list_delete(plist);
- plist_pop(&master->str);
}
master->recent = NULL;
diff --git a/lib/prefix.h b/lib/prefix.h
index 7b2f889874..b904311539 100644
--- a/lib/prefix.h
+++ b/lib/prefix.h
@@ -674,6 +674,7 @@ static inline bool ipv4_mcast_ssm(const struct in_addr *addr)
#pragma FRR printfrr_ext "%pFX" (struct prefix_eth *)
#pragma FRR printfrr_ext "%pFX" (struct prefix_evpn *)
#pragma FRR printfrr_ext "%pFX" (struct prefix_fs *)
+#pragma FRR printfrr_ext "%pRD" (struct prefix_rd *)
#pragma FRR printfrr_ext "%pPSG4" (struct prefix_sg *)
#endif
diff --git a/lib/routemap.c b/lib/routemap.c
index 9529b79419..3cc010c148 100644
--- a/lib/routemap.c
+++ b/lib/routemap.c
@@ -812,17 +812,13 @@ int route_map_mark_updated(const char *name)
return (ret);
}
-static int route_map_clear_updated(struct route_map *map)
+static void route_map_clear_updated(struct route_map *map)
{
- int ret = -1;
-
if (map) {
map->to_be_processed = false;
if (map->deleted)
route_map_free_map(map);
}
-
- return (ret);
}
/* Lookup route map. If there isn't route map create one and return
@@ -1063,7 +1059,6 @@ static int vty_show_route_map(struct vty *vty, const char *name, bool use_json)
if (map) {
vty_show_route_map_entry(vty, map, json_proto);
- return CMD_SUCCESS;
} else if (!use_json) {
vty_out(vty, "%s: 'route-map %s' not found\n",
frr_protonameinst, name);
diff --git a/lib/routemap.h b/lib/routemap.h
index ad391981e0..a365925854 100644
--- a/lib/routemap.h
+++ b/lib/routemap.h
@@ -280,6 +280,8 @@ DECLARE_QOBJ_TYPE(route_map);
#define IS_MATCH_ORIGIN(C) \
(strmatch(C, "frr-bgp-route-map:match-origin"))
#define IS_MATCH_RPKI(C) (strmatch(C, "frr-bgp-route-map:rpki"))
+#define IS_MATCH_RPKI_EXTCOMMUNITY(C) \
+ (strmatch(C, "frr-bgp-route-map:rpki-extcommunity"))
#define IS_MATCH_PROBABILITY(C) \
(strmatch(C, "frr-bgp-route-map:probability"))
#define IS_MATCH_SRC_VRF(C) \
@@ -387,6 +389,8 @@ DECLARE_QOBJ_TYPE(route_map);
(strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv4"))
#define IS_SET_BGP_EVPN_GATEWAY_IP_IPV6(A) \
(strmatch(A, "frr-bgp-route-map:set-evpn-gateway-ip-ipv6"))
+#define IS_SET_BGP_L3VPN_NEXTHOP_ENCAPSULATION(A) \
+ (strmatch(A, "frr-bgp-route-map:set-l3vpn-nexthop-encapsulation"))
enum ecommunity_lb_type {
EXPLICIT_BANDWIDTH,
diff --git a/lib/routemap_cli.c b/lib/routemap_cli.c
index ff98a14c41..6be5d15ec4 100644
--- a/lib/routemap_cli.c
+++ b/lib/routemap_cli.c
@@ -650,6 +650,11 @@ void route_map_condition_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(
dnode,
"./rmap-match-condition/frr-bgp-route-map:rpki"));
+ } else if (IS_MATCH_RPKI_EXTCOMMUNITY(condition)) {
+ vty_out(vty, " match rpki-extcommunity %s\n",
+ yang_dnode_get_string(
+ dnode,
+ "./rmap-match-condition/frr-bgp-route-map:rpki-extcommunity"));
} else if (IS_MATCH_PROBABILITY(condition)) {
vty_out(vty, " match probability %s\n",
yang_dnode_get_string(
@@ -1258,6 +1263,11 @@ void route_map_action_show(struct vty *vty, const struct lyd_node *dnode,
yang_dnode_get_string(
dnode,
"./rmap-set-action/frr-bgp-route-map:evpn-gateway-ip-ipv6"));
+ } else if (IS_SET_BGP_L3VPN_NEXTHOP_ENCAPSULATION(action)) {
+ vty_out(vty, " set l3vpn next-hop encapsulation %s\n",
+ yang_dnode_get_string(
+ dnode,
+ "./rmap-set-action/frr-bgp-route-map:l3vpn-nexthop-encapsulation"));
}
}
diff --git a/lib/sigevent.c b/lib/sigevent.c
index 0f20bc0270..985bedeb92 100644
--- a/lib/sigevent.c
+++ b/lib/sigevent.c
@@ -134,8 +134,7 @@ int frr_sigevent_process(void)
#ifdef SIGEVENT_BLOCK_SIGNALS
if (sigprocmask(SIG_UNBLOCK, &oldmask, NULL) < 0)
- ;
- return -1;
+ return -1;
#endif /* SIGEVENT_BLOCK_SIGNALS */
return 0;
diff --git a/lib/sockopt.c b/lib/sockopt.c
index a66a5224e8..de11a9eab3 100644
--- a/lib/sockopt.c
+++ b/lib/sockopt.c
@@ -268,12 +268,9 @@ int setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr,
&& (errno == EADDRINUSE)) {
/* see above: handle possible problem when interface comes back
* up */
- char buf[1][INET_ADDRSTRLEN];
zlog_info(
- "setsockopt_ipv4_multicast attempting to drop and re-add (fd %d, mcast %s, ifindex %u)",
- sock, inet_ntop(AF_INET, &mreqn.imr_multiaddr, buf[0],
- sizeof(buf[0])),
- ifindex);
+ "setsockopt_ipv4_multicast attempting to drop and re-add (fd %d, mcast %pI4, ifindex %u)",
+ sock, &mreqn.imr_multiaddr, ifindex);
setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreqn,
sizeof(mreqn));
ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
@@ -309,12 +306,9 @@ int setsockopt_ipv4_multicast(int sock, int optname, struct in_addr if_addr,
&& (errno == EADDRINUSE)) {
/* see above: handle possible problem when interface comes back
* up */
- char buf[1][INET_ADDRSTRLEN];
zlog_info(
- "setsockopt_ipv4_multicast attempting to drop and re-add (fd %d, mcast %s, ifindex %u)",
- sock, inet_ntop(AF_INET, &mreq.imr_multiaddr, buf[0],
- sizeof(buf[0])),
- ifindex);
+ "setsockopt_ipv4_multicast attempting to drop and re-add (fd %d, mcast %pI4, ifindex %u)",
+ sock, &mreq.imr_multiaddr, ifindex);
setsockopt(sock, IPPROTO_IP, IP_DROP_MEMBERSHIP, (void *)&mreq,
sizeof(mreq));
ret = setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP,
diff --git a/lib/sockunion.c b/lib/sockunion.c
index eff38798cc..36ae21fdd1 100644
--- a/lib/sockunion.c
+++ b/lib/sockunion.c
@@ -290,8 +290,10 @@ int sockopt_reuseaddr(int sock)
ret = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void *)&on,
sizeof(on));
if (ret < 0) {
- flog_err(EC_LIB_SOCKET,
- "can't set sockopt SO_REUSEADDR to socket %d", sock);
+ flog_err(
+ EC_LIB_SOCKET,
+ "can't set sockopt SO_REUSEADDR to socket %d errno=%d: %s",
+ sock, errno, safe_strerror(errno));
return -1;
}
return 0;
diff --git a/lib/subdir.am b/lib/subdir.am
index b0c311e7f2..d6defd7149 100644
--- a/lib/subdir.am
+++ b/lib/subdir.am
@@ -469,11 +469,7 @@ am__v_XRELFO_ = $(am__v_XRELFO_$(AM_DEFAULT_VERBOSITY))
am__v_XRELFO_0 = @echo " XRELFO " $@;
am__v_XRELFO_1 =
-if DEV_BUILD
XRELFO_FLAGS = -Wlog-format -Wlog-args
-else
-XRELFO_FLAGS =
-endif
SUFFIXES += .xref
%.xref: % $(CLIPPY)
diff --git a/lib/termtable.h b/lib/termtable.h
index 698cc73465..e61c7fa302 100644
--- a/lib/termtable.h
+++ b/lib/termtable.h
@@ -105,13 +105,6 @@ struct ttable *ttable_new(const struct ttable_style *tts);
void ttable_del(struct ttable *tt);
/**
- * Deletes an individual cell.
- *
- * @param cell the cell to destroy
- */
-void ttable_cell_del(struct ttable_cell *cell);
-
-/**
* Inserts a new row at the given index.
*
* The row contents are determined by a format string. The format string has
diff --git a/lib/thread.c b/lib/thread.c
index c3613b5b0e..9eac9b410a 100644
--- a/lib/thread.c
+++ b/lib/thread.c
@@ -1354,9 +1354,9 @@ static void do_thread_cancel(struct thread_master *master)
struct thread_list_head *list = NULL;
struct thread **thread_array = NULL;
struct thread *thread;
-
struct cancel_req *cr;
struct listnode *ln;
+
for (ALL_LIST_ELEMENTS_RO(master->cancel_req, ln, cr)) {
/*
* If this is an event object cancellation, search
@@ -1379,6 +1379,9 @@ static void do_thread_cancel(struct thread_master *master)
if (!thread)
continue;
+ list = NULL;
+ thread_array = NULL;
+
/* Determine the appropriate queue to cancel the thread from */
switch (thread->type) {
case THREAD_READ:
diff --git a/lib/typesafe.h b/lib/typesafe.h
index 50c410ad24..8aeabb34e6 100644
--- a/lib/typesafe.h
+++ b/lib/typesafe.h
@@ -850,9 +850,12 @@ macro_inline type *prefix ## _add(struct prefix##_head *h, type *item) \
struct thash_item **np = &h->hh.entries[hbits]; \
while (*np && (*np)->hashval < hval) \
np = &(*np)->next; \
- if (*np && cmpfn(container_of(*np, type, field.hi), item) == 0) { \
- h->hh.count--; \
- return container_of(*np, type, field.hi); \
+ while (*np && (*np)->hashval == hval) { \
+ if (cmpfn(container_of(*np, type, field.hi), item) == 0) { \
+ h->hh.count--; \
+ return container_of(*np, type, field.hi); \
+ } \
+ np = &(*np)->next; \
} \
item->field.hi.next = *np; \
*np = &item->field.hi; \
diff --git a/lib/yang_wrappers.c b/lib/yang_wrappers.c
index bee76c6e0f..ea21d1324b 100644
--- a/lib/yang_wrappers.c
+++ b/lib/yang_wrappers.c
@@ -715,7 +715,7 @@ size_t yang_dnode_get_binary_buf(char *buf, size_t size,
canon = YANG_DNODE_XPATH_GET_CANON(dnode, xpath_fmt);
cannon_len = strlen(canon);
- decode_len = cannon_len;
+ decode_len = cannon_len + 1;
value_str = (char *)malloc(decode_len);
base64_init_decodestate(&s);
cnt = base64_decode_block(canon, cannon_len, value_str, &s);
diff --git a/lib/zclient.c b/lib/zclient.c
index e556b768ac..8ec82ab7bb 100644
--- a/lib/zclient.c
+++ b/lib/zclient.c
@@ -447,7 +447,7 @@ enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
{
struct prefix_ipv6 p = {};
struct zapi_route api = {};
- struct nexthop nh = {};
+ struct zapi_nexthop *znh;
p.family = AF_INET6;
p.prefixlen = IPV6_MAX_BITLEN;
@@ -465,12 +465,16 @@ enum zclient_send_status zclient_send_localsid(struct zclient *zclient,
SET_FLAG(api.flags, ZEBRA_FLAG_ALLOW_RECURSION);
SET_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP);
- nh.type = NEXTHOP_TYPE_IFINDEX;
- nh.ifindex = oif;
- SET_FLAG(nh.flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
- nexthop_add_srv6_seg6local(&nh, action, context);
+ znh = &api.nexthops[0];
+
+ memset(znh, 0, sizeof(*znh));
+
+ znh->type = NEXTHOP_TYPE_IFINDEX;
+ znh->ifindex = oif;
+ SET_FLAG(znh->flags, ZAPI_NEXTHOP_FLAG_SEG6LOCAL);
+ znh->seg6local_action = action;
+ memcpy(&znh->seg6local_ctx, context, sizeof(struct seg6local_context));
- zapi_nexthop_from_nexthop(&api.nexthops[0], &nh);
api.nexthop_num = 1;
return zclient_route_send(ZEBRA_ROUTE_ADD, zclient, &api);
diff --git a/lib/zlog.c b/lib/zlog.c
index e0bb34a258..6a36a0b123 100644
--- a/lib/zlog.c
+++ b/lib/zlog.c
@@ -991,16 +991,14 @@ void zlog_init(const char *progname, const char *protoname,
zlog_instance = instance;
if (instance) {
- snprintfrr(zlog_tmpdir, sizeof(zlog_tmpdir),
- "/var/tmp/frr/%s-%d.%ld",
- progname, instance, (long)getpid());
+ snprintfrr(zlog_tmpdir, sizeof(zlog_tmpdir), "%s/%s-%d.%ld",
+ TMPBASEDIR, progname, instance, (long)getpid());
zlog_prefixsz = snprintfrr(zlog_prefix, sizeof(zlog_prefix),
"%s[%d]: ", protoname, instance);
} else {
- snprintfrr(zlog_tmpdir, sizeof(zlog_tmpdir),
- "/var/tmp/frr/%s.%ld",
- progname, (long)getpid());
+ snprintfrr(zlog_tmpdir, sizeof(zlog_tmpdir), "%s/%s.%ld",
+ TMPBASEDIR, progname, (long)getpid());
zlog_prefixsz = snprintfrr(zlog_prefix, sizeof(zlog_prefix),
"%s: ", protoname);
diff --git a/nhrpd/nhrp_interface.c b/nhrpd/nhrp_interface.c
index 1092ce13a1..4ac30a7d75 100644
--- a/nhrpd/nhrp_interface.c
+++ b/nhrpd/nhrp_interface.c
@@ -165,8 +165,7 @@ static void nhrp_interface_interface_notifier(struct notifier_block *n,
switch (cmd) {
case NOTIFY_INTERFACE_CHANGED:
- nhrp_interface_update_mtu(nifp->ifp, AFI_IP);
- nhrp_interface_update_source(nifp->ifp);
+ nhrp_interface_update_nbma(nifp->ifp, NULL);
break;
case NOTIFY_INTERFACE_ADDRESS_CHANGED:
nifp->nbma = nbmanifp->afi[AFI_IP].addr;
diff --git a/nhrpd/nhrp_peer.c b/nhrpd/nhrp_peer.c
index 4b03032566..e7f2eaf5a7 100644
--- a/nhrpd/nhrp_peer.c
+++ b/nhrpd/nhrp_peer.c
@@ -17,6 +17,7 @@
#include "memory.h"
#include "thread.h"
#include "hash.h"
+#include "network.h"
#include "nhrpd.h"
#include "nhrp_protocol.h"
@@ -334,7 +335,7 @@ int nhrp_peer_check(struct nhrp_peer *p, int establish)
&p->t_fallback);
} else {
/* Maximum timeout is 1 second */
- int r_time_ms = rand() % 1000;
+ int r_time_ms = frr_weak_random() % 1000;
debugf(NHRP_DEBUG_COMMON,
"Initiating IPsec connection request to %pSU after %d ms:",
diff --git a/ospf6d/ospf6_abr.c b/ospf6d/ospf6_abr.c
index 5af1139d9b..e9c42bb80c 100644
--- a/ospf6d/ospf6_abr.c
+++ b/ospf6d/ospf6_abr.c
@@ -488,7 +488,12 @@ int ospf6_abr_originate_summary_to_area(struct ospf6_route *route,
zlog_debug(
"Suppressed by range %pFX of area %s",
&range->prefix, route_area->name);
- ospf6_abr_delete_route(summary, summary_table, old);
+ /* The existing summary route could be a range, don't
+ * remove it in this case
+ */
+ if (summary && summary->type != OSPF6_DEST_TYPE_RANGE)
+ ospf6_abr_delete_route(summary, summary_table,
+ old);
return 0;
}
}
diff --git a/ospf6d/ospf6_interface.c b/ospf6d/ospf6_interface.c
index efa5d2b7ab..155374d3f0 100644
--- a/ospf6d/ospf6_interface.c
+++ b/ospf6d/ospf6_interface.c
@@ -966,10 +966,6 @@ static const char *ospf6_iftype_str(uint8_t iftype)
return "UNKNOWN";
}
-#if CONFDATE > 20220709
-CPP_NOTICE("Time to remove ospf6Enabled from JSON output")
-#endif
-
/* show specified interface structure */
static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
json_object *json_obj, bool use_json)
@@ -996,11 +992,8 @@ static int ospf6_interface_show(struct vty *vty, struct interface *ifp,
ospf6_iftype_str(default_iftype));
json_object_int_add(json_obj, "interfaceId", ifp->ifindex);
- if (ifp->info == NULL) {
- json_object_boolean_false_add(json_obj, "ospf6Enabled");
+ if (ifp->info == NULL)
return 0;
- }
- json_object_boolean_true_add(json_obj, "ospf6Enabled");
oi = (struct ospf6_interface *)ifp->info;
@@ -1719,8 +1712,11 @@ void ospf6_interface_start(struct ospf6_interface *oi)
if (oi->area_id_format == OSPF6_AREA_FMT_UNSET)
return;
- if (oi->area)
+ if (oi->area) {
+ /* Recompute cost */
+ ospf6_interface_recalculate_cost(oi);
return;
+ }
ospf6 = oi->interface->vrf->info;
if (!ospf6)
diff --git a/ospf6d/ospf6_intra.c b/ospf6d/ospf6_intra.c
index b5ea3ada36..52bb745d74 100644
--- a/ospf6d/ospf6_intra.c
+++ b/ospf6d/ospf6_intra.c
@@ -1765,10 +1765,8 @@ void ospf6_intra_prefix_lsa_add(struct ospf6_lsa *lsa)
intra_prefix_lsa =
(struct ospf6_intra_prefix_lsa *)OSPF6_LSA_HEADER_END(
lsa->header);
- if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER))
- ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
- intra_prefix_lsa->ref_id, &ls_prefix);
- else if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
+ if (intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_ROUTER) ||
+ intra_prefix_lsa->ref_type == htons(OSPF6_LSTYPE_NETWORK))
ospf6_linkstate_prefix(intra_prefix_lsa->ref_adv_router,
intra_prefix_lsa->ref_id, &ls_prefix);
else {
diff --git a/ospf6d/ospf6_message.c b/ospf6d/ospf6_message.c
index 93a062b215..360a9db0d6 100644
--- a/ospf6d/ospf6_message.c
+++ b/ospf6d/ospf6_message.c
@@ -2086,7 +2086,6 @@ static void ospf6_write(struct thread *thread)
{
struct ospf6 *ospf6 = THREAD_ARG(thread);
struct ospf6_interface *oi;
- struct ospf6_interface *last_serviced_oi = NULL;
struct ospf6_header *oh;
struct ospf6_packet *op;
struct listnode *node;
@@ -2106,9 +2105,7 @@ static void ospf6_write(struct thread *thread)
assert(node);
oi = listgetdata(node);
- while ((pkt_count < ospf6->write_oi_count) && oi
- && (last_serviced_oi != oi)) {
-
+ while ((pkt_count < ospf6->write_oi_count) && oi) {
op = ospf6_fifo_head(oi->obuf);
assert(op);
assert(op->length >= OSPF6_HEADER_SIZE);
@@ -2221,7 +2218,6 @@ static void ospf6_write(struct thread *thread)
list_delete_node(ospf6->oi_write_q, node);
if (ospf6_fifo_head(oi->obuf) == NULL) {
oi->on_write_q = 0;
- last_serviced_oi = NULL;
oi = NULL;
} else {
listnode_add(ospf6->oi_write_q, oi);
diff --git a/ospfclient/ospf_apiclient.c b/ospfclient/ospf_apiclient.c
index 41f0b25b91..b5e6389d4c 100644
--- a/ospfclient/ospf_apiclient.c
+++ b/ospfclient/ospf_apiclient.c
@@ -439,6 +439,12 @@ int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient,
struct lsa_header *lsah;
uint32_t tmp;
+ /* Validate opaque LSA length */
+ if ((size_t)opaquelen > sizeof(buf) - sizeof(struct lsa_header)) {
+ fprintf(stderr, "opaquelen(%d) is larger than buf size %zu\n",
+ opaquelen, sizeof(buf));
+ return OSPF_API_NOMEMORY;
+ }
/* We can only originate opaque LSAs */
if (!IS_OPAQUE_LSA(lsa_type)) {
@@ -447,12 +453,6 @@ int ospf_apiclient_lsa_originate(struct ospf_apiclient *oclient,
return OSPF_API_ILLEGALLSATYPE;
}
- if ((size_t)opaquelen > sizeof(buf) - sizeof(struct lsa_header)) {
- fprintf(stderr, "opaquelen(%d) is larger than buf size %zu\n",
- opaquelen, sizeof(buf));
- return OSPF_API_NOMEMORY;
- }
-
/* Make a new LSA from parameters */
lsah = (struct lsa_header *)buf;
lsah->ls_age = 0;
diff --git a/ospfd/ospf_abr.c b/ospfd/ospf_abr.c
index 7aa3a27c60..4746b2fc66 100644
--- a/ospfd/ospf_abr.c
+++ b/ospfd/ospf_abr.c
@@ -350,7 +350,6 @@ static int ospf_abr_nssa_am_elected(struct ospf_area *area)
struct ospf_lsa *lsa;
struct router_lsa *rlsa;
struct in_addr *best = NULL;
- char buf[PREFIX_STRLEN];
LSDB_LOOP (ROUTER_LSDB(area), rn, lsa) {
/* sanity checks */
@@ -367,9 +366,8 @@ static int ospf_abr_nssa_am_elected(struct ospf_area *area)
/* Router has Nt flag - always translate */
if (IS_ROUTER_LSA_NT(rlsa)) {
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_nssa_am_elected: router %pI4 asserts Nt",
- &lsa->data->id);
+ zlog_debug("%s: router %pI4 asserts Nt",
+ __func__, &lsa->data->id);
return 0;
}
@@ -381,10 +379,7 @@ static int ospf_abr_nssa_am_elected(struct ospf_area *area)
}
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_nssa_am_elected: best electable ABR is: %s",
- (best) ? inet_ntop(AF_INET, best, buf, sizeof(buf)) :
- "<none>");
+ zlog_debug("%s: best electable ABR is: %pI4", __func__, best);
if (best == NULL)
return 1;
@@ -410,14 +405,12 @@ void ospf_abr_nssa_check_status(struct ospf *ospf)
continue;
if (IS_DEBUG_OSPF(nssa, NSSA))
- zlog_debug(
- "ospf_abr_nssa_check_status: checking area %pI4",
- &area->area_id);
+ zlog_debug("%s: checking area %pI4", __func__,
+ &area->area_id);
if (!IS_OSPF_ABR(area->ospf)) {
if (IS_DEBUG_OSPF(nssa, NSSA))
- zlog_debug(
- "ospf_abr_nssa_check_status: not ABR");
+ zlog_debug("%s: not ABR", __func__);
area->NSSATranslatorState =
OSPF_NSSA_TRANSLATE_DISABLED;
} else {
@@ -426,8 +419,8 @@ void ospf_abr_nssa_check_status(struct ospf *ospf)
/* We never Translate Type-7 LSA. */
/* TODO: check previous state and flush? */
if (IS_DEBUG_OSPF(nssa, NSSA))
- zlog_debug(
- "ospf_abr_nssa_check_status: never translate");
+ zlog_debug("%s: never translate",
+ __func__);
area->NSSATranslatorState =
OSPF_NSSA_TRANSLATE_DISABLED;
break;
@@ -438,8 +431,8 @@ void ospf_abr_nssa_check_status(struct ospf *ospf)
* or let the nssa abr task take care of it?
*/
if (IS_DEBUG_OSPF(nssa, NSSA))
- zlog_debug(
- "ospf_abr_nssa_check_status: translate always");
+ zlog_debug("%s: translate always",
+ __func__);
area->NSSATranslatorState =
OSPF_NSSA_TRANSLATE_ENABLED;
break;
@@ -451,13 +444,14 @@ void ospf_abr_nssa_check_status(struct ospf *ospf)
OSPF_NSSA_TRANSLATE_ENABLED;
if (IS_DEBUG_OSPF(nssa, NSSA))
zlog_debug(
- "ospf_abr_nssa_check_status: elected translator");
+ "%s: elected translator",
+ __func__);
} else {
area->NSSATranslatorState =
OSPF_NSSA_TRANSLATE_DISABLED;
if (IS_DEBUG_OSPF(nssa, NSSA))
- zlog_debug(
- "ospf_abr_nssa_check_status: not elected");
+ zlog_debug("%s: not elected",
+ __func__);
}
break;
}
@@ -493,7 +487,7 @@ void ospf_check_abr_status(struct ospf *ospf)
uint8_t new_flags = ospf->flags;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_check_abr_status(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS(ospf->areas, node, nnode, area)) {
if (listcount(area->oiflist)) {
@@ -512,14 +506,13 @@ void ospf_check_abr_status(struct ospf *ospf)
}
if (IS_DEBUG_OSPF_EVENT) {
- zlog_debug("ospf_check_abr_status(): looked through areas");
- zlog_debug("ospf_check_abr_status(): bb_configured: %d",
- bb_configured);
- zlog_debug("ospf_check_abr_status(): bb_act_attached: %d",
+ zlog_debug("%s: looked through areas", __func__);
+ zlog_debug("%s: bb_configured: %d", __func__, bb_configured);
+ zlog_debug("%s: bb_act_attached: %d", __func__,
bb_act_attached);
- zlog_debug("ospf_check_abr_status(): areas_configured: %d",
+ zlog_debug("%s: areas_configured: %d", __func__,
areas_configured);
- zlog_debug("ospf_check_abr_status(): areas_act_attached: %d",
+ zlog_debug("%s: areas_act_attached: %d", __func__,
areas_act_attached);
}
@@ -552,9 +545,8 @@ void ospf_check_abr_status(struct ospf *ospf)
if (new_flags != ospf->flags) {
ospf_spf_calculate_schedule(ospf, SPF_FLAG_ABR_STATUS_CHANGE);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_check_abr_status(): new router flags: %x",
- new_flags);
+ zlog_debug("%s: new router flags: %x", __func__,
+ new_flags);
ospf->flags = new_flags;
ospf_router_lsa_update(ospf);
}
@@ -565,37 +557,33 @@ static void ospf_abr_update_aggregate(struct ospf_area_range *range,
struct ospf_area *area)
{
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_update_aggregate(): Start");
+ zlog_debug("%s: Start", __func__);
if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED)
&& (range->cost != OSPF_STUB_MAX_METRIC_SUMMARY_COST)) {
range->cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_update_aggregate(): use summary max-metric 0x%08x",
- range->cost);
+ zlog_debug("%s: use summary max-metric 0x%08x",
+ __func__, range->cost);
} else if (range->cost_config != OSPF_AREA_RANGE_COST_UNSPEC) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_update_aggregate(): use configured cost %d",
- range->cost_config);
+ zlog_debug("%s: use configured cost %d", __func__,
+ range->cost_config);
range->cost = range->cost_config;
} else {
if (range->specifics == 0) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_update_aggregate(): use or->cost %d",
- or->cost);
+ zlog_debug("%s: use or->cost %d", __func__,
+ or->cost);
range->cost = or->cost; /* 1st time get 1st cost */
}
if (or->cost > range->cost) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_update_aggregate(): update to %d",
- or->cost);
+ zlog_debug("%s: update to %d", __func__,
+ or->cost);
range->cost = or->cost;
}
@@ -635,16 +623,14 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
if (!CHECK_FLAG(lsa->data->options, OSPF_OPTION_NP)) {
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_translate_nssa(): LSA Id %pI4, P-bit off, NO Translation",
- &lsa->data->id);
+ zlog_debug("%s: LSA Id %pI4, P-bit off, NO Translation",
+ __func__, &lsa->data->id);
return 1;
}
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_translate_nssa(): LSA Id %pI4, TRANSLATING 7 to 5",
- &lsa->data->id);
+ zlog_debug("%s: LSA Id %pI4, TRANSLATING 7 to 5", __func__,
+ &lsa->data->id);
ext7 = (struct as_external_lsa *)(lsa->data);
p.prefix = lsa->data->id;
@@ -653,8 +639,8 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
if (ext7->e[0].fwd_addr.s_addr == OSPF_DEFAULT_DESTINATION) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_abr_translate_nssa(): LSA Id %pI4, Forward address is 0, NO Translation",
- &lsa->data->id);
+ "%s: LSA Id %pI4, Forward address is 0, NO Translation",
+ __func__, &lsa->data->id);
return 1;
}
@@ -667,8 +653,8 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
UNSET_FLAG(old->flags, OSPF_LSA_APPROVED);
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_abr_translate_nssa(): remove old translated LSA id %pI4",
- &old->data->id);
+ "%s: remove old translated LSA id %pI4",
+ __func__, &old->data->id);
}
/* if type-7 is removed and type-5 does not exist, do not
* originate */
@@ -678,16 +664,16 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
if (old && CHECK_FLAG(old->flags, OSPF_LSA_APPROVED)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_abr_translate_nssa(): found old translated LSA Id %pI4, refreshing",
- &old->data->id);
+ "%s: found old translated LSA Id %pI4, refreshing",
+ __func__, &old->data->id);
/* refresh */
new = ospf_translated_nssa_refresh(area->ospf, lsa, old);
if (!new) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_abr_translate_nssa(): could not refresh translated LSA Id %pI4",
- &old->data->id);
+ "%s: could not refresh translated LSA Id %pI4",
+ __func__, &old->data->id);
}
} else {
/* no existing external route for this LSA Id
@@ -698,8 +684,8 @@ static int ospf_abr_translate_nssa(struct ospf_area *area, struct ospf_lsa *lsa)
== NULL) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_abr_translate_nssa(): Could not translate Type-7 for %pI4 to Type-5",
- &lsa->data->id);
+ "%s: Could not translate Type-7 for %pI4 to Type-5",
+ __func__, &lsa->data->id);
return 1;
}
}
@@ -725,7 +711,7 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost,
uint32_t full_cost;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_network_to_area(): Start");
+ zlog_debug("%s: Start", __func__);
if (CHECK_FLAG(area->stub_router_state, OSPF_AREA_IS_STUB_ROUTED))
full_cost = OSPF_STUB_MAX_METRIC_SUMMARY_COST;
@@ -736,28 +722,25 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost,
area->ospf->router_id);
if (old) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network_to_area(): old summary found");
+ zlog_debug("%s: old summary found", __func__);
sl = (struct summary_lsa *)old->data;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network_to_area(): old metric: %d, new metric: %d",
- GET_METRIC(sl->metric), cost);
+ zlog_debug("%s: old metric: %d, new metric: %d",
+ __func__, GET_METRIC(sl->metric), cost);
if ((GET_METRIC(sl->metric) == full_cost)
&& ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) {
/* unchanged. simply reapprove it */
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network_to_area(): old summary approved");
+ zlog_debug("%s: old summary approved",
+ __func__);
SET_FLAG(old->flags, OSPF_LSA_APPROVED);
} else {
/* LSA is changed, refresh it */
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network_to_area(): refreshing summary");
+ zlog_debug("%s: refreshing summary", __func__);
set_metric(old, full_cost);
lsa = ospf_lsa_refresh(area->ospf, old);
@@ -774,8 +757,7 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost,
}
} else {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network_to_area(): creating new summary");
+ zlog_debug("%s: creating new summary", __func__);
lsa = ospf_summary_lsa_originate(p, full_cost, area);
/* This will flood through area. */
@@ -789,12 +771,12 @@ void ospf_abr_announce_network_to_area(struct prefix_ipv4 *p, uint32_t cost,
SET_FLAG(lsa->flags, OSPF_LSA_APPROVED);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network_to_area(): flooding new version of summary");
+ zlog_debug("%s: flooding new version of summary",
+ __func__);
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_network_to_area(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static int ospf_abr_nexthops_belong_to_area(struct ospf_route * or,
@@ -868,16 +850,15 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p,
struct listnode *node;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_network(): Start");
+ zlog_debug("%s: Start", __func__);
or_area = ospf_area_lookup_by_area_id(ospf, or->u.std.area_id);
assert(or_area);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s: looking at area %pI4", __func__,
+ &area->area_id);
if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id))
continue;
@@ -888,16 +869,16 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p,
if (!ospf_abr_should_accept(p, area)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_network(): prefix %pFX was denied by import-list",
- p);
+ "%s: prefix %pFX was denied by import-list",
+ __func__, p);
continue;
}
if (!ospf_abr_plist_in_check(area, or, p)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_network(): prefix %pFX was denied by prefix-list",
- p);
+ "%s: prefix %pFX was denied by prefix-list",
+ __func__, p);
continue;
}
@@ -905,16 +886,16 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p,
&& area->no_summary) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_network(): area %pI4 is stub and no_summary",
- &area->area_id);
+ "%s: area %pI4 is stub and no_summary",
+ __func__, &area->area_id);
continue;
}
if (or->path_type == OSPF_PATH_INTER_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_network(): this is inter-area route to %pFX",
- p);
+ "%s: this is inter-area route to %pFX",
+ __func__, p);
if (!OSPF_IS_AREA_BACKBONE(area))
ospf_abr_announce_network_to_area(p, or->cost,
@@ -924,8 +905,8 @@ static void ospf_abr_announce_network(struct ospf *ospf, struct prefix_ipv4 *p,
if (or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_network(): this is intra-area route to %pFX",
- p);
+ "%s: this is intra-area route to %pFX",
+ __func__, p);
if ((range = ospf_area_range_match(or_area, p))
&& !ospf_area_is_transit(area))
ospf_abr_update_aggregate(range, or, area);
@@ -973,7 +954,7 @@ static void ospf_abr_process_nssa_translates(struct ospf *ospf)
struct ospf_lsa *lsa;
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_process_nssa_translates(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (!area->NSSATranslatorState)
@@ -983,16 +964,15 @@ static void ospf_abr_process_nssa_translates(struct ospf *ospf)
continue; /* skip if not Nssa Area */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_process_nssa_translates(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s(): looking at area %pI4", __func__,
+ &area->area_id);
LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
ospf_abr_translate_nssa(area, lsa);
}
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_process_nssa_translates(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_process_network_rt(struct ospf *ospf,
@@ -1003,7 +983,7 @@ static void ospf_abr_process_network_rt(struct ospf *ospf,
struct route_node *rn;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_process_network_rt(): Start");
+ zlog_debug("%s: Start", __func__);
for (rn = route_top(rt); rn; rn = route_next(rn)) {
if ((or = rn->info) == NULL)
@@ -1013,33 +993,35 @@ static void ospf_abr_process_network_rt(struct ospf *ospf,
or->u.std.area_id))) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_network_rt(): area %pI4 no longer exists",
- &or->u.std.area_id);
+ "%s: area %pI4 no longer exists", __func__,
+ &or->u.std.area_id);
continue;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_process_network_rt(): this is a route to %pFX",
- &rn->p);
+ zlog_debug("%s: this is a route to %pFX", __func__,
+ &rn->p);
if (or->path_type >= OSPF_PATH_TYPE1_EXTERNAL) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_network_rt(): this is an External router, skipping");
+ "%s: this is an External router, skipping",
+ __func__);
continue;
}
if (or->cost >= OSPF_LS_INFINITY) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_network_rt(): this route's cost is infinity, skipping");
+ "%s: this route's cost is infinity, skipping",
+ __func__);
continue;
}
if (or->type == OSPF_DESTINATION_DISCARD) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_network_rt(): this is a discard entry, skipping");
+ "%s: this is a discard entry, skipping",
+ __func__);
continue;
}
@@ -1049,8 +1031,8 @@ static void ospf_abr_process_network_rt(struct ospf *ospf,
ospf, (struct prefix_ipv4 *)&rn->p,
or)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_process_network_rt(): denied by export-list");
+ zlog_debug("%s: denied by export-list",
+ __func__);
continue;
}
@@ -1060,8 +1042,8 @@ static void ospf_abr_process_network_rt(struct ospf *ospf,
area, or,
(struct prefix_ipv4 *)&rn->p)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_process_network_rt(): denied by prefix-list");
+ zlog_debug("%s: denied by prefix-list",
+ __func__);
continue;
}
@@ -1069,7 +1051,8 @@ static void ospf_abr_process_network_rt(struct ospf *ospf,
&& !OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_network_rt(): this is route is not backbone one, skipping");
+ "%s: this route is not backbone one, skipping",
+ __func__);
continue;
}
@@ -1081,18 +1064,19 @@ static void ospf_abr_process_network_rt(struct ospf *ospf,
or->path_type != OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_network_rt(): ALT ABR: No BB connection, skip not intra-area routes");
+ "%s: ALT ABR: No BB connection, skip not intra-area routes",
+ __func__);
continue;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_process_network_rt(): announcing");
+ zlog_debug("%s: announcing", __func__);
ospf_abr_announce_network(ospf, (struct prefix_ipv4 *)&rn->p,
or);
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_process_network_rt(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, uint32_t cost,
@@ -1102,31 +1086,28 @@ static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, uint32_t cost,
struct summary_lsa *slsa = NULL;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_rtr_to_area(): Start");
+ zlog_debug("%s: Start", __func__);
old = ospf_lsa_lookup_by_prefix(area->lsdb, OSPF_ASBR_SUMMARY_LSA, p,
area->ospf->router_id);
if (old) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_rtr_to_area(): old summary found");
+ zlog_debug("%s: old summary found", __func__);
slsa = (struct summary_lsa *)old->data;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_network_to_area(): old metric: %d, new metric: %d",
- GET_METRIC(slsa->metric), cost);
+ zlog_debug("%s: old metric: %d, new metric: %d",
+ __func__, GET_METRIC(slsa->metric), cost);
}
if (old && (GET_METRIC(slsa->metric) == cost)
&& ((old->flags & OSPF_LSA_IN_MAXAGE) == 0)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_rtr_to_area(): old summary approved");
+ zlog_debug("%s: old summary approved", __func__);
SET_FLAG(old->flags, OSPF_LSA_APPROVED);
} else {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_rtr_to_area(): 2.2");
+ zlog_debug("%s: 2.2", __func__);
if (old) {
set_metric(old, cost);
@@ -1142,8 +1123,8 @@ static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, uint32_t cost,
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_rtr_to_area(): flooding new version of summary");
+ zlog_debug("%s: flooding new version of summary",
+ __func__);
/*
zlog_info ("ospf_abr_announce_rtr_to_area(): creating new
@@ -1155,7 +1136,7 @@ static void ospf_abr_announce_rtr_to_area(struct prefix_ipv4 *p, uint32_t cost,
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_rtr_to_area(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
@@ -1166,13 +1147,12 @@ static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p,
struct ospf_area *area;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_rtr(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_rtr(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s: looking at area %pI4", __func__,
+ &area->area_id);
if (IPV4_ADDR_SAME(& or->u.std.area_id, &area->area_id))
continue;
@@ -1184,24 +1164,24 @@ static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p,
if (or->u.std.external_routing == OSPF_AREA_NSSA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_rtr(): do not generate LSA Type-4 %pI4 from NSSA",
- &p->prefix);
+ "%s: do not generate LSA Type-4 %pI4 from NSSA",
+ __func__, &p->prefix);
continue;
}
if (area->external_routing != OSPF_AREA_DEFAULT) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_rtr(): area %pI4 doesn't support external routing",
- &area->area_id);
+ "%s: area %pI4 doesn't support external routing",
+ __func__, &area->area_id);
continue;
}
if (or->path_type == OSPF_PATH_INTER_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_rtr(): this is inter-area route to %pI4",
- &p->prefix);
+ "%s: this is inter-area route to %pI4",
+ __func__, &p->prefix);
if (!OSPF_IS_AREA_BACKBONE(area))
ospf_abr_announce_rtr_to_area(p, or->cost,
area);
@@ -1210,14 +1190,14 @@ static void ospf_abr_announce_rtr(struct ospf *ospf, struct prefix_ipv4 *p,
if (or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_rtr(): this is intra-area route to %pI4",
- &p->prefix);
+ "%s: this is intra-area route to %pI4",
+ __func__, &p->prefix);
ospf_abr_announce_rtr_to_area(p, or->cost, area);
}
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_rtr(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_process_router_rt(struct ospf *ospf,
@@ -1228,7 +1208,7 @@ static void ospf_abr_process_router_rt(struct ospf *ospf,
struct list *l;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_process_router_rt(): Start");
+ zlog_debug("%s: Start", __func__);
for (rn = route_top(rt); rn; rn = route_next(rn)) {
struct listnode *node, *nnode;
@@ -1241,16 +1221,15 @@ static void ospf_abr_process_router_rt(struct ospf *ospf,
l = rn->info;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_process_router_rt(): this is a route to %pI4",
- &rn->p.u.prefix4);
+ zlog_debug("%s: this is a route to %pI4", __func__,
+ &rn->p.u.prefix4);
for (ALL_LIST_ELEMENTS(l, node, nnode, or)) {
if (!ospf_area_lookup_by_area_id(ospf,
or->u.std.area_id)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_router_rt(): area %pI4 no longer exists",
+ "%s: area %pI4 no longer exists", __func__,
&or->u.std.area_id);
continue;
}
@@ -1259,7 +1238,8 @@ static void ospf_abr_process_router_rt(struct ospf *ospf,
if (!CHECK_FLAG(or->u.std.flags, ROUTER_LSA_EXTERNAL)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_router_rt(): This is not an ASBR, skipping");
+ "%s: This is not an ASBR, skipping",
+ __func__);
continue;
}
@@ -1275,7 +1255,8 @@ static void ospf_abr_process_router_rt(struct ospf *ospf,
if (or != best) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_router_rt(): This route is not the best among possible, skipping");
+ "%s: This route is not the best among possible, skipping",
+ __func__);
continue;
}
@@ -1285,14 +1266,16 @@ static void ospf_abr_process_router_rt(struct ospf *ospf,
or->u.std.area_id)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_router_rt(): This route is not a backbone one, skipping");
+ "%s: This route is not a backbone one, skipping",
+ __func__);
continue;
}
if (or->cost >= OSPF_LS_INFINITY) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_router_rt(): This route has LS_INFINITY metric, skipping");
+ "%s: This route has LS_INFINITY metric, skipping",
+ __func__);
continue;
}
@@ -1302,7 +1285,8 @@ static void ospf_abr_process_router_rt(struct ospf *ospf,
or->path_type != OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_process_network_rt(): ALT ABR: No BB connection, skip not intra-area routes");
+ "%s: ALT ABR: No BB connection, skip not intra-area routes",
+ __func__);
continue;
}
@@ -1312,7 +1296,7 @@ static void ospf_abr_process_router_rt(struct ospf *ospf,
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_process_router_rt(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void
@@ -1322,7 +1306,7 @@ ospf_abr_unapprove_translates(struct ospf *ospf) /* For NSSA Translations */
struct route_node *rn;
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_unapprove_translates(): Start");
+ zlog_debug("%s: Start", __func__);
/* NSSA Translator is not checked, because it may have gone away,
and we would want to flush any residuals anyway */
@@ -1331,13 +1315,12 @@ ospf_abr_unapprove_translates(struct ospf *ospf) /* For NSSA Translations */
if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) {
UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED);
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_unapprove_translates(): approved unset on link id %pI4",
- &lsa->data->id);
+ zlog_debug("%s: approved unset on link id %pI4",
+ __func__, &lsa->data->id);
}
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_unapprove_translates(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_unapprove_summaries(struct ospf *ospf)
@@ -1348,19 +1331,18 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf)
struct ospf_lsa *lsa;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_unapprove_summaries(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_unapprove_summaries(): considering area %pI4",
- &area->area_id);
+ zlog_debug("%s: considering area %pI4", __func__,
+ &area->area_id);
LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
if (ospf_lsa_is_self_originated(ospf, lsa)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_unapprove_summaries(): approved unset on summary link id %pI4",
- &lsa->data->id);
+ "%s: approved unset on summary link id %pI4",
+ __func__, &lsa->data->id);
UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED);
}
@@ -1368,14 +1350,14 @@ static void ospf_abr_unapprove_summaries(struct ospf *ospf)
if (ospf_lsa_is_self_originated(ospf, lsa)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_unapprove_summaries(): approved unset on asbr-summary link id %pI4",
- &lsa->data->id);
+ "%s: approved unset on asbr-summary link id %pI4",
+ __func__, &lsa->data->id);
UNSET_FLAG(lsa->flags, OSPF_LSA_APPROVED);
}
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_unapprove_summaries(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_prepare_aggregates(struct ospf *ospf)
@@ -1386,7 +1368,7 @@ static void ospf_abr_prepare_aggregates(struct ospf *ospf)
struct ospf_area *area;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_prepare_aggregates(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
for (rn = route_top(area->ranges); rn; rn = route_next(rn))
@@ -1397,7 +1379,7 @@ static void ospf_abr_prepare_aggregates(struct ospf *ospf)
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_prepare_aggregates(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_announce_aggregates(struct ospf *ospf)
@@ -1409,13 +1391,12 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
struct listnode *node, *n;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_aggregates(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_aggregates(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s: looking at area %pI4", __func__,
+ &area->area_id);
for (rn = route_top(area->ranges); rn; rn = route_next(rn))
if ((range = rn->info)) {
@@ -1423,7 +1404,8 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
OSPF_AREA_RANGE_ADVERTISE)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_aggregates(): discarding suppress-ranges");
+ "%s: discarding suppress-ranges",
+ __func__);
continue;
}
@@ -1432,9 +1414,8 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
p.prefixlen = range->masklen;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_aggregates(): this is range: %pFX",
- &p);
+ zlog_debug("%s: this is range: %pFX",
+ __func__, &p);
if (CHECK_FLAG(range->flags,
OSPF_AREA_RANGE_SUBSTITUTE)) {
@@ -1445,8 +1426,8 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
if (range->specifics) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_aggregates(): active range");
+ zlog_debug("%s: active range",
+ __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas,
n, ar)) {
@@ -1469,7 +1450,8 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
area)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_abr_announce_aggregates(): Skipping announcement of BB aggregate into a transit area");
+ "%s: Skipping announcement of BB aggregate into a transit area",
+ __func__);
continue;
}
ospf_abr_announce_network_to_area(
@@ -1482,7 +1464,7 @@ static void ospf_abr_announce_aggregates(struct ospf *ospf)
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_aggregates(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void
@@ -1495,16 +1477,15 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
struct prefix_ipv4 p;
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_send_nssa_aggregates(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (!area->NSSATranslatorState)
continue;
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_send_nssa_aggregates(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s: looking at area %pI4", __func__,
+ &area->area_id);
for (rn = route_top(area->ranges); rn; rn = route_next(rn)) {
if (rn->info == NULL)
@@ -1516,7 +1497,8 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
OSPF_AREA_RANGE_ADVERTISE)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_abr_send_nssa_aggregates(): discarding suppress-ranges");
+ "%s: discarding suppress-ranges",
+ __func__);
continue;
}
@@ -1525,9 +1507,8 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
p.prefixlen = range->masklen;
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_send_nssa_aggregates(): this is range: %pFX",
- &p);
+ zlog_debug("%s: this is range: %pFX", __func__,
+ &p);
if (CHECK_FLAG(range->flags,
OSPF_AREA_RANGE_SUBSTITUTE)) {
@@ -1538,8 +1519,8 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
if (range->specifics) {
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_send_nssa_aggregates(): active range");
+ zlog_debug("%s: active range",
+ __func__);
/* Fetch LSA-Type-7 from aggregate prefix, and
* then
@@ -1552,7 +1533,7 @@ ospf_abr_send_nssa_aggregates(struct ospf *ospf) /* temporarily turned off */
} /* all areas */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_send_nssa_aggregates(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_announce_stub_defaults(struct ospf *ospf)
@@ -1565,7 +1546,7 @@ static void ospf_abr_announce_stub_defaults(struct ospf *ospf)
return;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_stub_defaults(): Start");
+ zlog_debug("%s: Start", __func__);
p.family = AF_INET;
p.prefix.s_addr = OSPF_DEFAULT_DESTINATION;
@@ -1573,9 +1554,8 @@ static void ospf_abr_announce_stub_defaults(struct ospf *ospf)
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_stub_defaults(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s: looking at area %pI4", __func__,
+ &area->area_id);
if ((area->external_routing != OSPF_AREA_STUB)
&& (area->external_routing != OSPF_AREA_NSSA))
@@ -1585,14 +1565,13 @@ static void ospf_abr_announce_stub_defaults(struct ospf *ospf)
continue; /* Sanity Check */
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_announce_stub_defaults(): announcing 0.0.0.0/0 to area %pI4",
- &area->area_id);
+ zlog_debug("%s: announcing 0.0.0.0/0 to area %pI4",
+ __func__, &area->area_id);
ospf_abr_announce_network_to_area(&p, area->default_cost, area);
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_announce_stub_defaults(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf,
@@ -1600,9 +1579,8 @@ static int ospf_abr_remove_unapproved_translates_apply(struct ospf *ospf,
{
if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)
&& !CHECK_FLAG(lsa->flags, OSPF_LSA_APPROVED)) {
- zlog_info(
- "ospf_abr_remove_unapproved_translates(): removing unapproved translates, ID: %pI4",
- &lsa->data->id);
+ zlog_info("%s: removing unapproved translates, ID: %pI4",
+ __func__, &lsa->data->id);
/* FLUSH THROUGHOUT AS */
ospf_lsa_flush_as(ospf, lsa);
@@ -1620,13 +1598,13 @@ static void ospf_abr_remove_unapproved_translates(struct ospf *ospf)
/* All AREA PROCESS should have APPROVED necessary LSAs */
/* Remove any left over and not APPROVED */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_remove_unapproved_translates(): Start");
+ zlog_debug("%s: Start", __func__);
LSDB_LOOP (EXTERNAL_LSDB(ospf), rn, lsa)
ospf_abr_remove_unapproved_translates_apply(ospf, lsa);
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_remove_unapproved_translates(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf)
@@ -1637,13 +1615,12 @@ static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf)
struct ospf_lsa *lsa;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_remove_unapproved_summaries(): Start");
+ zlog_debug("%s: Start", __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_remove_unapproved_summaries(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s: looking at area %pI4", __func__,
+ &area->area_id);
LSDB_LOOP (SUMMARY_LSDB(area), rn, lsa)
if (ospf_lsa_is_self_originated(ospf, lsa))
@@ -1657,7 +1634,7 @@ static void ospf_abr_remove_unapproved_summaries(struct ospf *ospf)
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_remove_unapproved_summaries(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_manage_discard_routes(struct ospf *ospf)
@@ -1727,17 +1704,17 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
/* Each area must confirm TranslatorRole */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_nssa_task(): Start");
+ zlog_debug("%s: Start", __func__);
/* For all Global Entries flagged "local-translate", unset APPROVED */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_nssa_task(): unapprove translates");
+ zlog_debug("%s: unapprove translates", __func__);
ospf_abr_unapprove_translates(ospf);
/* RESET all Ranges in every Area, same as summaries */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_nssa_task(): NSSA initialize aggregates");
+ zlog_debug("%s: NSSA initialize aggregates", __func__);
ospf_abr_prepare_aggregates(ospf); /*TURNED OFF just for now */
/* For all NSSAs, Type-7s, translate to 5's, INSTALL/FLOOD, or
@@ -1745,7 +1722,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
* Install or Approve in Type-5 Global LSDB
*/
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_nssa_task(): process translates");
+ zlog_debug("%s: process translates", __func__);
ospf_abr_process_nssa_translates(ospf);
/* Translate/Send any "ranged" aggregates, and also 5-Install and
@@ -1754,7 +1731,7 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
* Install/Flood/Approve
*/
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_nssa_task(): send NSSA aggregates");
+ zlog_debug("%s: send NSSA aggregates", __func__);
ospf_abr_send_nssa_aggregates(ospf); /*TURNED OFF FOR NOW */
/* Send any NSSA defaults as Type-5
@@ -1766,14 +1743,13 @@ static void ospf_abr_nssa_task(struct ospf *ospf) /* called only if any_nssa */
/* Flush any unapproved previous translates from Global Data Base */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_abr_nssa_task(): remove unapproved translates");
+ zlog_debug("%s: remove unapproved translates", __func__);
ospf_abr_remove_unapproved_translates(ospf);
ospf_abr_manage_discard_routes(ospf); /* same as normal...discard */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_abr_nssa_task(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
/* This is the function taking care about ABR stuff, i.e.
@@ -1784,49 +1760,49 @@ void ospf_abr_task(struct ospf *ospf)
return;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): Start");
+ zlog_debug("%s: Start", __func__);
if (ospf->new_table == NULL || ospf->new_rtrs == NULL) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_abr_task(): Routing tables are not yet ready");
+ zlog_debug("%s: Routing tables are not yet ready",
+ __func__);
return;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): unapprove summaries");
+ zlog_debug("%s: unapprove summaries", __func__);
ospf_abr_unapprove_summaries(ospf);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): prepare aggregates");
+ zlog_debug("%s: prepare aggregates", __func__);
ospf_abr_prepare_aggregates(ospf);
if (IS_OSPF_ABR(ospf)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): process network RT");
+ zlog_debug("%s: process network RT", __func__);
ospf_abr_process_network_rt(ospf, ospf->new_table);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): process router RT");
+ zlog_debug("%s: process router RT", __func__);
ospf_abr_process_router_rt(ospf, ospf->new_rtrs);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): announce aggregates");
+ zlog_debug("%s: announce aggregates", __func__);
ospf_abr_announce_aggregates(ospf);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): announce stub defaults");
+ zlog_debug("%s: announce stub defaults", __func__);
ospf_abr_announce_stub_defaults(ospf);
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): remove unapproved summaries");
+ zlog_debug("%s: remove unapproved summaries", __func__);
ospf_abr_remove_unapproved_summaries(ospf);
ospf_abr_manage_discard_routes(ospf);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_abr_task(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static void ospf_abr_task_timer(struct thread *thread)
diff --git a/ospfd/ospf_apiserver.c b/ospfd/ospf_apiserver.c
index b8567830b1..f5ed77dab5 100644
--- a/ospfd/ospf_apiserver.c
+++ b/ospfd/ospf_apiserver.c
@@ -378,7 +378,7 @@ void ospf_apiserver_read(struct thread *thread)
apiserv->t_sync_read = NULL;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("API: ospf_apiserver_read: Peer: %pI4/%u",
+ zlog_debug("API: %s: Peer: %pI4/%u", __func__,
&apiserv->peer_sync.sin_addr,
ntohs(apiserv->peer_sync.sin_port));
}
@@ -388,13 +388,13 @@ void ospf_apiserver_read(struct thread *thread)
apiserv->t_async_read = NULL;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("API: ospf_apiserver_read: Peer: %pI4/%u",
+ zlog_debug("API: %s: Peer: %pI4/%u", __func__,
&apiserv->peer_async.sin_addr,
ntohs(apiserv->peer_async.sin_port));
}
#endif /* USE_ASYNC_READ */
else {
- zlog_warn("ospf_apiserver_read: Unknown fd(%d)", fd);
+ zlog_warn("%s: Unknown fd(%d)", __func__, fd);
ospf_apiserver_free(apiserv);
return;
}
@@ -402,9 +402,8 @@ void ospf_apiserver_read(struct thread *thread)
/* Read message from fd. */
msg = msg_read(fd);
if (msg == NULL) {
- zlog_warn(
- "ospf_apiserver_read: read failed on fd=%d, closing connection",
- fd);
+ zlog_warn("%s: read failed on fd=%d, closing connection",
+ __func__, fd);
/* Perform cleanup. */
ospf_apiserver_free(apiserv);
@@ -438,20 +437,19 @@ void ospf_apiserver_sync_write(struct thread *thread)
/* Sanity check */
if (fd != apiserv->fd_sync) {
- zlog_warn("ospf_apiserver_sync_write: Unknown fd=%d", fd);
+ zlog_warn("%s: Unknown fd=%d", __func__, fd);
goto out;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("API: ospf_apiserver_sync_write: Peer: %pI4/%u",
+ zlog_debug("API: %s: Peer: %pI4/%u", __func__,
&apiserv->peer_sync.sin_addr,
ntohs(apiserv->peer_sync.sin_port));
/* Check whether there is really a message in the fifo. */
msg = msg_fifo_pop(apiserv->out_sync_fifo);
if (!msg) {
- zlog_warn(
- "API: ospf_apiserver_sync_write: No message in Sync-FIFO?");
+ zlog_warn("API: %s: No message in Sync-FIFO?", __func__);
return;
}
@@ -464,8 +462,7 @@ void ospf_apiserver_sync_write(struct thread *thread)
msg_free(msg);
if (rc < 0) {
- zlog_warn("ospf_apiserver_sync_write: write failed on fd=%d",
- fd);
+ zlog_warn("%s: write failed on fd=%d", __func__, fd);
goto out;
}
@@ -500,20 +497,19 @@ void ospf_apiserver_async_write(struct thread *thread)
/* Sanity check */
if (fd != apiserv->fd_async) {
- zlog_warn("ospf_apiserver_async_write: Unknown fd=%d", fd);
+ zlog_warn("%s: Unknown fd=%d", __func__, fd);
goto out;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("API: ospf_apiserver_async_write: Peer: %pI4/%u",
+ zlog_debug("API: %s: Peer: %pI4/%u", __func__,
&apiserv->peer_async.sin_addr,
ntohs(apiserv->peer_async.sin_port));
/* Check whether there is really a message in the fifo. */
msg = msg_fifo_pop(apiserv->out_async_fifo);
if (!msg) {
- zlog_warn(
- "API: ospf_apiserver_async_write: No message in Async-FIFO?");
+ zlog_warn("API: %s: No message in Async-FIFO?", __func__);
return;
}
@@ -526,8 +522,7 @@ void ospf_apiserver_async_write(struct thread *thread)
msg_free(msg);
if (rc < 0) {
- zlog_warn("ospf_apiserver_async_write: write failed on fd=%d",
- fd);
+ zlog_warn("%s: write failed on fd=%d", __func__, fd);
goto out;
}
@@ -575,8 +570,7 @@ int ospf_apiserver_serv_sock_family(unsigned short port, int family)
/* Listen socket under queue length 3. */
rc = listen(accept_sock, 3);
if (rc < 0) {
- zlog_warn("ospf_apiserver_serv_sock_family: listen: %s",
- safe_strerror(errno));
+ zlog_warn("%s: listen: %s", __func__, safe_strerror(errno));
close(accept_sock); /* Close socket */
return rc;
}
@@ -608,8 +602,7 @@ void ospf_apiserver_accept(struct thread *thread)
/* Accept connection for synchronous messages */
new_sync_sock = sockunion_accept(accept_sock, &su);
if (new_sync_sock < 0) {
- zlog_warn("ospf_apiserver_accept: accept: %s",
- safe_strerror(errno));
+ zlog_warn("%s: accept: %s", __func__, safe_strerror(errno));
return;
}
@@ -622,16 +615,15 @@ void ospf_apiserver_accept(struct thread *thread)
ret = getpeername(new_sync_sock, (struct sockaddr *)&peer_sync,
&peerlen);
if (ret < 0) {
- zlog_warn("ospf_apiserver_accept: getpeername: %s",
+ zlog_warn("%s: getpeername: %s", __func__,
safe_strerror(errno));
close(new_sync_sock);
return;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("API: ospf_apiserver_accept: New peer: %pI4/%u",
- &peer_sync.sin_addr,
- ntohs(peer_sync.sin_port));
+ zlog_debug("API: %s: New peer: %pI4/%u", __func__,
+ &peer_sync.sin_addr, ntohs(peer_sync.sin_port));
/* Create new socket for asynchronous messages. */
peer_async = peer_sync;
@@ -640,18 +632,16 @@ void ospf_apiserver_accept(struct thread *thread)
/* Check if remote port number to make reverse connection is valid one.
*/
if (ntohs(peer_async.sin_port) == ospf_apiserver_getport()) {
- zlog_warn(
- "API: ospf_apiserver_accept: Peer(%pI4/%u): Invalid async port number?",
- &peer_async.sin_addr,
- ntohs(peer_async.sin_port));
+ zlog_warn("API: %s: Peer(%pI4/%u): Invalid async port number?",
+ __func__, &peer_async.sin_addr,
+ ntohs(peer_async.sin_port));
close(new_sync_sock);
return;
}
new_async_sock = socket(AF_INET, SOCK_STREAM, 0);
if (new_async_sock < 0) {
- zlog_warn("ospf_apiserver_accept: socket: %s",
- safe_strerror(errno));
+ zlog_warn("%s: socket: %s", __func__, safe_strerror(errno));
close(new_sync_sock);
return;
}
@@ -660,8 +650,7 @@ void ospf_apiserver_accept(struct thread *thread)
sizeof(struct sockaddr_in));
if (ret < 0) {
- zlog_warn("ospf_apiserver_accept: connect: %s",
- safe_strerror(errno));
+ zlog_warn("%s: connect: %s", __func__, safe_strerror(errno));
close(new_sync_sock);
close(new_async_sock);
return;
@@ -672,8 +661,7 @@ void ospf_apiserver_accept(struct thread *thread)
/* Make the asynchronous channel write-only. */
ret = shutdown(new_async_sock, SHUT_RD);
if (ret < 0) {
- zlog_warn("ospf_apiserver_accept: shutdown: %s",
- safe_strerror(errno));
+ zlog_warn("%s: shutdown: %s", __func__, safe_strerror(errno));
close(new_sync_sock);
close(new_async_sock);
return;
@@ -734,7 +722,7 @@ static int ospf_apiserver_send_msg(struct ospf_apiserver *apiserv,
event = OSPF_APISERVER_ASYNC_WRITE;
break;
default:
- zlog_warn("ospf_apiserver_send_msg: Unknown message type %d",
+ zlog_warn("%s: Unknown message type %d", __func__,
msg->hdr.msgtype);
return -1;
}
@@ -759,7 +747,7 @@ int ospf_apiserver_send_reply(struct ospf_apiserver *apiserv, uint32_t seqnr,
int ret;
if (!msg) {
- zlog_warn("ospf_apiserver_send_reply: msg_new failed");
+ zlog_warn("%s: msg_new failed", __func__);
#ifdef NOTYET
/* Cannot allocate new message. What should we do? */
ospf_apiserver_free(apiserv);
@@ -815,7 +803,7 @@ int ospf_apiserver_handle_msg(struct ospf_apiserver *apiserv, struct msg *msg)
rc = ospf_apiserver_handle_sync_router_id(apiserv, msg);
break;
default:
- zlog_warn("ospf_apiserver_handle_msg: Unknown message type: %d",
+ zlog_warn("%s: Unknown message type: %d", __func__,
msg->hdr.msgtype);
rc = -1;
}
@@ -846,8 +834,7 @@ int ospf_apiserver_register_opaque_type(struct ospf_apiserver *apiserv,
originator_func = ospf_apiserver_lsa11_originator;
break;
default:
- zlog_warn("ospf_apiserver_register_opaque_type: lsa_type(%d)",
- lsa_type);
+ zlog_warn("%s: lsa_type(%d)", __func__, lsa_type);
return OSPF_API_ILLEGALLSATYPE;
}
@@ -1018,8 +1005,8 @@ void ospf_apiserver_notify_ready_type9(struct ospf_apiserver *apiserv)
0, OSPF_OPAQUE_LINK_LSA, r->opaque_type,
oi->address->u.prefix4);
if (!msg) {
- zlog_warn(
- "apiserver_notify_ready_type9: msg_new failed");
+ zlog_warn("%s: msg_new failed",
+ __func__);
#ifdef NOTYET
/* Cannot allocate new message. What
* should we do? */
@@ -1067,8 +1054,8 @@ void ospf_apiserver_notify_ready_type10(struct ospf_apiserver *apiserv)
0, OSPF_OPAQUE_AREA_LSA, r->opaque_type,
area->area_id);
if (!msg) {
- zlog_warn(
- "apiserver_notify_ready_type10: msg_new failed");
+ zlog_warn("%s: msg_new failed",
+ __func__);
#ifdef NOTYET
/* Cannot allocate new message. What
* should we do? */
@@ -1110,8 +1097,7 @@ void ospf_apiserver_notify_ready_type11(struct ospf_apiserver *apiserv)
r->opaque_type, noarea_id);
if (!msg) {
- zlog_warn(
- "apiserver_notify_ready_type11: msg_new failed");
+ zlog_warn("%s: msg_new failed", __func__);
#ifdef NOTYET
/* Cannot allocate new message. What should we
* do? */
@@ -1234,8 +1220,7 @@ static int apiserver_sync_callback(struct ospf_lsa *lsa, void *p_arg,
MSG_LSA_UPDATE_NOTIFY, seqnum, ifaddr, area_id,
lsa->flags & OSPF_LSA_SELF, lsa->data);
if (!msg) {
- zlog_warn(
- "apiserver_sync_callback: new_msg_update failed");
+ zlog_warn("%s: new_msg_update failed", __func__);
#ifdef NOTYET
/* Cannot allocate new message. What should we do? */
/* ospf_apiserver_free (apiserv);*/ /* Do nothing
@@ -1534,7 +1519,7 @@ struct ospf_lsa *ospf_apiserver_opaque_lsa_new(struct ospf_area *area,
/* Create a stream for internal opaque LSA */
if ((s = stream_new(OSPF_MAX_LSA_SIZE)) == NULL) {
- zlog_warn("ospf_apiserver_opaque_lsa_new: stream_new failed");
+ zlog_warn("%s: stream_new failed", __func__);
return NULL;
}
@@ -1627,7 +1612,7 @@ int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
case OSPF_OPAQUE_LINK_LSA:
oi = ospf_apiserver_if_lookup_by_addr(omsg->ifaddr);
if (!oi) {
- zlog_warn("apiserver_originate: unknown interface %pI4",
+ zlog_warn("%s: unknown interface %pI4", __func__,
&omsg->ifaddr);
rc = OSPF_API_NOSUCHINTERFACE;
goto out;
@@ -1638,7 +1623,7 @@ int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
case OSPF_OPAQUE_AREA_LSA:
area = ospf_area_lookup_by_area_id(ospf, omsg->area_id);
if (!area) {
- zlog_warn("apiserver_originate: unknown area %pI4",
+ zlog_warn("%s: unknown area %pI4", __func__,
&omsg->area_id);
rc = OSPF_API_NOSUCHAREA;
goto out;
@@ -1650,9 +1635,8 @@ int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
break;
default:
/* We can only handle opaque types here */
- zlog_warn(
- "apiserver_originate: Cannot originate non-opaque LSA type %d",
- data->type);
+ zlog_warn("%s: Cannot originate non-opaque LSA type %d",
+ __func__, data->type);
rc = OSPF_API_ILLEGALLSATYPE;
goto out;
}
@@ -1663,9 +1647,8 @@ int ospf_apiserver_handle_originate_request(struct ospf_apiserver *apiserv,
if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
opaque_type)) {
- zlog_warn(
- "apiserver_originate: LSA-type(%d)/Opaque-type(%d): Not registered",
- lsa_type, opaque_type);
+ zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
+ __func__, lsa_type, opaque_type);
rc = OSPF_API_OPAQUETYPENOTREGISTERED;
goto out;
}
@@ -1785,9 +1768,8 @@ int ospf_apiserver_originate1(struct ospf_lsa *lsa, struct ospf_lsa *old)
*/
assert(!ospf_opaque_is_owned(old));
if (IS_LSA_MAX_SEQ(old)) {
- flog_warn(
- EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_apiserver_originate1: old LSA at maxseq");
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "%s: old LSA at maxseq", __func__);
return -1;
}
lsa->data->ls_seqnum = lsa_seqnum_increment(old);
@@ -1869,9 +1851,8 @@ struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
apiserv = lookup_apiserver_by_lsa(lsa);
if (!apiserv) {
- zlog_warn(
- "ospf_apiserver_lsa_refresher: LSA[%s]: No apiserver?",
- dump_lsa_key(lsa));
+ zlog_warn("%s: LSA[%s]: No apiserver?", __func__,
+ dump_lsa_key(lsa));
lsa->data->ls_age =
htons(OSPF_LSA_MAXAGE); /* Flush it anyway. */
goto out;
@@ -1889,8 +1870,7 @@ struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
new = ospf_apiserver_opaque_lsa_new(lsa->area, lsa->oi,
lsa->data);
if (!new) {
- zlog_warn(
- "ospf_apiserver_lsa_refresher: Cannot create a new LSA?");
+ zlog_warn("%s: Cannot create a new LSA?", __func__);
goto out;
}
} else {
@@ -1908,9 +1888,8 @@ struct ospf_lsa *ospf_apiserver_lsa_refresher(struct ospf_lsa *lsa)
/* Install LSA into LSDB. */
if (ospf_lsa_install(ospf, new->oi, new) == NULL) {
- flog_warn(
- EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_apiserver_lsa_refresher: ospf_lsa_install failed");
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "%s: ospf_lsa_install failed", __func__);
ospf_lsa_unlock(&new);
goto out;
}
@@ -1962,7 +1941,7 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
case OSPF_OPAQUE_AREA_LSA:
area = ospf_area_lookup_by_area_id(ospf, dmsg->area_id);
if (!area) {
- zlog_warn("ospf_apiserver_lsa_delete: unknown area %pI4",
+ zlog_warn("%s: unknown area %pI4", __func__,
&dmsg->area_id);
rc = OSPF_API_NOSUCHAREA;
goto out;
@@ -1973,9 +1952,8 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
area = NULL;
break;
default:
- zlog_warn(
- "ospf_apiserver_lsa_delete: Cannot delete non-opaque LSA type %d",
- dmsg->lsa_type);
+ zlog_warn("%s: Cannot delete non-opaque LSA type %d", __func__,
+ dmsg->lsa_type);
rc = OSPF_API_ILLEGALLSATYPE;
goto out;
}
@@ -1986,9 +1964,8 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
if (!apiserver_is_opaque_type_registered(apiserv, lsa_type,
opaque_type)) {
- zlog_warn(
- "ospf_apiserver_lsa_delete: LSA-type(%d)/Opaque-type(%d): Not registered",
- lsa_type, opaque_type);
+ zlog_warn("%s: LSA-type(%d)/Opaque-type(%d): Not registered",
+ __func__, lsa_type, opaque_type);
rc = OSPF_API_OPAQUETYPENOTREGISTERED;
goto out;
}
@@ -2004,9 +1981,8 @@ int ospf_apiserver_handle_delete_request(struct ospf_apiserver *apiserv,
*/
old = ospf_lsa_lookup(ospf, area, dmsg->lsa_type, id, ospf->router_id);
if (!old) {
- zlog_warn(
- "ospf_apiserver_lsa_delete: LSA[Type%d:%pI4] not in LSDB",
- dmsg->lsa_type, &id);
+ zlog_warn("%s: LSA[Type%d:%pI4] not in LSDB", __func__,
+ dmsg->lsa_type, &id);
rc = OSPF_API_NOSUCHLSA;
goto out;
}
@@ -2114,7 +2090,7 @@ int ospf_apiserver_new_if(struct interface *ifp)
if (ifp->name[0] == '\0') {
/* interface has empty name */
- zlog_warn("ospf_apiserver_new_if: interface has no name?");
+ zlog_warn("%s: interface has no name?", __func__);
return 0;
}
@@ -2125,7 +2101,7 @@ int ospf_apiserver_new_if(struct interface *ifp)
if (ifp->name[0] == '\0') {
/* interface has empty name */
- zlog_warn("ospf_apiserver_new_if: interface has no name?");
+ zlog_warn("%s: interface has no name?", __func__);
return 0;
}
@@ -2134,9 +2110,8 @@ int ospf_apiserver_new_if(struct interface *ifp)
if (!oi) {
/* This interface is known to Zebra but not to OSPF daemon yet.
*/
- zlog_warn(
- "ospf_apiserver_new_if: interface %s not known to OSPFd?",
- ifp->name);
+ zlog_warn("%s: interface %s not known to OSPFd?", __func__,
+ ifp->name);
return 0;
}
@@ -2154,9 +2129,8 @@ int ospf_apiserver_del_if(struct interface *ifp)
struct ospf_interface *oi;
/* zlog_warn for debugging */
- zlog_warn("ospf_apiserver_del_if");
- zlog_warn("ifp name=%s status=%d index=%d", ifp->name, ifp->status,
- ifp->ifindex);
+ zlog_warn("%s ifp name=%s status=%d index=%d", __func__, ifp->name,
+ ifp->status, ifp->ifindex);
oi = ospf_apiserver_if_lookup_by_ifp(ifp);
@@ -2179,20 +2153,19 @@ void ospf_apiserver_ism_change(struct ospf_interface *oi, int old_state)
/* Tell clients about interface change */
/* zlog_warn for debugging */
- zlog_warn("ospf_apiserver_ism_change");
+ zlog_warn("%s", __func__);
if (listcount(apiserver_list) > 0) {
ospf_apiserver_clients_notify_ism_change(oi);
}
- zlog_warn("oi->ifp->name=%s", oi->ifp->name);
- zlog_warn("old_state=%d", old_state);
- zlog_warn("oi->state=%d", oi->state);
+ zlog_warn("%s oi->ifp->name=%s old_state=%d oi->state=%d", __func__,
+ oi->ifp->name, old_state, oi->state);
}
void ospf_apiserver_nsm_change(struct ospf_neighbor *nbr, int old_status)
{
/* Neighbor status changed, tell clients about it */
- zlog_warn("ospf_apiserver_nsm_change");
+ zlog_warn("%s", __func__);
if (listcount(apiserver_list) > 0) {
ospf_apiserver_clients_notify_nsm_change(nbr);
}
@@ -2300,7 +2273,8 @@ void ospf_apiserver_clients_notify_ready_type9(struct ospf_interface *oi)
oi->address->u.prefix4);
if (!msg) {
zlog_warn(
- "ospf_apiserver_clients_notify_ready_type9: new_msg_ready_notify failed");
+ "%s: new_msg_ready_notify failed",
+ __func__);
#ifdef NOTYET
/* Cannot allocate new message. What
* should we do? */
@@ -2344,7 +2318,8 @@ void ospf_apiserver_clients_notify_ready_type10(struct ospf_area *area)
area->area_id);
if (!msg) {
zlog_warn(
- "ospf_apiserver_clients_notify_ready_type10: new_msg_ready_nofity failed");
+ "%s: new_msg_ready_nofity failed",
+ __func__);
#ifdef NOTYET
/* Cannot allocate new message. What
* should we do? */
@@ -2390,7 +2365,8 @@ void ospf_apiserver_clients_notify_ready_type11(struct ospf *top)
id_null);
if (!msg) {
zlog_warn(
- "ospf_apiserver_clients_notify_ready_type11: new_msg_ready_notify failed");
+ "%s: new_msg_ready_notify failed",
+ __func__);
#ifdef NOTYET
/* Cannot allocate new message. What
* should we do? */
@@ -2449,8 +2425,7 @@ void ospf_apiserver_clients_notify_ism_change(struct ospf_interface *oi)
msg = new_msg_ism_change(0, ifaddr, area_id, oi->state);
if (!msg) {
- zlog_warn(
- "apiserver_clients_notify_ism_change: msg_new failed");
+ zlog_warn("%s: msg_new failed", __func__);
return;
}
@@ -2473,8 +2448,7 @@ void ospf_apiserver_clients_notify_nsm_change(struct ospf_neighbor *nbr)
msg = new_msg_nsm_change(0, ifaddr, nbraddr, nbr->router_id,
nbr->state);
if (!msg) {
- zlog_warn(
- "apiserver_clients_notify_nsm_change: msg_new failed");
+ zlog_warn("%s: msg_new failed", __func__);
return;
}
@@ -2509,8 +2483,7 @@ static int apiserver_clients_lsa_change_notify(uint8_t msgtype,
ifaddr, area_id,
lsa->flags & OSPF_LSA_SELF, lsa->data);
if (!msg) {
- zlog_warn(
- "apiserver_clients_lsa_change_notify: msg_new failed");
+ zlog_warn("%s: msg_new failed", __func__);
return -1;
}
diff --git a/ospfd/ospf_ase.c b/ospfd/ospf_ase.c
index 23c7a1e706..706a22e9bf 100644
--- a/ospfd/ospf_ase.c
+++ b/ospfd/ospf_ase.c
@@ -212,12 +212,12 @@ int ospf_ase_calculate_route(struct ospf *ospf, struct ospf_lsa *lsa)
if (lsa->data->type == OSPF_AS_NSSA_LSA)
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_ase_calc(): Processing Type-7");
+ zlog_debug("%s: Processing Type-7", __func__);
/* Stay away from any Local Translated Type-7 LSAs */
if (CHECK_FLAG(lsa->flags, OSPF_LSA_LOCAL_XLT)) {
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug("ospf_ase_calc(): Rejecting Local Xlt'd");
+ zlog_debug("%s: Rejecting Local Xlt'd", __func__);
return 0;
}
@@ -589,9 +589,8 @@ static void ospf_ase_calculate_timer(struct thread *t)
if (ospf->anyNSSA)
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area)) {
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_ase_calculate_timer(): looking at area %pI4",
- &area->area_id);
+ zlog_debug("%s: looking at area %pI4",
+ __func__, &area->area_id);
if (area->external_routing == OSPF_AREA_NSSA)
LSDB_LOOP (NSSA_LSDB(area), rn, lsa)
diff --git a/ospfd/ospf_dump.c b/ospfd/ospf_dump.c
index 258a93fb16..9b347891ec 100644
--- a/ospfd/ospf_dump.c
+++ b/ospfd/ospf_dump.c
@@ -54,13 +54,13 @@ unsigned long conf_debug_ospf_nsm = 0;
unsigned long conf_debug_ospf_lsa = 0;
unsigned long conf_debug_ospf_zebra = 0;
unsigned long conf_debug_ospf_nssa = 0;
-unsigned long conf_debug_ospf_te = 0;
+unsigned long conf_debug_ospf_te;
unsigned long conf_debug_ospf_ext = 0;
-unsigned long conf_debug_ospf_sr = 0;
-unsigned long conf_debug_ospf_ti_lfa = 0;
-unsigned long conf_debug_ospf_defaultinfo = 0;
-unsigned long conf_debug_ospf_ldp_sync = 0;
-unsigned long conf_debug_ospf_gr = 0;
+unsigned long conf_debug_ospf_sr;
+unsigned long conf_debug_ospf_ti_lfa;
+unsigned long conf_debug_ospf_defaultinfo;
+unsigned long conf_debug_ospf_ldp_sync;
+unsigned long conf_debug_ospf_gr;
unsigned long conf_debug_ospf_bfd;
unsigned long conf_debug_ospf_client_api;
@@ -72,13 +72,13 @@ unsigned long term_debug_ospf_nsm = 0;
unsigned long term_debug_ospf_lsa = 0;
unsigned long term_debug_ospf_zebra = 0;
unsigned long term_debug_ospf_nssa = 0;
-unsigned long term_debug_ospf_te = 0;
+unsigned long term_debug_ospf_te;
unsigned long term_debug_ospf_ext = 0;
-unsigned long term_debug_ospf_sr = 0;
-unsigned long term_debug_ospf_ti_lfa = 0;
+unsigned long term_debug_ospf_sr;
+unsigned long term_debug_ospf_ti_lfa;
unsigned long term_debug_ospf_defaultinfo;
unsigned long term_debug_ospf_ldp_sync;
-unsigned long term_debug_ospf_gr = 0;
+unsigned long term_debug_ospf_gr;
unsigned long term_debug_ospf_bfd;
unsigned long term_debug_ospf_client_api;
@@ -628,84 +628,9 @@ void ospf_packet_dump(struct stream *s)
stream_set_getp(s, gp);
}
-DEFUN (debug_ospf_packet,
+DEFPY (debug_ospf_packet,
debug_ospf_packet_cmd,
- "debug ospf [(1-65535)] packet <hello|dd|ls-request|ls-update|ls-ack|all> [<send [detail]|recv [detail]|detail>]",
- DEBUG_STR
- OSPF_STR
- "Instance ID\n"
- "OSPF packets\n"
- "OSPF Hello\n"
- "OSPF Database Description\n"
- "OSPF Link State Request\n"
- "OSPF Link State Update\n"
- "OSPF Link State Acknowledgment\n"
- "OSPF all packets\n"
- "Packet sent\n"
- "Detail Information\n"
- "Packet received\n"
- "Detail Information\n"
- "Detail Information\n")
-{
- int inst = (argv[2]->type == RANGE_TKN) ? 1 : 0;
- int detail = strmatch(argv[argc - 1]->text, "detail");
- int send = strmatch(argv[argc - (1 + detail)]->text, "send");
- int recv = strmatch(argv[argc - (1 + detail)]->text, "recv");
- char *packet = argv[3 + inst]->text;
-
- if (inst) // user passed instance ID
- {
- if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
- int type = 0;
- int flag = 0;
- int i;
-
- /* Check packet type. */
- if (strmatch(packet, "hello"))
- type = OSPF_DEBUG_HELLO;
- else if (strmatch(packet, "dd"))
- type = OSPF_DEBUG_DB_DESC;
- else if (strmatch(packet, "ls-request"))
- type = OSPF_DEBUG_LS_REQ;
- else if (strmatch(packet, "ls-update"))
- type = OSPF_DEBUG_LS_UPD;
- else if (strmatch(packet, "ls-ack"))
- type = OSPF_DEBUG_LS_ACK;
- else if (strmatch(packet, "all"))
- type = OSPF_DEBUG_ALL;
-
- /* Cases:
- * (none) = send + recv
- * detail = send + recv + detail
- * recv = recv
- * send = send
- * recv detail = recv + detail
- * send detail = send + detail
- */
- if (!send && !recv)
- send = recv = 1;
-
- flag |= (send) ? OSPF_DEBUG_SEND : 0;
- flag |= (recv) ? OSPF_DEBUG_RECV : 0;
- flag |= (detail) ? OSPF_DEBUG_DETAIL : 0;
-
- for (i = 0; i < 5; i++)
- if (type & (0x01 << i)) {
- if (vty->node == CONFIG_NODE)
- DEBUG_PACKET_ON(i, flag);
- else
- TERM_DEBUG_PACKET_ON(i, flag);
- }
-
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_ospf_packet,
- no_debug_ospf_packet_cmd,
- "no debug ospf [(1-65535)] packet <hello|dd|ls-request|ls-update|ls-ack|all> [<send [detail]|recv [detail]|detail>]",
+ "[no$no] debug ospf [(1-65535)$inst] packet <hello|dd|ls-request|ls-update|ls-ack|all>$packet [<send$send [detail$detail]|recv$recv [detail$detail]|detail$detail>]",
NO_STR
DEBUG_STR
OSPF_STR
@@ -723,22 +648,13 @@ DEFUN (no_debug_ospf_packet,
"Detail Information\n"
"Detail Information\n")
{
- int inst = (argv[3]->type == RANGE_TKN) ? 1 : 0;
- int detail = strmatch(argv[argc - 1]->text, "detail");
- int send = strmatch(argv[argc - (1 + detail)]->text, "send");
- int recv = strmatch(argv[argc - (1 + detail)]->text, "recv");
- char *packet = argv[4 + inst]->text;
-
- if (inst) // user passed instance ID
- {
- if (inst != ospf_instance)
- return CMD_NOT_MY_INSTANCE;
- }
-
int type = 0;
int flag = 0;
int i;
+ if (inst && inst != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
/* Check packet type. */
if (strmatch(packet, "hello"))
type = OSPF_DEBUG_HELLO;
@@ -761,8 +677,10 @@ DEFUN (no_debug_ospf_packet,
* recv detail = recv + detail
* send detail = send + detail
*/
- if (!send && !recv)
- send = recv = 1;
+ if (!send && !recv) {
+ flag |= OSPF_DEBUG_SEND;
+ flag |= OSPF_DEBUG_RECV;
+ }
flag |= (send) ? OSPF_DEBUG_SEND : 0;
flag |= (recv) ? OSPF_DEBUG_RECV : 0;
@@ -770,10 +688,17 @@ DEFUN (no_debug_ospf_packet,
for (i = 0; i < 5; i++)
if (type & (0x01 << i)) {
- if (vty->node == CONFIG_NODE)
- DEBUG_PACKET_OFF(i, flag);
- else
- TERM_DEBUG_PACKET_OFF(i, flag);
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_PACKET_OFF(i, flag);
+ else
+ DEBUG_PACKET_ON(i, flag);
+ } else {
+ if (no)
+ TERM_DEBUG_PACKET_OFF(i, flag);
+ else
+ TERM_DEBUG_PACKET_ON(i, flag);
+ }
}
#ifdef DEBUG
@@ -1457,194 +1382,221 @@ DEFUN (no_debug_ospf_instance_nssa,
return CMD_SUCCESS;
}
-DEFUN (debug_ospf_te,
+DEFPY (debug_ospf_te,
debug_ospf_te_cmd,
- "debug ospf te",
- DEBUG_STR
- OSPF_STR
- "OSPF-TE information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(te, TE);
- TERM_DEBUG_ON(te, TE);
- return CMD_SUCCESS;
-}
-
-DEFUN (no_debug_ospf_te,
- no_debug_ospf_te_cmd,
- "no debug ospf te",
+ "[no$no] debug ospf [(1-65535)$instance] te",
NO_STR
DEBUG_STR
OSPF_STR
+ "Instance ID\n"
"OSPF-TE information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(te, TE);
- TERM_DEBUG_OFF(te, TE);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(te, TE);
+ else
+ DEBUG_ON(te, TE);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(te, TE);
+ else
+ TERM_DEBUG_ON(te, TE);
+ }
+
return CMD_SUCCESS;
}
-DEFUN (debug_ospf_sr,
+DEFPY (debug_ospf_sr,
debug_ospf_sr_cmd,
- "debug ospf sr",
+ "[no$no] debug ospf [(1-65535)$instance] sr",
+ NO_STR
DEBUG_STR
OSPF_STR
+ "Instance ID\n"
"OSPF-SR information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(sr, SR);
- TERM_DEBUG_ON(sr, SR);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(sr, SR);
+ else
+ DEBUG_ON(sr, SR);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(sr, SR);
+ else
+ TERM_DEBUG_ON(sr, SR);
+ }
+
return CMD_SUCCESS;
}
-DEFUN (no_debug_ospf_sr,
- no_debug_ospf_sr_cmd,
- "no debug ospf sr",
+DEFPY (debug_ospf_ti_lfa,
+ debug_ospf_ti_lfa_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] ti-lfa",
NO_STR
DEBUG_STR
OSPF_STR
- "OSPF-SR information\n")
+ "Instance ID\n"
+ "OSPF-SR TI-LFA information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(sr, SR);
- TERM_DEBUG_OFF(sr, SR);
- return CMD_SUCCESS;
-}
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
-DEFUN(debug_ospf_ti_lfa, debug_ospf_ti_lfa_cmd, "debug ospf ti-lfa",
- DEBUG_STR OSPF_STR "OSPF-SR TI-LFA information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(ti_lfa, TI_LFA);
- TERM_DEBUG_ON(ti_lfa, TI_LFA);
- return CMD_SUCCESS;
-}
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(ti_lfa, TI_LFA);
+ else
+ DEBUG_ON(ti_lfa, TI_LFA);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(ti_lfa, TI_LFA);
+ else
+ TERM_DEBUG_ON(ti_lfa, TI_LFA);
+ }
-DEFUN(no_debug_ospf_ti_lfa, no_debug_ospf_ti_lfa_cmd, "no debug ospf ti-lfa",
- NO_STR DEBUG_STR OSPF_STR "OSPF-SR TI-LFA information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(ti_lfa, TI_LFA);
- TERM_DEBUG_OFF(ti_lfa, TI_LFA);
return CMD_SUCCESS;
}
-DEFUN (debug_ospf_default_info,
+DEFPY (debug_ospf_default_info,
debug_ospf_default_info_cmd,
- "debug ospf default-information",
+ "[no$no] debug ospf [(1-65535)$instance] default-information",
+ NO_STR
DEBUG_STR
OSPF_STR
+ "Instance ID\n"
"OSPF default information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(defaultinfo, DEFAULTINFO);
- TERM_DEBUG_ON(defaultinfo, DEFAULTINFO);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(defaultinfo, DEFAULTINFO);
+ else
+ DEBUG_ON(defaultinfo, DEFAULTINFO);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
+ else
+ TERM_DEBUG_ON(defaultinfo, DEFAULTINFO);
+ }
+
return CMD_SUCCESS;
}
-DEFUN (no_debug_ospf_default_info,
- no_debug_ospf_default_info_cmd,
- "no debug ospf default-information",
+DEFPY (debug_ospf_ldp_sync,
+ debug_ospf_ldp_sync_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] ldp-sync",
NO_STR
DEBUG_STR
OSPF_STR
- "OSPF default information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(defaultinfo, DEFAULTINFO);
- TERM_DEBUG_OFF(defaultinfo, DEFAULTINFO);
- return CMD_SUCCESS;
-}
-
-DEFUN(debug_ospf_ldp_sync,
- debug_ospf_ldp_sync_cmd,
- "debug ospf ldp-sync",
- DEBUG_STR OSPF_STR
- "OSPF LDP-Sync information\n")
+ "Instance ID\n"
+ "OSPF LDP-Sync information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(ldp_sync, LDP_SYNC);
- TERM_DEBUG_ON(ldp_sync, LDP_SYNC);
- return CMD_SUCCESS;
-}
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
-DEFUN(no_debug_ospf_ldp_sync,
- no_debug_ospf_ldp_sync_cmd,
- "no debug ospf ldp-sync",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "OSPF LDP-Sync information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(ldp_sync, LDP_SYNC);
- TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(ldp_sync, LDP_SYNC);
+ else
+ DEBUG_ON(ldp_sync, LDP_SYNC);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(ldp_sync, LDP_SYNC);
+ else
+ TERM_DEBUG_ON(ldp_sync, LDP_SYNC);
+ }
return CMD_SUCCESS;
}
-DEFPY(debug_ospf_gr, debug_ospf_gr_cmd, "[no$no] debug ospf graceful-restart",
- NO_STR DEBUG_STR OSPF_STR "OSPF Graceful Restart\n")
+DEFPY (debug_ospf_gr,
+ debug_ospf_gr_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] graceful-restart",
+ NO_STR
+ DEBUG_STR
+ OSPF_STR
+ "Instance ID\n"
+ "OSPF Graceful Restart\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(gr, GR);
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
- if (!no)
- TERM_DEBUG_ON(gr, GR);
- else
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ CONF_DEBUG_OFF(gr, GR);
+ else
+ CONF_DEBUG_ON(gr, GR);
+ }
+
+ if (no)
TERM_DEBUG_OFF(gr, GR);
+ else
+ TERM_DEBUG_ON(gr, GR);
return CMD_SUCCESS;
}
-DEFPY(debug_ospf_bfd, debug_ospf_bfd_cmd,
- "[no] debug ospf bfd",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "Bidirection Forwarding Detection\n")
+DEFPY (debug_ospf_bfd,
+ debug_ospf_bfd_cmd,
+ "[no] debug ospf [(1-65535)$instance] bfd",
+ NO_STR
+ DEBUG_STR
+ OSPF_STR
+ "Instance ID\n"
+ "Bidirection Forwarding Detection\n")
{
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
+
if (vty->node == CONFIG_NODE) {
if (no) {
bfd_protocol_integration_set_debug(false);
- CONF_DEBUG_OFF(bfd, BFD_LIB);
+ DEBUG_OFF(bfd, BFD_LIB);
} else {
bfd_protocol_integration_set_debug(true);
- CONF_DEBUG_ON(bfd, BFD_LIB);
+ DEBUG_ON(bfd, BFD_LIB);
}
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(bfd, BFD_LIB);
+ else
+ TERM_DEBUG_ON(bfd, BFD_LIB);
}
- if (no)
- TERM_DEBUG_OFF(bfd, BFD_LIB);
- else
- TERM_DEBUG_ON(bfd, BFD_LIB);
-
return CMD_SUCCESS;
}
-DEFUN(debug_ospf_client_api,
- debug_ospf_client_api_cmd,
- "debug ospf client-api",
- DEBUG_STR OSPF_STR
- "OSPF client API information\n")
+DEFPY (debug_ospf_client_api,
+ debug_ospf_client_api_cmd,
+ "[no$no] debug ospf [(1-65535)$instance] client-api",
+ NO_STR
+ DEBUG_STR
+ OSPF_STR
+ "Instance ID\n"
+ "OSPF client API information\n")
{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_ON(client_api, CLIENT_API);
- TERM_DEBUG_ON(client_api, CLIENT_API);
- return CMD_SUCCESS;
-}
+ if (instance && instance != ospf_instance)
+ return CMD_NOT_MY_INSTANCE;
-DEFUN(no_debug_ospf_client_api,
- no_debug_ospf_client_api_cmd,
- "no debug ospf client-api",
- NO_STR
- DEBUG_STR
- OSPF_STR
- "OSPF client API information\n")
-{
- if (vty->node == CONFIG_NODE)
- CONF_DEBUG_OFF(client_api, CLIENT_API);
- TERM_DEBUG_OFF(client_api, CLIENT_API);
+ if (vty->node == CONFIG_NODE) {
+ if (no)
+ DEBUG_OFF(client_api, CLIENT_API);
+ else
+ DEBUG_ON(client_api, CLIENT_API);
+ } else {
+ if (no)
+ TERM_DEBUG_OFF(client_api, CLIENT_API);
+ else
+ TERM_DEBUG_ON(client_api, CLIENT_API);
+ }
return CMD_SUCCESS;
}
@@ -1816,7 +1768,7 @@ static int show_debugging_ospf_common(struct vty *vty)
}
if (IS_DEBUG_OSPF(defaultinfo, DEFAULTINFO) == OSPF_DEBUG_DEFAULTINFO)
- vty_out(vty, "OSPF default information is on\n");
+ vty_out(vty, " OSPF default information is on\n");
/* Show debug status for NSSA. */
if (IS_DEBUG_OSPF(nssa, NSSA) == OSPF_DEBUG_NSSA)
@@ -1978,7 +1930,7 @@ static int config_write_debug(struct vty *vty)
& (OSPF_DEBUG_SEND_RECV | OSPF_DEBUG_DETAIL);
if (r == (OSPF_DEBUG_SEND_RECV | OSPF_DEBUG_DETAIL)) {
vty_out(vty, "debug ospf%s packet all detail\n", str);
- return 1;
+ write = 1;
}
/* debug ospf packet all. */
@@ -1991,7 +1943,7 @@ static int config_write_debug(struct vty *vty)
if (conf_debug_ospf_packet[i] & OSPF_DEBUG_DETAIL)
vty_out(vty, "debug ospf%s packet %s detail\n",
str, type_str[i]);
- return 1;
+ write = 1;
}
/* debug ospf packet (hello|dd|ls-request|ls-update|ls-ack)
@@ -2047,6 +1999,13 @@ static int config_write_debug(struct vty *vty)
write = 1;
}
+ /* debug ospf default-information */
+ if (IS_CONF_DEBUG_OSPF(defaultinfo, DEFAULTINFO) ==
+ OSPF_DEBUG_DEFAULTINFO) {
+ vty_out(vty, "debug ospf%s default-information\n", str);
+ write = 1;
+ }
+
return write;
}
@@ -2074,18 +2033,11 @@ void ospf_debug_init(void)
install_element(ENABLE_NODE, &no_debug_ospf_zebra_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_event_cmd);
install_element(ENABLE_NODE, &no_debug_ospf_nssa_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_te_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_sr_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_ti_lfa_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_default_info_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_ldp_sync_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_client_api_cmd);
install_element(ENABLE_NODE, &debug_ospf_gr_cmd);
install_element(ENABLE_NODE, &debug_ospf_bfd_cmd);
install_element(ENABLE_NODE, &show_debugging_ospf_instance_cmd);
install_element(ENABLE_NODE, &debug_ospf_packet_cmd);
- install_element(ENABLE_NODE, &no_debug_ospf_packet_cmd);
install_element(ENABLE_NODE, &debug_ospf_instance_nsm_cmd);
install_element(ENABLE_NODE, &debug_ospf_instance_lsa_cmd);
@@ -2100,7 +2052,6 @@ void ospf_debug_init(void)
install_element(ENABLE_NODE, &no_debug_ospf_cmd);
install_element(CONFIG_NODE, &debug_ospf_packet_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_packet_cmd);
install_element(CONFIG_NODE, &debug_ospf_ism_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_ism_cmd);
@@ -2120,12 +2071,6 @@ void ospf_debug_init(void)
install_element(CONFIG_NODE, &no_debug_ospf_zebra_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_event_cmd);
install_element(CONFIG_NODE, &no_debug_ospf_nssa_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_te_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_sr_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_ti_lfa_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_default_info_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_ldp_sync_cmd);
- install_element(CONFIG_NODE, &no_debug_ospf_client_api_cmd);
install_element(CONFIG_NODE, &debug_ospf_gr_cmd);
install_element(CONFIG_NODE, &debug_ospf_bfd_cmd);
diff --git a/ospfd/ospf_flood.c b/ospfd/ospf_flood.c
index 8f9153d766..e686a93ba9 100644
--- a/ospfd/ospf_flood.c
+++ b/ospfd/ospf_flood.c
@@ -454,16 +454,13 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
struct ospf_neighbor *onbr;
struct route_node *rn;
int retx_flag;
- char buf[PREFIX_STRLEN];
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "%s: considering int %s (%s), INBR(%s), LSA[%s] AGE %u",
+ "%s: considering int %s (%s), INBR(%pI4), LSA[%s] AGE %u",
__func__, IF_NAME(oi), ospf_get_name(oi->ospf),
- inbr ? inet_ntop(AF_INET, &inbr->router_id, buf,
- sizeof(buf))
- : "NULL",
- dump_lsa_key(lsa), ntohs(lsa->data->ls_age));
+ inbr ? &inbr->router_id : NULL, dump_lsa_key(lsa),
+ ntohs(lsa->data->ls_age));
if (!ospf_if_is_enable(oi))
return 0;
@@ -641,13 +638,15 @@ int ospf_flood_through_interface(struct ospf_interface *oi,
if (oi->type == OSPF_IFTYPE_NBMA) {
struct ospf_neighbor *nbr;
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info) != NULL)
- if (nbr != oi->nbr_self
- && nbr->state >= NSM_Exchange)
- ospf_ls_upd_send_lsa(
- nbr, lsa,
- OSPF_SEND_PACKET_DIRECT);
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+
+ if (!nbr)
+ continue;
+ if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
+ ospf_ls_upd_send_lsa(nbr, lsa,
+ OSPF_SEND_PACKET_DIRECT);
+ }
} else
ospf_ls_upd_send_lsa(oi->nbr_self, lsa,
OSPF_SEND_PACKET_INDIRECT);
@@ -805,8 +804,7 @@ int ospf_flood_through(struct ospf *ospf, struct ospf_neighbor *inbr,
/* Any P-bit was installed with the Type-7. */
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_flood_through: LOCAL NSSA FLOOD of Type-7.");
+ zlog_debug("%s: LOCAL NSSA FLOOD of Type-7.", __func__);
/* Fallthrough */
default:
lsa_ack_flag = ospf_flood_through_area(lsa->area, inbr, lsa);
@@ -994,18 +992,20 @@ static void ospf_ls_retransmit_delete_nbr_if(struct ospf_interface *oi,
struct ospf_lsa *lsr;
if (ospf_if_is_enable(oi))
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
/* If LSA find in LS-retransmit list, then remove it. */
- if ((nbr = rn->info) != NULL) {
- lsr = ospf_ls_retransmit_lookup(nbr, lsa);
+ nbr = rn->info;
- /* If LSA find in ls-retransmit list, remove it.
- */
- if (lsr != NULL
- && lsr->data->ls_seqnum
- == lsa->data->ls_seqnum)
- ospf_ls_retransmit_delete(nbr, lsr);
- }
+ if (!nbr)
+ continue;
+
+ lsr = ospf_ls_retransmit_lookup(nbr, lsa);
+
+ /* If LSA find in ls-retransmit list, remove it. */
+ if (lsr != NULL &&
+ lsr->data->ls_seqnum == lsa->data->ls_seqnum)
+ ospf_ls_retransmit_delete(nbr, lsr);
+ }
}
void ospf_ls_retransmit_delete_nbr_area(struct ospf_area *area,
diff --git a/ospfd/ospf_ia.c b/ospfd/ospf_ia.c
index f805899b81..f9869a6733 100644
--- a/ospfd/ospf_ia.c
+++ b/ospfd/ospf_ia.c
@@ -75,9 +75,7 @@ static void ospf_ia_network_route(struct ospf *ospf, struct route_table *rt,
struct ospf_route * or ;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_network_route(): processing summary route to %pFX",
- p);
+ zlog_debug("%s: processing summary route to %pFX", __func__, p);
/* Find a route to the same dest */
if ((rn1 = route_node_lookup(rt, (struct prefix *)p))) {
@@ -88,7 +86,8 @@ static void ospf_ia_network_route(struct ospf *ospf, struct route_table *rt,
if ((or = rn1->info)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_ia_network_route(): Found a route to the same network");
+ "%s: Found a route to the same network",
+ __func__);
/* Check the existing route. */
if ((res = ospf_route_cmp(ospf, new_or, or)) < 0) {
/* New route is better, so replace old one. */
@@ -112,9 +111,7 @@ static void ospf_ia_network_route(struct ospf *ospf, struct route_table *rt,
} /*if (rn1)*/
else { /* no route */
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_network_route(): add new route to %pFX",
- p);
+ zlog_debug("%s: add new route to %pFX", __func__, p);
ospf_route_add(rt, p, new_or, abr_or);
}
}
@@ -129,7 +126,7 @@ static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs,
int ret;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ia_router_route(): considering %pFX", p);
+ zlog_debug("%s: considering %pFX", __func__, p);
/* Find a route to the same dest */
rn = route_node_get(rtrs, (struct prefix *)p);
@@ -150,7 +147,8 @@ static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs,
if (or) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_ia_router_route(): a route to the same ABR through the same area exists");
+ "%s: a route to the same ABR through the same area exists",
+ __func__);
/* New route is better */
if ((ret = ospf_route_cmp(ospf, new_or, or)) < 0) {
listnode_delete(rn->info, or);
@@ -160,8 +158,8 @@ static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs,
/* Routes are the same */
else if (ret == 0) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_router_route(): merging the new route");
+ zlog_debug("%s: merging the new route",
+ __func__);
ospf_route_copy_nexthops(or, abr_or->paths);
ospf_route_free(new_or);
@@ -170,8 +168,8 @@ static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs,
/* New route is worse */
else {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_router_route(): skipping the new route");
+ zlog_debug("%s: skipping the new route",
+ __func__);
ospf_route_free(new_or);
return;
}
@@ -180,7 +178,7 @@ static void ospf_ia_router_route(struct ospf *ospf, struct route_table *rtrs,
ospf_route_copy_nexthops(new_or, abr_or->paths);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ia_router_route(): adding the new route");
+ zlog_debug("%s: adding the new route", __func__);
listnode_add(rn->info, new_or);
}
@@ -202,8 +200,7 @@ static int process_summary_lsa(struct ospf_area *area, struct route_table *rt,
sl = (struct summary_lsa *)lsa->data;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("process_summary_lsa(): LS ID: %pI4",
- &sl->header.id);
+ zlog_debug("%s: LS ID: %pI4", __func__, &sl->header.id);
metric = GET_METRIC(sl->metric);
@@ -311,8 +308,8 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt,
if (abr_or == NULL) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_update_network_route(): can't find a route to the ABR");
+ zlog_debug("%s: can't find a route to the ABR",
+ __func__);
return;
}
@@ -326,8 +323,8 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt,
installed
backbone paths */
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_update_network_route(): Allowing Shortcut ABR to add new route");
+ zlog_debug("%s: Allowing Shortcut ABR to add new route",
+ __func__);
new_or = ospf_route_new();
new_or->type = OSPF_DESTINATION_NETWORK;
new_or->id = lsa->header.id;
@@ -352,8 +349,7 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt,
if (or->path_type != OSPF_PATH_INTRA_AREA &&
or->path_type != OSPF_PATH_INTER_AREA) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_update_network_route(): ERR: path type is wrong");
+ zlog_debug("%s: ERR: path type is wrong", __func__);
return;
}
@@ -364,37 +360,39 @@ static void ospf_update_network_route(struct ospf *ospf, struct route_table *rt,
or->u.std.area_id)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_update_network_route(): Shortcut: this intra-area path is not backbone");
+ "%s: Shortcut: this intra-area path is not backbone",
+ __func__);
return;
}
} else /* Not Shortcut ABR */
{
if (!OSPF_IS_AREA_ID_BACKBONE(or->u.std.area_id)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_update_network_route(): route is not BB-associated");
+ zlog_debug("%s: route is not BB-associated",
+ __func__);
return; /* We can update only BB routes */
}
}
if (or->cost < cost) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_update_network_route(): new route is worse");
+ zlog_debug("%s: new route is worse", __func__);
return;
}
if (or->cost == cost) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_update_network_route(): new route is same distance, adding nexthops");
+ "%s: new route is same distance, adding nexthops",
+ __func__);
ospf_route_copy_nexthops(or, abr_or->paths);
}
if (or->cost > cost) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_update_network_route(): new route is better, overriding nexthops");
+ "%s: new route is better, overriding nexthops",
+ __func__);
ospf_route_subst_nexthops(or, abr_or->paths);
or->cost = cost;
@@ -431,8 +429,8 @@ static void ospf_update_router_route(struct ospf *ospf,
if (abr_or == NULL) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_update_router_route(): can't find a route to the ABR");
+ zlog_debug("%s: can't find a route to the ABR",
+ __func__);
return;
}
@@ -481,8 +479,8 @@ static void ospf_update_router_route(struct ospf *ospf,
if (!(or->u.std.flags & ROUTER_LSA_EXTERNAL)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_upd_router_route(): the remote router is not an ASBR");
+ zlog_debug("%s: the remote router is not an ASBR",
+ __func__);
return;
}
@@ -524,28 +522,24 @@ static int process_transit_summary_lsa(struct ospf_area *area,
sl = (struct summary_lsa *)lsa->data;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("process_transit_summaries(): LS ID: %pI4",
- &lsa->data->id);
+ zlog_debug("%s: LS ID: %pI4", __func__, &lsa->data->id);
metric = GET_METRIC(sl->metric);
if (metric == OSPF_LS_INFINITY) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "process_transit_summaries(): metric is infinity, skip");
+ zlog_debug("%s: metric is infinity, skip", __func__);
return 0;
}
if (IS_LSA_MAXAGE(lsa)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "process_transit_summaries(): This LSA is too old");
+ zlog_debug("%s: This LSA is too old", __func__);
return 0;
}
if (ospf_lsa_is_self_originated(area->ospf, lsa)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "process_transit_summaries(): This LSA is mine, skip");
+ zlog_debug("%s: This LSA is mine, skip", __func__);
return 0;
}
@@ -586,20 +580,19 @@ void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,
struct ospf_area *area;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ia_routing():start");
+ zlog_debug("%s:start", __func__);
if (IS_OSPF_ABR(ospf)) {
switch (ospf->abr_type) {
case OSPF_ABR_STAND:
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ia_routing():Standard ABR");
+ zlog_debug("%s:Standard ABR", __func__);
if ((area = ospf->backbone)) {
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug(
- "ospf_ia_routing():backbone area found");
- zlog_debug(
- "ospf_ia_routing():examining summaries");
+ "%s:backbone area found, examining summaries",
+ __func__);
}
OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
@@ -611,23 +604,22 @@ void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,
OSPF_EXAMINE_TRANSIT_SUMMARIES_ALL(
area, rt, rtrs);
} else if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_routing():backbone area NOT found");
+ zlog_debug("%s:backbone area NOT found",
+ __func__);
break;
case OSPF_ABR_IBM:
case OSPF_ABR_CISCO:
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_routing():Alternative Cisco/IBM ABR");
+ zlog_debug("%s:Alternative Cisco/IBM ABR",
+ __func__);
area = ospf->backbone; /* Find the BB */
/* If we have an active BB connection */
if (area && ospf_act_bb_connection(ospf)) {
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug(
- "ospf_ia_routing(): backbone area found");
- zlog_debug(
- "ospf_ia_routing(): examining BB summaries");
+ "%s: backbone area found, examining BB summaries",
+ __func__);
}
OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
@@ -642,7 +634,8 @@ void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,
*/
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_ia_routing(): Active BB connection not found");
+ "%s: Active BB connection not found",
+ __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node,
area))
OSPF_EXAMINE_SUMMARIES_ALL(area, rt,
@@ -651,17 +644,15 @@ void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,
break;
case OSPF_ABR_SHORTCUT:
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_routing():Alternative Shortcut");
+ zlog_debug("%s:Alternative Shortcut", __func__);
area = ospf->backbone; /* Find the BB */
/* If we have an active BB connection */
if (area && ospf_act_bb_connection(ospf)) {
if (IS_DEBUG_OSPF_EVENT) {
zlog_debug(
- "ospf_ia_routing(): backbone area found");
- zlog_debug(
- "ospf_ia_routing(): examining BB summaries");
+ "%s: backbone area found, examining BB summaries",
+ __func__);
}
OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
}
@@ -683,8 +674,8 @@ void ospf_ia_routing(struct ospf *ospf, struct route_table *rt,
}
} else {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_ia_routing():not ABR, considering all areas");
+ zlog_debug("%s:not ABR, considering all areas",
+ __func__);
for (ALL_LIST_ELEMENTS_RO(ospf->areas, node, area))
OSPF_EXAMINE_SUMMARIES_ALL(area, rt, rtrs);
diff --git a/ospfd/ospf_interface.c b/ospfd/ospf_interface.c
index 633ab05131..646d318362 100644
--- a/ospfd/ospf_interface.c
+++ b/ospfd/ospf_interface.c
@@ -66,15 +66,16 @@ int ospf_interface_neighbor_count(struct ospf_interface *oi)
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
- if (nbr) {
- /* Do not show myself. */
- if (nbr == oi->nbr_self)
- continue;
- /* Down state is not shown. */
- if (nbr->state == NSM_Down)
- continue;
- count++;
- }
+ if (!nbr)
+ continue;
+
+ /* Do not show myself. */
+ if (nbr == oi->nbr_self)
+ continue;
+ /* Down state is not shown. */
+ if (nbr->state == NSM_Down)
+ continue;
+ count++;
}
return count;
@@ -315,10 +316,11 @@ void ospf_if_cleanup(struct ospf_interface *oi)
}
/* send Neighbor event KillNbr to all associated neighbors. */
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
if ((nbr = rn->info) != NULL)
if (nbr != oi->nbr_self)
OSPF_NSM_EVENT_EXECUTE(nbr, NSM_KillNbr);
+ }
/* Cleanup Link State Acknowlegdment list. */
for (ALL_LIST_ELEMENTS(oi->ls_ack, node, nnode, lsa))
@@ -492,6 +494,20 @@ struct ospf_interface *ospf_if_lookup_recv_if(struct ospf *ospf,
return match;
}
+void ospf_interface_fifo_flush(struct ospf_interface *oi)
+{
+ struct ospf *ospf = oi->ospf;
+
+ ospf_fifo_flush(oi->obuf);
+
+ if (oi->on_write_q) {
+ listnode_delete(ospf->oi_write_q, oi);
+ if (list_isempty(ospf->oi_write_q))
+ THREAD_OFF(ospf->t_write);
+ oi->on_write_q = 0;
+ }
+}
+
static void ospf_if_reset_stats(struct ospf_interface *oi)
{
oi->hello_in = oi->hello_out = 0;
@@ -503,19 +519,10 @@ static void ospf_if_reset_stats(struct ospf_interface *oi)
void ospf_if_stream_unset(struct ospf_interface *oi)
{
- struct ospf *ospf = oi->ospf;
-
/* flush the interface packet queue */
- ospf_fifo_flush(oi->obuf);
+ ospf_interface_fifo_flush(oi);
/*reset protocol stats */
ospf_if_reset_stats(oi);
-
- if (oi->on_write_q) {
- listnode_delete(ospf->oi_write_q, oi);
- if (list_isempty(ospf->oi_write_q))
- THREAD_OFF(ospf->t_write);
- oi->on_write_q = 0;
- }
}
@@ -902,18 +909,19 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf,
struct prefix_ipv4 *p;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_vl_new()(%s): Start", ospf_get_name(ospf));
+ zlog_debug("%s: (%s): Start", __func__, ospf_get_name(ospf));
if (vlink_count == OSPF_VL_MAX_COUNT) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_vl_new(): Alarm: cannot create more than OSPF_MAX_VL_COUNT virtual links");
+ "%s: Alarm: cannot create more than OSPF_MAX_VL_COUNT virtual links",
+ __func__);
+
return NULL;
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_vl_new(): creating pseudo zebra interface vrf id %u",
- ospf->vrf_id);
+ zlog_debug("%s: creating pseudo zebra interface vrf id %u",
+ __func__, ospf->vrf_id);
snprintf(ifname, sizeof(ifname), "VLINK%u", vlink_count);
vi = if_get_by_name(ifname, ospf->vrf_id, ospf->name);
@@ -937,7 +945,9 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf,
if (voi == NULL) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_vl_new(): Alarm: OSPF int structure is not created");
+ "%s: Alarm: OSPF int structure is not created",
+ __func__);
+
return NULL;
}
voi->connected = co;
@@ -947,17 +957,15 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf,
vlink_count++;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_vl_new(): Created name: %s", ifname);
- if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_vl_new(): set if->name to %s", vi->name);
+ zlog_debug("%s: Created name: %s set if->name to %s", __func__,
+ ifname, vi->name);
area_id.s_addr = INADDR_ANY;
area = ospf_area_get(ospf, area_id);
voi->area = area;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_vl_new(): set associated area to the backbone");
+ zlog_debug("%s: set associated area to the backbone", __func__);
/* Add pseudo neighbor. */
ospf_nbr_self_reset(voi, voi->ospf->router_id);
@@ -965,7 +973,7 @@ struct ospf_interface *ospf_vl_new(struct ospf *ospf,
ospf_area_add_if(voi->area, voi);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_vl_new(): Stop");
+ zlog_debug("%s: Stop", __func__);
return voi;
}
@@ -1160,10 +1168,8 @@ void ospf_vl_up_check(struct ospf_area *area, struct in_addr rid,
struct ospf_interface *oi;
if (IS_DEBUG_OSPF_EVENT) {
- zlog_debug("ospf_vl_up_check(): Start");
- zlog_debug("ospf_vl_up_check(): Router ID is %pI4",
- &rid);
- zlog_debug("ospf_vl_up_check(): Area is %pI4",
+ zlog_debug("%s: Start", __func__);
+ zlog_debug("%s: Router ID is %pI4 Area is %pI4", __func__, &rid,
&area->area_id);
}
@@ -1182,13 +1188,13 @@ void ospf_vl_up_check(struct ospf_area *area, struct in_addr rid,
SET_FLAG(vl_data->flags, OSPF_VL_FLAG_APPROVED);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_vl_up_check(): this VL matched");
+ zlog_debug("%s: this VL matched", __func__);
if (oi->state == ISM_Down) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_vl_up_check(): VL is down, waking it up");
+ "%s: VL is down, waking it up",
+ __func__);
SET_FLAG(oi->ifp->flags, IFF_UP);
OSPF_ISM_EVENT_EXECUTE(oi, ISM_InterfaceUp);
}
@@ -1196,13 +1202,15 @@ void ospf_vl_up_check(struct ospf_area *area, struct in_addr rid,
if (ospf_vl_set_params(area, vl_data, v)) {
if (IS_DEBUG_OSPF(ism, ISM_EVENTS))
zlog_debug(
- "ospf_vl_up_check: VL cost change, scheduling router lsa refresh");
+ "%s: VL cost change, scheduling router lsa refresh",
+ __func__);
if (ospf->backbone)
ospf_router_lsa_update_area(
ospf->backbone);
else if (IS_DEBUG_OSPF(ism, ISM_EVENTS))
zlog_debug(
- "ospf_vl_up_check: VL cost change, no backbone!");
+ "%s: VL cost change, no backbone!",
+ __func__);
}
}
}
diff --git a/ospfd/ospf_interface.h b/ospfd/ospf_interface.h
index e441016406..51fc1bf3c3 100644
--- a/ospfd/ospf_interface.h
+++ b/ospfd/ospf_interface.h
@@ -351,6 +351,8 @@ extern void ospf_if_interface(struct interface *ifp);
extern uint32_t ospf_if_count_area_params(struct interface *ifp);
extern void ospf_reset_hello_timer(struct interface *ifp, struct in_addr addr,
bool is_addr);
+
+extern void ospf_interface_fifo_flush(struct ospf_interface *oi);
DECLARE_HOOK(ospf_vl_add, (struct ospf_vl_data * vd), (vd));
DECLARE_HOOK(ospf_vl_delete, (struct ospf_vl_data * vd), (vd));
diff --git a/ospfd/ospf_ldp_sync.c b/ospfd/ospf_ldp_sync.c
index 330a433627..77e96f1733 100644
--- a/ospfd/ospf_ldp_sync.c
+++ b/ospfd/ospf_ldp_sync.c
@@ -62,9 +62,8 @@ int ospf_ldp_sync_state_update(struct ldp_igp_sync_if_state state)
if (ifp == NULL || if_is_loopback(ifp))
return 0;
- ols_debug("ldp_sync: rcvd %s from LDP if %s",
- state.sync_start ? "sync-start" : "sync-complete",
- ifp->name);
+ ols_debug("%s: rcvd %s from LDP if %s", __func__,
+ state.sync_start ? "sync-start" : "sync-complete", ifp->name);
if (state.sync_start)
ospf_ldp_sync_if_start(ifp, false);
else
@@ -88,7 +87,7 @@ int ospf_ldp_sync_announce_update(struct ldp_igp_sync_announce announce)
if (announce.proto != ZEBRA_ROUTE_LDP)
return 0;
- ols_debug("ldp_sync: rcvd announce from LDP");
+ ols_debug("%s: rcvd announce from LDP", __func__);
/* LDP just started up:
* set cost to LSInfinity
@@ -105,7 +104,7 @@ void ospf_ldp_sync_state_req_msg(struct interface *ifp)
{
struct ldp_igp_sync_if_state_req request;
- ols_debug("ldp_sync: send state request to LDP for %s", ifp->name);
+ ols_debug("%s: send state request to LDP for %s", __func__, ifp->name);
memset(&request, 0, sizeof(request));
strlcpy(request.name, ifp->name, sizeof(ifp->name));
@@ -134,7 +133,7 @@ void ospf_ldp_sync_if_init(struct ospf_interface *oi)
LDP_SYNC_FLAG_ENABLE)))
return;
- ols_debug("ldp_sync: init if %s",ifp->name);
+ ols_debug("%s: init if %s", __func__, ifp->name);
params = IF_DEF_PARAMS(ifp);
if (params->ldp_sync_info == NULL)
params->ldp_sync_info = ldp_sync_info_create();
@@ -174,8 +173,8 @@ void ospf_ldp_sync_if_start(struct interface *ifp, bool send_state_req)
if (ldp_sync_info &&
ldp_sync_info->enabled == LDP_IGP_SYNC_ENABLED &&
ldp_sync_info->state != LDP_IGP_SYNC_STATE_NOT_REQUIRED) {
- ols_debug("ldp_sync: start on if %s state: %s",
- ifp->name, "Holding down until Sync");
+ ols_debug("%s: start on if %s state: %s", __func__, ifp->name,
+ "Holding down until Sync");
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_NOT_UP;
ospf_if_recalculate_output_cost(ifp);
ospf_ldp_sync_holddown_timer_add(ifp);
@@ -229,7 +228,7 @@ void ospf_ldp_sync_handle_client_close(struct zapi_client_close_info *info)
* set cost to LSInfinity
* send request to LDP for LDP-SYNC state for each interface
*/
- zlog_err("ldp_sync: LDP down");
+ zlog_err("%s: LDP down", __func__);
vrf = vrf_lookup_by_id(ospf->vrf_id);
FOR_ALL_INTERFACES (vrf, ifp)
@@ -275,7 +274,7 @@ void ospf_ldp_sync_if_down(struct interface *ifp)
if (ldp_sync_if_down(ldp_sync_info) == false)
return;
- ols_debug("ldp_sync: down on if %s", ifp->name);
+ ols_debug("%s: down on if %s", __func__, ifp->name);
/* Interface down:
* can occur from a link down or changing config
@@ -317,7 +316,7 @@ void ospf_ldp_sync_if_remove(struct interface *ifp, bool remove)
* delete ldp instance on interface
* restore cost
*/
- ols_debug("ldp_sync: Removed from if %s", ifp->name);
+ ols_debug("%s: Removed from if %s", __func__, ifp->name);
THREAD_OFF(ldp_sync_info->t_holddown);
@@ -370,8 +369,8 @@ static void ospf_ldp_sync_holddown_timer(struct thread *thread)
ldp_sync_info->state = LDP_IGP_SYNC_STATE_REQUIRED_UP;
- ols_debug("ldp_sync: holddown timer expired for %s state: %s",
- ifp->name, "Sync achieved");
+ ols_debug("%s: holddown timer expired for %s state: %s",
+ __func__, ifp->name, "Sync achieved");
ospf_if_recalculate_output_cost(ifp);
}
@@ -394,7 +393,7 @@ void ospf_ldp_sync_holddown_timer_add(struct interface *ifp)
ldp_sync_info->holddown == LDP_IGP_SYNC_HOLDDOWN_DEFAULT)
return;
- ols_debug("ldp_sync: start holddown timer for %s time %d",
+ ols_debug("%s: start holddown timer for %s time %d", __func__,
ifp->name, ldp_sync_info->holddown);
thread_add_timer(master, ospf_ldp_sync_holddown_timer,
@@ -459,7 +458,7 @@ void ospf_if_set_ldp_sync_enable(struct ospf *ospf, struct interface *ifp)
ldp_sync_info->enabled = LDP_IGP_SYNC_ENABLED;
- ols_debug("ldp_sync: enable if %s", ifp->name);
+ ols_debug("%s: enable if %s", __func__, ifp->name);
/* send message to LDP if ptop link */
if (params->type == OSPF_IFTYPE_POINTOPOINT ||
@@ -468,7 +467,7 @@ void ospf_if_set_ldp_sync_enable(struct ospf *ospf, struct interface *ifp)
ospf_ldp_sync_state_req_msg(ifp);
} else {
ldp_sync_info->state = LDP_IGP_SYNC_STATE_NOT_REQUIRED;
- zlog_debug("ldp_sync: Sync only runs on P2P links %s",
+ zlog_debug("%s: Sync only runs on P2P links %s", __func__,
ifp->name);
}
}
diff --git a/ospfd/ospf_lsa.c b/ospfd/ospf_lsa.c
index af05f5b59e..0df0072f6d 100644
--- a/ospfd/ospf_lsa.c
+++ b/ospfd/ospf_lsa.c
@@ -1978,9 +1978,8 @@ static struct ospf_lsa *ospf_lsa_translated_nssa_new(struct ospf *ospf,
if (type7->area->suppress_fa) {
extnew->e[0].fwd_addr.s_addr = 0;
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_lsa_translated_nssa_new(): Suppress forwarding address for %pI4",
- &ei.p.prefix);
+ zlog_debug("%s: Suppress forwarding address for %pI4",
+ __func__, &ei.p.prefix);
} else
extnew->e[0].fwd_addr.s_addr = ext->e[0].fwd_addr.s_addr;
new->data->ls_seqnum = type7->data->ls_seqnum;
@@ -2103,9 +2102,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
/* do we have type7? */
if (!type7) {
if (IS_DEBUG_OSPF_NSSA)
- zlog_debug(
- "ospf_translated_nssa_refresh(): no Type-7 found for Type-5 LSA Id %pI4",
- &type5->data->id);
+ zlog_debug("%s: no Type-7 found for Type-5 LSA Id %pI4",
+ __func__, &type5->data->id);
return NULL;
}
@@ -2113,8 +2111,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
if (type5 == NULL || !CHECK_FLAG(type5->flags, OSPF_LSA_LOCAL_XLT)) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_translated_nssa_refresh(): No translated Type-5 found for Type-7 with Id %pI4",
- &type7->data->id);
+ "%s: No translated Type-5 found for Type-7 with Id %pI4",
+ __func__, &type7->data->id);
return NULL;
}
@@ -2131,8 +2129,8 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
if ((new = ospf_lsa_translated_nssa_new(ospf, type7)) == NULL) {
if (IS_DEBUG_OSPF_NSSA)
zlog_debug(
- "ospf_translated_nssa_refresh(): Could not translate Type-7 for %pI4 to Type-5",
- &type7->data->id);
+ "%s: Could not translate Type-7 for %pI4 to Type-5",
+ __func__, &type7->data->id);
return NULL;
}
@@ -2142,10 +2140,9 @@ struct ospf_lsa *ospf_translated_nssa_refresh(struct ospf *ospf,
}
if (!(new = ospf_lsa_install(ospf, NULL, new))) {
- flog_warn(
- EC_OSPF_LSA_INSTALL_FAILURE,
- "ospf_translated_nssa_refresh(): Could not install translated LSA, Id %pI4",
- &type7->data->id);
+ flog_warn(EC_OSPF_LSA_INSTALL_FAILURE,
+ "%s: Could not install translated LSA, Id %pI4",
+ __func__, &type7->data->id);
return NULL;
}
@@ -2434,7 +2431,7 @@ void ospf_external_lsa_flush(struct ospf *ospf, uint8_t type,
}
if (IS_DEBUG_OSPF(lsa, LSA_FLOODING))
- zlog_debug("ospf_external_lsa_flush(): stop");
+ zlog_debug("%s: stop", __func__);
}
void ospf_external_lsa_refresh_default(struct ospf *ospf)
@@ -2868,10 +2865,11 @@ struct ospf_lsa *ospf_lsa_install(struct ospf *ospf, struct ospf_interface *oi,
* So, router should be aborted from HELPER role
* if it is detected as TOPO change.
*/
- if (ospf->active_restarter_cnt
- && CHECK_LSA_TYPE_1_TO_5_OR_7(lsa->data->type)
- && ospf_lsa_different(old, lsa, true))
- ospf_helper_handle_topo_chg(ospf, lsa);
+ if (ospf->active_restarter_cnt &&
+ CHECK_LSA_TYPE_1_TO_5_OR_7(lsa->data->type)) {
+ if (old == NULL || ospf_lsa_different(old, lsa, true))
+ ospf_helper_handle_topo_chg(ospf, lsa);
+ }
rt_recalc = 1;
}
@@ -3023,7 +3021,7 @@ int ospf_check_nbr_status(struct ospf *ospf)
}
-static void ospf_maxage_lsa_remover(struct thread *thread)
+void ospf_maxage_lsa_remover(struct thread *thread)
{
struct ospf *ospf = THREAD_ARG(thread);
struct ospf_lsa *lsa, *old;
@@ -3901,8 +3899,9 @@ void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
if (lsa->refresh_list < 0) {
int delay;
int min_delay =
- OSPF_LS_REFRESH_TIME - (2 * OSPF_LS_REFRESH_JITTER);
- int max_delay = OSPF_LS_REFRESH_TIME - OSPF_LS_REFRESH_JITTER;
+ ospf->lsa_refresh_timer - (2 * OSPF_LS_REFRESH_JITTER);
+ int max_delay =
+ ospf->lsa_refresh_timer - OSPF_LS_REFRESH_JITTER;
/* We want to refresh the LSA within OSPF_LS_REFRESH_TIME which
* is
@@ -3935,9 +3934,9 @@ void ospf_refresher_register_lsa(struct ospf *ospf, struct ospf_lsa *lsa)
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
zlog_debug(
- "LSA[Refresh:Type%d:%pI4]: ospf_refresher_register_lsa(): setting refresh_list on lsa %p (slot %d)",
- lsa->data->type, &lsa->data->id, (void *)lsa,
- index);
+ "LSA[Refresh:Type%d:%pI4]: %s: setting refresh_list on lsa %p (slot %d)",
+ lsa->data->type, &lsa->data->id, __func__,
+ (void *)lsa, index);
}
}
@@ -3968,7 +3967,7 @@ void ospf_lsa_refresh_walker(struct thread *t)
struct list *lsa_to_refresh = list_new();
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
- zlog_debug("LSA[Refresh]: ospf_lsa_refresh_walker(): start");
+ zlog_debug("LSA[Refresh]: %s: start", __func__);
i = ospf->lsa_refresh_queue.index;
@@ -3985,16 +3984,14 @@ void ospf_lsa_refresh_walker(struct thread *t)
% OSPF_LSA_REFRESHER_SLOTS;
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
- zlog_debug(
- "LSA[Refresh]: ospf_lsa_refresh_walker(): next index %d",
- ospf->lsa_refresh_queue.index);
+ zlog_debug("LSA[Refresh]: %s: next index %d", __func__,
+ ospf->lsa_refresh_queue.index);
for (; i != ospf->lsa_refresh_queue.index;
i = (i + 1) % OSPF_LSA_REFRESHER_SLOTS) {
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
- zlog_debug(
- "LSA[Refresh]: ospf_lsa_refresh_walker(): refresh index %d",
- i);
+ zlog_debug("LSA[Refresh]: %s: refresh index %d",
+ __func__, i);
refresh_list = ospf->lsa_refresh_queue.qs[i];
@@ -4007,10 +4004,9 @@ void ospf_lsa_refresh_walker(struct thread *t)
lsa)) {
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
zlog_debug(
- "LSA[Refresh:Type%d:%pI4]: ospf_lsa_refresh_walker(): refresh lsa %p (slot %d)",
- lsa->data->type,
- &lsa->data->id,
- (void *)lsa, i);
+ "LSA[Refresh:Type%d:%pI4]: %s: refresh lsa %p (slot %d)",
+ lsa->data->type, &lsa->data->id,
+ __func__, (void *)lsa, i);
assert(lsa->lock > 0);
list_delete_node(refresh_list, node);
@@ -4036,7 +4032,7 @@ void ospf_lsa_refresh_walker(struct thread *t)
list_delete(&lsa_to_refresh);
if (IS_DEBUG_OSPF(lsa, LSA_REFRESH))
- zlog_debug("LSA[Refresh]: ospf_lsa_refresh_walker(): end");
+ zlog_debug("LSA[Refresh]: %s: end", __func__);
}
/* Flush the LSAs for the specific area */
diff --git a/ospfd/ospf_lsa.h b/ospfd/ospf_lsa.h
index 4b3be15382..97c15d1e3c 100644
--- a/ospfd/ospf_lsa.h
+++ b/ospfd/ospf_lsa.h
@@ -354,4 +354,5 @@ extern void ospf_check_and_gen_init_seq_lsa(struct ospf_interface *oi,
struct ospf_lsa *lsa);
extern void ospf_flush_lsa_from_area(struct ospf *ospf, struct in_addr area_id,
int type);
+extern void ospf_maxage_lsa_remover(struct thread *thread);
#endif /* _ZEBRA_OSPF_LSA_H */
diff --git a/ospfd/ospf_nsm.c b/ospfd/ospf_nsm.c
index 333389596b..a27550853b 100644
--- a/ospfd/ospf_nsm.c
+++ b/ospfd/ospf_nsm.c
@@ -382,6 +382,10 @@ static void nsm_clear_adj(struct ospf_neighbor *nbr)
static int nsm_kill_nbr(struct ospf_neighbor *nbr)
{
+ struct ospf_interface *oi = nbr->oi;
+ struct ospf_neighbor *on;
+ struct route_node *rn;
+
/* killing nbr_self is invalid */
if (nbr == nbr->oi->nbr_self) {
assert(nbr != nbr->oi->nbr_self);
@@ -407,6 +411,35 @@ static int nsm_kill_nbr(struct ospf_neighbor *nbr)
ospf_get_name(nbr->oi->ospf));
}
+ /*
+ * Do we have any neighbors that are also operating
+ * on this interface?
+ */
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ on = rn->info;
+
+ if (!on)
+ continue;
+
+ if (on == nbr || on == oi->nbr_self)
+ continue;
+
+ /*
+ * on is in some state where we might be
+ * sending packets on this interface
+ */
+ if (on->state > NSM_Down) {
+ route_unlock_node(rn);
+ return 0;
+ }
+ }
+ /*
+ * If we get here we know that this interface
+ * has no neighbors in a state where we could
+ * be sending packets. Let's flush anything
+ * we got.
+ */
+ ospf_interface_fifo_flush(oi);
return 0;
}
diff --git a/ospfd/ospf_opaque.c b/ospfd/ospf_opaque.c
index c7ac81d961..261d69df33 100644
--- a/ospfd/ospf_opaque.c
+++ b/ospfd/ospf_opaque.c
@@ -358,9 +358,8 @@ static struct list *ospf_get_opaque_funclist(uint8_t lsa_type)
funclist = ospf_opaque_type11_funclist;
break;
default:
- flog_warn(EC_OSPF_LSA_UNEXPECTED,
- "ospf_get_opaque_funclist: Unexpected LSA-type(%u)",
- lsa_type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, lsa_type);
break;
}
return funclist;
@@ -396,8 +395,8 @@ int ospf_register_opaque_functab(
if (functab->opaque_type == opaque_type) {
flog_warn(
EC_OSPF_LSA,
- "ospf_register_opaque_functab: Duplicated entry?: lsa_type(%u), opaque_type(%u)",
- lsa_type, opaque_type);
+ "%s: Duplicated entry?: lsa_type(%u), opaque_type(%u)",
+ __func__, lsa_type, opaque_type);
return -1;
}
@@ -565,10 +564,8 @@ register_opaque_info_per_type(struct ospf_opaque_functab *functab,
listnode_add(top->opaque_lsa_self, oipt);
break;
default:
- flog_warn(
- EC_OSPF_LSA_UNEXPECTED,
- "register_opaque_info_per_type: Unexpected LSA-type(%u)",
- new->data->type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, new->data->type);
free_opaque_info_per_type(oipt, true);
oipt = NULL;
goto out; /* This case may not exist. */
@@ -675,9 +672,8 @@ lookup_opaque_info_by_type(struct ospf_lsa *lsa)
listtop = top->opaque_lsa_self;
break;
default:
- flog_warn(EC_OSPF_LSA_UNEXPECTED,
- "lookup_opaque_info_by_type: Unexpected LSA-type(%u)",
- lsa->data->type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, lsa->data->type);
break;
}
@@ -1303,16 +1299,14 @@ void ospf_opaque_lsa_originate_schedule(struct ospf_interface *oi, int *delay0)
if ((top = oi_to_top(oi)) == NULL || (area = oi->area) == NULL) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_opaque_lsa_originate_schedule: Invalid argument?");
+ zlog_debug("%s: Invalid argument?", __func__);
return;
}
/* It may not a right time to schedule origination now. */
if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_opaque_lsa_originate_schedule: Not operational.");
+ zlog_debug("%s: Not operational.", __func__);
return; /* This is not an error. */
}
@@ -1529,10 +1523,8 @@ static void ospf_opaque_lsa_reoriginate_resume(struct list *listtop, void *arg)
continue;
if ((*functab->lsa_originator)(arg) != 0) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_resume: Failed (opaque-type=%u)",
- oipt->opaque_type);
+ flog_warn(EC_OSPF_LSA, "%s: Failed (opaque-type=%u)",
+ __func__, oipt->opaque_type);
continue;
}
}
@@ -1570,8 +1562,7 @@ struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
}
/* Register the new lsa entry */
else if (register_opaque_lsa(lsa) == NULL) {
- flog_warn(EC_OSPF_LSA,
- "ospf_opaque_lsa_install: register_opaque_lsa() ?");
+ flog_warn(EC_OSPF_LSA, "%s: register_opaque_lsa() ?", __func__);
goto out;
}
@@ -1583,16 +1574,16 @@ struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
case OSPF_OPAQUE_LINK_LSA:
if ((top = oi_to_top(lsa->oi)) == NULL) {
/* Above conditions must have passed. */
- flog_warn(EC_OSPF_LSA,
- "ospf_opaque_lsa_install: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?",
+ __func__);
goto out;
}
break;
case OSPF_OPAQUE_AREA_LSA:
if (lsa->area == NULL || (top = lsa->area->ospf) == NULL) {
/* Above conditions must have passed. */
- flog_warn(EC_OSPF_LSA,
- "ospf_opaque_lsa_install: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?",
+ __func__);
goto out;
}
break;
@@ -1600,15 +1591,14 @@ struct ospf_lsa *ospf_opaque_lsa_install(struct ospf_lsa *lsa, int rt_recalc)
top = ospf_lookup_by_vrf_id(lsa->vrf_id);
if (lsa->area != NULL && (top = lsa->area->ospf) == NULL) {
/* Above conditions must have passed. */
- flog_warn(EC_OSPF_LSA,
- "ospf_opaque_lsa_install: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?",
+ __func__);
goto out;
}
break;
default:
- flog_warn(EC_OSPF_LSA_UNEXPECTED,
- "ospf_opaque_lsa_install: Unexpected LSA-type(%u)",
- lsa->data->type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, lsa->data->type);
goto out;
}
@@ -1679,16 +1669,14 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
case OSPF_OPAQUE_LINK_LSA:
if ((oi = (struct ospf_interface *)lsa_type_dependent)
== NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_schedule: Type-9 Opaque-LSA: Invalid parameter?");
+ flog_warn(EC_OSPF_LSA,
+ "%s: Type-9 Opaque-LSA: Invalid parameter?",
+ __func__);
goto out;
}
if ((top = oi_to_top(oi)) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_schedule: OI(%s) -> TOP?",
- IF_NAME(oi));
+ flog_warn(EC_OSPF_LSA, "%s: OI(%s) -> TOP?", __func__,
+ IF_NAME(oi));
goto out;
}
if (!list_isempty(ospf_opaque_type9_funclist)
@@ -1704,16 +1692,14 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
break;
case OSPF_OPAQUE_AREA_LSA:
if ((area = (struct ospf_area *)lsa_type_dependent) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_schedule: Type-10 Opaque-LSA: Invalid parameter?");
+ flog_warn(EC_OSPF_LSA,
+ "%s: Type-10 Opaque-LSA: Invalid parameter?",
+ __func__);
goto out;
}
if ((top = area->ospf) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_schedule: AREA(%pI4) -> TOP?",
- &area->area_id);
+ flog_warn(EC_OSPF_LSA, "%s: AREA(%pI4) -> TOP?",
+ __func__, &area->area_id);
goto out;
}
if (!list_isempty(ospf_opaque_type10_funclist)
@@ -1729,9 +1715,9 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
break;
case OSPF_OPAQUE_AS_LSA:
if ((top = (struct ospf *)lsa_type_dependent) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_schedule: Type-11 Opaque-LSA: Invalid parameter?");
+ flog_warn(EC_OSPF_LSA,
+ "%s: Type-11 Opaque-LSA: Invalid parameter?",
+ __func__);
goto out;
}
if (!list_isempty(ospf_opaque_type11_funclist)
@@ -1751,18 +1737,15 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
func = ospf_opaque_type11_lsa_reoriginate_timer;
break;
default:
- flog_warn(
- EC_OSPF_LSA_UNEXPECTED,
- "ospf_opaque_lsa_reoriginate_schedule: Unexpected LSA-type(%u)",
- lsa_type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, lsa_type);
goto out;
}
/* It may not a right time to schedule reorigination now. */
if (!CHECK_FLAG(top->opaque, OPAQUE_OPERATION_READY_BIT)) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_opaque_lsa_reoriginate_schedule: Not operational.");
+ zlog_debug("%s: Not operational.", __func__);
goto out; /* This is not an error. */
}
@@ -1775,16 +1758,16 @@ void ospf_opaque_lsa_reoriginate_schedule(void *lsa_type_dependent,
if ((functab = ospf_opaque_functab_lookup(lsa)) == NULL) {
flog_warn(
EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_schedule: No associated function?: lsa_type(%u), opaque_type(%u)",
- lsa_type, opaque_type);
+ "%s: No associated function?: lsa_type(%u), opaque_type(%u)",
+ __func__, lsa_type, opaque_type);
goto out;
}
if ((oipt = register_opaque_info_per_type(functab, lsa))
== NULL) {
flog_warn(
EC_OSPF_LSA,
- "ospf_opaque_lsa_reoriginate_schedule: Cannot get a control info?: lsa_type(%u), opaque_type(%u)",
- lsa_type, opaque_type);
+ "%s: Cannot get a control info?: lsa_type(%u), opaque_type(%u)",
+ __func__, lsa_type, opaque_type);
goto out;
}
}
@@ -1850,17 +1833,13 @@ static void ospf_opaque_type9_lsa_reoriginate_timer(struct thread *t)
if ((functab = oipt->functab) == NULL
|| functab->lsa_originator == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_type9_lsa_reoriginate_timer: No associated function?");
+ flog_warn(EC_OSPF_LSA, "%s: No associated function?", __func__);
return;
}
oi = (struct ospf_interface *)oipt->owner;
if ((top = oi_to_top(oi)) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_type9_lsa_reoriginate_timer: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
return;
}
@@ -1898,17 +1877,13 @@ static void ospf_opaque_type10_lsa_reoriginate_timer(struct thread *t)
if ((functab = oipt->functab) == NULL
|| functab->lsa_originator == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_type10_lsa_reoriginate_timer: No associated function?");
+ flog_warn(EC_OSPF_LSA, "%s: No associated function?", __func__);
return;
}
area = (struct ospf_area *)oipt->owner;
if (area == NULL || (top = area->ospf) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_type10_lsa_reoriginate_timer: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
return;
}
@@ -1947,16 +1922,12 @@ static void ospf_opaque_type11_lsa_reoriginate_timer(struct thread *t)
if ((functab = oipt->functab) == NULL
|| functab->lsa_originator == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_type11_lsa_reoriginate_timer: No associated function?");
+ flog_warn(EC_OSPF_LSA, "%s: No associated function?", __func__);
return;
}
if ((top = (struct ospf *)oipt->owner) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_type11_lsa_reoriginate_timer: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
return;
}
@@ -1988,16 +1959,13 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
|| (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
- flog_warn(
- EC_OSPF_LSA,
- "ospf_opaque_lsa_refresh_schedule: Invalid parameter?");
+ flog_warn(EC_OSPF_LSA, "%s: Invalid parameter?", __func__);
goto out;
}
/* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
if ((lsa = oipi->lsa) == NULL) {
- flog_warn(EC_OSPF_LSA,
- "ospf_opaque_lsa_refresh_schedule: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
goto out;
}
@@ -2024,10 +1992,8 @@ void ospf_opaque_lsa_refresh_schedule(struct ospf_lsa *lsa0)
ospf_ls_retransmit_delete_nbr_as(top, lsa);
break;
default:
- flog_warn(
- EC_OSPF_LSA_UNEXPECTED,
- "ospf_opaque_lsa_refresh_schedule: Unexpected LSA-type(%u)",
- lsa->data->type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, lsa->data->type);
goto out;
}
@@ -2074,15 +2040,13 @@ void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0)
if ((oipt = lookup_opaque_info_by_type(lsa0)) == NULL
|| (oipi = lookup_opaque_info_by_id(oipt, lsa0)) == NULL) {
- flog_warn(EC_OSPF_LSA,
- "ospf_opaque_lsa_flush_schedule: Invalid parameter?");
+ flog_warn(EC_OSPF_LSA, "%s: Invalid parameter?", __func__);
goto out;
}
/* Given "lsa0" and current "oipi->lsa" may different, but harmless. */
if ((lsa = oipi->lsa) == NULL) {
- flog_warn(EC_OSPF_LSA,
- "ospf_opaque_lsa_flush_schedule: Something wrong?");
+ flog_warn(EC_OSPF_LSA, "%s: Something wrong?", __func__);
goto out;
}
@@ -2098,10 +2062,8 @@ void ospf_opaque_lsa_flush_schedule(struct ospf_lsa *lsa0)
ospf_ls_retransmit_delete_nbr_as(top, lsa);
break;
default:
- flog_warn(
- EC_OSPF_LSA_UNEXPECTED,
- "ospf_opaque_lsa_flush_schedule: Unexpected LSA-type(%u)",
- lsa->data->type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, lsa->data->type);
goto out;
}
@@ -2154,10 +2116,8 @@ void ospf_opaque_self_originated_lsa_received(struct ospf_neighbor *nbr,
ospf_flood_through_as(top, NULL /*inbr*/, lsa);
break;
default:
- flog_warn(
- EC_OSPF_LSA_UNEXPECTED,
- "ospf_opaque_self_originated_lsa_received: Unexpected LSA-type(%u)",
- lsa->data->type);
+ flog_warn(EC_OSPF_LSA_UNEXPECTED, "%s: Unexpected LSA-type(%u)",
+ __func__, lsa->data->type);
return;
}
ospf_lsa_discard(lsa); /* List "lsas" will be deleted by caller. */
diff --git a/ospfd/ospf_packet.c b/ospfd/ospf_packet.c
index 4b3f30a3f1..57643f637e 100644
--- a/ospfd/ospf_packet.c
+++ b/ospfd/ospf_packet.c
@@ -440,10 +440,10 @@ static int ospf_make_md5_digest(struct ospf_interface *oi,
if (stream_get_endp(op->s) != op->length)
/* XXX size_t */
- flog_warn(
- EC_OSPF_MD5,
- "ospf_make_md5_digest: length mismatch stream %lu ospf_packet %u",
- (unsigned long)stream_get_endp(op->s), op->length);
+ flog_warn(EC_OSPF_MD5,
+ "%s: length mismatch stream %lu ospf_packet %u",
+ __func__, (unsigned long)stream_get_endp(op->s),
+ op->length);
return OSPF_AUTH_MD5_SIZE;
}
@@ -596,15 +596,14 @@ static void ospf_write_frags(int fd, struct ospf_packet *op, struct ip *iph,
if (ret < 0)
flog_err(
EC_LIB_SOCKET,
- "*** ospf_write_frags: sendmsg failed to %pI4, id %d, off %d, len %d, mtu %u failed with %s",
- &iph->ip_dst, iph->ip_id, iph->ip_off,
+ "*** %s: sendmsg failed to %pI4, id %d, off %d, len %d, mtu %u failed with %s",
+ __func__, &iph->ip_dst, iph->ip_id, iph->ip_off,
iph->ip_len, mtu, safe_strerror(errno));
if (IS_DEBUG_OSPF_PACKET(type - 1, SEND)) {
- zlog_debug(
- "ospf_write_frags: sent id %d, off %d, len %d to %pI4",
- iph->ip_id, iph->ip_off, iph->ip_len,
- &iph->ip_dst);
+ zlog_debug("%s: sent id %d, off %d, len %d to %pI4",
+ __func__, iph->ip_id, iph->ip_off,
+ iph->ip_len, &iph->ip_dst);
}
iph->ip_off += offset;
@@ -623,7 +622,6 @@ static void ospf_write(struct thread *thread)
{
struct ospf *ospf = THREAD_ARG(thread);
struct ospf_interface *oi;
- struct ospf_interface *last_serviced_oi = NULL;
struct ospf_packet *op;
struct sockaddr_in sa_dst;
struct ip iph;
@@ -648,9 +646,8 @@ static void ospf_write(struct thread *thread)
if (ospf->fd < 0 || ospf->oi_running == 0) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_write failed to send, fd %d, instance %u",
- ospf->fd, ospf->oi_running);
+ zlog_debug("%s failed to send, fd %d, instance %u",
+ __func__, ospf->fd, ospf->oi_running);
return;
}
@@ -664,13 +661,7 @@ static void ospf_write(struct thread *thread)
ipid = (time(NULL) & 0xffff);
#endif /* WANT_OSPF_WRITE_FRAGMENT */
- while ((pkt_count < ospf->write_oi_count) && oi
- && (last_serviced_oi != oi)) {
- /* If there is only packet in the queue, the oi is removed from
- write-q, so fix up the last interface that was serviced */
- if (last_serviced_oi == NULL) {
- last_serviced_oi = oi;
- }
+ while ((pkt_count < ospf->write_oi_count) && oi) {
pkt_count++;
#ifdef WANT_OSPF_WRITE_FRAGMENT
/* convenience - max OSPF data per packet */
@@ -789,8 +780,8 @@ static void ospf_write(struct thread *thread)
sockopt_iphdrincl_swab_systoh(&iph);
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_write to %pI4, id %d, off %d, len %d, interface %s, mtu %u:",
- &iph.ip_dst, iph.ip_id, iph.ip_off,
+ "%s to %pI4, id %d, off %d, len %d, interface %s, mtu %u:",
+ __func__, &iph.ip_dst, iph.ip_id, iph.ip_off,
iph.ip_len, oi->ifp->name, oi->ifp->mtu);
/* sendmsg will return EPERM if firewall is blocking sending.
@@ -802,8 +793,8 @@ static void ospf_write(struct thread *thread)
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",
- &iph.ip_dst, iph.ip_id, iph.ip_off,
+ "*** sendmsg in %s failed to %pI4, id %d, off %d, len %d, interface %s, mtu %u: %s",
+ __func__, &iph.ip_dst, iph.ip_id, iph.ip_off,
iph.ip_len, oi->ifp->name, oi->ifp->mtu,
safe_strerror(errno));
@@ -853,11 +844,9 @@ static void ospf_write(struct thread *thread)
list_delete_node(ospf->oi_write_q, node);
if (ospf_fifo_head(oi->obuf) == NULL) {
oi->on_write_q = 0;
- last_serviced_oi = NULL;
oi = NULL;
- } else {
+ } else
listnode_add(ospf->oi_write_q, oi);
- }
/* Setup to service from the head of the queue again */
if (!list_isempty(ospf->oi_write_q)) {
@@ -2327,8 +2316,8 @@ static struct stream *ospf_recv_packet(struct ospf *ospf, int fd,
if ((unsigned int)ret < sizeof(struct ip)) {
flog_warn(
EC_OSPF_PACKET,
- "ospf_recv_packet: discarding runt packet of length %d (ip header size is %u)",
- ret, (unsigned int)sizeof(iph));
+ "%s: discarding runt packet of length %d (ip header size is %u)",
+ __func__, ret, (unsigned int)sizeof(iph));
return NULL;
}
@@ -2373,8 +2362,8 @@ static struct stream *ospf_recv_packet(struct ospf *ospf, int fd,
if (ret != ip_len) {
flog_warn(
EC_OSPF_PACKET,
- "ospf_recv_packet read length mismatch: ip_len is %d, but recvmsg returned %d",
- ip_len, ret);
+ "%s read length mismatch: ip_len is %d, but recvmsg returned %d",
+ __func__, ip_len, ret);
return NULL;
}
@@ -2596,8 +2585,8 @@ static int ospf_check_sum(struct ospf_header *ospfh)
ret = in_cksum(ospfh, ntohs(ospfh->length));
if (ret != sum) {
- zlog_info("ospf_check_sum(): checksum mismatch, my %X, his %X",
- ret, sum);
+ zlog_info("%s: checksum mismatch, my %X, his %X", __func__, ret,
+ sum);
return 0;
}
@@ -3337,7 +3326,7 @@ static int ospf_make_hello(struct ospf_interface *oi, struct stream *s)
stream_putw(s, 0); /* hello-interval of 0 for fast-hellos */
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("make_hello: options: %x, int: %s", OPTIONS(oi),
+ zlog_debug("%s: options: %x, int: %s", __func__, OPTIONS(oi),
IF_NAME(oi));
/* Set Options. */
@@ -3358,49 +3347,44 @@ static int ospf_make_hello(struct ospf_interface *oi, struct stream *s)
stream_put_ipv4(s, BDR(oi).s_addr);
/* Add neighbor seen. */
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info))
- if (nbr->router_id.s_addr
- != INADDR_ANY) /* Ignore 0.0.0.0 node. */
- if (nbr->state
- != NSM_Attempt) /* Ignore Down neighbor. */
- if (nbr->state
- != NSM_Down) /* This is myself for
- DR election. */
- if (!IPV4_ADDR_SAME(
- &nbr->router_id,
- &oi->ospf->router_id)) {
- /* Check neighbor is
- * sane? */
- if (nbr->d_router.s_addr
- != INADDR_ANY
- && IPV4_ADDR_SAME(
- &nbr->d_router,
- &oi->address
- ->u
- .prefix4)
- && IPV4_ADDR_SAME(
- &nbr->bd_router,
- &oi->address
- ->u
- .prefix4))
- flag = 1;
-
- /* Hello packet overflows interface MTU. */
- if (length + sizeof(uint32_t)
- > ospf_packet_max(oi)) {
- flog_err(
- EC_OSPF_LARGE_HELLO,
- "Oversized Hello packet! Larger than MTU. Not sending it out");
- return 0;
- }
-
- stream_put_ipv4(
- s,
- nbr->router_id
- .s_addr);
- length += 4;
- }
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+
+ if (!nbr)
+ continue;
+
+ /* Ignore the 0.0.0.0 node */
+ if (nbr->router_id.s_addr == INADDR_ANY)
+ continue;
+
+ /* Ignore Down neighbor */
+ if (nbr->state == NSM_Attempt)
+ continue;
+
+ /* This is myself for DR election */
+ if (nbr->state == NSM_Down)
+ continue;
+
+ if (IPV4_ADDR_SAME(&nbr->router_id, &oi->ospf->router_id))
+ continue;
+ /* Check neighbor is sane? */
+ if (nbr->d_router.s_addr != INADDR_ANY &&
+ IPV4_ADDR_SAME(&nbr->d_router, &oi->address->u.prefix4) &&
+ IPV4_ADDR_SAME(&nbr->bd_router, &oi->address->u.prefix4))
+ flag = 1;
+
+ /* Hello packet overflows interface MTU.
+ */
+ if (length + sizeof(uint32_t) > ospf_packet_max(oi)) {
+ flog_err(
+ EC_OSPF_LARGE_HELLO,
+ "Oversized Hello packet! Larger than MTU. Not sending it out");
+ return 0;
+ }
+
+ stream_put_ipv4(s, nbr->router_id.s_addr);
+ length += 4;
+ }
/* Let neighbor generate BackupSeen. */
if (flag == 1)
@@ -3581,7 +3565,7 @@ static int ospf_make_ls_upd(struct ospf_interface *oi, struct list *update,
int count = 0;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_make_ls_upd: Start");
+ zlog_debug("%s: Start", __func__);
pp = stream_get_endp(s);
stream_forward_endp(s, OSPF_LS_UPD_MIN_SIZE);
@@ -3631,7 +3615,7 @@ static int ospf_make_ls_upd(struct ospf_interface *oi, struct list *update,
stream_putl_at(s, pp, count);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_make_ls_upd: Stop");
+ zlog_debug("%s: Stop", __func__);
return length;
}
@@ -3781,54 +3765,44 @@ void ospf_hello_send(struct ospf_interface *oi)
struct ospf_neighbor *nbr;
struct route_node *rn;
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info))
- if (nbr != oi->nbr_self)
- if (nbr->state != NSM_Down) {
- /* RFC 2328 Section 9.5.1
- If the router is not
- eligible to become Designated
- Router,
- it must periodically send
- Hello Packets to both the
- Designated Router and the
- Backup Designated Router (if
- they
- exist). */
- if (PRIORITY(oi) == 0
- && IPV4_ADDR_CMP(
- &DR(oi),
- &nbr->address.u
- .prefix4)
- && IPV4_ADDR_CMP(
- &BDR(oi),
- &nbr->address.u
- .prefix4))
- continue;
-
- /* If the router is eligible to
- become Designated Router, it
- must periodically send Hello
- Packets to all neighbors that
- are also eligible. In
- addition, if the router is
- itself the
- Designated Router or Backup
- Designated Router, it must
- also
- send periodic Hello Packets
- to all other neighbors. */
-
- if (nbr->priority == 0
- && oi->state == ISM_DROther)
- continue;
- /* if oi->state == Waiting, send
- * hello to all neighbors */
- ospf_hello_send_sub(
- oi,
- nbr->address.u.prefix4
- .s_addr);
- }
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+ if (!nbr)
+ continue;
+
+ if (nbr == oi->nbr_self)
+ continue;
+
+ if (nbr->state == NSM_Down)
+ continue;
+
+ /*
+ * RFC 2328 Section 9.5.1
+ * If the router is not eligible to become Designated
+ * Router, it must periodically send Hello Packets to
+ * both the Designated Router and the Backup
+ * Designated Router (if they exist).
+ */
+ if (PRIORITY(oi) == 0 &&
+ IPV4_ADDR_CMP(&DR(oi), &nbr->address.u.prefix4) &&
+ IPV4_ADDR_CMP(&BDR(oi), &nbr->address.u.prefix4))
+ continue;
+
+ /*
+ * If the router is eligible to become Designated
+ * Router, it must periodically send Hello Packets to
+ * all neighbors that are also eligible. In addition,
+ * if the router is itself the Designated Router or
+ * Backup Designated Router, it must also send periodic
+ * Hello Packets to all other neighbors.
+ */
+ if (nbr->priority == 0 && oi->state == ISM_DROther)
+ continue;
+
+ /* if oi->state == Waiting, send
+ * hello to all neighbors */
+ ospf_hello_send_sub(oi, nbr->address.u.prefix4.s_addr);
+ }
} else {
/* Decide destination address. */
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
@@ -3989,14 +3963,15 @@ static struct ospf_packet *ospf_ls_upd_packet_new(struct list *update,
if (!warned) {
flog_warn(
EC_OSPF_LARGE_LSA,
- "ospf_ls_upd_packet_new: oversized LSA encountered!will need to fragment. Not optimal. Try divide up your network with areas. Use 'debug ospf packet send' to see details, or look at 'show ip ospf database ..'");
+ "%s: oversized LSA encountered!will need to fragment. Not optimal. Try divide up your network with areas. Use 'debug ospf packet send' to see details, or look at 'show ip ospf database ..'",
+ __func__);
warned = 1;
}
if (IS_DEBUG_OSPF_PACKET(0, SEND))
zlog_debug(
- "ospf_ls_upd_packet_new: oversized LSA id:%pI4, %d bytes originated by %pI4, will be fragmented!",
- &lsa->data->id,
+ "%s: oversized LSA id:%pI4, %d bytes originated by %pI4, will be fragmented!",
+ __func__, &lsa->data->id,
ntohs(lsa->data->length),
&lsa->data->adv_router);
@@ -4012,10 +3987,11 @@ static struct ospf_packet *ospf_ls_upd_packet_new(struct list *update,
size = oi->ifp->mtu;
if (size > OSPF_MAX_PACKET_SIZE) {
- flog_warn(EC_OSPF_LARGE_LSA,
- "ospf_ls_upd_packet_new: oversized LSA id:%pI4 too big, %d bytes, packet size %ld, dropping it completely. OSPF routing is broken!",
- &lsa->data->id, ntohs(lsa->data->length),
- (long int)size);
+ flog_warn(
+ EC_OSPF_LARGE_LSA,
+ "%s: oversized LSA id:%pI4 too big, %d bytes, packet size %ld, dropping it completely. OSPF routing is broken!",
+ __func__, &lsa->data->id, ntohs(lsa->data->length),
+ (long int)size);
list_delete_node(update, ln);
return NULL;
}
@@ -4121,7 +4097,7 @@ static void ospf_ls_upd_send_queue_event(struct thread *thread)
oi->t_ls_upd_event = NULL;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ls_upd_send_queue start");
+ zlog_debug("%s start", __func__);
for (rn = route_top(oi->ls_upd_queue); rn; rn = rnext) {
rnext = route_next(rn);
@@ -4144,15 +4120,15 @@ static void ospf_ls_upd_send_queue_event(struct thread *thread)
if (again != 0) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_ls_upd_send_queue: update lists not cleared, %d nodes to try again, raising new event",
- again);
+ "%s: update lists not cleared, %d nodes to try again, raising new event",
+ __func__, again);
oi->t_ls_upd_event = NULL;
thread_add_event(master, ospf_ls_upd_send_queue_event, oi, 0,
&oi->t_ls_upd_event);
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_ls_upd_send_queue stop");
+ zlog_debug("%s stop", __func__);
}
void ospf_ls_upd_send(struct ospf_neighbor *nbr, struct list *update, int flag,
@@ -4300,14 +4276,18 @@ void ospf_ls_ack_send_delayed(struct ospf_interface *oi)
struct ospf_neighbor *nbr;
struct route_node *rn;
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info) != NULL)
- if (nbr != oi->nbr_self
- && nbr->state >= NSM_Exchange)
- while (listcount(oi->ls_ack))
- ospf_ls_ack_send_list(
- oi, oi->ls_ack,
- nbr->address.u.prefix4);
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+
+ if (!nbr)
+ continue;
+
+ if (nbr != oi->nbr_self && nbr->state >= NSM_Exchange)
+ while (listcount(oi->ls_ack))
+ ospf_ls_ack_send_list(
+ oi, oi->ls_ack,
+ nbr->address.u.prefix4);
+ }
return;
}
if (oi->type == OSPF_IFTYPE_VIRTUALLINK)
diff --git a/ospfd/ospf_route.c b/ospfd/ospf_route.c
index c5b26bbd76..6360d8ec60 100644
--- a/ospfd/ospf_route.c
+++ b/ospfd/ospf_route.c
@@ -371,13 +371,12 @@ void ospf_intra_add_router(struct route_table *rt, struct vertex *v,
struct router_lsa *lsa;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_router: Start");
+ zlog_debug("%s: Start", __func__);
lsa = (struct router_lsa *)v->lsa;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_router: LS ID: %pI4",
- &lsa->header.id);
+ zlog_debug("%s: LS ID: %pI4", __func__, &lsa->header.id);
if (!OSPF_IS_AREA_BACKBONE(area))
ospf_vl_up_check(area, lsa->header.id, v);
@@ -392,7 +391,8 @@ void ospf_intra_add_router(struct route_table *rt, struct vertex *v,
!IS_ROUTER_LSA_EXTERNAL(lsa)) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_intra_add_router: this router is neither ASBR nor ABR, skipping it");
+ "%s: this router is neither ASBR nor ABR, skipping it",
+ __func__);
return;
}
@@ -434,7 +434,7 @@ void ospf_intra_add_router(struct route_table *rt, struct vertex *v,
apply_mask_ipv4(&p);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_router: talking about %pFX", &p);
+ zlog_debug("%s: talking about %pFX", __func__, &p);
rn = route_node_get(rt, (struct prefix *)&p);
@@ -449,7 +449,7 @@ void ospf_intra_add_router(struct route_table *rt, struct vertex *v,
listnode_add(rn->info, or);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_router: Stop");
+ zlog_debug("%s: Stop", __func__);
}
/* RFC2328 16.1. (4). For transit network. */
@@ -526,7 +526,7 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
struct ospf_path *path;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_stub(): Start");
+ zlog_debug("%s: Start", __func__);
lsa = (struct router_lsa *)v->lsa;
@@ -536,8 +536,7 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
apply_mask_ipv4(&p);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_stub(): processing route to %pFX",
- &p);
+ zlog_debug("%s: processing route to %pFX", __func__, &p);
/* (1) Calculate the distance D of stub network from the root. D is
equal to the distance from the root to the router vertex
@@ -546,9 +545,8 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
cost = v->distance + ntohs(link->m[0].metric);
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): calculated cost is %d + %d = %d",
- v->distance, ntohs(link->m[0].metric), cost);
+ zlog_debug("%s: calculated cost is %d + %d = %d", __func__,
+ v->distance, ntohs(link->m[0].metric), cost);
/* PtP links with /32 masks adds host routes to remote, directly
* connected hosts, see RFC 2328, 12.4.1.1, Option 1.
@@ -574,8 +572,8 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_intra_add_stub(): another route to the same prefix found with cost %u",
- cur_or->cost);
+ "%s: another route to the same prefix found with cost %u",
+ __func__, cur_or->cost);
/* Compare this distance to the current best cost to the stub
network. This is done by looking up the stub network's
@@ -584,8 +582,8 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
LSA. */
if (cost > cur_or->cost) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): old route is better, exit");
+ zlog_debug("%s: old route is better, exit",
+ __func__);
return;
}
@@ -604,8 +602,8 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
if (cost == cur_or->cost) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): routes are equal, merge");
+ zlog_debug("%s: routes are equal, merge",
+ __func__);
ospf_route_copy_nexthops_from_vertex(area, cur_or, v);
@@ -625,8 +623,8 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
if (cost < cur_or->cost) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): new route is better, set it");
+ zlog_debug("%s: new route is better, set it",
+ __func__);
cur_or->cost = cost;
@@ -640,7 +638,7 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_stub(): installing new route");
+ zlog_debug("%s: installing new route", __func__);
or = ospf_route_new();
@@ -655,13 +653,13 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
/* Nexthop is depend on connection type. */
if (v != area->spf) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): this network is on remote router");
+ zlog_debug("%s: this network is on remote router",
+ __func__);
ospf_route_copy_nexthops_from_vertex(area, or, v);
} else {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): this network is on this router");
+ zlog_debug("%s: this network is on this router",
+ __func__);
/*
* Only deal with interface data when we
@@ -672,9 +670,8 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
if (oi || area->spf_dry_run) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): the lsa pos is %d",
- lsa_pos);
+ zlog_debug("%s: the lsa pos is %d", __func__,
+ lsa_pos);
path = ospf_path_new();
path->nexthop.s_addr = INADDR_ANY;
@@ -689,15 +686,15 @@ void ospf_intra_add_stub(struct route_table *rt, struct router_lsa_link *link,
listnode_add(or->paths, path);
} else {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_intra_add_stub(): where's the interface ?");
+ zlog_debug("%s: where's the interface ?",
+ __func__);
}
}
rn->info = or ;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_intra_add_stub(): Stop");
+ zlog_debug("%s: Stop", __func__);
}
static const char *const ospf_path_type_str[] = {
@@ -931,7 +928,7 @@ void ospf_route_add(struct route_table *rt, struct prefix_ipv4 *p,
if (rn->info) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_route_add(): something's wrong !");
+ zlog_debug("%s: something's wrong !", __func__);
route_unlock_node(rn);
return;
}
@@ -1016,8 +1013,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
if (rn == NULL) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_add_discard_route(): router installation error");
+ zlog_debug("%s: router installation error", __func__);
return 0;
}
@@ -1029,15 +1025,16 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
if (or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_add_discard_route(): an intra-area route exists");
+ zlog_debug("%s: an intra-area route exists",
+ __func__);
return 0;
}
if (or->type == OSPF_DESTINATION_DISCARD) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_add_discard_route(): discard entry already installed");
+ "%s: discard entry already installed",
+ __func__);
return 0;
}
@@ -1045,7 +1042,7 @@ int ospf_add_discard_route(struct ospf *ospf, struct route_table *rt,
}
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_add_discard_route(): adding %pFX", p);
+ zlog_debug("%s: adding %pFX", __func__, p);
new_or = ospf_route_new();
new_or->type = OSPF_DESTINATION_DISCARD;
@@ -1068,14 +1065,13 @@ void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
struct ospf_route * or ;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_delete_discard_route(): deleting %pFX", p);
+ zlog_debug("%s: deleting %pFX", __func__, p);
rn = route_node_lookup(rt, (struct prefix *)p);
if (rn == NULL) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_delete_discard_route(): no route found");
+ zlog_debug("%s: no route found", __func__);
return;
}
@@ -1083,15 +1079,13 @@ void ospf_delete_discard_route(struct ospf *ospf, struct route_table *rt,
if (or->path_type == OSPF_PATH_INTRA_AREA) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_delete_discard_route(): an intra-area route exists");
+ zlog_debug("%s: an intra-area route exists", __func__);
return;
}
if (or->type != OSPF_DESTINATION_DISCARD) {
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_delete_discard_route(): not a discard entry");
+ zlog_debug("%s: not a discard entry", __func__);
return;
}
diff --git a/ospfd/ospf_spf.c b/ospfd/ospf_spf.c
index 74a5674273..4edc1de811 100644
--- a/ospfd/ospf_spf.c
+++ b/ospfd/ospf_spf.c
@@ -48,7 +48,10 @@
#include "ospfd/ospf_sr.h"
#include "ospfd/ospf_ti_lfa.h"
#include "ospfd/ospf_errors.h"
+
+#ifdef SUPPORT_OSPF_API
#include "ospfd/ospf_apiserver.h"
+#endif
/* Variables to ensure a SPF scheduled log message is printed only once */
@@ -799,7 +802,7 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
unsigned int added = 0;
if (IS_DEBUG_OSPF_EVENT) {
- zlog_debug("ospf_nexthop_calculation(): Start");
+ zlog_debug("%s: Start", __func__);
ospf_vertex_dump("V (parent):", v, 1, 1);
ospf_vertex_dump("W (dest) :", w, 1, 1);
zlog_debug("V->W distance: %d", distance);
@@ -1021,7 +1024,8 @@ static unsigned int ospf_nexthop_calculation(struct ospf_area *area,
return 1;
} else
zlog_info(
- "ospf_nexthop_calculation(): vl_data for VL link not found");
+ "%s: vl_data for VL link not found",
+ __func__);
} /* end virtual-link from V to W */
return 0;
} /* end W is a Router vertex */
@@ -1569,7 +1573,7 @@ static void ospf_spf_process_stubs(struct ospf_area *area, struct vertex *v,
struct vertex *child;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_process_stub():processing stubs for area %pI4",
+ zlog_debug("%s: processing stubs for area %pI4", __func__,
&area->area_id);
if (v->type == OSPF_VERTEX_ROUTER) {
@@ -1580,16 +1584,14 @@ static void ospf_spf_process_stubs(struct ospf_area *area, struct vertex *v,
int lsa_pos = 0;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_process_stubs():processing router LSA, id: %pI4",
- &v->lsa->id);
+ zlog_debug("%s: processing router LSA, id: %pI4",
+ __func__, &v->lsa->id);
router_lsa = (struct router_lsa *)v->lsa;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug(
- "ospf_process_stubs(): we have %d links to process",
- ntohs(router_lsa->links));
+ zlog_debug("%s: we have %d links to process", __func__,
+ ntohs(router_lsa->links));
p = ((uint8_t *)v->lsa) + OSPF_LSA_HEADER_SIZE + 4;
lim = ((uint8_t *)v->lsa) + ntohs(v->lsa->length);
@@ -1683,9 +1685,8 @@ void ospf_spf_calculate(struct ospf_area *area, struct ospf_lsa *root_lsa,
struct vertex *v;
if (IS_DEBUG_OSPF_EVENT) {
- zlog_debug("ospf_spf_calculate: Start");
- zlog_debug("ospf_spf_calculate: running Dijkstra for area %pI4",
- &area->area_id);
+ zlog_debug("%s: Start: running Dijkstra for area %pI4",
+ __func__, &area->area_id);
}
/*
@@ -1696,8 +1697,8 @@ void ospf_spf_calculate(struct ospf_area *area, struct ospf_lsa *root_lsa,
if (!root_lsa) {
if (IS_DEBUG_OSPF_EVENT)
zlog_debug(
- "ospf_spf_calculate: Skip area %pI4's calculation due to empty root LSA",
- &area->area_id);
+ "%s: Skip area %pI4's calculation due to empty root LSA",
+ __func__, &area->area_id);
return;
}
@@ -1777,7 +1778,7 @@ void ospf_spf_calculate(struct ospf_area *area, struct ospf_lsa *root_lsa,
area->ts_spf = area->ospf->ts_spf;
if (IS_DEBUG_OSPF_EVENT)
- zlog_debug("ospf_spf_calculate: Stop. %zd vertices",
+ zlog_debug("%s: Stop. %zd vertices", __func__,
mtype_stats_alloc(MTYPE_OSPF_VERTEX));
}
@@ -1897,7 +1898,9 @@ static void ospf_spf_calculate_schedule_worker(struct thread *thread)
/* Update all routers routing table */
ospf->oall_rtrs = ospf->all_rtrs;
ospf->all_rtrs = all_rtrs;
+#ifdef SUPPORT_OSPF_API
ospf_apiserver_notify_reachable(ospf->oall_rtrs, ospf->all_rtrs);
+#endif
/* Free old ABR/ASBR routing table */
if (ospf->old_rtrs)
diff --git a/ospfd/ospf_sr.c b/ospfd/ospf_sr.c
index 2c7c80686c..3a71e55710 100644
--- a/ospfd/ospf_sr.c
+++ b/ospfd/ospf_sr.c
@@ -756,13 +756,14 @@ static struct ospf_neighbor *get_neighbor_by_addr(struct ospf *top,
for (ALL_LIST_ELEMENTS_RO(top->oiflist, node, oi))
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
nbr = rn->info;
- if (nbr)
- if (IPV4_ADDR_SAME(&nbr->address.u.prefix4,
- &addr)
- || IPV4_ADDR_SAME(&nbr->router_id, &addr)) {
- route_unlock_node(rn);
- return nbr;
- }
+ if (!nbr)
+ continue;
+
+ if (IPV4_ADDR_SAME(&nbr->address.u.prefix4, &addr) ||
+ IPV4_ADDR_SAME(&nbr->router_id, &addr)) {
+ route_unlock_node(rn);
+ return nbr;
+ }
}
return NULL;
}
diff --git a/ospfd/ospf_vty.c b/ospfd/ospf_vty.c
index 1c22fad669..c957c8c014 100644
--- a/ospfd/ospf_vty.c
+++ b/ospfd/ospf_vty.c
@@ -4008,13 +4008,15 @@ static void show_ip_ospf_interface_traffic_sub(struct vty *vty,
oi->ls_ack_in);
json_object_int_add(json_interface_sub, "lsAckOut",
oi->ls_ack_out);
+ json_object_int_add(json_interface_sub, "packetsQueued",
+ listcount(oi->obuf));
} else {
vty_out(vty,
- "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u\n",
+ "%-10s %8u/%-8u %7u/%-7u %7u/%-7u %7u/%-7u %7u/%-7u %12lu\n",
oi->ifp->name, oi->hello_in, oi->hello_out,
oi->db_desc_in, oi->db_desc_out, oi->ls_req_in,
oi->ls_req_out, oi->ls_upd_in, oi->ls_upd_out,
- oi->ls_ack_in, oi->ls_ack_out);
+ oi->ls_ack_in, oi->ls_ack_out, listcount(oi->obuf));
}
}
@@ -4030,14 +4032,14 @@ static int show_ip_ospf_interface_traffic_common(
if (!use_json && !display_once) {
vty_out(vty, "\n");
- vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s\n", "Interface",
- " HELLO", " DB-Desc", " LS-Req", " LS-Update",
- " LS-Ack");
- vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s\n", "",
+ vty_out(vty, "%-12s%-17s%-17s%-17s%-17s%-17s%-17s\n",
+ "Interface", " HELLO", " DB-Desc", " LS-Req",
+ " LS-Update", " LS-Ack", " Packets");
+ vty_out(vty, "%-10s%-18s%-18s%-17s%-17s%-17s%-17s\n", "",
" Rx/Tx", " Rx/Tx", " Rx/Tx", " Rx/Tx",
- " Rx/Tx");
+ " Rx/Tx", " Queued");
vty_out(vty,
- "--------------------------------------------------------------------------------------------\n");
+ "-------------------------------------------------------------------------------------------------------------\n");
} else if (use_json) {
if (use_vrf)
json_vrf = json_object_new_object();
@@ -4476,19 +4478,22 @@ static void show_ip_ospf_neighbor_sub(struct vty *vty,
struct ospf_neighbor *nbr, *prev_nbr = NULL;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
- if ((nbr = rn->info)) {
- /* Do not show myself. */
- if (nbr == oi->nbr_self)
- continue;
- /* Down state is not shown. */
- if (nbr->state == NSM_Down)
- continue;
+ nbr = rn->info;
- prev_nbr = nbr;
+ if (!nbr)
+ continue;
- show_ip_ospf_neighbour_brief(vty, nbr, prev_nbr, json,
- use_json);
- }
+ /* Do not show myself. */
+ if (nbr == oi->nbr_self)
+ continue;
+ /* Down state is not shown. */
+ if (nbr->state == NSM_Down)
+ continue;
+
+ prev_nbr = nbr;
+
+ show_ip_ospf_neighbour_brief(vty, nbr, prev_nbr, json,
+ use_json);
}
}
@@ -5402,14 +5407,17 @@ static int show_ip_ospf_neighbor_id_common(struct vty *vty, struct ospf *ospf,
ospf_show_vrf_name(ospf, vty, json, use_vrf);
for (ALL_LIST_ELEMENTS_RO(ospf->oiflist, node, oi)) {
- if ((nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, router_id))) {
- if (is_detail)
- show_ip_ospf_neighbor_detail_sub(
- vty, oi, nbr, NULL, json, use_json);
- else
- show_ip_ospf_neighbour_brief(vty, nbr, NULL,
- json, use_json);
- }
+ nbr = ospf_nbr_lookup_by_routerid(oi->nbrs, router_id);
+
+ if (!nbr)
+ continue;
+
+ if (is_detail)
+ show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, NULL,
+ json, use_json);
+ else
+ show_ip_ospf_neighbour_brief(vty, nbr, NULL, json,
+ use_json);
}
if (use_json)
@@ -5498,16 +5506,19 @@ static int show_ip_ospf_neighbor_detail_common(struct vty *vty,
struct ospf_neighbor *nbr, *prev_nbr = NULL;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
- if ((nbr = rn->info)) {
- if (nbr != oi->nbr_self) {
- if (nbr->state != NSM_Down) {
- show_ip_ospf_neighbor_detail_sub(
- vty, oi, nbr, prev_nbr,
- json_nbr_sub, use_json);
- }
+ nbr = rn->info;
+
+ if (!nbr)
+ continue;
+
+ if (nbr != oi->nbr_self) {
+ if (nbr->state != NSM_Down) {
+ show_ip_ospf_neighbor_detail_sub(
+ vty, oi, nbr, prev_nbr,
+ json_nbr_sub, use_json);
}
- prev_nbr = nbr;
}
+ prev_nbr = nbr;
}
}
@@ -5668,27 +5679,29 @@ static int show_ip_ospf_neighbor_detail_all_common(struct vty *vty,
struct ospf_nbr_nbma *nbr_nbma;
for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
- if ((nbr = rn->info)) {
- if (nbr != oi->nbr_self)
- if (nbr->state != NSM_Down)
- show_ip_ospf_neighbor_detail_sub(
- vty, oi, rn->info,
- prev_nbr,
- json_vrf, use_json);
- prev_nbr = nbr;
- }
+ nbr = rn->info;
+
+ if (!nbr)
+ continue;
+
+ if (nbr != oi->nbr_self)
+ if (nbr->state != NSM_Down)
+ show_ip_ospf_neighbor_detail_sub(
+ vty, oi, rn->info, prev_nbr,
+ json_vrf, use_json);
+ prev_nbr = nbr;
}
- if (oi->type == OSPF_IFTYPE_NBMA) {
- struct listnode *nd;
+ if (oi->type != OSPF_IFTYPE_NBMA)
+ continue;
+
+ struct listnode *nd;
- for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nd, nbr_nbma)) {
- if (nbr_nbma->nbr == NULL
- || nbr_nbma->nbr->state == NSM_Down)
- show_ip_ospf_nbr_nbma_detail_sub(
- vty, oi, nbr_nbma, use_json,
- json_vrf);
- }
+ for (ALL_LIST_ELEMENTS_RO(oi->nbr_nbma, nd, nbr_nbma)) {
+ if (nbr_nbma->nbr == NULL ||
+ nbr_nbma->nbr->state == NSM_Down)
+ show_ip_ospf_nbr_nbma_detail_sub(
+ vty, oi, nbr_nbma, use_json, json_vrf);
}
}
@@ -5853,19 +5866,25 @@ static int show_ip_ospf_neighbor_int_detail_common(struct vty *vty,
}
for (rn = route_top(IF_OIFS(ifp)); rn; rn = route_next(rn)) {
- if ((oi = rn->info)) {
- for (nrn = route_top(oi->nbrs); nrn;
- nrn = route_next(nrn)) {
- if ((nbr = nrn->info)) {
- if (nbr != oi->nbr_self) {
- if (nbr->state != NSM_Down)
- show_ip_ospf_neighbor_detail_sub(
- vty, oi, nbr,
- NULL,
- json, use_json);
- }
- }
- }
+ oi = rn->info;
+
+ if (!oi)
+ continue;
+
+ for (nrn = route_top(oi->nbrs); nrn; nrn = route_next(nrn)) {
+ nbr = nrn->info;
+
+ if (!nbr)
+ continue;
+
+ if (nbr == oi->nbr_self)
+ continue;
+
+ if (nbr->state == NSM_Down)
+ continue;
+
+ show_ip_ospf_neighbor_detail_sub(vty, oi, nbr, NULL,
+ json, use_json);
}
}
@@ -8019,13 +8038,17 @@ static void ospf_nbr_timer_update(struct ospf_interface *oi)
struct route_node *rn;
struct ospf_neighbor *nbr;
- for (rn = route_top(oi->nbrs); rn; rn = route_next(rn))
- if ((nbr = rn->info)) {
- nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
- nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
- nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
- nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
- }
+ for (rn = route_top(oi->nbrs); rn; rn = route_next(rn)) {
+ nbr = rn->info;
+
+ if (!nbr)
+ continue;
+
+ nbr->v_inactivity = OSPF_IF_PARAM(oi, v_wait);
+ nbr->v_db_desc = OSPF_IF_PARAM(oi, retransmit_interval);
+ nbr->v_ls_req = OSPF_IF_PARAM(oi, retransmit_interval);
+ nbr->v_ls_upd = OSPF_IF_PARAM(oi, retransmit_interval);
+ }
}
static int ospf_vty_dead_interval_set(struct vty *vty, const char *interval_str,
@@ -9869,49 +9892,6 @@ DEFPY(no_ospf_gr_helper_enable,
return CMD_SUCCESS;
}
-#if CONFDATE > 20220921
-CPP_NOTICE(
- "Time to remove the deprecated \"[no] graceful-restart helper-only\" commands")
-#endif
-
-DEFPY_HIDDEN(ospf_gr_helper_only, ospf_gr_helper_only_cmd,
- "graceful-restart helper-only [A.B.C.D]",
- "OSPF Graceful Restart\n"
- "Enable Helper support\n"
- "Advertising router id\n")
-{
- VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf);
- struct in_addr addr;
- int ret;
-
- vty_out(vty,
- "%% This command is deprecated. Please, use `graceful-restart helper enable` instead.\n");
-
- if (argc == 3) {
- ret = inet_aton(argv[2]->arg, &addr);
- if (!ret) {
- vty_out(vty,
- "Please specify the valid routerid address.\n");
- return CMD_WARNING_CONFIG_FAILED;
- }
-
- ospf_gr_helper_support_set_per_routerid(ospf, &addr, OSPF_GR_TRUE);
- return CMD_SUCCESS;
- }
-
- ospf_gr_helper_support_set(ospf, OSPF_GR_TRUE);
-
- return CMD_SUCCESS;
-}
-
-ALIAS_HIDDEN(no_ospf_gr_helper_enable,
- no_ospf_gr_helper_only_cmd,
- "no graceful-restart helper-only [A.B.C.D]",
- NO_STR
- "OSPF Graceful Restart\n"
- "Disable Helper support\n"
- "Advertising router id\n")
-
DEFPY(ospf_gr_helper_enable_lsacheck,
ospf_gr_helper_enable_lsacheck_cmd,
"graceful-restart helper strict-lsa-checking",
@@ -10095,6 +10075,21 @@ static int ospf_print_vty_helper_dis_rtr_walkcb(struct hash_bucket *bucket,
return HASHWALK_CONTINUE;
}
+static int ospf_print_json_helper_enabled_rtr_walkcb(struct hash_bucket *bucket,
+ void *arg)
+{
+ struct advRtr *rtr = bucket->data;
+ struct json_object *json_rid_array = arg;
+ struct json_object *json_rid;
+
+ json_rid = json_object_new_object();
+
+ json_object_string_addf(json_rid, "routerId", "%pI4", &rtr->advRtrAddr);
+ json_object_array_add(json_rid_array, json_rid);
+
+ return HASHWALK_CONTINUE;
+}
+
static int ospf_show_gr_helper_details(struct vty *vty, struct ospf *ospf,
uint8_t use_vrf, json_object *json,
bool uj, bool detail)
@@ -10214,6 +10209,18 @@ CPP_NOTICE("Remove JSON object commands with keys starting with capital")
if (ospf->active_restarter_cnt)
json_object_int_add(json_vrf, "activeRestarterCnt",
ospf->active_restarter_cnt);
+
+ if (OSPF_HELPER_ENABLE_RTR_COUNT(ospf)) {
+ struct json_object *json_rid_array =
+ json_object_new_array();
+
+ json_object_object_add(json_vrf, "enabledRouterIds",
+ json_rid_array);
+
+ hash_walk(ospf->enable_rtr_list,
+ ospf_print_json_helper_enabled_rtr_walkcb,
+ json_rid_array);
+ }
}
@@ -12812,8 +12819,6 @@ static void ospf_vty_zebra_init(void)
/*Ospf garcefull restart helper configurations */
install_element(OSPF_NODE, &ospf_gr_helper_enable_cmd);
install_element(OSPF_NODE, &no_ospf_gr_helper_enable_cmd);
- install_element(OSPF_NODE, &ospf_gr_helper_only_cmd);
- install_element(OSPF_NODE, &no_ospf_gr_helper_only_cmd);
install_element(OSPF_NODE, &ospf_gr_helper_enable_lsacheck_cmd);
install_element(OSPF_NODE, &no_ospf_gr_helper_enable_lsacheck_cmd);
install_element(OSPF_NODE, &ospf_gr_helper_supported_grace_time_cmd);
@@ -12902,6 +12907,42 @@ DEFUN (clear_ip_ospf_interface,
return CMD_SUCCESS;
}
+DEFPY_HIDDEN(ospf_lsa_refresh_timer, ospf_lsa_refresh_timer_cmd,
+ "[no$no] ospf lsa-refresh [(120-1800)]$value",
+ NO_STR OSPF_STR
+ "OSPF lsa refresh timer\n"
+ "timer value in seconds\n")
+{
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf)
+
+ if (no)
+ ospf->lsa_refresh_timer = OSPF_LS_REFRESH_TIME;
+ else
+ ospf->lsa_refresh_timer = value;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY_HIDDEN(ospf_maxage_delay_timer, ospf_maxage_delay_timer_cmd,
+ "[no$no] ospf maxage-delay [(0-60)]$value",
+ NO_STR OSPF_STR
+ "OSPF lsa maxage delay timer\n"
+ "timer value in seconds\n")
+{
+ VTY_DECLVAR_INSTANCE_CONTEXT(ospf, ospf)
+
+ if (no)
+ ospf->maxage_delay = OSPF_LSA_MAXAGE_REMOVE_DELAY_DEFAULT;
+ else
+ ospf->maxage_delay = value;
+
+ THREAD_OFF(ospf->t_maxage);
+ OSPF_TIMER_ON(ospf->t_maxage, ospf_maxage_lsa_remover,
+ ospf->maxage_delay);
+
+ return CMD_SUCCESS;
+}
+
void ospf_vty_clear_init(void)
{
install_element(ENABLE_NODE, &clear_ip_ospf_interface_cmd);
@@ -13059,6 +13100,9 @@ void ospf_vty_init(void)
vrf_cmd_init(NULL);
+ install_element(OSPF_NODE, &ospf_lsa_refresh_timer_cmd);
+ install_element(OSPF_NODE, &ospf_maxage_delay_timer_cmd);
+
/* Init interface related vty commands. */
ospf_vty_if_init();
diff --git a/ospfd/ospfd.c b/ospfd/ospfd.c
index 8512b6a339..e0c36d86fe 100644
--- a/ospfd/ospfd.c
+++ b/ospfd/ospfd.c
@@ -392,6 +392,7 @@ struct ospf *ospf_new_alloc(unsigned short instance, const char *name)
new->lsa_refresh_queue.index = 0;
new->lsa_refresh_interval = OSPF_LSA_REFRESH_INTERVAL_DEFAULT;
+ new->lsa_refresh_timer = OSPF_LS_REFRESH_TIME;
new->t_lsa_refresher = NULL;
thread_add_timer(master, ospf_lsa_refresh_walker, new,
new->lsa_refresh_interval, &new->t_lsa_refresher);
diff --git a/ospfd/ospfd.h b/ospfd/ospfd.h
index 8478c96ddc..3a43010f85 100644
--- a/ospfd/ospfd.h
+++ b/ospfd/ospfd.h
@@ -313,6 +313,7 @@ struct ospf {
time_t lsa_refresher_started;
#define OSPF_LSA_REFRESH_INTERVAL_DEFAULT 10
uint16_t lsa_refresh_interval;
+ uint16_t lsa_refresh_timer;
/* Distance parameter. */
uint8_t distance_all;
diff --git a/pathd/path_pcep_pcc.c b/pathd/path_pcep_pcc.c
index b72a536ef4..a1c56f93ad 100644
--- a/pathd/path_pcep_pcc.c
+++ b/pathd/path_pcep_pcc.c
@@ -1326,9 +1326,9 @@ void handle_pcep_lsp_initiate(struct ctrl_state *ctrl_state,
* possibly disconnect and blacklist */
flog_warn(EC_PATH_PCEP_UNSUPPORTED_PCEP_FEATURE,
"Unsupported PCEP protocol feature: %s", err);
- pcep_free_path(path);
send_pcep_error(pcc_state, PCEP_ERRT_INVALID_OPERATION,
PCEP_ERRV_LSP_NOT_PCE_INITIATED, path);
+ pcep_free_path(path);
}
}
diff --git a/pathd/path_ted.c b/pathd/path_ted.c
index 270c664daf..316255a97e 100644
--- a/pathd/path_ted.c
+++ b/pathd/path_ted.c
@@ -243,16 +243,16 @@ uint32_t path_ted_query_type_f(struct ipaddr *local, struct ipaddr *remote)
}
break;
case IPADDR_V6:
- key = (uint64_t)(local->ip._v6_addr.s6_addr32[0] & 0xffffffff)
- | ((uint64_t)local->ip._v6_addr.s6_addr32[1] << 32);
+ key = (uint64_t)ntohl(local->ip._v6_addr.s6_addr32[2]) << 32 |
+ (uint64_t)ntohl(local->ip._v6_addr.s6_addr32[3]);
edge = ls_find_edge_by_key(ted_state_g.ted, key);
if (edge) {
- if ((memcmp(&edge->attributes->standard.remote6,
- &remote->ip._v6_addr,
- sizeof(remote->ip._v6_addr))
- && CHECK_FLAG(edge->attributes->flags,
- LS_ATTR_ADJ_SID))) {
- sid = edge->attributes->adj_sid[0]
+ if ((0 == memcmp(&edge->attributes->standard.remote6,
+ &remote->ip._v6_addr,
+ sizeof(remote->ip._v6_addr)) &&
+ CHECK_FLAG(edge->attributes->flags,
+ LS_ATTR_ADJ_SID6))) {
+ sid = edge->attributes->adj_sid[ADJ_PRI_IPV6]
.sid; /* from primary */
break;
}
@@ -385,7 +385,7 @@ DEFUN (no_path_ted,
"Disable the TE Database functionality\n")
/* clang-format on */
{
- if (ted_state_g.enabled) {
+ if (!ted_state_g.enabled) {
PATH_TED_DEBUG("%s: PATHD-TED: OFF -> OFF", __func__);
return CMD_SUCCESS;
}
@@ -462,7 +462,7 @@ DEFPY (show_pathd_ted_db,
json_object *json = NULL;
if (!ted_state_g.enabled) {
- vty_out(vty, "PATHD TED database is not enabled\n");
+ vty_out(vty, "Traffic Engineering database is not enabled\n");
return CMD_WARNING;
}
if (strcmp(ver_json, "json") == 0) {
diff --git a/pbrd/pbr_vty.c b/pbrd/pbr_vty.c
index d68bcfa160..a2b3431b94 100644
--- a/pbrd/pbr_vty.c
+++ b/pbrd/pbr_vty.c
@@ -137,6 +137,9 @@ DEFPY(pbr_map_match_src, pbr_map_match_src_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (pbrms->dst && pbrms->family && prefix->family != pbrms->family) {
vty_out(vty, "Cannot mismatch families within match src/dst\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -170,6 +173,9 @@ DEFPY(pbr_map_match_dst, pbr_map_match_dst_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (pbrms->src && pbrms->family && prefix->family != pbrms->family) {
vty_out(vty, "Cannot mismatch families within match src/dst\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -204,6 +210,9 @@ DEFPY(pbr_map_match_ip_proto, pbr_map_match_ip_proto_cmd,
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
struct protoent *p;
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no) {
p = getprotobyname(ip_proto);
if (!p) {
@@ -228,6 +237,9 @@ DEFPY(pbr_map_match_src_port, pbr_map_match_src_port_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no) {
if (pbrms->src_prt == port)
return CMD_SUCCESS;
@@ -250,6 +262,9 @@ DEFPY(pbr_map_match_dst_port, pbr_map_match_dst_port_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no) {
if (pbrms->dst_prt == port)
return CMD_SUCCESS;
@@ -274,6 +289,9 @@ DEFPY(pbr_map_match_dscp, pbr_map_match_dscp_cmd,
char dscpname[100];
uint8_t rawDscp;
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
/* Discriminate dscp enums (cs0, cs1 etc.) and numbers */
bool isANumber = true;
for (int i = 0; i < (int)strlen(dscp); i++) {
@@ -333,6 +351,9 @@ DEFPY(pbr_map_match_ecn, pbr_map_match_ecn_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no) {
if ((pbrms->dsfield & PBR_DSFIELD_ECN) == ecn)
return CMD_SUCCESS;
@@ -357,6 +378,9 @@ DEFPY(pbr_map_match_mark, pbr_map_match_mark_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
#ifndef GNU_LINUX
vty_out(vty, "pbr marks are not supported on this platform\n");
return CMD_WARNING_CONFIG_FAILED;
@@ -417,6 +441,9 @@ DEFPY(pbr_map_action_queue_id, pbr_map_action_queue_id_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no)
pbrms->action_queue_id = queue_id;
else if ((uint32_t)queue_id == pbrms->action_queue_id)
@@ -435,6 +462,9 @@ DEFPY(pbr_map_action_pcp, pbr_map_action_pcp_cmd, "[no] set pcp <(0-7)$pcp>",
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no)
pbrms->action_pcp = pcp;
else if (pcp == pbrms->action_pcp)
@@ -454,6 +484,9 @@ DEFPY(pbr_map_action_vlan_id, pbr_map_action_vlan_id_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no)
pbrms->action_vlan_id = vlan_id;
else if (pbrms->action_vlan_id == vlan_id)
@@ -472,6 +505,9 @@ DEFPY(pbr_map_action_strip_vlan, pbr_map_action_strip_vlan_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (!no)
pbrms->action_vlan_flags = PBR_MAP_STRIP_INNER_ANY;
else
@@ -492,6 +528,9 @@ DEFPY(pbr_map_nexthop_group, pbr_map_nexthop_group_cmd,
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
struct nexthop_group_cmd *nhgc;
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
nhgc = nhgc_find(name);
if (!nhgc) {
vty_out(vty, "Specified nexthop-group %s does not exist\n",
@@ -522,6 +561,9 @@ DEFPY(no_pbr_map_nexthop_group, no_pbr_map_nexthop_group_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
pbrms_clear_set_config(pbrms);
return CMD_SUCCESS;
@@ -548,6 +590,9 @@ DEFPY(pbr_map_nexthop, pbr_map_nexthop_cmd,
struct nexthop nhop;
struct nexthop *nh = NULL;
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
if (vrf_name)
vrf = vrf_lookup_by_name(vrf_name);
else
@@ -670,6 +715,9 @@ DEFPY(no_pbr_map_nexthop, no_pbr_map_nexthop_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
pbrms_clear_set_config(pbrms);
return CMD_SUCCESS;
@@ -684,6 +732,9 @@ DEFPY(pbr_map_vrf, pbr_map_vrf_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
/*
* If an equivalent set vrf * exists, just return success.
*/
@@ -722,6 +773,9 @@ DEFPY(no_pbr_map_vrf, no_pbr_map_vrf_cmd,
{
struct pbr_map_sequence *pbrms = VTY_GET_CONTEXT(pbr_map_sequence);
+ if (!pbrms)
+ return CMD_WARNING_CONFIG_FAILED;
+
pbrms_clear_set_config(pbrms);
return CMD_SUCCESS;
diff --git a/pimd/mtracebis_netlink.c b/pimd/mtracebis_netlink.c
index fe2cb56a26..81e28f2407 100644
--- a/pimd/mtracebis_netlink.c
+++ b/pimd/mtracebis_netlink.c
@@ -92,7 +92,7 @@ int rtnl_open_byproto(struct rtnl_handle *rth, unsigned subscriptions,
rth->local.nl_family);
return -1;
}
- rth->seq = time(NULL);
+ rth->seq = (uint32_t)time(NULL);
return 0;
}
diff --git a/pimd/pim6_cmd.c b/pimd/pim6_cmd.c
index d72a67243b..49248798bf 100644
--- a/pimd/pim6_cmd.c
+++ b/pimd/pim6_cmd.c
@@ -1260,6 +1260,19 @@ DEFPY (clear_ipv6_pim_statistics,
return CMD_SUCCESS;
}
+DEFPY (clear_ipv6_pim_interface_traffic,
+ clear_ipv6_pim_interface_traffic_cmd,
+ "clear ipv6 pim [vrf NAME] interface traffic",
+ CLEAR_STR
+ IPV6_STR
+ CLEAR_IP_PIM_STR
+ VRF_CMD_HELP_STR
+ "Reset PIM interfaces\n"
+ "Reset Protocol Packet counters\n")
+{
+ return clear_pim_interface_traffic(vrf, vty);
+}
+
DEFPY (clear_ipv6_mroute,
clear_ipv6_mroute_cmd,
"clear ipv6 mroute [vrf NAME]$name",
@@ -1503,6 +1516,136 @@ DEFPY (debug_pimv6_zebra,
return CMD_SUCCESS;
}
+DEFPY (debug_mroute6,
+ debug_mroute6_cmd,
+ "[no] debug mroute6",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MROUTE6_STR)
+{
+ if (!no)
+ PIM_DO_DEBUG_MROUTE;
+ else
+ PIM_DONT_DEBUG_MROUTE;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mroute6_detail,
+ debug_mroute6_detail_cmd,
+ "[no] debug mroute6 detail",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MROUTE6_STR
+ "detailed\n")
+{
+ if (!no)
+ PIM_DO_DEBUG_MROUTE_DETAIL;
+ else
+ PIM_DONT_DEBUG_MROUTE_DETAIL;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN_NOSH (show_debugging_pimv6,
+ show_debugging_pimv6_cmd,
+ "show debugging [pimv6]",
+ SHOW_STR
+ DEBUG_STR
+ "PIMv6 Information\n")
+{
+ vty_out(vty, "PIMv6 debugging status\n");
+
+ pim_debug_config_write(vty);
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld,
+ debug_mld_cmd,
+ "[no] debug mld",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR)
+{
+ if (!no) {
+ PIM_DO_DEBUG_GM_EVENTS;
+ PIM_DO_DEBUG_GM_PACKETS;
+ PIM_DO_DEBUG_GM_TRACE;
+ } else {
+ PIM_DONT_DEBUG_GM_EVENTS;
+ PIM_DONT_DEBUG_GM_PACKETS;
+ PIM_DONT_DEBUG_GM_TRACE;
+ }
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_events,
+ debug_mld_events_cmd,
+ "[no] debug mld events",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_EVENTS_STR)
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_EVENTS;
+ else
+ PIM_DONT_DEBUG_GM_EVENTS;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_packets,
+ debug_mld_packets_cmd,
+ "[no] debug mld packets",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_PACKETS_STR)
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_PACKETS;
+ else
+ PIM_DONT_DEBUG_GM_PACKETS;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_trace,
+ debug_mld_trace_cmd,
+ "[no] debug mld trace",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_TRACE_STR)
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_TRACE;
+ else
+ PIM_DONT_DEBUG_GM_TRACE;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (debug_mld_trace_detail,
+ debug_mld_trace_detail_cmd,
+ "[no] debug mld trace detail",
+ NO_STR
+ DEBUG_STR
+ DEBUG_MLD_STR
+ DEBUG_MLD_TRACE_STR
+ "detailed\n")
+{
+ if (!no)
+ PIM_DO_DEBUG_GM_TRACE_DETAIL;
+ else
+ PIM_DONT_DEBUG_GM_TRACE_DETAIL;
+
+ return CMD_SUCCESS;
+}
+
void pim_cmd_init(void)
{
if_cmd_init(pim_interface_config_write);
@@ -1619,6 +1762,9 @@ void pim_cmd_init(void)
install_element(ENABLE_NODE, &clear_ipv6_mroute_count_cmd);
install_element(ENABLE_NODE, &clear_ipv6_pim_bsr_db_cmd);
install_element(ENABLE_NODE, &clear_ipv6_pim_interfaces_cmd);
+ install_element(ENABLE_NODE, &clear_ipv6_pim_interface_traffic_cmd);
+
+ install_element(ENABLE_NODE, &show_debugging_pimv6_cmd);
install_element(ENABLE_NODE, &debug_pimv6_cmd);
install_element(ENABLE_NODE, &debug_pimv6_nht_cmd);
@@ -1630,6 +1776,13 @@ void pim_cmd_init(void)
install_element(ENABLE_NODE, &debug_pimv6_trace_cmd);
install_element(ENABLE_NODE, &debug_pimv6_trace_detail_cmd);
install_element(ENABLE_NODE, &debug_pimv6_zebra_cmd);
+ install_element(ENABLE_NODE, &debug_mroute6_cmd);
+ install_element(ENABLE_NODE, &debug_mroute6_detail_cmd);
+ install_element(ENABLE_NODE, &debug_mld_cmd);
+ install_element(ENABLE_NODE, &debug_mld_events_cmd);
+ install_element(ENABLE_NODE, &debug_mld_packets_cmd);
+ install_element(ENABLE_NODE, &debug_mld_trace_cmd);
+ install_element(ENABLE_NODE, &debug_mld_trace_detail_cmd);
install_element(CONFIG_NODE, &debug_pimv6_cmd);
install_element(CONFIG_NODE, &debug_pimv6_nht_cmd);
@@ -1641,4 +1794,11 @@ void pim_cmd_init(void)
install_element(CONFIG_NODE, &debug_pimv6_trace_cmd);
install_element(CONFIG_NODE, &debug_pimv6_trace_detail_cmd);
install_element(CONFIG_NODE, &debug_pimv6_zebra_cmd);
+ install_element(CONFIG_NODE, &debug_mroute6_cmd);
+ install_element(CONFIG_NODE, &debug_mroute6_detail_cmd);
+ install_element(CONFIG_NODE, &debug_mld_cmd);
+ install_element(CONFIG_NODE, &debug_mld_events_cmd);
+ install_element(CONFIG_NODE, &debug_mld_packets_cmd);
+ install_element(CONFIG_NODE, &debug_mld_trace_cmd);
+ install_element(CONFIG_NODE, &debug_mld_trace_detail_cmd);
}
diff --git a/pimd/pim6_cmd.h b/pimd/pim6_cmd.h
index 8fb82d9f26..c45c998453 100644
--- a/pimd/pim6_cmd.h
+++ b/pimd/pim6_cmd.h
@@ -57,6 +57,7 @@
#define DEBUG_PIMV6_PACKETDUMP_RECV_STR "Dump received packets\n"
#define DEBUG_PIMV6_TRACE_STR "PIMv6 internal daemon activity\n"
#define DEBUG_PIMV6_ZEBRA_STR "ZEBRA protocol activity\n"
+#define DEBUG_MROUTE6_STR "PIMv6 interaction with kernel MFC cache\n"
void pim_cmd_init(void);
diff --git a/pimd/pim6_main.c b/pimd/pim6_main.c
index b3f4e4256c..7ac22fd025 100644
--- a/pimd/pim6_main.c
+++ b/pimd/pim6_main.c
@@ -119,9 +119,7 @@ static const struct frr_yang_module_info *const pim6d_yang_modules[] = {
/* clang-format off */
FRR_DAEMON_INFO(pim6d, PIM6,
- .vty_port = 0,
- .flags = FRR_NO_SPLIT_CONFIG,
-
+ .vty_port = PIM6D_VTY_PORT,
.proghelp = "Protocol Independent Multicast (RFC7761) for IPv6",
.signals = pim6d_signals,
@@ -161,8 +159,6 @@ int main(int argc, char **argv, char **envp)
}
pim_router_init();
- /* TODO PIM6: temporary enable all debugs, remove later in PIMv6 work */
- router->debugs = ~0U;
access_list_init();
prefix_list_init();
diff --git a/pimd/pim6_mld.c b/pimd/pim6_mld.c
index 255fd62ba7..23042ef14e 100644
--- a/pimd/pim6_mld.c
+++ b/pimd/pim6_mld.c
@@ -33,12 +33,15 @@
#include "lib/prefix.h"
#include "lib/checksum.h"
#include "lib/thread.h"
+#include "termtable.h"
#include "pimd/pim6_mld.h"
#include "pimd/pim6_mld_protocol.h"
#include "pimd/pim_memory.h"
#include "pimd/pim_instance.h"
#include "pimd/pim_iface.h"
+#include "pimd/pim6_cmd.h"
+#include "pimd/pim_cmd_common.h"
#include "pimd/pim_util.h"
#include "pimd/pim_tib.h"
#include "pimd/pimd.h"
@@ -398,7 +401,7 @@ static void gm_sg_update(struct gm_sg *sg, bool has_expired)
desired = GM_SG_NOINFO;
if (desired != sg->state && !gm_ifp->stopping) {
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(log_sg(sg, "%s => %s"), gm_states[sg->state],
gm_states[desired]);
@@ -415,7 +418,7 @@ static void gm_sg_update(struct gm_sg *sg, bool has_expired)
gm_sg_timer_start(gm_ifp, sg, timers.expire_wait);
THREAD_OFF(sg->t_sg_query);
- sg->n_query = gm_ifp->cur_qrv;
+ sg->n_query = gm_ifp->cur_lmqc;
sg->query_sbit = false;
gm_trigger_specific(sg);
}
@@ -457,7 +460,7 @@ static void gm_sg_update(struct gm_sg *sg, bool has_expired)
gm_packet_sg_subs_count(sg->subs_positive),
gm_packet_sg_subs_count(sg->subs_negative), grp);
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(log_sg(sg, "dropping"));
gm_sgs_del(gm_ifp->sgs, sg);
@@ -547,7 +550,7 @@ static void gm_packet_drop(struct gm_packet_state *pkt, bool trace)
if (!sg)
continue;
- if (trace && PIM_DEBUG_IGMP_TRACE)
+ if (trace && PIM_DEBUG_GM_TRACE)
zlog_debug(log_sg(sg, "general-dropping from %pPA"),
&pkt->subscriber->addr);
deleted = gm_packet_sg_drop(&pkt->items[i]);
@@ -583,7 +586,7 @@ static void gm_packet_sg_remove_sources(struct gm_if *gm_ifp,
static void gm_sg_expiry_cancel(struct gm_sg *sg)
{
- if (sg->t_sg_expire && PIM_DEBUG_IGMP_TRACE)
+ if (sg->t_sg_expire && PIM_DEBUG_GM_TRACE)
zlog_debug(log_sg(sg, "alive, cancelling expiry timer"));
THREAD_OFF(sg->t_sg_expire);
sg->query_sbit = true;
@@ -814,7 +817,7 @@ static void gm_handle_v2_report(struct gm_if *gm_ifp,
struct gm_packet_state *pkt;
if (len < sizeof(*hdr)) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(log_pkt_src(
"malformed MLDv2 report (truncated header)"));
gm_ifp->stats.rx_drop_malformed++;
@@ -920,7 +923,7 @@ static void gm_handle_v1_report(struct gm_if *gm_ifp,
size_t max_entries;
if (len < sizeof(*hdr)) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(log_pkt_src(
"malformed MLDv1 report (truncated)"));
gm_ifp->stats.rx_drop_malformed++;
@@ -986,7 +989,7 @@ static void gm_handle_v1_leave(struct gm_if *gm_ifp,
struct gm_packet_sg *old_grp;
if (len < sizeof(*hdr)) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(log_pkt_src(
"malformed MLDv1 leave (truncated)"));
gm_ifp->stats.rx_drop_malformed++;
@@ -1046,7 +1049,7 @@ static void gm_t_expire(struct thread *t)
remain_ms = monotime_until(&pend->expiry, &remain);
if (remain_ms > 0) {
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(
log_ifp("next general expiry in %" PRId64 "ms"),
remain_ms / 1000);
@@ -1060,7 +1063,7 @@ static void gm_t_expire(struct thread *t)
if (timercmp(&pkt->received, &pend->query, >=))
break;
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(log_ifp("expire packet %p"), pkt);
gm_packet_drop(pkt, true);
}
@@ -1070,7 +1073,7 @@ static void gm_t_expire(struct thread *t)
gm_ifp->n_pending * sizeof(gm_ifp->pending[0]));
}
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(log_ifp("next general expiry waiting for query"));
}
@@ -1099,7 +1102,7 @@ static void gm_handle_q_general(struct gm_if *gm_ifp,
* it's "supersetted" within the preexisting query
*/
- if (PIM_DEBUG_IGMP_TRACE_DETAIL)
+ if (PIM_DEBUG_GM_TRACE_DETAIL)
zlog_debug(
log_ifp("zapping supersetted general timer %pTVMu"),
&pend->expiry);
@@ -1118,13 +1121,13 @@ static void gm_handle_q_general(struct gm_if *gm_ifp,
pend->expiry = expiry;
if (!gm_ifp->n_pending++) {
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(
log_ifp("starting general timer @ 0: %pTVMu"),
&pend->expiry);
thread_add_timer_tv(router->master, gm_t_expire, gm_ifp,
&timers->expire_wait, &gm_ifp->t_expire);
- } else if (PIM_DEBUG_IGMP_TRACE)
+ } else if (PIM_DEBUG_GM_TRACE)
zlog_debug(log_ifp("appending general timer @ %u: %pTVMu"),
gm_ifp->n_pending, &pend->expiry);
}
@@ -1205,7 +1208,7 @@ static void gm_sg_timer_start(struct gm_if *gm_ifp, struct gm_sg *sg,
if (gm_sg_check_recent(gm_ifp, sg, now))
return;
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(log_sg(sg, "expiring in %pTVI"), &expire_wait);
if (sg->t_sg_expire) {
@@ -1247,7 +1250,7 @@ static void gm_t_grp_expire(struct thread *t)
struct gm_if *gm_ifp = pend->iface;
struct gm_sg *sg, *sg_start, sg_ref = {};
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(log_ifp("*,%pPAs S,G timer expired"), &pend->grp);
/* gteq lookup - try to find *,G or S,G (S,G is > *,G)
@@ -1302,7 +1305,7 @@ static void gm_handle_q_group(struct gm_if *gm_ifp,
if (pim_addr_is_any(sg->sgaddr.src)) {
/* actually found *,G entry here */
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(log_ifp("*,%pPAs expiry timer starting"),
&grp);
gm_sg_timer_start(gm_ifp, sg, timers->expire_wait);
@@ -1335,7 +1338,7 @@ static void gm_handle_q_group(struct gm_if *gm_ifp,
thread_add_timer_tv(router->master, gm_t_grp_expire, pend,
&timers->expire_wait, &pend->t_expire);
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(log_ifp("*,%pPAs S,G timer started: %pTHD"), &grp,
pend->t_expire);
}
@@ -1439,7 +1442,7 @@ static void gm_handle_query(struct gm_if *gm_ifp,
}
if (IPV6_ADDR_CMP(&pkt_src->sin6_addr, &gm_ifp->querier) < 0) {
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(
log_pkt_src("replacing elected querier %pPA"),
&gm_ifp->querier);
@@ -1460,7 +1463,7 @@ static void gm_handle_query(struct gm_if *gm_ifp,
gm_expiry_calc(&timers);
- if (PIM_DEBUG_IGMP_TRACE_DETAIL)
+ if (PIM_DEBUG_GM_TRACE_DETAIL)
zlog_debug(
log_ifp("query timers: QRV=%u max_resp=%ums qqic=%ums expire_wait=%pTVI"),
timers.qrv, timers.max_resp_ms, timers.qqic_ms,
@@ -1606,7 +1609,7 @@ static void gm_t_recv(struct thread *t)
char rxbuf[2048];
struct msghdr mh[1] = {};
struct iovec iov[1];
- struct sockaddr_in6 pkt_src[1];
+ struct sockaddr_in6 pkt_src[1] = {};
ssize_t nread;
size_t pktlen;
@@ -1799,7 +1802,7 @@ static void gm_send_query(struct gm_if *gm_ifp, pim_addr grp,
query.hdr.icmp6_cksum = in_cksumv(iov, iov_len);
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(
log_ifp("MLD query %pPA -> %pI6 (grp=%pPA, %zu srcs)"),
&pim_ifp->ll_lowest, &dstaddr.sin6_addr, &grp, n_srcs);
@@ -1922,7 +1925,7 @@ static void gm_trigger_specific(struct gm_sg *sg)
if (gm_ifp->pim->gm_socket == -1)
return;
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(log_sg(sg, "triggered query"));
if (pim_addr_is_any(sg->sgaddr.src)) {
@@ -2088,11 +2091,12 @@ static void gm_start(struct interface *ifp)
else
gm_ifp->cur_version = GM_MLDV2;
- /* hardcoded for dev without CLI */
- gm_ifp->cur_qrv = 2;
+ gm_ifp->cur_qrv = pim_ifp->gm_default_robustness_variable;
gm_ifp->cur_query_intv = pim_ifp->gm_default_query_interval * 1000;
- gm_ifp->cur_query_intv_trig = gm_ifp->cur_query_intv;
- gm_ifp->cur_max_resp = 250;
+ gm_ifp->cur_query_intv_trig =
+ pim_ifp->gm_specific_query_max_response_time_dsec * 100;
+ gm_ifp->cur_max_resp = pim_ifp->gm_query_max_response_time_dsec * 100;
+ gm_ifp->cur_lmqc = pim_ifp->gm_last_member_query_count;
gm_ifp->cfg_timing_fuzz.tv_sec = 0;
gm_ifp->cfg_timing_fuzz.tv_usec = 10 * 1000;
@@ -2118,22 +2122,54 @@ static void gm_start(struct interface *ifp)
}
}
-void gm_ifp_teardown(struct interface *ifp)
+void gm_group_delete(struct gm_if *gm_ifp)
{
- struct pim_interface *pim_ifp = ifp->info;
- struct gm_if *gm_ifp;
+ struct gm_sg *sg;
struct gm_packet_state *pkt;
struct gm_grp_pending *pend_grp;
struct gm_gsq_pending *pend_gsq;
struct gm_subscriber *subscriber;
- struct gm_sg *sg;
+
+ while ((pkt = gm_packet_expires_first(gm_ifp->expires)))
+ gm_packet_drop(pkt, false);
+
+ while ((pend_grp = gm_grp_pends_pop(gm_ifp->grp_pends))) {
+ THREAD_OFF(pend_grp->t_expire);
+ XFREE(MTYPE_GM_GRP_PENDING, pend_grp);
+ }
+
+ while ((pend_gsq = gm_gsq_pends_pop(gm_ifp->gsq_pends))) {
+ THREAD_OFF(pend_gsq->t_send);
+ XFREE(MTYPE_GM_GSQ_PENDING, pend_gsq);
+ }
+
+ while ((sg = gm_sgs_pop(gm_ifp->sgs))) {
+ THREAD_OFF(sg->t_sg_expire);
+ assertf(!gm_packet_sg_subs_count(sg->subs_negative), "%pSG",
+ &sg->sgaddr);
+ assertf(!gm_packet_sg_subs_count(sg->subs_positive), "%pSG",
+ &sg->sgaddr);
+
+ gm_sg_free(sg);
+ }
+ while ((subscriber = gm_subscribers_pop(gm_ifp->subscribers))) {
+ assertf(!gm_packets_count(subscriber->packets), "%pPA",
+ &subscriber->addr);
+ XFREE(MTYPE_GM_SUBSCRIBER, subscriber);
+ }
+}
+
+void gm_ifp_teardown(struct interface *ifp)
+{
+ struct pim_interface *pim_ifp = ifp->info;
+ struct gm_if *gm_ifp;
if (!pim_ifp || !pim_ifp->mld)
return;
gm_ifp = pim_ifp->mld;
gm_ifp->stopping = true;
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(log_ifp("MLD stop"));
THREAD_OFF(gm_ifp->t_query);
@@ -2157,34 +2193,7 @@ void gm_ifp_teardown(struct interface *ifp)
gm_vrf_socket_decref(gm_ifp->pim);
- while ((pkt = gm_packet_expires_first(gm_ifp->expires)))
- gm_packet_drop(pkt, false);
-
- while ((pend_grp = gm_grp_pends_pop(gm_ifp->grp_pends))) {
- THREAD_OFF(pend_grp->t_expire);
- XFREE(MTYPE_GM_GRP_PENDING, pend_grp);
- }
-
- while ((pend_gsq = gm_gsq_pends_pop(gm_ifp->gsq_pends))) {
- THREAD_OFF(pend_gsq->t_send);
- XFREE(MTYPE_GM_GSQ_PENDING, pend_gsq);
- }
-
- while ((sg = gm_sgs_pop(gm_ifp->sgs))) {
- THREAD_OFF(sg->t_sg_expire);
- assertf(!gm_packet_sg_subs_count(sg->subs_negative), "%pSG",
- &sg->sgaddr);
- assertf(!gm_packet_sg_subs_count(sg->subs_positive), "%pSG",
- &sg->sgaddr);
-
- gm_sg_free(sg);
- }
-
- while ((subscriber = gm_subscribers_pop(gm_ifp->subscribers))) {
- assertf(!gm_packets_count(subscriber->packets), "%pPA",
- &subscriber->addr);
- XFREE(MTYPE_GM_SUBSCRIBER, subscriber);
- }
+ gm_group_delete(gm_ifp);
gm_grp_pends_fini(gm_ifp->grp_pends);
gm_packet_expires_fini(gm_ifp->expires);
@@ -2246,8 +2255,16 @@ void gm_ifp_update(struct interface *ifp)
return;
}
- if (!pim_ifp->mld)
+ /*
+ * If ipv6 mld is not enabled on interface, do not start mld activites.
+ */
+ if (!pim_ifp->gm_enable)
+ return;
+
+ if (!pim_ifp->mld) {
+ changed = true;
gm_start(ifp);
+ }
gm_ifp = pim_ifp->mld;
if (IPV6_ADDR_CMP(&pim_ifp->ll_lowest, &gm_ifp->cur_ll_lowest))
@@ -2257,10 +2274,26 @@ void gm_ifp_update(struct interface *ifp)
if (gm_ifp->cur_query_intv != cfg_query_intv) {
gm_ifp->cur_query_intv = cfg_query_intv;
- gm_ifp->cur_query_intv_trig = cfg_query_intv;
changed = true;
}
+ unsigned int cfg_query_intv_trig =
+ pim_ifp->gm_specific_query_max_response_time_dsec * 100;
+
+ if (gm_ifp->cur_query_intv_trig != cfg_query_intv_trig) {
+ gm_ifp->cur_query_intv_trig = cfg_query_intv_trig;
+ changed = true;
+ }
+
+ unsigned int cfg_max_response =
+ pim_ifp->gm_query_max_response_time_dsec * 100;
+
+ if (gm_ifp->cur_max_resp != cfg_max_response)
+ gm_ifp->cur_max_resp = cfg_max_response;
+
+ if (gm_ifp->cur_lmqc != pim_ifp->gm_last_member_query_count)
+ gm_ifp->cur_lmqc = pim_ifp->gm_last_member_query_count;
+
enum gm_version cfg_version;
if (pim_ifp->mld_version == 1)
@@ -2273,7 +2306,7 @@ void gm_ifp_update(struct interface *ifp)
}
if (changed) {
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(log_ifp(
"MLD querier config changed, querying"));
gm_bump_querier(gm_ifp);
@@ -2290,8 +2323,6 @@ void gm_ifp_update(struct interface *ifp)
#include "pimd/pim6_mld_clippy.c"
#endif
-#define MLD_STR "Multicast Listener Discovery\n"
-
static struct vrf *gm_cmd_vrf_lookup(struct vty *vty, const char *vrf_str,
int *err)
{
@@ -2381,6 +2412,7 @@ static void gm_show_if_one(struct vty *vty, struct interface *ifp,
querier = IPV6_ADDR_SAME(&gm_ifp->querier, &pim_ifp->ll_lowest);
if (js_if) {
+ json_object_string_add(js_if, "name", ifp->name);
json_object_string_add(js_if, "state", "up");
json_object_string_addf(js_if, "version", "%d",
gm_ifp->cur_version);
@@ -2396,6 +2428,16 @@ static void gm_show_if_one(struct vty *vty, struct interface *ifp,
json_object_string_addf(js_if, "otherQuerierTimer",
"%pTH",
gm_ifp->t_other_querier);
+ json_object_int_add(js_if, "timerRobustnessValue",
+ gm_ifp->cur_qrv);
+ json_object_int_add(js_if, "lastMemberQueryCount",
+ gm_ifp->cur_lmqc);
+ json_object_int_add(js_if, "timerQueryIntervalMsec",
+ gm_ifp->cur_query_intv);
+ json_object_int_add(js_if, "timerQueryResponseTimerMsec",
+ gm_ifp->cur_max_resp);
+ json_object_int_add(js_if, "timerLastMemberQueryIntervalMsec",
+ gm_ifp->cur_query_intv_trig);
} else {
vty_out(vty, "%-16s %-5s %d %-25pPA %-5s %11pTH %pTVMs\n",
ifp->name, "up", gm_ifp->cur_version, &gm_ifp->querier,
@@ -2453,13 +2495,13 @@ static void gm_show_if(struct vty *vty, struct vrf *vrf, const char *ifname,
DEFPY(gm_show_interface,
gm_show_interface_cmd,
- "show ipv6 mld [vrf <VRF|all>$vrf_str] interface [IFNAME] [detail$detail|json$json]",
- DEBUG_STR
+ "show ipv6 mld [vrf <VRF|all>$vrf_str] interface [IFNAME | detail$detail] [json$json]",
SHOW_STR
IPV6_STR
MLD_STR
VRF_FULL_CMD_HELP_STR
"MLD interface information\n"
+ "Interface name\n"
"Detailed output\n"
JSON_STR)
{
@@ -2831,6 +2873,125 @@ DEFPY(gm_show_interface_joins,
return vty_json(vty, js);
}
+static void gm_show_groups(struct vty *vty, struct vrf *vrf, bool uj)
+{
+ struct interface *ifp;
+ struct ttable *tt = NULL;
+ char *table;
+ json_object *json = NULL;
+ json_object *json_iface = NULL;
+ json_object *json_group = NULL;
+ json_object *json_groups = NULL;
+ struct pim_instance *pim = vrf->info;
+
+ if (uj) {
+ json = json_object_new_object();
+ json_object_int_add(json, "totalGroups", pim->gm_group_count);
+ json_object_int_add(json, "watermarkLimit",
+ pim->gm_watermark_limit);
+ } else {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Interface|Group|Version|Uptime");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+
+ vty_out(vty, "Total MLD groups: %u\n", pim->gm_group_count);
+ vty_out(vty, "Watermark warn limit(%s): %u\n",
+ pim->gm_watermark_limit ? "Set" : "Not Set",
+ pim->gm_watermark_limit);
+ }
+
+ /* scan interfaces */
+ FOR_ALL_INTERFACES (vrf, ifp) {
+
+ struct pim_interface *pim_ifp = ifp->info;
+ struct gm_if *gm_ifp;
+ struct gm_sg *sg;
+
+ if (!pim_ifp)
+ continue;
+
+ gm_ifp = pim_ifp->mld;
+ if (!gm_ifp)
+ continue;
+
+ /* scan mld groups */
+ frr_each (gm_sgs, gm_ifp->sgs, sg) {
+
+ if (uj) {
+ json_object_object_get_ex(json, ifp->name,
+ &json_iface);
+
+ if (!json_iface) {
+ json_iface = json_object_new_object();
+ json_object_pim_ifp_add(json_iface,
+ ifp);
+ json_object_object_add(json, ifp->name,
+ json_iface);
+ json_groups = json_object_new_array();
+ json_object_object_add(json_iface,
+ "groups",
+ json_groups);
+ }
+
+ json_group = json_object_new_object();
+ json_object_string_addf(json_group, "group",
+ "%pPAs",
+ &sg->sgaddr.grp);
+
+ json_object_int_add(json_group, "version",
+ pim_ifp->mld_version);
+ json_object_string_addf(json_group, "uptime",
+ "%pTVMs", &sg->created);
+ json_object_array_add(json_groups, json_group);
+ } else {
+ ttable_add_row(tt, "%s|%pPAs|%d|%pTVMs",
+ ifp->name, &sg->sgaddr.grp,
+ pim_ifp->mld_version,
+ &sg->created);
+ }
+ } /* scan gm groups */
+ } /* scan interfaces */
+
+ if (uj)
+ vty_json(vty, json);
+ else {
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
+}
+
+DEFPY(gm_show_mld_groups,
+ gm_show_mld_groups_cmd,
+ "show ipv6 mld [vrf <VRF|all>$vrf_str] groups [json$json]",
+ SHOW_STR
+ IPV6_STR
+ MLD_STR
+ VRF_FULL_CMD_HELP_STR
+ MLD_GROUP_STR
+ JSON_STR)
+{
+ int ret = CMD_SUCCESS;
+ struct vrf *vrf;
+
+ vrf = gm_cmd_vrf_lookup(vty, vrf_str, &ret);
+ if (ret != CMD_SUCCESS)
+ return ret;
+
+ if (vrf)
+ gm_show_groups(vty, vrf, !!json);
+ else
+ RB_FOREACH (vrf, vrf_name_head, &vrfs_by_name)
+ gm_show_groups(vty, vrf, !!json);
+
+ return CMD_SUCCESS;
+}
+
DEFPY(gm_debug_show,
gm_debug_show_cmd,
"debug show mld interface IFNAME",
@@ -3005,6 +3166,7 @@ void gm_cli_init(void)
install_element(VIEW_NODE, &gm_show_interface_cmd);
install_element(VIEW_NODE, &gm_show_interface_stats_cmd);
install_element(VIEW_NODE, &gm_show_interface_joins_cmd);
+ install_element(VIEW_NODE, &gm_show_mld_groups_cmd);
install_element(VIEW_NODE, &gm_debug_show_cmd);
install_element(INTERFACE_NODE, &gm_debug_iface_cfg_cmd);
diff --git a/pimd/pim6_mld.h b/pimd/pim6_mld.h
index 9c7a637007..540d2e1899 100644
--- a/pimd/pim6_mld.h
+++ b/pimd/pim6_mld.h
@@ -324,6 +324,7 @@ struct gm_if {
unsigned int cur_query_intv_trig; /* ms */
unsigned int cur_max_resp; /* ms */
enum gm_version cur_version;
+ int cur_lmqc; /* last member query count in ds */
/* this value (positive, default 10ms) defines our "timing tolerance":
* - added to deadlines for expiring joins
@@ -352,6 +353,7 @@ struct gm_if {
#if PIM_IPV == 6
extern void gm_ifp_update(struct interface *ifp);
extern void gm_ifp_teardown(struct interface *ifp);
+extern void gm_group_delete(struct gm_if *gm_ifp);
#else
static inline void gm_ifp_update(struct interface *ifp)
{
diff --git a/pimd/pim_addr.h b/pimd/pim_addr.h
index 2f0743b570..d15e978855 100644
--- a/pimd/pim_addr.h
+++ b/pimd/pim_addr.h
@@ -31,12 +31,16 @@ typedef struct in_addr pim_addr;
#define PIM_ADDRSTRLEN INET_ADDRSTRLEN
#define PIM_AF AF_INET
#define PIM_AFI AFI_IP
+#define PIM_PROTO_REG IPPROTO_RAW
#define PIM_IPADDR IPADDR_V4
#define ipaddr_pim ipaddr_v4
#define PIM_MAX_BITLEN IPV4_MAX_BITLEN
#define PIM_AF_NAME "ip"
#define PIM_AF_DBG "pim"
+#define GM_AF_DBG "igmp"
+#define PIM_MROUTE_DBG "mroute"
#define PIMREG "pimreg"
+#define GM "IGMP"
#define PIM_ADDR_FUNCNAME(name) ipv4_##name
@@ -56,12 +60,16 @@ typedef struct in6_addr pim_addr;
#define PIM_ADDRSTRLEN INET6_ADDRSTRLEN
#define PIM_AF AF_INET6
#define PIM_AFI AFI_IP6
+#define PIM_PROTO_REG IPPROTO_PIM
#define PIM_IPADDR IPADDR_V6
#define ipaddr_pim ipaddr_v6
#define PIM_MAX_BITLEN IPV6_MAX_BITLEN
#define PIM_AF_NAME "ipv6"
#define PIM_AF_DBG "pimv6"
+#define GM_AF_DBG "mld"
+#define PIM_MROUTE_DBG "mroute6"
#define PIMREG "pim6reg"
+#define GM "MLD"
#define PIM_ADDR_FUNCNAME(name) ipv6_##name
diff --git a/pimd/pim_cmd.c b/pimd/pim_cmd.c
index 9681493808..c2f7396c18 100644
--- a/pimd/pim_cmd.c
+++ b/pimd/pim_cmd.c
@@ -1129,11 +1129,11 @@ static void igmp_show_groups(struct pim_instance *pim, struct vty *vty, bool uj)
if (uj) {
json = json_object_new_object();
- json_object_int_add(json, "totalGroups", pim->igmp_group_count);
+ json_object_int_add(json, "totalGroups", pim->gm_group_count);
json_object_int_add(json, "watermarkLimit",
pim->gm_watermark_limit);
} else {
- vty_out(vty, "Total IGMP groups: %u\n", pim->igmp_group_count);
+ vty_out(vty, "Total IGMP groups: %u\n", pim->gm_group_count);
vty_out(vty, "Watermark warn limit(%s): %u\n",
pim->gm_watermark_limit ? "Set" : "Not Set",
pim->gm_watermark_limit);
@@ -1678,50 +1678,17 @@ DEFPY (clear_ip_pim_interfaces,
return CMD_SUCCESS;
}
-DEFUN (clear_ip_pim_interface_traffic,
+DEFPY (clear_ip_pim_interface_traffic,
clear_ip_pim_interface_traffic_cmd,
"clear ip pim [vrf NAME] interface traffic",
- "Reset functions\n"
- "IP information\n"
- "PIM clear commands\n"
+ CLEAR_STR
+ IP_STR
+ CLEAR_IP_PIM_STR
VRF_CMD_HELP_STR
"Reset PIM interfaces\n"
"Reset Protocol Packet counters\n")
{
- int idx = 2;
- struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
- struct interface *ifp = NULL;
- struct pim_interface *pim_ifp = NULL;
-
- if (!vrf)
- return CMD_WARNING;
-
- FOR_ALL_INTERFACES (vrf, ifp) {
- pim_ifp = ifp->info;
-
- if (!pim_ifp)
- continue;
-
- pim_ifp->pim_ifstat_hello_recv = 0;
- pim_ifp->pim_ifstat_hello_sent = 0;
- pim_ifp->pim_ifstat_join_recv = 0;
- pim_ifp->pim_ifstat_join_send = 0;
- pim_ifp->pim_ifstat_prune_recv = 0;
- pim_ifp->pim_ifstat_prune_send = 0;
- pim_ifp->pim_ifstat_reg_recv = 0;
- pim_ifp->pim_ifstat_reg_send = 0;
- pim_ifp->pim_ifstat_reg_stop_recv = 0;
- pim_ifp->pim_ifstat_reg_stop_send = 0;
- pim_ifp->pim_ifstat_assert_recv = 0;
- pim_ifp->pim_ifstat_assert_send = 0;
- pim_ifp->pim_ifstat_bsm_rx = 0;
- pim_ifp->pim_ifstat_bsm_tx = 0;
- pim_ifp->igmp_ifstat_joins_sent = 0;
- pim_ifp->igmp_ifstat_joins_failed = 0;
- pim_ifp->igmp_peak_group_count = 0;
- }
-
- return CMD_SUCCESS;
+ return clear_pim_interface_traffic(vrf, vty);
}
DEFPY (clear_ip_pim_oil,
@@ -4391,9 +4358,9 @@ DEFUN (debug_igmp,
DEBUG_STR
DEBUG_IGMP_STR)
{
- PIM_DO_DEBUG_IGMP_EVENTS;
- PIM_DO_DEBUG_IGMP_PACKETS;
- PIM_DO_DEBUG_IGMP_TRACE;
+ PIM_DO_DEBUG_GM_EVENTS;
+ PIM_DO_DEBUG_GM_PACKETS;
+ PIM_DO_DEBUG_GM_TRACE;
return CMD_SUCCESS;
}
@@ -4404,9 +4371,9 @@ DEFUN (no_debug_igmp,
DEBUG_STR
DEBUG_IGMP_STR)
{
- PIM_DONT_DEBUG_IGMP_EVENTS;
- PIM_DONT_DEBUG_IGMP_PACKETS;
- PIM_DONT_DEBUG_IGMP_TRACE;
+ PIM_DONT_DEBUG_GM_EVENTS;
+ PIM_DONT_DEBUG_GM_PACKETS;
+ PIM_DONT_DEBUG_GM_TRACE;
return CMD_SUCCESS;
}
@@ -4418,7 +4385,7 @@ DEFUN (debug_igmp_events,
DEBUG_IGMP_STR
DEBUG_IGMP_EVENTS_STR)
{
- PIM_DO_DEBUG_IGMP_EVENTS;
+ PIM_DO_DEBUG_GM_EVENTS;
return CMD_SUCCESS;
}
@@ -4430,7 +4397,7 @@ DEFUN (no_debug_igmp_events,
DEBUG_IGMP_STR
DEBUG_IGMP_EVENTS_STR)
{
- PIM_DONT_DEBUG_IGMP_EVENTS;
+ PIM_DONT_DEBUG_GM_EVENTS;
return CMD_SUCCESS;
}
@@ -4442,7 +4409,7 @@ DEFUN (debug_igmp_packets,
DEBUG_IGMP_STR
DEBUG_IGMP_PACKETS_STR)
{
- PIM_DO_DEBUG_IGMP_PACKETS;
+ PIM_DO_DEBUG_GM_PACKETS;
return CMD_SUCCESS;
}
@@ -4454,7 +4421,7 @@ DEFUN (no_debug_igmp_packets,
DEBUG_IGMP_STR
DEBUG_IGMP_PACKETS_STR)
{
- PIM_DONT_DEBUG_IGMP_PACKETS;
+ PIM_DONT_DEBUG_GM_PACKETS;
return CMD_SUCCESS;
}
@@ -4466,7 +4433,7 @@ DEFUN (debug_igmp_trace,
DEBUG_IGMP_STR
DEBUG_IGMP_TRACE_STR)
{
- PIM_DO_DEBUG_IGMP_TRACE;
+ PIM_DO_DEBUG_GM_TRACE;
return CMD_SUCCESS;
}
@@ -4478,7 +4445,7 @@ DEFUN (no_debug_igmp_trace,
DEBUG_IGMP_STR
DEBUG_IGMP_TRACE_STR)
{
- PIM_DONT_DEBUG_IGMP_TRACE;
+ PIM_DONT_DEBUG_GM_TRACE;
return CMD_SUCCESS;
}
@@ -4491,7 +4458,7 @@ DEFUN (debug_igmp_trace_detail,
DEBUG_IGMP_TRACE_STR
"detailed\n")
{
- PIM_DO_DEBUG_IGMP_TRACE_DETAIL;
+ PIM_DO_DEBUG_GM_TRACE_DETAIL;
return CMD_SUCCESS;
}
@@ -4504,7 +4471,7 @@ DEFUN (no_debug_igmp_trace_detail,
DEBUG_IGMP_TRACE_STR
"detailed\n")
{
- PIM_DONT_DEBUG_IGMP_TRACE_DETAIL;
+ PIM_DONT_DEBUG_GM_TRACE_DETAIL;
return CMD_SUCCESS;
}
@@ -5559,12 +5526,13 @@ DEFUN (show_ip_msdp_mesh_group,
int idx = 2;
struct pim_msdp_mg *mg;
struct vrf *vrf = pim_cmd_lookup_vrf(vty, argv, argc, &idx);
- struct pim_instance *pim = vrf->info;
+ struct pim_instance *pim;
struct json_object *json = NULL;
if (!vrf)
return CMD_WARNING;
+ pim = vrf->info;
/* Quick case: list is empty. */
if (SLIST_EMPTY(&pim->msdp.mglist)) {
if (uj)
diff --git a/pimd/pim_cmd_common.c b/pimd/pim_cmd_common.c
index b7bd7375c5..9283016d08 100644
--- a/pimd/pim_cmd_common.c
+++ b/pimd/pim_cmd_common.c
@@ -32,6 +32,7 @@
#include "ferr.h"
#include "lib/srcdest_table.h"
#include "lib/linklist.h"
+#include "termtable.h"
#include "pimd.h"
#include "pim_instance.h"
@@ -56,6 +57,7 @@
#include "pim_addr.h"
#include "pim_static.h"
#include "pim_util.h"
+#include "pim6_mld.h"
/**
* Get current node VRF name.
@@ -886,6 +888,8 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
{
struct pim_upstream *up;
time_t now = pim_time_monotonic_sec();
+ struct ttable *tt = NULL;
+ char *table = NULL;
json_object *json_group = NULL;
json_object *json_row = NULL;
@@ -893,8 +897,15 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
if (!json) {
vty_out(vty, "\n");
- vty_out(vty,
- "Source Group RpfIface RpfAddress RibNextHop Metric Pref\n");
+
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Source|Group|RpfIface|RpfAddress|RibNextHop|Metric|Pref");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
}
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
@@ -942,8 +953,8 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
json_object_object_add(json_group, src_str, json_row);
} else {
- vty_out(vty,
- "%-15pPAs %-15pPAs %-16s %-15pPA %-15pPAs %6d %4d\n",
+ ttable_add_row(
+ tt, "%pPAs|%pPAs|%s|%pPA|%pPAs|%d|%d",
&up->sg.src, &up->sg.grp, rpf_ifname,
&rpf->rpf_addr,
&rpf->source_nexthop.mrib_nexthop_addr,
@@ -951,14 +962,27 @@ void pim_show_rpf(struct pim_instance *pim, struct vty *vty, json_object *json)
rpf->source_nexthop.mrib_metric_preference);
}
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
{
struct interface *ifp;
+ struct ttable *tt = NULL;
+ char *table = NULL;
- vty_out(vty,
- "Interface Address Neighbor Secondary \n");
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Interface|Address|Neighbor|Secondary");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
FOR_ALL_INTERFACES (pim->vrf, ifp) {
struct pim_interface *pim_ifp;
@@ -986,12 +1010,16 @@ void pim_show_neighbors_secondary(struct pim_instance *pim, struct vty *vty)
for (ALL_LIST_ELEMENTS_RO(neigh->prefix_list,
prefix_node, p))
- vty_out(vty,
- "%-16s %-15pPAs %-15pPAs %-15pFX\n",
- ifp->name, &ifaddr, &neigh->source_addr,
- p);
+ ttable_add_row(tt, "%s|%pPAs|%pPAs|%pFX",
+ ifp->name, &ifaddr,
+ &neigh->source_addr, p);
}
}
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
}
void pim_show_state(struct pim_instance *pim, struct vty *vty,
@@ -999,6 +1027,11 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty,
json_object *json)
{
struct channel_oil *c_oil;
+#if PIM_IPV != 4
+ struct ttable *tt = NULL;
+ char *table = NULL;
+#endif
+ char flag[50];
json_object *json_group = NULL;
json_object *json_ifp_in = NULL;
json_object *json_ifp_out = NULL;
@@ -1010,9 +1043,18 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty,
if (!json) {
vty_out(vty,
- "Codes: J -> Pim Join, I -> IGMP Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted");
+ "Codes: J -> Pim Join, I -> " GM " Report, S -> Source, * -> Inherited from (*,G), V -> VxLAN, M -> Muted\n");
+#if PIM_IPV == 4
vty_out(vty,
- "\nActive Source Group RPT IIF OIL\n");
+ "Active Source Group RPT IIF OIL\n");
+#else
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Active|Source|Group|RPT|IIF|OIL");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+#endif
}
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil) {
@@ -1125,11 +1167,14 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty,
"wrongInterface",
c_oil->cc.wrong_if);
}
- } else
+ }
+#if PIM_IPV == 4
+ else
vty_out(vty, "%-6d %-15pPAs %-15pPAs %-3s %-16s ",
c_oil->installed, oil_origin(c_oil),
oil_mcastgrp(c_oil), isRpt ? "y" : "n",
in_ifname);
+#endif
for (oif_vif_index = 0; oif_vif_index < MAXVIFS;
++oif_vif_index) {
@@ -1171,72 +1216,72 @@ void pim_show_state(struct pim_instance *pim, struct vty *vty,
json_object_object_add(json_ifp_in, out_ifname,
json_ifp_out);
} else {
+ flag[0] = '\0';
+ snprintf(flag, sizeof(flag), "(%c%c%c%c%c)",
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_GM)
+ ? 'I'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_PIM)
+ ? 'J'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_VXLAN)
+ ? 'V'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_PROTO_STAR)
+ ? '*'
+ : ' ',
+ (c_oil->oif_flags[oif_vif_index] &
+ PIM_OIF_FLAG_MUTE)
+ ? 'M'
+ : ' ');
+
if (first_oif) {
first_oif = 0;
- vty_out(vty, "%s(%c%c%c%c%c)",
- out_ifname,
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_GM)
- ? 'I'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_PIM)
- ? 'J'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_VXLAN)
- ? 'V'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_STAR)
- ? '*'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_MUTE)
- ? 'M'
- : ' ');
- } else
- vty_out(vty, ", %s(%c%c%c%c%c)",
- out_ifname,
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_GM)
- ? 'I'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_PIM)
- ? 'J'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_VXLAN)
- ? 'V'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_PROTO_STAR)
- ? '*'
- : ' ',
- (c_oil->oif_flags
- [oif_vif_index] &
- PIM_OIF_FLAG_MUTE)
- ? 'M'
- : ' ');
+#if PIM_IPV == 4
+ vty_out(vty, "%s%s", out_ifname, flag);
+#else
+ ttable_add_row(
+ tt, "%d|%pPAs|%pPAs|%s|%s|%s%s",
+ c_oil->installed,
+ oil_origin(c_oil),
+ oil_mcastgrp(c_oil),
+ isRpt ? "y" : "n", in_ifname,
+ out_ifname, flag);
+#endif
+ } else {
+#if PIM_IPV == 4
+ vty_out(vty, ", %s%s", out_ifname,
+ flag);
+#else
+ ttable_add_row(tt,
+ "%c|%c|%c|%c|%c|%s%s",
+ ' ', ' ', ' ', ' ', ' ',
+ out_ifname, flag);
+#endif
+ }
}
}
-
+#if PIM_IPV == 4
if (!json)
vty_out(vty, "\n");
+#endif
}
- if (!json)
+ /* Dump the generated table. */
+ if (!json) {
+#if PIM_IPV == 4
vty_out(vty, "\n");
+#else
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+#endif
+ }
}
/* pim statistics - just adding only bsm related now.
@@ -1315,15 +1360,24 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
pim_sgaddr *sg, json_object *json)
{
struct pim_upstream *up;
+ struct ttable *tt = NULL;
+ char *table = NULL;
time_t now;
json_object *json_group = NULL;
json_object *json_row = NULL;
now = pim_time_monotonic_sec();
- if (!json)
- vty_out(vty,
- "Iif Source Group State Uptime JoinTimer RSTimer KATimer RefCnt\n");
+ if (!json) {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Iif|Source|Group|State|Uptime|JoinTimer|RSTimer|KATimer|RefCnt");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
char uptime[10];
@@ -1444,8 +1498,8 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
json_object_int_add(json_row, "sptBit", up->sptbit);
json_object_object_add(json_group, src_str, json_row);
} else {
- vty_out(vty,
- "%-16s%-15pPAs %-15pPAs %-11s %-8s %-9s %-9s %-9s %6d\n",
+ ttable_add_row(tt,
+ "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s|%d",
up->rpf.source_nexthop.interface
? up->rpf.source_nexthop.interface->name
: "Unknown",
@@ -1453,12 +1507,20 @@ void pim_show_upstream(struct pim_instance *pim, struct vty *vty,
join_timer, rs_timer, ka_timer, up->ref_count);
}
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
static void pim_show_join_desired_helper(struct pim_instance *pim,
struct vty *vty,
struct pim_upstream *up,
- json_object *json, bool uj)
+ json_object *json, bool uj,
+ struct ttable *tt)
{
json_object *json_group = NULL;
json_object *json_row = NULL;
@@ -1489,45 +1551,68 @@ static void pim_show_join_desired_helper(struct pim_instance *pim,
json_object_object_add(json_group, src_str, json_row);
} else {
- vty_out(vty, "%-15pPAs %-15pPAs %-6s\n", &up->sg.src,
- &up->sg.grp,
- pim_upstream_evaluate_join_desired(pim, up) ? "yes"
- : "no");
+ ttable_add_row(tt, "%pPAs|%pPAs|%s", &up->sg.src, &up->sg.grp,
+ pim_upstream_evaluate_join_desired(pim, up)
+ ? "yes"
+ : "no");
}
}
void pim_show_join_desired(struct pim_instance *pim, struct vty *vty, bool uj)
{
struct pim_upstream *up;
+ struct ttable *tt = NULL;
+ char *table = NULL;
json_object *json = NULL;
if (uj)
json = json_object_new_object();
- else
- vty_out(vty, "Source Group EvalJD\n");
+ else {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Source|Group|EvalJD");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
/* scan all interfaces */
- pim_show_join_desired_helper(pim, vty, up, json, uj);
+ pim_show_join_desired_helper(pim, vty, up, json, uj, tt);
}
if (uj)
vty_json(vty, json);
+ else {
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
{
struct pim_upstream *up;
+ struct ttable *tt = NULL;
+ char *table = NULL;
json_object *json = NULL;
json_object *json_group = NULL;
json_object *json_row = NULL;
if (uj)
json = json_object_new_object();
- else
- vty_out(vty,
- "Source Group RpfIface RibNextHop RpfAddress \n");
+ else {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt,
+ "Source|Group|RpfIface|RibNextHop|RpfAddress");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
frr_each (rb_pim_upstream, &pim->upstream_head, up) {
struct pim_rpf *rpf;
@@ -1569,21 +1654,27 @@ void pim_show_upstream_rpf(struct pim_instance *pim, struct vty *vty, bool uj)
&rpf->rpf_addr);
json_object_object_add(json_group, src_str, json_row);
} else {
- vty_out(vty,
- "%-15pPAs %-15pPAs %-16s %-15pPA %-15pPA\n",
- &up->sg.src, &up->sg.grp, rpf_ifname,
- &rpf->source_nexthop.mrib_nexthop_addr,
- &rpf->rpf_addr);
+ ttable_add_row(tt, "%pPAs|%pPAs|%s|%pPA|%pPA",
+ &up->sg.src, &up->sg.grp, rpf_ifname,
+ &rpf->source_nexthop.mrib_nexthop_addr,
+ &rpf->rpf_addr);
}
}
if (uj)
vty_json(vty, json);
+ else {
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
-static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
+static void pim_show_join_helper(struct pim_interface *pim_ifp,
struct pim_ifchannel *ch, json_object *json,
- time_t now)
+ time_t now, struct ttable *tt)
{
json_object *json_iface = NULL;
json_object *json_row = NULL;
@@ -1650,8 +1741,8 @@ static void pim_show_join_helper(struct vty *vty, struct pim_interface *pim_ifp,
json_object_object_addf(json_grp, json_row, "%pPAs",
&ch->sg.src);
} else {
- vty_out(vty,
- "%-16s %-15pPAs %-15pPAs %-15pPAs %-10s %8s %-6s %5s\n",
+ ttable_add_row(
+ tt, "%s|%pPAs|%pPAs|%pPAs|%s|%s|%s|%s",
ch->interface->name, &ifaddr, &ch->sg.src, &ch->sg.grp,
pim_ifchannel_ifjoin_name(ch->ifjoin_state, ch->flags),
uptime, expire, prune);
@@ -1732,12 +1823,21 @@ void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
struct pim_ifchannel *ch;
struct interface *ifp;
time_t now;
+ struct ttable *tt = NULL;
+ char *table = NULL;
now = pim_time_monotonic_sec();
- if (!json)
- vty_out(vty,
- "Interface Address Source Group State Uptime Expire Prune\n");
+ if (!json) {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Interface|Address|Source|Group|State|Uptime|Expire|Prune");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
@@ -1748,18 +1848,26 @@ void pim_show_join(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
if (!pim_sgaddr_match(ch->sg, *sg))
continue;
- pim_show_join_helper(vty, pim_ifp, ch, json, now);
+ pim_show_join_helper(pim_ifp, ch, json, now, tt);
} /* scan interface channels */
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
-static void pim_show_jp_agg_helper(struct vty *vty, struct interface *ifp,
+static void pim_show_jp_agg_helper(struct interface *ifp,
struct pim_neighbor *neigh,
- struct pim_upstream *up, int is_join)
+ struct pim_upstream *up, int is_join,
+ struct ttable *tt)
{
- vty_out(vty, "%-16s %-15pPAs %-15pPAs %-15pPAs %5s\n", ifp->name,
- &neigh->source_addr, &up->sg.src, &up->sg.grp,
- is_join ? "J" : "P");
+ ttable_add_row(tt, "%s|%pPAs|%pPAs|%pPAs|%s", ifp->name,
+ &neigh->source_addr, &up->sg.src, &up->sg.grp,
+ is_join ? "J" : "P");
}
int pim_show_jp_agg_list_cmd_helper(const char *vrf, struct vty *vty)
@@ -1795,9 +1903,15 @@ void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
struct pim_jp_agg_group *jag;
struct listnode *js_node;
struct pim_jp_sources *js;
+ struct ttable *tt;
+ char *table;
- vty_out(vty,
- "Interface RPF Nbr Source Group State\n");
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Interface|RPF Nbr|Source|Group|State");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
FOR_ALL_INTERFACES (pim->vrf, ifp) {
pim_ifp = ifp->info;
@@ -1810,13 +1924,19 @@ void pim_show_jp_agg_list(struct pim_instance *pim, struct vty *vty)
jag_node, jag)) {
for (ALL_LIST_ELEMENTS_RO(jag->sources, js_node,
js)) {
- pim_show_jp_agg_helper(vty, ifp, neigh,
+ pim_show_jp_agg_helper(ifp, neigh,
js->up,
- js->is_join);
+ js->is_join, tt);
}
}
}
}
+
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
}
int pim_show_membership_cmd_helper(const char *vrf, struct vty *vty, bool uj)
@@ -1866,6 +1986,8 @@ void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
enum json_type type;
json_object *json = NULL;
json_object *json_tmp = NULL;
+ struct ttable *tt = NULL;
+ char *table = NULL;
json = json_object_new_object();
@@ -1882,8 +2004,12 @@ void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
if (uj) {
vty_json(vty, json);
} else {
- vty_out(vty,
- "Interface Address Source Group Membership\n");
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Interface|Address|Source|Group|Membership");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
/*
* Example of the json data we are traversing
@@ -1920,41 +2046,47 @@ void pim_show_membership(struct pim_instance *pim, struct vty *vty, bool uj)
type = json_object_get_type(if_field_val);
if (type == json_type_object) {
- vty_out(vty, "%-16s ", key);
+ const char *address, *source,
+ *localMembership;
json_object_object_get_ex(
val, "address", &json_tmp);
- vty_out(vty, "%-15s ",
- json_object_get_string(
- json_tmp));
+ address = json_object_get_string(
+ json_tmp);
json_object_object_get_ex(if_field_val,
"source",
&json_tmp);
- vty_out(vty, "%-15s ",
- json_object_get_string(
- json_tmp));
-
- /* Group */
- vty_out(vty, "%-15s ", if_field_key);
+ source = json_object_get_string(
+ json_tmp);
json_object_object_get_ex(
if_field_val, "localMembership",
&json_tmp);
- vty_out(vty, "%-10s\n",
+ localMembership =
json_object_get_string(
- json_tmp));
+ json_tmp);
+
+ ttable_add_row(tt, "%s|%s|%s|%s|%s",
+ key, address, source,
+ if_field_key,
+ localMembership);
}
}
}
json_object_free(json);
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
}
}
-static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
+static void pim_show_channel_helper(struct pim_instance *pim,
struct pim_interface *pim_ifp,
struct pim_ifchannel *ch, json_object *json,
- bool uj)
+ bool uj, struct ttable *tt)
{
struct pim_upstream *up = ch->upstream;
json_object *json_group = NULL;
@@ -1997,17 +2129,17 @@ static void pim_show_channel_helper(struct pim_instance *pim, struct vty *vty,
&up->sg.src);
} else {
- vty_out(vty,
- "%-16s %-15pPAs %-15pPAs %-10s %-5s %-10s %-11s %-6s\n",
- ch->interface->name, &up->sg.src, &up->sg.grp,
- pim_macro_ch_lost_assert(ch) ? "yes" : "no",
- pim_macro_chisin_joins(ch) ? "yes" : "no",
- pim_macro_chisin_pim_include(ch) ? "yes" : "no",
- PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
- ? "yes"
- : "no",
- pim_upstream_evaluate_join_desired(pim, up) ? "yes"
- : "no");
+ ttable_add_row(tt, "%s|%pPAs|%pPAs|%s|%s|%s|%s|%s",
+ ch->interface->name, &up->sg.src, &up->sg.grp,
+ pim_macro_ch_lost_assert(ch) ? "yes" : "no",
+ pim_macro_chisin_joins(ch) ? "yes" : "no",
+ pim_macro_chisin_pim_include(ch) ? "yes" : "no",
+ PIM_UPSTREAM_FLAG_TEST_DR_JOIN_DESIRED(up->flags)
+ ? "yes"
+ : "no",
+ pim_upstream_evaluate_join_desired(pim, up)
+ ? "yes"
+ : "no");
}
}
@@ -2016,14 +2148,22 @@ void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
struct pim_interface *pim_ifp;
struct pim_ifchannel *ch;
struct interface *ifp;
-
+ struct ttable *tt = NULL;
json_object *json = NULL;
+ char *table = NULL;
if (uj)
json = json_object_new_object();
- else
- vty_out(vty,
- "Interface Source Group LostAssert Joins PimInclude JoinDesired EvalJD\n");
+ else {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Interface|Source|Group|LostAssert|Joins|PimInclude|JoinDesired|EvalJD");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
/* scan per-interface (S,G) state */
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -2031,16 +2171,21 @@ void pim_show_channel(struct pim_instance *pim, struct vty *vty, bool uj)
if (!pim_ifp)
continue;
-
RB_FOREACH (ch, pim_ifchannel_rb, &pim_ifp->ifchannel_rb) {
/* scan all interfaces */
- pim_show_channel_helper(pim, vty, pim_ifp, ch, json,
- uj);
+ pim_show_channel_helper(pim, pim_ifp, ch, json, uj, tt);
}
}
if (uj)
vty_json(vty, json);
+ else {
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
int pim_show_channel_cmd_helper(const char *vrf, struct vty *vty, bool uj)
@@ -2124,6 +2269,8 @@ void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
int pim_nbrs = 0;
int pim_ifchannels = 0;
bool uj = true;
+ struct ttable *tt = NULL;
+ char *table = NULL;
json_object *json_row = NULL;
json_object *json_tmp;
@@ -2167,43 +2314,61 @@ void pim_show_interfaces(struct pim_instance *pim, struct vty *vty, bool mlag,
}
if (!uj) {
- vty_out(vty,
- "Interface State Address PIM Nbrs PIM DR FHR IfChannels\n");
+
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Interface|State|Address|PIM Nbrs|PIM DR|FHR|IfChannels");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
json_object_object_foreach(json, key, val)
{
- vty_out(vty, "%-16s ", key);
+ const char *state, *address, *pimdr;
+ int neighbors, firsthpr, pimifchnl;
json_object_object_get_ex(val, "state", &json_tmp);
- vty_out(vty, "%5s ", json_object_get_string(json_tmp));
+ state = json_object_get_string(json_tmp);
json_object_object_get_ex(val, "address", &json_tmp);
- vty_out(vty, "%15s ",
- json_object_get_string(json_tmp));
+ address = json_object_get_string(json_tmp);
json_object_object_get_ex(val, "pimNeighbors",
&json_tmp);
- vty_out(vty, "%8d ", json_object_get_int(json_tmp));
+ neighbors = json_object_get_int(json_tmp);
if (json_object_object_get_ex(
val, "pimDesignatedRouterLocal",
&json_tmp)) {
- vty_out(vty, "%15s ", "local");
+ pimdr = "local";
} else {
json_object_object_get_ex(
val, "pimDesignatedRouter", &json_tmp);
- vty_out(vty, "%15s ",
- json_object_get_string(json_tmp));
+ pimdr = json_object_get_string(json_tmp);
}
json_object_object_get_ex(val, "firstHopRouter",
&json_tmp);
- vty_out(vty, "%3d ", json_object_get_int(json_tmp));
+ firsthpr = json_object_get_int(json_tmp);
json_object_object_get_ex(val, "pimIfChannels",
&json_tmp);
- vty_out(vty, "%9d\n", json_object_get_int(json_tmp));
+ pimifchnl = json_object_get_int(json_tmp);
+
+ ttable_add_row(tt, "%s|%s|%s|%d|%s|%d|%d", key, state,
+ address, neighbors, pimdr, firsthpr,
+ pimifchnl);
}
+ json_object_free(json);
+
+ /* Dump the generated table. */
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+
+ ttable_del(tt);
}
}
@@ -3059,6 +3224,8 @@ void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
struct interface *ifp;
struct pim_interface *pim_ifp;
struct pim_neighbor *neigh;
+ struct ttable *tt = NULL;
+ char *table = NULL;
time_t now;
char uptime[10];
char expire[10];
@@ -3069,8 +3236,12 @@ void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
now = pim_time_monotonic_sec();
if (!json) {
- vty_out(vty,
- "Interface Neighbor Uptime Holdtime DR Pri\n");
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt, "Interface|Neighbor|Uptime|Holdtime|DR Pri");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
}
FOR_ALL_INTERFACES (pim->vrf, ifp) {
@@ -3112,9 +3283,10 @@ void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
neigh_src_str, json_row);
} else {
- vty_out(vty, "%-16s %15s %8s %8s %6d\n",
- ifp->name, neigh_src_str, uptime,
- expire, neigh->dr_priority);
+ ttable_add_row(tt, "%s|%pPAs|%s|%s|%d",
+ ifp->name, &neigh->source_addr,
+ uptime, expire,
+ neigh->dr_priority);
}
}
@@ -3123,6 +3295,13 @@ void pim_show_neighbors(struct pim_instance *pim, struct vty *vty,
json_ifp_rows = NULL;
}
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
int gm_process_query_max_response_time_cmd(struct vty *vty,
@@ -3264,13 +3443,22 @@ void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
json_object *json)
{
struct interface *ifp;
+ struct ttable *tt = NULL;
+ char *table = NULL;
json_object *json_row = NULL;
vty_out(vty, "\n");
- if (!json)
- vty_out(vty,
- "Interface Address ifi Vif PktsIn PktsOut BytesIn BytesOut\n");
+ if (!json) {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "Interface|Address|ifi|Vif|PktsIn|PktsOut|BytesIn|BytesOut");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
FOR_ALL_INTERFACES (pim->vrf, ifp) {
struct pim_interface *pim_ifp;
@@ -3326,16 +3514,22 @@ void show_multicast_interfaces(struct pim_instance *pim, struct vty *vty,
(unsigned long)vreq.obytes);
json_object_object_add(json, ifp->name, json_row);
} else {
- vty_out(vty,
- "%-16s %-15pPAs %3d %3d %7lu %7lu %10lu %10lu\n",
- ifp->name, &pim_ifp->primary_address,
- ifp->ifindex, pim_ifp->mroute_vif_index,
- (unsigned long)vreq.icount,
- (unsigned long)vreq.ocount,
- (unsigned long)vreq.ibytes,
- (unsigned long)vreq.obytes);
+ ttable_add_row(tt, "%s|%pPAs|%d|%d|%lu|%lu|%lu|%lu",
+ ifp->name, &pim_ifp->primary_address,
+ ifp->ifindex, pim_ifp->mroute_vif_index,
+ (unsigned long)vreq.icount,
+ (unsigned long)vreq.ocount,
+ (unsigned long)vreq.ibytes,
+ (unsigned long)vreq.obytes);
}
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
@@ -3352,6 +3546,8 @@ void pim_cmd_show_ip_multicast_helper(struct pim_instance *pim, struct vty *vty)
vty_out(vty, "Mroute socket descriptor:");
vty_out(vty, " %d(%s)\n", pim->mroute_socket, vrf->name);
+ vty_out(vty, "PIM Register socket descriptor:");
+ vty_out(vty, " %d(%s)\n", pim->reg_sock, vrf->name);
pim_time_uptime(uptime, sizeof(uptime),
now - pim->mroute_socket_creation);
@@ -3389,6 +3585,8 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
struct listnode *node;
struct channel_oil *c_oil;
struct static_route *s_route;
+ struct ttable *tt = NULL;
+ char *table = NULL;
time_t now;
json_object *json_group = NULL;
json_object *json_source = NULL;
@@ -3411,8 +3609,14 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
vty_out(vty, "Flags: S - Sparse, C - Connected, P - Pruned\n");
vty_out(vty,
" R - SGRpt Pruned, F - Register flag, T - SPT-bit set\n");
- vty_out(vty,
- "\nSource Group Flags Proto Input Output TTL Uptime\n");
+
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt, "Source|Group|Flags|Proto|Input|Output|TTL|Uptime");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
}
now = pim_time_monotonic_sec();
@@ -3616,11 +3820,10 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
strlcpy(proto, "STAR", sizeof(proto));
}
- vty_out(vty,
- "%-15s %-15s %-8s %-6s %-16s %-16s %-3d %8s\n",
- src_str, grp_str, state_str, proto,
- in_ifname, out_ifname, ttl,
- mroute_uptime);
+ ttable_add_row(tt, "%s|%s|%s|%s|%s|%s|%d|%s",
+ src_str, grp_str, state_str,
+ proto, in_ifname, out_ifname,
+ ttl, mroute_uptime);
if (first) {
src_str[0] = '\0';
@@ -3634,11 +3837,10 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
}
if (!json && !found_oif) {
- vty_out(vty,
- "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n",
- oil_origin(c_oil), oil_mcastgrp(c_oil),
- state_str, "none", in_ifname, "none", 0,
- "--:--:--");
+ ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
+ oil_origin(c_oil), oil_mcastgrp(c_oil),
+ state_str, "none", in_ifname, "none", 0,
+ "--:--:--");
}
}
@@ -3742,8 +3944,8 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
json_object_object_add(json_oil, out_ifname,
json_ifp_out);
} else {
- vty_out(vty,
- "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n",
+ ttable_add_row(
+ tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
&s_route->source, &s_route->group, "-",
proto, in_ifname, out_ifname, ttl,
oif_uptime);
@@ -3757,17 +3959,23 @@ void show_mroute(struct pim_instance *pim, struct vty *vty, pim_sgaddr *sg,
}
if (!json && !found_oif) {
- vty_out(vty,
- "%-15pPAs %-15pPAs %-8s %-6s %-16s %-16s %-3d %8s\n",
- &s_route->source, &s_route->group, "-", proto,
- in_ifname, "none", 0, "--:--:--");
+ ttable_add_row(tt, "%pPAs|%pPAs|%s|%s|%s|%s|%d|%s",
+ &s_route->source, &s_route->group, "-",
+ proto, in_ifname, "none", 0, "--:--:--");
}
}
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
json_object *json,
- struct vty *vty)
+ struct ttable *tt)
{
json_object *json_group = NULL;
json_object *json_source = NULL;
@@ -3802,12 +4010,12 @@ static void show_mroute_count_per_channel_oil(struct channel_oil *c_oil,
json_object_int_add(json_source, "wrongIf", c_oil->cc.wrong_if);
} else {
- vty_out(vty, "%-15pPAs %-15pPAs %-8llu %-7ld %-10ld %-7ld\n",
- oil_origin(c_oil), oil_mcastgrp(c_oil),
- c_oil->cc.lastused / 100,
- c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
- c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
- c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
+ ttable_add_row(tt, "%pPAs|%pPAs|%llu|%ld|%ld|%ld",
+ oil_origin(c_oil), oil_mcastgrp(c_oil),
+ c_oil->cc.lastused / 100,
+ c_oil->cc.pktcnt - c_oil->cc.origpktcnt,
+ c_oil->cc.bytecnt - c_oil->cc.origbytecnt,
+ c_oil->cc.wrong_if - c_oil->cc.origwrong_if);
}
}
@@ -3817,20 +4025,35 @@ void show_mroute_count(struct pim_instance *pim, struct vty *vty,
struct listnode *node;
struct channel_oil *c_oil;
struct static_route *sr;
+ struct ttable *tt = NULL;
+ char *table = NULL;
if (!json) {
vty_out(vty, "\n");
- vty_out(vty,
- "Source Group LastUsed Packets Bytes WrongIf \n");
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(tt,
+ "Source|Group|LastUsed|Packets|Bytes|WrongIf");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
}
/* Print PIM and IGMP route counts */
frr_each (rb_pim_oil, &pim->channel_oil_head, c_oil)
- show_mroute_count_per_channel_oil(c_oil, json, vty);
+ show_mroute_count_per_channel_oil(c_oil, json, tt);
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, sr))
- show_mroute_count_per_channel_oil(&sr->c_oil, json, vty);
+ show_mroute_count_per_channel_oil(&sr->c_oil, json, tt);
+
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ }
}
void show_mroute_summary(struct pim_instance *pim, struct vty *vty,
@@ -3994,6 +4217,12 @@ void clear_mroute(struct pim_instance *pim)
igmp_group_delete(grp);
}
}
+#else
+ struct gm_if *gm_ifp;
+
+ gm_ifp = pim_ifp->mld;
+ if (gm_ifp)
+ gm_group_delete(gm_ifp);
#endif
}
@@ -4023,6 +4252,46 @@ void clear_pim_statistics(struct pim_instance *pim)
}
}
+int clear_pim_interface_traffic(const char *vrf, struct vty *vty)
+{
+ struct interface *ifp = NULL;
+ struct pim_interface *pim_ifp = NULL;
+
+ struct vrf *v = pim_cmd_lookup(vty, vrf);
+
+ if (!v)
+ return CMD_WARNING;
+
+ FOR_ALL_INTERFACES (v, ifp) {
+ pim_ifp = ifp->info;
+
+ if (!pim_ifp)
+ continue;
+
+ pim_ifp->pim_ifstat_hello_recv = 0;
+ pim_ifp->pim_ifstat_hello_sent = 0;
+ pim_ifp->pim_ifstat_join_recv = 0;
+ pim_ifp->pim_ifstat_join_send = 0;
+ pim_ifp->pim_ifstat_prune_recv = 0;
+ pim_ifp->pim_ifstat_prune_send = 0;
+ pim_ifp->pim_ifstat_reg_recv = 0;
+ pim_ifp->pim_ifstat_reg_send = 0;
+ pim_ifp->pim_ifstat_reg_stop_recv = 0;
+ pim_ifp->pim_ifstat_reg_stop_send = 0;
+ pim_ifp->pim_ifstat_assert_recv = 0;
+ pim_ifp->pim_ifstat_assert_send = 0;
+ pim_ifp->pim_ifstat_bsm_rx = 0;
+ pim_ifp->pim_ifstat_bsm_tx = 0;
+#if PIM_IPV == 4
+ pim_ifp->igmp_ifstat_joins_sent = 0;
+ pim_ifp->igmp_ifstat_joins_failed = 0;
+ pim_ifp->igmp_peak_group_count = 0;
+#endif
+ }
+
+ return CMD_SUCCESS;
+}
+
int pim_debug_pim_cmd(void)
{
PIM_DO_DEBUG_PIM_EVENTS;
@@ -4045,6 +4314,8 @@ int pim_no_debug_pim_cmd(void)
PIM_DONT_DEBUG_PIM_PACKETDUMP_SEND;
PIM_DONT_DEBUG_PIM_PACKETDUMP_RECV;
+ PIM_DONT_DEBUG_BSM;
+ PIM_DONT_DEBUG_VXLAN;
return CMD_SUCCESS;
}
diff --git a/pimd/pim_cmd_common.h b/pimd/pim_cmd_common.h
index 02acb16858..27c029670e 100644
--- a/pimd/pim_cmd_common.h
+++ b/pimd/pim_cmd_common.h
@@ -139,6 +139,7 @@ int clear_ip_mroute_count_command(struct vty *vty, const char *name);
struct vrf *pim_cmd_lookup(struct vty *vty, const char *name);
void clear_mroute(struct pim_instance *pim);
void clear_pim_statistics(struct pim_instance *pim);
+int clear_pim_interface_traffic(const char *vrf, struct vty *vty);
int pim_debug_pim_cmd(void);
int pim_no_debug_pim_cmd(void);
int pim_debug_pim_packets_cmd(const char *hello, const char *joins,
diff --git a/pimd/pim_hello.c b/pimd/pim_hello.c
index 833103c27f..03ce8687e5 100644
--- a/pimd/pim_hello.c
+++ b/pimd/pim_hello.c
@@ -389,8 +389,10 @@ int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf,
uint8_t *curr = tlv_buf;
uint8_t *pastend = tlv_buf + tlv_buf_size;
uint8_t *tmp;
+#if PIM_IPV == 4
struct pim_interface *pim_ifp = ifp->info;
struct pim_instance *pim = pim_ifp->pim;
+#endif
/*
* Append options
@@ -452,19 +454,20 @@ int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf,
/* Secondary Address List */
if (ifp->connected->count) {
- curr = pim_tlv_append_addrlist_ucast(curr, pastend,
- ifp->connected, AF_INET);
+ curr = pim_tlv_append_addrlist_ucast(curr, pastend, ifp,
+ PIM_AF);
if (!curr) {
if (PIM_DEBUG_PIM_HELLO) {
zlog_debug(
- "%s: could not set PIM hello v4 Secondary Address List option for interface %s",
- __func__, ifp->name);
+ "%s: could not set PIM hello %s Secondary Address List option for interface %s",
+ __func__, PIM_AF_NAME, ifp->name);
}
return -4;
}
+#if PIM_IPV == 4
if (pim->send_v6_secondary) {
- curr = pim_tlv_append_addrlist_ucast(
- curr, pastend, ifp->connected, AF_INET6);
+ curr = pim_tlv_append_addrlist_ucast(curr, pastend, ifp,
+ AF_INET6);
if (!curr) {
if (PIM_DEBUG_PIM_HELLO) {
zlog_debug(
@@ -474,6 +477,7 @@ int pim_hello_build_tlv(struct interface *ifp, uint8_t *tlv_buf,
return -4;
}
}
+#endif
}
return curr - tlv_buf;
diff --git a/pimd/pim_iface.c b/pimd/pim_iface.c
index 20a5a2f528..6f272f0085 100644
--- a/pimd/pim_iface.c
+++ b/pimd/pim_iface.c
@@ -115,7 +115,7 @@ static int pim_sec_addr_comp(const void *p1, const void *p2)
return 0;
}
-struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
+struct pim_interface *pim_if_new(struct interface *ifp, bool gm, bool pim,
bool ispimreg, bool is_vxlan_term)
{
struct pim_interface *pim_ifp;
@@ -131,13 +131,13 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_ifp->igmp_version = IGMP_DEFAULT_VERSION;
pim_ifp->mld_version = MLD_DEFAULT_VERSION;
pim_ifp->gm_default_robustness_variable =
- IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
- pim_ifp->gm_default_query_interval = IGMP_GENERAL_QUERY_INTERVAL;
+ GM_DEFAULT_ROBUSTNESS_VARIABLE;
+ pim_ifp->gm_default_query_interval = GM_GENERAL_QUERY_INTERVAL;
pim_ifp->gm_query_max_response_time_dsec =
- IGMP_QUERY_MAX_RESPONSE_TIME_DSEC;
+ GM_QUERY_MAX_RESPONSE_TIME_DSEC;
pim_ifp->gm_specific_query_max_response_time_dsec =
- IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
- pim_ifp->gm_last_member_query_count = IGMP_DEFAULT_ROBUSTNESS_VARIABLE;
+ GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC;
+ pim_ifp->gm_last_member_query_count = GM_DEFAULT_ROBUSTNESS_VARIABLE;
/* BSM config on interface: true by default */
pim_ifp->bsm_enable = true;
@@ -154,9 +154,7 @@ struct pim_interface *pim_if_new(struct interface *ifp, bool igmp, bool pim,
pim_ifp->pim_enable = pim;
pim_ifp->pim_passive_enable = false;
-#if PIM_IPV == 4
- pim_ifp->gm_enable = igmp;
-#endif
+ pim_ifp->gm_enable = gm;
pim_ifp->gm_join_list = NULL;
pim_ifp->pim_neighbor_list = NULL;
@@ -224,6 +222,9 @@ void pim_if_delete(struct interface *ifp)
list_delete(&pim_ifp->upstream_switch_list);
list_delete(&pim_ifp->sec_addr_list);
+ if (pim_ifp->bfd_config.profile)
+ XFREE(MTYPE_TMP, pim_ifp->bfd_config.profile);
+
XFREE(MTYPE_PIM_INTERFACE, pim_ifp->boundary_oil_plist);
XFREE(MTYPE_PIM_INTERFACE, pim_ifp);
@@ -801,25 +802,16 @@ void pim_if_addr_add_all(struct interface *ifp)
pim_if_addr_add(ifc);
}
- if (!v4_addrs && v6_addrs && !if_is_loopback(ifp)) {
- if (pim_ifp->pim_enable) {
-
- /* Interface has a valid primary address ? */
- if (!pim_addr_is_any(pim_ifp->primary_address)) {
-
- /* Interface has a valid socket ? */
- if (pim_ifp->pim_sock_fd < 0) {
- if (pim_sock_add(ifp)) {
- zlog_warn(
- "Failure creating PIM socket for interface %s",
- ifp->name);
- }
- }
- }
- } /* pim */
+ if (!v4_addrs && v6_addrs && !if_is_loopback(ifp) &&
+ pim_ifp->pim_enable && !pim_addr_is_any(pim_ifp->primary_address) &&
+ pim_ifp->pim_sock_fd < 0 && pim_sock_add(ifp)) {
+ /* Interface has a valid primary address ? */
+ /* Interface has a valid socket ? */
+ zlog_warn("Failure creating PIM socket for interface %s",
+ ifp->name);
}
/*
- * PIM or IGMP is enabled on interface, and there is at least one
+ * PIM or IGMP/MLD is enabled on interface, and there is at least one
* address assigned, then try to create a vif_index.
*/
if (pim_ifp->mroute_vif_index < 0) {
@@ -891,7 +883,7 @@ pim_addr pim_find_primary_addr(struct interface *ifp)
return pim_ifp->update_source;
#if PIM_IPV == 6
- if (pim_ifp)
+ if (pim_ifp && !pim_addr_is_any(pim_ifp->ll_highest))
return pim_ifp->ll_highest;
pim_addr best_addr = PIMADDR_ANY;
@@ -1356,7 +1348,7 @@ ferr_r pim_if_igmp_join_add(struct interface *ifp, struct in_addr group_addr,
(void)igmp_join_new(ifp, group_addr, source_addr);
- if (PIM_DEBUG_IGMP_EVENTS) {
+ if (PIM_DEBUG_GM_EVENTS) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<grp?>", group_addr, group_str,
diff --git a/pimd/pim_ifchannel.c b/pimd/pim_ifchannel.c
index ac2eee0a30..ce252366ce 100644
--- a/pimd/pim_ifchannel.c
+++ b/pimd/pim_ifchannel.c
@@ -539,10 +539,7 @@ struct pim_ifchannel *pim_ifchannel_add(struct interface *ifp, pim_sgaddr *sg,
if (up_flags == PIM_UPSTREAM_FLAG_MASK_SRC_IGMP)
PIM_IF_FLAG_SET_PROTO_IGMP(ch->flags);
- if (ch->upstream)
- ch->upstream->flags |= up_flags;
- else if (PIM_DEBUG_EVENTS)
- zlog_debug("%s:%pSG No Upstream found", __func__, sg);
+ ch->upstream->flags |= up_flags;
return ch;
}
@@ -637,8 +634,7 @@ static void ifjoin_to_noinfo(struct pim_ifchannel *ch)
pim_ifchannel_ifjoin_switch(__func__, ch, PIM_IFJOIN_NOINFO);
pim_forward_stop(ch);
- if (ch->upstream)
- PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags);
+ PIM_UPSTREAM_FLAG_UNSET_SRC_PIM(ch->upstream->flags);
PIM_IF_FLAG_UNSET_PROTO_PIM(ch->flags);
@@ -696,31 +692,29 @@ static void on_ifjoin_prune_pending_timer(struct thread *t)
* message on RP path upon prune timer expiry.
*/
ch->ifjoin_state = PIM_IFJOIN_PRUNE;
- if (ch->upstream) {
- struct pim_upstream *parent =
- ch->upstream->parent;
+ struct pim_upstream *parent =
+ ch->upstream->parent;
- pim_upstream_update_join_desired(pim_ifp->pim,
- ch->upstream);
+ pim_upstream_update_join_desired(pim_ifp->pim,
+ ch->upstream);
- pim_jp_agg_single_upstream_send(&parent->rpf,
- parent, true);
- /*
- * SGRpt prune pending expiry has to install
- * SG entry with empty olist to drop the SG
- * traffic incase no other intf exists.
- * On that scenario, SG entry wouldn't have
- * got installed until Prune pending timer
- * expired. So install now.
- */
- pim_channel_del_oif(
- ch->upstream->channel_oil, ifp,
- PIM_OIF_FLAG_PROTO_STAR, __func__);
- if (!ch->upstream->channel_oil->installed)
- pim_upstream_mroute_add(
- ch->upstream->channel_oil,
- __func__);
- }
+ pim_jp_agg_single_upstream_send(&parent->rpf,
+ parent, true);
+ /*
+ * SGRpt prune pending expiry has to install
+ * SG entry with empty olist to drop the SG
+ * traffic incase no other intf exists.
+ * On that scenario, SG entry wouldn't have
+ * got installed until Prune pending timer
+ * expired. So install now.
+ */
+ pim_channel_del_oif(
+ ch->upstream->channel_oil, ifp,
+ PIM_OIF_FLAG_PROTO_STAR, __func__);
+ if (!ch->upstream->channel_oil->installed)
+ pim_upstream_mroute_add(
+ ch->upstream->channel_oil,
+ __func__);
}
/* from here ch may have been deleted */
}
diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c
index 6ffeeb9657..308cba0697 100644
--- a/pimd/pim_igmp.c
+++ b/pimd/pim_igmp.c
@@ -175,7 +175,7 @@ void igmp_source_forward_start(struct pim_instance *pim,
sg.src = source->source_addr;
sg.grp = source->source_group->group_addr;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg,
source->source_group->interface->name,
IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
@@ -220,7 +220,7 @@ void igmp_source_forward_stop(struct gm_source *source)
sg.src = source->source_addr;
sg.grp = source->source_group->group_addr;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
zlog_debug("%s: (S,G)=%pSG oif=%s fwd=%d", __func__, &sg,
source->source_group->interface->name,
IGMP_SOURCE_TEST_FORWARDING(source->source_flags));
@@ -346,7 +346,7 @@ static void pim_igmp_other_querier_expire(struct thread *t)
assert(!igmp->t_igmp_query_timer);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
sizeof(ifaddr_str));
@@ -382,7 +382,7 @@ void pim_igmp_other_querier_timer_on(struct gm_sock *igmp)
then reset the other-querier-present timer.
*/
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
sizeof(ifaddr_str));
@@ -423,7 +423,7 @@ void pim_igmp_other_querier_timer_on(struct gm_sock *igmp)
igmp->querier_robustness_variable, igmp->querier_query_interval,
pim_ifp->gm_query_max_response_time_dsec);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
sizeof(ifaddr_str));
@@ -442,7 +442,7 @@ void pim_igmp_other_querier_timer_off(struct gm_sock *igmp)
{
assert(igmp);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
if (igmp->t_other_querier_timer) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
@@ -501,14 +501,14 @@ static int igmp_recv_query(struct gm_sock *igmp, int query_version,
}
if (!pim_if_connected_to_source(ifp, from)) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug("Recv IGMP query on interface: %s from a non-connected source: %s",
ifp->name, from_str);
return 0;
}
if (if_address_is_local(&from, AF_INET, ifp->vrf->vrf_id)) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug("Recv IGMP query on interface: %s from ourself %s",
ifp->name, from_str);
return 0;
@@ -554,7 +554,7 @@ static int igmp_recv_query(struct gm_sock *igmp, int query_version,
return 0;
}
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group_addr, group_str,
sizeof(group_str));
@@ -593,14 +593,14 @@ static int igmp_recv_query(struct gm_sock *igmp, int query_version,
if (!group->t_group_query_retransmit_timer)
continue;
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(
"%s: lower address query packet from %s is ignored when last member query interval timer is running",
ifp->name, from_str);
return 0;
}
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
sizeof(ifaddr_str));
@@ -610,10 +610,17 @@ static int igmp_recv_query(struct gm_sock *igmp, int query_version,
ntohl(igmp->ifaddr.s_addr), from_str,
ntohl(from.s_addr));
}
- if (ntohl(from.s_addr) < ntohl(igmp->querier_addr.s_addr))
+ /* Reset the other querier timer only if query is received from
+ * the previously elected querier or a better new querier
+ * This will make sure that non-querier elects the new querier
+ * whose ip address is higher than the old querier
+ * in case the old querier goes down via other querier present
+ * timer expiry
+ */
+ if (ntohl(from.s_addr) <= ntohl(igmp->querier_addr.s_addr)) {
igmp->querier_addr.s_addr = from.s_addr;
-
- pim_igmp_other_querier_timer_on(igmp);
+ pim_igmp_other_querier_timer_on(igmp);
+ }
}
/* IGMP version 3 is the only one where we process the RXed query */
@@ -627,7 +634,7 @@ static int igmp_recv_query(struct gm_sock *igmp, int query_version,
static void on_trace(const char *label, struct interface *ifp,
struct in_addr from)
{
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char from_str[INET_ADDRSTRLEN];
pim_inet4_dump("<from?>", from, from_str, sizeof(from_str));
zlog_debug("%s: from %s on %s", label, from_str, ifp->name);
@@ -664,7 +671,7 @@ static int igmp_v1_recv_report(struct gm_sock *igmp, struct in_addr from,
/* Collecting IGMP Rx stats */
igmp->igmp_stats.report_v1++;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
zlog_warn("%s %s: FIXME WRITEME", __FILE__, __func__);
}
@@ -750,7 +757,7 @@ int pim_igmp_packet(struct gm_sock *igmp, char *buf, size_t len)
pim_inet4_dump("<src?>", ip_hdr->ip_src, from_str, sizeof(from_str));
pim_inet4_dump("<dst?>", ip_hdr->ip_dst, to_str, sizeof(to_str));
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"Recv IGMP packet from %s to %s on %s: size=%zu ttl=%d msg_type=%d msg_size=%d",
from_str, to_str, igmp->interface->name, len, ip_hdr->ip_ttl,
@@ -862,7 +869,7 @@ void pim_igmp_general_query_on(struct gm_sock *igmp)
query_interval = igmp->querier_query_interval;
}
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
sizeof(ifaddr_str));
@@ -879,7 +886,7 @@ void pim_igmp_general_query_off(struct gm_sock *igmp)
{
assert(igmp);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
if (igmp->t_igmp_query_timer) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
@@ -928,7 +935,7 @@ static void pim_igmp_general_query(struct thread *t)
dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
group_addr.s_addr = PIM_NET_INADDR_ANY;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char querier_str[INET_ADDRSTRLEN];
char dst_str[INET_ADDRSTRLEN];
pim_inet4_dump("<querier?>", igmp->ifaddr, querier_str,
@@ -951,7 +958,7 @@ static void sock_close(struct gm_sock *igmp)
pim_igmp_other_querier_timer_off(igmp);
pim_igmp_general_query_off(igmp);
- if (PIM_DEBUG_IGMP_TRACE_DETAIL) {
+ if (PIM_DEBUG_GM_TRACE_DETAIL) {
if (igmp->t_igmp_read) {
zlog_debug(
"Cancelling READ event on IGMP socket %pI4 fd=%d on interface %s",
@@ -969,7 +976,7 @@ static void sock_close(struct gm_sock *igmp)
igmp->interface->name, errno, safe_strerror(errno));
}
- if (PIM_DEBUG_IGMP_TRACE_DETAIL) {
+ if (PIM_DEBUG_GM_TRACE_DETAIL) {
zlog_debug("Deleted IGMP socket %pI4 fd=%d on interface %s",
&igmp->ifaddr, igmp->fd,
igmp->interface->name);
@@ -1008,12 +1015,11 @@ static void igmp_group_count_incr(struct pim_interface *pim_ifp)
{
uint32_t group_count = listcount(pim_ifp->gm_group_list);
- ++pim_ifp->pim->igmp_group_count;
- if (pim_ifp->pim->igmp_group_count ==
- pim_ifp->pim->gm_watermark_limit) {
+ ++pim_ifp->pim->gm_group_count;
+ if (pim_ifp->pim->gm_group_count == pim_ifp->pim->gm_watermark_limit) {
zlog_warn(
"IGMP group count reached watermark limit: %u(vrf: %s)",
- pim_ifp->pim->igmp_group_count,
+ pim_ifp->pim->gm_group_count,
VRF_LOGNAME(pim_ifp->pim->vrf));
}
@@ -1023,13 +1029,13 @@ static void igmp_group_count_incr(struct pim_interface *pim_ifp)
static void igmp_group_count_decr(struct pim_interface *pim_ifp)
{
- if (pim_ifp->pim->igmp_group_count == 0) {
+ if (pim_ifp->pim->gm_group_count == 0) {
zlog_warn("Cannot decrement igmp group count below 0(vrf: %s)",
VRF_LOGNAME(pim_ifp->pim->vrf));
return;
}
- --pim_ifp->pim->igmp_group_count;
+ --pim_ifp->pim->gm_group_count;
}
void igmp_group_delete(struct gm_group *group)
@@ -1039,7 +1045,7 @@ void igmp_group_delete(struct gm_group *group)
struct gm_source *src;
struct pim_interface *pim_ifp = group->interface->info;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1174,7 +1180,7 @@ static struct gm_sock *igmp_sock_new(int fd, struct in_addr ifaddr,
pim_ifp = ifp->info;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
zlog_debug(
"Creating IGMP socket fd=%d for address %pI4 on interface %s",
fd, &ifaddr, ifp->name);
@@ -1246,7 +1252,7 @@ done:
static void igmp_read_on(struct gm_sock *igmp)
{
- if (PIM_DEBUG_IGMP_TRACE_DETAIL) {
+ if (PIM_DEBUG_GM_TRACE_DETAIL) {
zlog_debug("Scheduling READ event on IGMP socket fd=%d",
igmp->fd);
}
@@ -1313,7 +1319,7 @@ static void igmp_group_timer(struct thread *t)
group = THREAD_ARG(t);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1348,7 +1354,7 @@ static void group_timer_off(struct gm_group *group)
if (!group->t_group_timer)
return;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1363,7 +1369,7 @@ void igmp_group_timer_on(struct gm_group *group, long interval_msec,
{
group_timer_off(group);
- if (PIM_DEBUG_IGMP_EVENTS) {
+ if (PIM_DEBUG_GM_EVENTS) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1415,7 +1421,7 @@ struct gm_group *igmp_add_group_by_addr(struct gm_sock *igmp,
}
if (pim_is_group_224_0_0_0_24(group_addr)) {
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(
"%s: Group specified %pI4 is part of 224.0.0.0/24",
__func__, &group_addr);
@@ -1455,7 +1461,7 @@ struct gm_group *igmp_add_group_by_addr(struct gm_sock *igmp,
listnode_add(pim_ifp->gm_group_list, group);
group = hash_get(pim_ifp->gm_group_hash, group, hash_alloc_intern);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1528,7 +1534,7 @@ void igmp_send_query_on_intf(struct interface *ifp, int igmp_ver)
dst_addr.s_addr = htonl(INADDR_ALLHOSTS_GROUP);
group_addr.s_addr = PIM_NET_INADDR_ANY;
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug("Issuing general query on request on %s", ifp->name);
for (ALL_LIST_ELEMENTS_RO(pim_ifp->gm_socket_list, sock_node, igmp)) {
diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h
index a642469f27..9ce3a2a17f 100644
--- a/pimd/pim_igmp.h
+++ b/pimd/pim_igmp.h
@@ -56,18 +56,6 @@
#define IGMP_V3_GROUP_RECORD_SOURCE_OFFSET (8)
#define IGMP_CHECKSUM_OFFSET (2)
-/* RFC 3376: 8.1. Robustness Variable - Default: 2 */
-#define IGMP_DEFAULT_ROBUSTNESS_VARIABLE (2)
-
-/* RFC 3376: 8.2. Query Interval - Default: 125 seconds */
-#define IGMP_GENERAL_QUERY_INTERVAL (125)
-
-/* RFC 3376: 8.3. Query Response Interval - Default: 100 deciseconds */
-#define IGMP_QUERY_MAX_RESPONSE_TIME_DSEC (100)
-
-/* RFC 3376: 8.8. Last Member Query Interval - Default: 10 deciseconds */
-#define IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC (10)
-
#define IGMP_DEFAULT_VERSION (3)
#define IGMP_GET_INT16(ptr, output) \
diff --git a/pimd/pim_igmpv2.c b/pimd/pim_igmpv2.c
index 8d0925cb56..188c1bfe4c 100644
--- a/pimd/pim_igmpv2.c
+++ b/pimd/pim_igmpv2.c
@@ -34,7 +34,7 @@
static void on_trace(const char *label, struct interface *ifp,
struct in_addr from)
{
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char from_str[INET_ADDRSTRLEN];
pim_inet4_dump("<from?>", from, from_str, sizeof(from_str));
zlog_debug("%s: from %s on %s", label, from_str, ifp->name);
@@ -68,7 +68,7 @@ void igmp_v2_send_query(struct gm_group *group, int fd, const char *ifname,
checksum = in_cksum(query_buf, msg_size);
*(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum;
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
char dst_str[INET_ADDRSTRLEN];
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
@@ -121,7 +121,7 @@ int igmp_v2_recv_report(struct gm_sock *igmp, struct in_addr from,
return 0;
if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(
"Recv IGMPv2 REPORT from %s on %s: size=%d other than correct=%d",
from_str, ifp->name, igmp_msg_len,
@@ -140,7 +140,7 @@ int igmp_v2_recv_report(struct gm_sock *igmp, struct in_addr from,
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
pim_inet4_dump("<dst?>", group_addr, group_str,
sizeof(group_str));
zlog_debug("Recv IGMPv2 REPORT from %s on %s for %s", from_str,
@@ -155,7 +155,7 @@ int igmp_v2_recv_report(struct gm_sock *igmp, struct in_addr from,
* the SSM range.
*/
if (pim_is_grp_ssm(pim_ifp->pim, group_addr)) {
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"Ignoring IGMPv2 group record %pI4 from %s on %s exclude mode in SSM range",
&group_addr.s_addr, from_str, ifp->name);
@@ -196,7 +196,7 @@ int igmp_v2_recv_leave(struct gm_sock *igmp, struct ip *ip_hdr,
return 0;
if (igmp_msg_len != IGMP_V12_MSG_SIZE) {
- if (PIM_DEBUG_IGMP_PACKETS)
+ if (PIM_DEBUG_GM_PACKETS)
zlog_debug(
"Recv IGMPv2 LEAVE from %s on %s: size=%d other than correct=%d",
from_str, ifp->name, igmp_msg_len,
@@ -213,7 +213,7 @@ int igmp_v2_recv_leave(struct gm_sock *igmp, struct ip *ip_hdr,
memcpy(&group_addr, igmp_msg + 4, sizeof(struct in_addr));
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
pim_inet4_dump("<dst?>", group_addr, group_str,
sizeof(group_str));
zlog_debug("Recv IGMPv2 LEAVE from %s on %s for %s", from_str,
@@ -237,7 +237,7 @@ int igmp_v2_recv_leave(struct gm_sock *igmp, struct ip *ip_hdr,
*/
if ((ntohl(ip_hdr->ip_dst.s_addr) != INADDR_ALLRTRS_GROUP)
&& (ip_hdr->ip_dst.s_addr != group_addr.s_addr)) {
- if (PIM_DEBUG_IGMP_EVENTS)
+ if (PIM_DEBUG_GM_EVENTS)
zlog_debug(
"IGMPv2 Leave message is ignored since received on address other than ALL-ROUTERS or Group-address");
return -1;
diff --git a/pimd/pim_igmpv3.c b/pimd/pim_igmpv3.c
index 6ed5c501b2..8961c93263 100644
--- a/pimd/pim_igmpv3.c
+++ b/pimd/pim_igmpv3.c
@@ -46,7 +46,7 @@ static void on_trace(const char *label, struct interface *ifp,
struct in_addr from, struct in_addr group_addr,
int num_sources, struct in_addr *sources)
{
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char from_str[INET_ADDRSTRLEN];
char group_str[INET_ADDRSTRLEN];
@@ -98,7 +98,7 @@ void igmp_group_reset_gmi(struct gm_group *group)
*/
group_membership_interval_msec = igmp_gmi_msec(group);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -129,7 +129,7 @@ static void igmp_source_timer(struct thread *t)
group = source->source_group;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
@@ -188,7 +188,7 @@ static void source_timer_off(struct gm_group *group, struct gm_source *source)
if (!source->t_source_timer)
return;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
@@ -209,7 +209,7 @@ static void igmp_source_timer_on(struct gm_group *group,
source_timer_off(group, source);
struct pim_interface *pim_ifp = group->interface->info;
- if (PIM_DEBUG_IGMP_EVENTS) {
+ if (PIM_DEBUG_GM_EVENTS) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
@@ -242,7 +242,7 @@ void igmp_source_reset_gmi(struct gm_group *group, struct gm_source *source)
group_membership_interval_msec = igmp_gmi_msec(group);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
@@ -351,7 +351,7 @@ void igmp_source_delete(struct gm_source *source)
group = source->source_group;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
@@ -452,7 +452,7 @@ struct gm_source *igmp_get_source_by_addr(struct gm_group *group,
if (src)
return src;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
@@ -1035,7 +1035,7 @@ static void group_retransmit_group(struct gm_group *group)
*/
s_flag = igmp_group_timer_remain_msec(group) > lmqt_msec;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1124,7 +1124,7 @@ static int group_retransmit_sources(struct gm_group *group,
source_addr2
- (struct in_addr *)(query_buf2 + IGMP_V3_SOURCES_OFFSET);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1221,7 +1221,7 @@ static void igmp_group_retransmit(struct thread *t)
group = THREAD_ARG(t);
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1284,7 +1284,7 @@ static void group_retransmit_timer_on(struct gm_group *group)
lmqi_msec = 100 * pim_ifp->gm_specific_query_max_response_time_dsec;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1513,7 +1513,7 @@ void igmp_group_timer_lower_to_lmqt(struct gm_group *group)
lmqt_msec = PIM_IGMP_LMQT_MSEC(
lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
sizeof(group_str));
@@ -1548,7 +1548,7 @@ void igmp_source_timer_lower_to_lmqt(struct gm_source *source)
lmqt_msec = PIM_IGMP_LMQT_MSEC(
lmqi_dsec, lmqc); /* lmqt_msec = (100 * lmqi_dsec) * lmqc */
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char group_str[INET_ADDRSTRLEN];
char source_str[INET_ADDRSTRLEN];
pim_inet4_dump("<group?>", group->group_addr, group_str,
@@ -1622,7 +1622,7 @@ void igmp_v3_send_query(struct gm_group *group, int fd, const char *ifname,
checksum = in_cksum(query_buf, msg_size);
*(uint16_t *)(query_buf + IGMP_CHECKSUM_OFFSET) = checksum;
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
char dst_str[INET_ADDRSTRLEN];
char group_str[INET_ADDRSTRLEN];
pim_inet4_dump("<dst?>", dst_addr, dst_str, sizeof(dst_str));
@@ -1735,7 +1735,7 @@ void igmp_v3_recv_query(struct gm_sock *igmp, const char *from_str,
igmp->querier_query_interval =
qqi ? qqi : pim_ifp->gm_default_query_interval;
- if (PIM_DEBUG_IGMP_TRACE) {
+ if (PIM_DEBUG_GM_TRACE) {
char ifaddr_str[INET_ADDRSTRLEN];
pim_inet4_dump("<ifaddr?>", igmp->ifaddr, ifaddr_str,
sizeof(ifaddr_str));
@@ -1835,7 +1835,7 @@ static bool igmp_pkt_grp_addr_ok(struct interface *ifp, const char *from_str,
/* determine filtering status for group */
if (pim_is_group_filtered(pim_ifp, &grp)) {
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"Filtering IGMPv3 group record %pI4 from %s on %s per prefix-list %s",
&grp.s_addr, from_str, ifp->name,
@@ -1852,7 +1852,7 @@ static bool igmp_pkt_grp_addr_ok(struct interface *ifp, const char *from_str,
grp_addr.s_addr = ntohl(grp.s_addr);
if (pim_is_group_224_0_0_0_24(grp_addr)) {
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"Ignoring IGMPv3 group record %pI4 from %s on %s group range falls in 224.0.0.0/24",
&grp.s_addr, from_str, ifp->name);
@@ -1871,7 +1871,7 @@ static bool igmp_pkt_grp_addr_ok(struct interface *ifp, const char *from_str,
switch (rec_type) {
case IGMP_GRP_REC_TYPE_MODE_IS_EXCLUDE:
case IGMP_GRP_REC_TYPE_CHANGE_TO_EXCLUDE_MODE:
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"Ignoring IGMPv3 group record %pI4 from %s on %s exclude mode in SSM range",
&grp.s_addr, from_str, ifp->name);
@@ -1930,7 +1930,7 @@ int igmp_v3_recv_report(struct gm_sock *igmp, struct in_addr from,
return -1;
}
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"Recv IGMP report v3 from %s on %s: size=%d groups=%d",
from_str, ifp->name, igmp_msg_len, num_groups);
@@ -1967,7 +1967,7 @@ int igmp_v3_recv_report(struct gm_sock *igmp, struct in_addr from,
group_record + IGMP_V3_GROUP_RECORD_GROUP_OFFSET,
sizeof(struct in_addr));
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
" Recv IGMP report v3 from %s on %s: record=%d type=%d auxdatalen=%d sources=%d group=%pI4",
from_str, ifp->name, i, rec_type,
@@ -1988,7 +1988,7 @@ int igmp_v3_recv_report(struct gm_sock *igmp, struct in_addr from,
return -1;
}
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
char src_str[200];
if (!inet_ntop(AF_INET, src, src_str,
diff --git a/pimd/pim_instance.c b/pimd/pim_instance.c
index 359e3db718..4b85d45751 100644
--- a/pimd/pim_instance.c
+++ b/pimd/pim_instance.c
@@ -36,6 +36,7 @@
#include "pim_vty.h"
#include "pim_bsm.h"
#include "pim_mlag.h"
+#include "pim_sock.h"
static void pim_instance_terminate(struct pim_instance *pim)
{
@@ -70,6 +71,8 @@ static void pim_instance_terminate(struct pim_instance *pim)
pim_msdp_exit(pim);
+ close(pim->reg_sock);
+
pim_mroute_socket_disable(pim);
XFREE(MTYPE_PIM_PLIST_NAME, pim->spt.plist);
@@ -131,6 +134,10 @@ static struct pim_instance *pim_instance_init(struct vrf *vrf)
pim->last_route_change_time = -1;
+ pim->reg_sock = pim_reg_sock();
+ if (pim->reg_sock < 0)
+ assert(0);
+
/* MSDP global timer defaults. */
pim->msdp.hold_time = PIM_MSDP_PEER_HOLD_TIME;
pim->msdp.keep_alive = PIM_MSDP_PEER_KA_TIME;
diff --git a/pimd/pim_instance.h b/pimd/pim_instance.h
index 684785dd13..57bc74efb4 100644
--- a/pimd/pim_instance.h
+++ b/pimd/pim_instance.h
@@ -136,6 +136,7 @@ struct pim_instance {
struct thread *thread;
int mroute_socket;
+ int reg_sock; /* Socket to send register msg */
int64_t mroute_socket_creation;
int64_t mroute_add_events;
int64_t mroute_add_last;
@@ -172,7 +173,7 @@ struct pim_instance {
int gm_socket;
struct thread *t_gm_recv;
- unsigned int igmp_group_count;
+ unsigned int gm_group_count;
unsigned int gm_watermark_limit;
unsigned int keep_alive_time;
unsigned int rp_keep_alive_time;
diff --git a/pimd/pim_main.c b/pimd/pim_main.c
index 92c34f51a1..c168c0b098 100644
--- a/pimd/pim_main.c
+++ b/pimd/pim_main.c
@@ -153,9 +153,9 @@ int main(int argc, char **argv, char **envp)
PIM_DO_DEBUG_PIM_EVENTS;
PIM_DO_DEBUG_PIM_PACKETS;
PIM_DO_DEBUG_PIM_TRACE;
- PIM_DO_DEBUG_IGMP_EVENTS;
- PIM_DO_DEBUG_IGMP_PACKETS;
- PIM_DO_DEBUG_IGMP_TRACE;
+ PIM_DO_DEBUG_GM_EVENTS;
+ PIM_DO_DEBUG_GM_PACKETS;
+ PIM_DO_DEBUG_GM_TRACE;
PIM_DO_DEBUG_ZEBRA;
#endif
diff --git a/pimd/pim_mroute.c b/pimd/pim_mroute.c
index 8f1e6184d0..220706945d 100644
--- a/pimd/pim_mroute.c
+++ b/pimd/pim_mroute.c
@@ -635,7 +635,7 @@ static int process_igmp_packet(struct pim_instance *pim, const char *buf,
connected_src = pim_if_connected_to_source(ifp, ip_hdr->ip_src);
if (!connected_src) {
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"Recv IGMP packet on interface: %s from a non-connected source: %pI4",
ifp->name, &ip_hdr->ip_src);
@@ -647,7 +647,7 @@ static int process_igmp_packet(struct pim_instance *pim, const char *buf,
ifaddr = connected_src->u.prefix4;
igmp = pim_igmp_sock_lookup_ifaddr(pim_ifp->gm_socket_list, ifaddr);
- if (PIM_DEBUG_IGMP_PACKETS) {
+ if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"%s(%s): igmp kernel upcall on %s(%p) for %pI4 -> %pI4",
__func__, pim->vrf->name, ifp->name, igmp,
@@ -655,7 +655,7 @@ static int process_igmp_packet(struct pim_instance *pim, const char *buf,
}
if (igmp)
pim_igmp_packet(igmp, (char *)buf, buf_size);
- else if (PIM_DEBUG_IGMP_PACKETS) {
+ else if (PIM_DEBUG_GM_PACKETS) {
zlog_debug(
"No IGMP socket on interface: %s with connected source: %pFX",
ifp->name, connected_src);
diff --git a/pimd/pim_nb_config.c b/pimd/pim_nb_config.c
index 408e86b698..12f8ffedfe 100644
--- a/pimd/pim_nb_config.c
+++ b/pimd/pim_nb_config.c
@@ -348,8 +348,7 @@ static bool is_pim_interface(const struct lyd_node *dnode)
return false;
}
-#if PIM_IPV == 4
-static int pim_cmd_igmp_start(struct interface *ifp)
+static int pim_cmd_gm_start(struct interface *ifp)
{
struct pim_interface *pim_ifp;
uint8_t need_startup = 0;
@@ -377,7 +376,6 @@ static int pim_cmd_igmp_start(struct interface *ifp)
return NB_OK;
}
-#endif /* PIM_IPV == 4 */
/*
* CLI reconfiguration affects the interface level (struct pim_interface).
@@ -397,7 +395,7 @@ static void igmp_sock_query_interval_reconfig(struct gm_sock *igmp)
ifp = igmp->interface;
pim_ifp = ifp->info;
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug("%s: Querier %pPAs on %s reconfig query_interval=%d",
__func__, &igmp->ifaddr, ifp->name,
pim_ifp->gm_default_query_interval);
@@ -456,14 +454,17 @@ static void change_query_interval(struct pim_interface *pim_ifp,
}
#endif
-#if PIM_IPV == 4
-static void change_query_max_response_time(struct pim_interface *pim_ifp,
- int query_max_response_time_dsec)
+static void change_query_max_response_time(struct interface *ifp,
+ int query_max_response_time_dsec)
{
+#if PIM_IPV == 4
struct listnode *sock_node;
struct gm_sock *igmp;
struct listnode *grp_node;
struct gm_group *grp;
+#endif
+
+ struct pim_interface *pim_ifp = ifp->info;
if (pim_ifp->gm_query_max_response_time_dsec ==
query_max_response_time_dsec)
@@ -471,6 +472,9 @@ static void change_query_max_response_time(struct pim_interface *pim_ifp,
pim_ifp->gm_query_max_response_time_dsec = query_max_response_time_dsec;
+#if PIM_IPV == 6
+ gm_ifp_update(ifp);
+#else
/*
* Below we modify socket/group/source timers in order to quickly
* reflect the change. Otherwise, those timers would args->eventually
@@ -503,8 +507,8 @@ static void change_query_max_response_time(struct pim_interface *pim_ifp,
igmp_source_reset_gmi(grp, src);
}
}
+#endif /* PIM_IPV == 4 */
}
-#endif
int routing_control_plane_protocols_name_validate(
struct nb_cb_create_args *args)
@@ -2584,7 +2588,6 @@ int lib_interface_gmp_address_family_destroy(struct nb_cb_destroy_args *args)
int lib_interface_gmp_address_family_enable_modify(
struct nb_cb_modify_args *args)
{
-#if PIM_IPV == 4
struct interface *ifp;
bool gm_enable;
struct pim_interface *pim_ifp;
@@ -2600,9 +2603,10 @@ int lib_interface_gmp_address_family_enable_modify(
/* Limiting mcast interfaces to number of VIFs */
if (mcast_if_count == MAXVIFS) {
ifp_name = yang_dnode_get_string(if_dnode, "name");
- snprintf(args->errmsg, args->errmsg_len,
- "Max multicast interfaces(%d) Reached. Could not enable IGMP on interface %s",
- MAXVIFS, ifp_name);
+ snprintf(
+ args->errmsg, args->errmsg_len,
+ "Max multicast interfaces(%d) Reached. Could not enable %s on interface %s",
+ MAXVIFS, GM, ifp_name);
return NB_ERR_VALIDATION;
}
break;
@@ -2614,7 +2618,7 @@ int lib_interface_gmp_address_family_enable_modify(
gm_enable = yang_dnode_get_bool(args->dnode, NULL);
if (gm_enable)
- return pim_cmd_igmp_start(ifp);
+ return pim_cmd_gm_start(ifp);
else {
pim_ifp = ifp->info;
@@ -2626,15 +2630,16 @@ int lib_interface_gmp_address_family_enable_modify(
pim_if_membership_clear(ifp);
+#if PIM_IPV == 4
pim_if_addr_del_all_igmp(ifp);
+#else
+ gm_ifp_teardown(ifp);
+#endif
if (!pim_ifp->pim_enable)
pim_if_delete(ifp);
}
}
-#else
- /* TBD Depends on MLD data structure changes */
-#endif /* PIM_IPV == 4 */
return NB_OK;
}
@@ -2798,7 +2803,6 @@ int lib_interface_gmp_address_family_query_interval_modify(
int lib_interface_gmp_address_family_query_max_response_time_modify(
struct nb_cb_modify_args *args)
{
-#if PIM_IPV == 4
struct interface *ifp;
int query_max_response_time_dsec;
@@ -2811,13 +2815,9 @@ int lib_interface_gmp_address_family_query_max_response_time_modify(
ifp = nb_running_get_entry(args->dnode, NULL, true);
query_max_response_time_dsec =
yang_dnode_get_uint16(args->dnode, NULL);
- change_query_max_response_time(ifp->info,
- query_max_response_time_dsec);
+ change_query_max_response_time(ifp,
+ query_max_response_time_dsec);
}
-#else
- /* TBD Depends on MLD data structure changes */
-#endif
-
return NB_OK;
}
@@ -2828,7 +2828,6 @@ int lib_interface_gmp_address_family_query_max_response_time_modify(
int lib_interface_gmp_address_family_last_member_query_interval_modify(
struct nb_cb_modify_args *args)
{
-#if PIM_IPV == 4
struct interface *ifp;
struct pim_interface *pim_ifp;
int last_member_query_interval;
@@ -2845,12 +2844,12 @@ int lib_interface_gmp_address_family_last_member_query_interval_modify(
yang_dnode_get_uint16(args->dnode, NULL);
pim_ifp->gm_specific_query_max_response_time_dsec =
last_member_query_interval;
+#if PIM_IPV == 6
+ gm_ifp_update(ifp);
+#endif
break;
}
-#else
- /* TBD Depends on MLD data structure changes */
-#endif
return NB_OK;
}
@@ -2861,7 +2860,6 @@ int lib_interface_gmp_address_family_last_member_query_interval_modify(
int lib_interface_gmp_address_family_robustness_variable_modify(
struct nb_cb_modify_args *args)
{
-#if PIM_IPV == 4
struct interface *ifp;
struct pim_interface *pim_ifp;
int last_member_query_count;
@@ -2877,12 +2875,11 @@ int lib_interface_gmp_address_family_robustness_variable_modify(
last_member_query_count =
yang_dnode_get_uint8(args->dnode, NULL);
pim_ifp->gm_last_member_query_count = last_member_query_count;
-
+#if PIM_IPV == 6
+ gm_ifp_update(ifp);
+#endif
break;
}
-#else
- /* TBD Depends on MLD data structure changes */
-#endif
return NB_OK;
}
diff --git a/pimd/pim_neighbor.c b/pimd/pim_neighbor.c
index 6d6dbb6465..7726ac00b0 100644
--- a/pimd/pim_neighbor.c
+++ b/pimd/pim_neighbor.c
@@ -441,15 +441,6 @@ struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
return NULL;
}
-struct pim_neighbor *pim_neighbor_find_prefix(struct interface *ifp,
- const struct prefix *src_prefix)
-{
- pim_addr addr;
-
- addr = pim_addr_from_prefix(src_prefix);
- return pim_neighbor_find(ifp, addr);
-}
-
/*
* Find the *one* interface out
* this interface. If more than
diff --git a/pimd/pim_neighbor.h b/pimd/pim_neighbor.h
index 2673d22480..a2a2df9e04 100644
--- a/pimd/pim_neighbor.h
+++ b/pimd/pim_neighbor.h
@@ -52,8 +52,6 @@ void pim_neighbor_timer_reset(struct pim_neighbor *neigh, uint16_t holdtime);
void pim_neighbor_free(struct pim_neighbor *neigh);
struct pim_neighbor *pim_neighbor_find(struct interface *ifp,
pim_addr source_addr);
-struct pim_neighbor *pim_neighbor_find_prefix(struct interface *ifp,
- const struct prefix *src_prefix);
struct pim_neighbor *pim_neighbor_find_by_secondary(struct interface *ifp,
struct prefix *src);
struct pim_neighbor *pim_neighbor_find_if(struct interface *ifp);
diff --git a/pimd/pim_nht.c b/pimd/pim_nht.c
index 2e5c0598c0..9feb064e96 100644
--- a/pimd/pim_nht.c
+++ b/pimd/pim_nht.c
@@ -436,7 +436,7 @@ static int pim_update_upstream_nh_helper(struct hash_bucket *bucket, void *arg)
* RPF nbr is now unreachable the MFC has already been updated
* by pim_rpf_clear
*/
- if (rpf_result != PIM_RPF_CHANGED)
+ if (rpf_result == PIM_RPF_CHANGED)
pim_upstream_mroute_iif_update(up->channel_oil, __func__);
if (rpf_result == PIM_RPF_CHANGED ||
diff --git a/pimd/pim_register.c b/pimd/pim_register.c
index 0eb49a7f91..4e2c44b172 100644
--- a/pimd/pim_register.c
+++ b/pimd/pim_register.c
@@ -331,7 +331,7 @@ void pim_register_send(const uint8_t *buf, int buf_size, pim_addr src,
if (!pinfo->pim_passive_enable)
++pinfo->pim_ifstat_reg_send;
- if (pim_msg_send(pinfo->pim_sock_fd, src, rpg->rpf_addr, buffer,
+ if (pim_msg_send(pinfo->pim->reg_sock, src, rpg->rpf_addr, buffer,
buf_size + PIM_MSG_REGISTER_LEN, ifp)) {
if (PIM_DEBUG_PIM_TRACE) {
zlog_debug(
diff --git a/pimd/pim_rp.c b/pimd/pim_rp.c
index 783c9b97e7..1dce6b3562 100644
--- a/pimd/pim_rp.c
+++ b/pimd/pim_rp.c
@@ -51,6 +51,7 @@
#include "pim_bsm.h"
#include "pim_util.h"
#include "pim_ssm.h"
+#include "termtable.h"
/* Cleanup pim->rpf_hash each node data */
void pim_rp_list_hash_clean(void *data)
@@ -1166,14 +1167,25 @@ void pim_rp_show_information(struct pim_instance *pim, struct prefix *range,
struct rp_info *rp_info;
struct rp_info *prev_rp_info = NULL;
struct listnode *node;
+ struct ttable *tt = NULL;
+ char *table = NULL;
char source[7];
+ char grp[INET6_ADDRSTRLEN];
json_object *json_rp_rows = NULL;
json_object *json_row = NULL;
- if (!json)
- vty_out(vty,
- "RP address group/prefix-list OIF I am RP Source Group-Type\n");
+ if (!json) {
+ /* Prepare table. */
+ tt = ttable_new(&ttable_styles[TTSTYLE_BLANK]);
+ ttable_add_row(
+ tt,
+ "RP address|group/prefix-list|OIF|I am RP|Source|Group-Type");
+ tt->style.cell.rpad = 2;
+ tt->style.corner = '+';
+ ttable_restyle(tt);
+ }
+
for (ALL_LIST_ELEMENTS_RO(pim->rp_list, node, rp_info)) {
if (pim_rpf_addr_is_inaddr_any(&rp_info->rp))
continue;
@@ -1243,32 +1255,31 @@ void pim_rp_show_information(struct pim_instance *pim, struct prefix *range,
json_object_array_add(json_rp_rows, json_row);
} else {
- vty_out(vty, "%-15pPA ", &rp_info->rp.rpf_addr);
-
- if (rp_info->plist)
- vty_out(vty, "%-18s ", rp_info->plist);
- else
- vty_out(vty, "%-18pFX ", &rp_info->group);
-
- if (rp_info->rp.source_nexthop.interface)
- vty_out(vty, "%-16s ",
- rp_info->rp.source_nexthop
- .interface->name);
- else
- vty_out(vty, "%-16s ", "(Unknown)");
-
- if (rp_info->i_am_rp)
- vty_out(vty, "yes");
- else
- vty_out(vty, "no");
-
- vty_out(vty, "%14s", source);
- vty_out(vty, "%6s\n", group_type);
+ prefix2str(&rp_info->group, grp, sizeof(grp));
+ ttable_add_row(tt, "%pPA|%s|%s|%s|%s|%s",
+ &rp_info->rp.rpf_addr,
+ rp_info->plist
+ ? rp_info->plist
+ : grp,
+ rp_info->rp.source_nexthop.interface
+ ? rp_info->rp.source_nexthop
+ .interface->name
+ : "Unknown",
+ rp_info->i_am_rp
+ ? "yes"
+ : "no",
+ source, group_type);
}
prev_rp_info = rp_info;
}
- if (json) {
+ /* Dump the generated table. */
+ if (!json) {
+ table = ttable_dump(tt, "\n");
+ vty_out(vty, "%s\n", table);
+ XFREE(MTYPE_TMP, table);
+ ttable_del(tt);
+ } else {
if (prev_rp_info && json_rp_rows)
json_object_object_addf(json, json_rp_rows, "%pPA",
&prev_rp_info->rp.rpf_addr);
diff --git a/pimd/pim_sock.c b/pimd/pim_sock.c
index afc5d47118..4b91bf07d9 100644
--- a/pimd/pim_sock.c
+++ b/pimd/pim_sock.c
@@ -179,6 +179,46 @@ static inline int pim_setsockopt(int protocol, int fd, struct interface *ifp)
}
#endif
+int pim_reg_sock(void)
+{
+ int fd;
+ long flags;
+
+ frr_with_privs (&pimd_privs) {
+ fd = socket(PIM_AF, SOCK_RAW, PIM_PROTO_REG);
+ }
+
+ if (fd < 0) {
+ zlog_warn("Could not create raw socket: errno=%d: %s", errno,
+ safe_strerror(errno));
+ return PIM_SOCK_ERR_SOCKET;
+ }
+
+ if (sockopt_reuseaddr(fd)) {
+ close(fd);
+ return PIM_SOCK_ERR_REUSE;
+ }
+
+ flags = fcntl(fd, F_GETFL, 0);
+ if (flags < 0) {
+ zlog_warn(
+ "Could not get fcntl(F_GETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s",
+ fd, errno, safe_strerror(errno));
+ close(fd);
+ return PIM_SOCK_ERR_NONBLOCK_GETFL;
+ }
+
+ if (fcntl(fd, F_SETFL, flags | O_NONBLOCK)) {
+ zlog_warn(
+ "Could not set fcntl(F_SETFL,O_NONBLOCK) on socket fd=%d: errno=%d: %s",
+ fd, errno, safe_strerror(errno));
+ close(fd);
+ return PIM_SOCK_ERR_NONBLOCK_SETFL;
+ }
+
+ return fd;
+}
+
int pim_socket_mcast(int protocol, pim_addr ifaddr, struct interface *ifp,
uint8_t loop)
{
diff --git a/pimd/pim_sock.h b/pimd/pim_sock.h
index ea9f7009bc..4dcb9e6466 100644
--- a/pimd/pim_sock.h
+++ b/pimd/pim_sock.h
@@ -51,4 +51,6 @@ int pim_socket_recvfromto(int fd, uint8_t *buf, size_t len,
int pim_socket_getsockname(int fd, struct sockaddr *name, socklen_t *namelen);
+int pim_reg_sock(void);
+
#endif /* PIM_SOCK_H */
diff --git a/pimd/pim_static.c b/pimd/pim_static.c
index 581b855f92..f5449d2824 100644
--- a/pimd/pim_static.c
+++ b/pimd/pim_static.c
@@ -97,10 +97,11 @@ int pim_static_add(struct pim_instance *pim, struct interface *iif,
}
for (ALL_LIST_ELEMENTS_RO(pim->static_routes, node, s_route)) {
- if (!pim_addr_cmp(s_route->group, group)
- && !pim_addr_cmp(s_route->source, source)) {
- if (s_route->iif == iif_index
- && s_route->oif_ttls[oif_index]) {
+ if (!pim_addr_cmp(s_route->group, group) &&
+ !pim_addr_cmp(s_route->source, source) &&
+ (s_route->iif == iif_index)) {
+
+ if (s_route->oif_ttls[oif_index]) {
zlog_warn(
"%s %s: Unable to add static route: Route already exists (iif=%d,oif=%d,group=%pPAs,source=%pPAs)",
__FILE__, __func__, iif_index,
@@ -122,42 +123,11 @@ int pim_static_add(struct pim_instance *pim, struct interface *iif,
/* Route exists and has the same input interface, but
* adding a new output interface */
- if (s_route->iif == iif_index) {
- s_route->oif_ttls[oif_index] = 1;
- oil_if_set(&s_route->c_oil, oif_index, 1);
- s_route->c_oil.oif_creation[oif_index] =
- pim_time_monotonic_sec();
- ++s_route->c_oil.oil_ref_count;
- } else {
- /* input interface changed */
- s_route->iif = iif_index;
- pim_static_mroute_iif_update(
- &s_route->c_oil, iif_index, __func__);
-
-#ifdef PIM_ENFORCE_LOOPFREE_MFC
- /* check to make sure the new input was not an
- * old output */
- if (s_route->oif_ttls[iif_index]) {
- s_route->oif_ttls[iif_index] = 0;
- s_route->c_oil.oif_creation[iif_index] =
- 0;
- oil_if_set(&s_route->c_oil, iif_index,
- 0);
- --s_route->c_oil.oil_ref_count;
- }
-#endif
-
- /* now add the new output, if it is new */
- if (!s_route->oif_ttls[oif_index]) {
- s_route->oif_ttls[oif_index] = 1;
- s_route->c_oil.oif_creation[oif_index] =
- pim_time_monotonic_sec();
- oil_if_set(&s_route->c_oil, oif_index,
- 1);
- ++s_route->c_oil.oil_ref_count;
- }
- }
-
+ s_route->oif_ttls[oif_index] = 1;
+ oil_if_set(&s_route->c_oil, oif_index, 1);
+ s_route->c_oil.oif_creation[oif_index] =
+ pim_time_monotonic_sec();
+ ++s_route->c_oil.oil_ref_count;
break;
}
}
diff --git a/pimd/pim_tib.c b/pimd/pim_tib.c
index 3b73c430b0..8f5de3e938 100644
--- a/pimd/pim_tib.c
+++ b/pimd/pim_tib.c
@@ -62,7 +62,7 @@ tib_sg_oil_setup(struct pim_instance *pim, pim_sgaddr sg, struct interface *oif)
__func__, &sg, &vif_source, input_iface_vif_index);
if (input_iface_vif_index < 1) {
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(
"%s %s: could not find input interface for %pSG",
__FILE__, __func__, &sg);
@@ -78,7 +78,7 @@ tib_sg_oil_setup(struct pim_instance *pim, pim_sgaddr sg, struct interface *oif)
if ((input_iface_vif_index == pim_oif->mroute_vif_index) &&
!(PIM_I_am_DR(pim_oif))) {
/* ignore request for looped MFC entry */
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(
"%s: ignoring request for looped MFC entry (S,G)=%pSG: oif=%s vif_index=%d",
__func__, &sg, oif->name,
@@ -96,7 +96,7 @@ bool tib_sg_gm_join(struct pim_instance *pim, pim_sgaddr sg,
struct pim_interface *pim_oif = oif->info;
if (!pim_oif) {
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug("%s: multicast not enabled on oif=%s?",
__func__, oif->name);
return false;
@@ -119,7 +119,7 @@ bool tib_sg_gm_join(struct pim_instance *pim, pim_sgaddr sg,
return false;
}
} else {
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(
"%s: %pSG was received on %s interface but we are not DR for that interface",
__func__, &sg, oif->name);
@@ -163,7 +163,7 @@ void tib_sg_gm_prune(struct pim_instance *pim, pim_sgaddr sg,
result = pim_channel_del_oif(*oilp, oif, PIM_OIF_FLAG_PROTO_GM,
__func__);
if (result) {
- if (PIM_DEBUG_IGMP_TRACE)
+ if (PIM_DEBUG_GM_TRACE)
zlog_debug(
"%s: pim_channel_del_oif() failed with return=%d",
__func__, result);
diff --git a/pimd/pim_tlv.c b/pimd/pim_tlv.c
index 65975ce146..c9caf0016e 100644
--- a/pimd/pim_tlv.c
+++ b/pimd/pim_tlv.c
@@ -29,6 +29,8 @@
#include "pim_tlv.h"
#include "pim_str.h"
#include "pim_msg.h"
+#include "pim_iface.h"
+#include "pim_addr.h"
#if PIM_IPV == 4
#define PIM_MSG_ADDRESS_FAMILY PIM_MSG_ADDRESS_FAMILY_IPV4
@@ -226,12 +228,15 @@ int pim_encode_addr_group(uint8_t *buf, afi_t afi, int bidir, int scope,
}
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
- struct list *ifconnected, int family)
+ struct interface *ifp, int family)
{
struct listnode *node;
uint16_t option_len = 0;
uint8_t *curr;
size_t uel;
+ struct list *ifconnected = ifp->connected;
+ struct pim_interface *pim_ifp = ifp->info;
+ pim_addr addr;
node = listhead(ifconnected);
@@ -252,7 +257,10 @@ uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
struct prefix *p = ifc->address;
int l_encode;
- if (!CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY))
+ addr = pim_addr_from_prefix(p);
+ if (!pim_addr_cmp(pim_ifp->primary_address, addr))
+ /* don't add the primary address
+ * into the secondary address list */
continue;
if ((curr + uel) > buf_pastend)
diff --git a/pimd/pim_tlv.h b/pimd/pim_tlv.h
index 64b3a0b6ba..63bd2c41f6 100644
--- a/pimd/pim_tlv.h
+++ b/pimd/pim_tlv.h
@@ -82,7 +82,7 @@ uint8_t *pim_tlv_append_2uint16(uint8_t *buf, const uint8_t *buf_pastend,
uint8_t *pim_tlv_append_uint32(uint8_t *buf, const uint8_t *buf_pastend,
uint16_t option_type, uint32_t option_value);
uint8_t *pim_tlv_append_addrlist_ucast(uint8_t *buf, const uint8_t *buf_pastend,
- struct list *ifconnected, int family);
+ struct interface *ifp, int family);
int pim_tlv_parse_holdtime(const char *ifname, pim_addr src_addr,
pim_hello_options *hello_options,
diff --git a/pimd/pim_upstream.c b/pimd/pim_upstream.c
index 25e7e52705..0742daa4de 100644
--- a/pimd/pim_upstream.c
+++ b/pimd/pim_upstream.c
@@ -1061,15 +1061,13 @@ struct pim_upstream *pim_upstream_add(struct pim_instance *pim, pim_sgaddr *sg,
}
if (PIM_DEBUG_PIM_TRACE) {
- if (up)
- zlog_debug("%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d",
- __func__, name,
- up->sg_str, &up->rpf.rpf_addr, up->rpf.source_nexthop.interface ?
- up->rpf.source_nexthop.interface->name : "Unknown" ,
- found, up->ref_count);
- else
- zlog_debug("%s(%s): (%pSG) failure to create", __func__,
- name, sg);
+ zlog_debug(
+ "%s(%s): %s, iif %pPA (%s) found: %d: ref_count: %d",
+ __func__, name, up->sg_str, &up->rpf.rpf_addr,
+ up->rpf.source_nexthop.interface ? up->rpf.source_nexthop
+ .interface->name
+ : "Unknown",
+ found, up->ref_count);
}
return up;
diff --git a/pimd/pim_vty.c b/pimd/pim_vty.c
index 43d9c29278..9021f1e12f 100644
--- a/pimd/pim_vty.c
+++ b/pimd/pim_vty.c
@@ -58,31 +58,31 @@ int pim_debug_config_write(struct vty *vty)
vty_out(vty, "debug msdp internal\n");
++writes;
}
- if (PIM_DEBUG_IGMP_EVENTS) {
- vty_out(vty, "debug igmp events\n");
+ if (PIM_DEBUG_GM_EVENTS) {
+ vty_out(vty, "debug " GM_AF_DBG " events\n");
++writes;
}
- if (PIM_DEBUG_IGMP_PACKETS) {
- vty_out(vty, "debug igmp packets\n");
+ if (PIM_DEBUG_GM_PACKETS) {
+ vty_out(vty, "debug " GM_AF_DBG " packets\n");
++writes;
}
- /* PIM_DEBUG_IGMP_TRACE catches _DETAIL too */
- if (router->debugs & PIM_MASK_IGMP_TRACE) {
- vty_out(vty, "debug igmp trace\n");
+ /* PIM_DEBUG_GM_TRACE catches _DETAIL too */
+ if (router->debugs & PIM_MASK_GM_TRACE) {
+ vty_out(vty, "debug " GM_AF_DBG " trace\n");
++writes;
}
- if (PIM_DEBUG_IGMP_TRACE_DETAIL) {
- vty_out(vty, "debug igmp trace detail\n");
+ if (PIM_DEBUG_GM_TRACE_DETAIL) {
+ vty_out(vty, "debug " GM_AF_DBG " trace detail\n");
++writes;
}
/* PIM_DEBUG_MROUTE catches _DETAIL too */
if (router->debugs & PIM_MASK_MROUTE) {
- vty_out(vty, "debug mroute\n");
+ vty_out(vty, "debug " PIM_MROUTE_DBG "\n");
++writes;
}
if (PIM_DEBUG_MROUTE_DETAIL) {
- vty_out(vty, "debug mroute detail\n");
+ vty_out(vty, "debug " PIM_MROUTE_DBG " detail\n");
++writes;
}
@@ -129,12 +129,12 @@ int pim_debug_config_write(struct vty *vty)
}
if (PIM_DEBUG_BSM) {
- vty_out(vty, "debug pim bsm\n");
+ vty_out(vty, "debug " PIM_AF_DBG " bsm\n");
++writes;
}
if (PIM_DEBUG_VXLAN) {
- vty_out(vty, "debug pim vxlan\n");
+ vty_out(vty, "debug " PIM_AF_DBG " vxlan\n");
++writes;
}
@@ -314,14 +314,14 @@ static int gm_config_write(struct vty *vty, int writes,
/* IF ip igmp query-max-response-time */
if (pim_ifp->gm_query_max_response_time_dsec !=
- IGMP_QUERY_MAX_RESPONSE_TIME_DSEC) {
+ GM_QUERY_MAX_RESPONSE_TIME_DSEC) {
vty_out(vty, " ip igmp query-max-response-time %d\n",
pim_ifp->gm_query_max_response_time_dsec);
++writes;
}
/* IF ip igmp query-interval */
- if (pim_ifp->gm_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL) {
+ if (pim_ifp->gm_default_query_interval != GM_GENERAL_QUERY_INTERVAL) {
vty_out(vty, " ip igmp query-interval %d\n",
pim_ifp->gm_default_query_interval);
++writes;
@@ -329,7 +329,7 @@ static int gm_config_write(struct vty *vty, int writes,
/* IF ip igmp last-member_query-count */
if (pim_ifp->gm_last_member_query_count !=
- IGMP_DEFAULT_ROBUSTNESS_VARIABLE) {
+ GM_DEFAULT_ROBUSTNESS_VARIABLE) {
vty_out(vty, " ip igmp last-member-query-count %d\n",
pim_ifp->gm_last_member_query_count);
++writes;
@@ -337,7 +337,7 @@ static int gm_config_write(struct vty *vty, int writes,
/* IF ip igmp last-member_query-interval */
if (pim_ifp->gm_specific_query_max_response_time_dsec !=
- IGMP_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC) {
+ GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC) {
vty_out(vty, " ip igmp last-member-query-interval %d\n",
pim_ifp->gm_specific_query_max_response_time_dsec);
++writes;
@@ -370,11 +370,37 @@ static int gm_config_write(struct vty *vty, int writes,
static int gm_config_write(struct vty *vty, int writes,
struct pim_interface *pim_ifp)
{
+ /* IF ipv6 mld */
+ if (pim_ifp->gm_enable) {
+ vty_out(vty, " ipv6 mld\n");
+ ++writes;
+ }
+
if (pim_ifp->mld_version != MLD_DEFAULT_VERSION)
vty_out(vty, " ipv6 mld version %d\n", pim_ifp->mld_version);
- if (pim_ifp->gm_default_query_interval != IGMP_GENERAL_QUERY_INTERVAL)
+
+ /* IF ipv6 mld query-max-response-time */
+ if (pim_ifp->gm_query_max_response_time_dsec !=
+ GM_QUERY_MAX_RESPONSE_TIME_DSEC)
+ vty_out(vty, " ipv6 mld query-max-response-time %d\n",
+ pim_ifp->gm_query_max_response_time_dsec);
+
+ if (pim_ifp->gm_default_query_interval != GM_GENERAL_QUERY_INTERVAL)
vty_out(vty, " ipv6 mld query-interval %d\n",
pim_ifp->gm_default_query_interval);
+
+ /* IF ipv6 mld last-member_query-count */
+ if (pim_ifp->gm_last_member_query_count !=
+ GM_DEFAULT_ROBUSTNESS_VARIABLE)
+ vty_out(vty, " ipv6 mld last-member-query-count %d\n",
+ pim_ifp->gm_last_member_query_count);
+
+ /* IF ipv6 mld last-member_query-interval */
+ if (pim_ifp->gm_specific_query_max_response_time_dsec !=
+ GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC)
+ vty_out(vty, " ipv6 mld last-member-query-interval %d\n",
+ pim_ifp->gm_specific_query_max_response_time_dsec);
+
return 0;
}
#endif
diff --git a/pimd/pimd.h b/pimd/pimd.h
index 9ffa075d2a..3a80c24f7c 100644
--- a/pimd/pimd.h
+++ b/pimd/pimd.h
@@ -32,9 +32,8 @@
#include "pim_memory.h"
#include "pim_assert.h"
-#define PIMD_PROGNAME "pimd"
-#define PIMD_DEFAULT_CONFIG "pimd.conf"
#define PIMD_VTY_PORT 2611
+#define PIM6D_VTY_PORT 2622
#define PIM_IP_PROTO_IGMP (2)
#define PIM_IP_PROTO_PIM (103)
@@ -90,10 +89,10 @@
#define PIM_MASK_PIM_PACKETDUMP_RECV (1 << 4)
#define PIM_MASK_PIM_TRACE (1 << 5)
#define PIM_MASK_PIM_TRACE_DETAIL (1 << 6)
-#define PIM_MASK_IGMP_EVENTS (1 << 7)
-#define PIM_MASK_IGMP_PACKETS (1 << 8)
-#define PIM_MASK_IGMP_TRACE (1 << 9)
-#define PIM_MASK_IGMP_TRACE_DETAIL (1 << 10)
+#define PIM_MASK_GM_EVENTS (1 << 7)
+#define PIM_MASK_GM_PACKETS (1 << 8)
+#define PIM_MASK_GM_TRACE (1 << 9)
+#define PIM_MASK_GM_TRACE_DETAIL (1 << 10)
#define PIM_MASK_ZEBRA (1 << 11)
#define PIM_MASK_SSMPINGD (1 << 12)
#define PIM_MASK_MROUTE (1 << 13)
@@ -160,12 +159,11 @@ extern uint8_t qpim_ecmp_rebalance_enable;
(router->debugs & (PIM_MASK_PIM_TRACE | PIM_MASK_PIM_TRACE_DETAIL))
#define PIM_DEBUG_PIM_TRACE_DETAIL \
(router->debugs & PIM_MASK_PIM_TRACE_DETAIL)
-#define PIM_DEBUG_IGMP_EVENTS (router->debugs & PIM_MASK_IGMP_EVENTS)
-#define PIM_DEBUG_IGMP_PACKETS (router->debugs & PIM_MASK_IGMP_PACKETS)
-#define PIM_DEBUG_IGMP_TRACE \
- (router->debugs & (PIM_MASK_IGMP_TRACE | PIM_MASK_IGMP_TRACE_DETAIL))
-#define PIM_DEBUG_IGMP_TRACE_DETAIL \
- (router->debugs & PIM_MASK_IGMP_TRACE_DETAIL)
+#define PIM_DEBUG_GM_EVENTS (router->debugs & PIM_MASK_GM_EVENTS)
+#define PIM_DEBUG_GM_PACKETS (router->debugs & PIM_MASK_GM_PACKETS)
+#define PIM_DEBUG_GM_TRACE \
+ (router->debugs & (PIM_MASK_GM_TRACE | PIM_MASK_GM_TRACE_DETAIL))
+#define PIM_DEBUG_GM_TRACE_DETAIL (router->debugs & PIM_MASK_GM_TRACE_DETAIL)
#define PIM_DEBUG_ZEBRA (router->debugs & PIM_MASK_ZEBRA)
#define PIM_DEBUG_MLAG (router->debugs & PIM_MASK_MLAG)
#define PIM_DEBUG_SSMPINGD (router->debugs & PIM_MASK_SSMPINGD)
@@ -187,15 +185,13 @@ extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DEBUG_BSM (router->debugs & PIM_MASK_BSM_PROC)
#define PIM_DEBUG_EVENTS \
- (router->debugs \
- & (PIM_MASK_PIM_EVENTS | PIM_MASK_IGMP_EVENTS \
- | PIM_MASK_MSDP_EVENTS | PIM_MASK_BSM_PROC))
+ (router->debugs & (PIM_MASK_PIM_EVENTS | PIM_MASK_GM_EVENTS | \
+ PIM_MASK_MSDP_EVENTS | PIM_MASK_BSM_PROC))
#define PIM_DEBUG_PACKETS \
- (router->debugs \
- & (PIM_MASK_PIM_PACKETS | PIM_MASK_IGMP_PACKETS \
- | PIM_MASK_MSDP_PACKETS))
+ (router->debugs & \
+ (PIM_MASK_PIM_PACKETS | PIM_MASK_GM_PACKETS | PIM_MASK_MSDP_PACKETS))
#define PIM_DEBUG_TRACE \
- (router->debugs & (PIM_MASK_PIM_TRACE | PIM_MASK_IGMP_TRACE))
+ (router->debugs & (PIM_MASK_PIM_TRACE | PIM_MASK_GM_TRACE))
#define PIM_DO_DEBUG_PIM_EVENTS (router->debugs |= PIM_MASK_PIM_EVENTS)
#define PIM_DO_DEBUG_PIM_PACKETS (router->debugs |= PIM_MASK_PIM_PACKETS)
@@ -206,11 +202,11 @@ extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DO_DEBUG_PIM_TRACE (router->debugs |= PIM_MASK_PIM_TRACE)
#define PIM_DO_DEBUG_PIM_TRACE_DETAIL \
(router->debugs |= PIM_MASK_PIM_TRACE_DETAIL)
-#define PIM_DO_DEBUG_IGMP_EVENTS (router->debugs |= PIM_MASK_IGMP_EVENTS)
-#define PIM_DO_DEBUG_IGMP_PACKETS (router->debugs |= PIM_MASK_IGMP_PACKETS)
-#define PIM_DO_DEBUG_IGMP_TRACE (router->debugs |= PIM_MASK_IGMP_TRACE)
-#define PIM_DO_DEBUG_IGMP_TRACE_DETAIL \
- (router->debugs |= PIM_MASK_IGMP_TRACE_DETAIL)
+#define PIM_DO_DEBUG_GM_EVENTS (router->debugs |= PIM_MASK_GM_EVENTS)
+#define PIM_DO_DEBUG_GM_PACKETS (router->debugs |= PIM_MASK_GM_PACKETS)
+#define PIM_DO_DEBUG_GM_TRACE (router->debugs |= PIM_MASK_GM_TRACE)
+#define PIM_DO_DEBUG_GM_TRACE_DETAIL \
+ (router->debugs |= PIM_MASK_GM_TRACE_DETAIL)
#define PIM_DO_DEBUG_ZEBRA (router->debugs |= PIM_MASK_ZEBRA)
#define PIM_DO_DEBUG_MLAG (router->debugs |= PIM_MASK_MLAG)
#define PIM_DO_DEBUG_SSMPINGD (router->debugs |= PIM_MASK_SSMPINGD)
@@ -239,11 +235,11 @@ extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DONT_DEBUG_PIM_TRACE (router->debugs &= ~PIM_MASK_PIM_TRACE)
#define PIM_DONT_DEBUG_PIM_TRACE_DETAIL \
(router->debugs &= ~PIM_MASK_PIM_TRACE_DETAIL)
-#define PIM_DONT_DEBUG_IGMP_EVENTS (router->debugs &= ~PIM_MASK_IGMP_EVENTS)
-#define PIM_DONT_DEBUG_IGMP_PACKETS (router->debugs &= ~PIM_MASK_IGMP_PACKETS)
-#define PIM_DONT_DEBUG_IGMP_TRACE (router->debugs &= ~PIM_MASK_IGMP_TRACE)
-#define PIM_DONT_DEBUG_IGMP_TRACE_DETAIL \
- (router->debugs &= ~PIM_MASK_IGMP_TRACE_DETAIL)
+#define PIM_DONT_DEBUG_GM_EVENTS (router->debugs &= ~PIM_MASK_GM_EVENTS)
+#define PIM_DONT_DEBUG_GM_PACKETS (router->debugs &= ~PIM_MASK_GM_PACKETS)
+#define PIM_DONT_DEBUG_GM_TRACE (router->debugs &= ~PIM_MASK_GM_TRACE)
+#define PIM_DONT_DEBUG_GM_TRACE_DETAIL \
+ (router->debugs &= ~PIM_MASK_GM_TRACE_DETAIL)
#define PIM_DONT_DEBUG_ZEBRA (router->debugs &= ~PIM_MASK_ZEBRA)
#define PIM_DONT_DEBUG_MLAG (router->debugs &= ~PIM_MASK_MLAG)
#define PIM_DONT_DEBUG_SSMPINGD (router->debugs &= ~PIM_MASK_SSMPINGD)
@@ -264,6 +260,24 @@ extern uint8_t qpim_ecmp_rebalance_enable;
#define PIM_DONT_DEBUG_VXLAN (router->debugs &= ~PIM_MASK_VXLAN)
#define PIM_DONT_DEBUG_BSM (router->debugs &= ~PIM_MASK_BSM_PROC)
+/* RFC 3376: 8.1. Robustness Variable - Default: 2 for IGMP */
+/* RFC 2710: 7.1. Robustness Variable - Default: 2 for MLD */
+#define GM_DEFAULT_ROBUSTNESS_VARIABLE 2
+
+/* RFC 3376: 8.2. Query Interval - Default: 125 seconds for IGMP */
+/* RFC 2710: 7.2. Query Interval - Default: 125 seconds for MLD */
+#define GM_GENERAL_QUERY_INTERVAL 125
+
+/* RFC 3376: 8.3. Query Response Interval - Default: 100 deciseconds for IGMP */
+/* RFC 2710: 7.3. Query Response Interval - Default: 100 deciseconds for MLD */
+#define GM_QUERY_MAX_RESPONSE_TIME_DSEC 100
+
+/* RFC 3376: 8.8. Last Member Query Interval - Default: 10 deciseconds for IGMP
+ */
+/* RFC 2710: 7.8. Last Listener Query Interval - Default: 10 deciseconds for MLD
+ */
+#define GM_SPECIFIC_QUERY_MAX_RESPONSE_TIME_DSEC 10
+
void pim_router_init(void);
void pim_router_terminate(void);
diff --git a/qpb/qpb.h b/qpb/qpb.h
index 9aeb7d01d4..45690fb4ac 100644
--- a/qpb/qpb.h
+++ b/qpb/qpb.h
@@ -121,11 +121,13 @@ static inline int qpb__l3_prefix__get(const Qpb__L3Prefix *pb_prefix,
switch (family) {
case AF_INET:
- memset(prefix, 0, sizeof(struct prefix_ipv4));
+ memset((struct prefix_ipv4 *)prefix, 0,
+ sizeof(struct prefix_ipv4));
break;
case AF_INET6:
- memset(prefix, 0, sizeof(struct prefix_ipv6));
+ memset((struct prefix_ipv6 *)prefix, 0,
+ sizeof(struct prefix_ipv6));
break;
default:
diff --git a/redhat/frr.logrotate b/redhat/frr.logrotate
index 04ae96b654..31061e3ae0 100644
--- a/redhat/frr.logrotate
+++ b/redhat/frr.logrotate
@@ -134,6 +134,14 @@
endscript
}
+/var/log/frr/pim6d.log {
+ notifempty
+ missingok
+ postrotate
+ /bin/kill -USR1 `cat /var/run/frr/pim6d.pid 2> /dev/null` 2> /dev/null || true
+ endscript
+}
+
/var/log/frr/sharpd.log {
notifempty
missingok
diff --git a/redhat/frr.spec.in b/redhat/frr.spec.in
index c94785ec01..8f469d2a07 100644
--- a/redhat/frr.spec.in
+++ b/redhat/frr.spec.in
@@ -409,9 +409,6 @@ routing state through standard SNMP MIBs.
--disable-bgp-vnc \
%endif
--enable-isisd \
-%if "%{initsystem}" == "systemd"
- --enable-systemd \
-%endif
--enable-rpki \
%if %{with_bfdd}
--enable-bfdd \
@@ -798,6 +795,8 @@ sed -i 's/ -M rpki//' %{_sysconfdir}/frr/daemons
* Wed Jul 20 2022 Martin Winter <mwinter@opensourcerouting.org> - %{version}
+* Tue Oct 04 2022 Donatas Abraitis <donatas@opensourcerouting.org> - 8.4
+
* Wed Jul 13 2022 Jafar Al-Gharaibeh <jafar@atcorp.com> - 8.3
- General:
- Add camelcase json keys in addition to pascalcase (Wrong JSON keys will be depracated)
diff --git a/ripd/ripd.c b/ripd/ripd.c
index 9798186036..8a321d9a91 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -996,6 +996,7 @@ static size_t rip_auth_md5_ah_write(struct stream *s, struct rip_interface *ri,
struct key *key)
{
size_t doff = 0;
+ static uint32_t seq = 0;
assert(s && ri && ri->auth_type == RIP_AUTH_MD5);
@@ -1028,7 +1029,7 @@ static size_t rip_auth_md5_ah_write(struct stream *s, struct rip_interface *ri,
/* RFC2080: The value used in the sequence number is
arbitrary, but two suggestions are the time of the
message's creation or a simple message counter. */
- stream_putl(s, time(NULL));
+ stream_putl(s, ++seq);
/* Reserved field must be zero. */
stream_putl(s, 0);
@@ -1081,10 +1082,9 @@ static void rip_auth_md5_set(struct stream *s, struct rip_interface *ri,
/* Check packet length. */
if (len < (RIP_HEADER_SIZE + RIP_RTE_SIZE)) {
- flog_err(
- EC_RIP_PACKET,
- "rip_auth_md5_set(): packet length %ld is less than minimum length.",
- len);
+ flog_err(EC_RIP_PACKET,
+ "%s: packet length %ld is less than minimum length.",
+ __func__, len);
return;
}
@@ -1450,9 +1450,8 @@ static int rip_send_packet(uint8_t *buf, int size, struct sockaddr_in *to,
inet_ntop(AF_INET, &sin.sin_addr, dst, sizeof(dst));
}
#undef ADDRESS_SIZE
- zlog_debug("rip_send_packet %pI4 > %s (%s)",
- &ifc->address->u.prefix4, dst,
- ifc->ifp->name);
+ zlog_debug("%s %pI4 > %s (%s)", __func__,
+ &ifc->address->u.prefix4, dst, ifc->ifp->name);
}
if (CHECK_FLAG(ifc->flags, ZEBRA_IFA_SECONDARY)) {
@@ -1771,8 +1770,8 @@ static void rip_read(struct thread *t)
/* If this packet come from unknown interface, ignore it. */
if (ifp == NULL) {
zlog_info(
- "rip_read: cannot find interface for packet from %pI4 port %d (VRF %s)",
- &from.sin_addr, ntohs(from.sin_port),
+ "%s: cannot find interface for packet from %pI4 port %d (VRF %s)",
+ __func__, &from.sin_addr, ntohs(from.sin_port),
rip->vrf_name);
return;
}
@@ -1785,8 +1784,8 @@ static void rip_read(struct thread *t)
if (ifc == NULL) {
zlog_info(
- "rip_read: cannot find connected address for packet from %pI4 port %d on interface %s (VRF %s)",
- &from.sin_addr, ntohs(from.sin_port),
+ "%s: cannot find connected address for packet from %pI4 port %d on interface %s (VRF %s)",
+ __func__, &from.sin_addr, ntohs(from.sin_port),
ifp->name, rip->vrf_name);
return;
}
diff --git a/sharpd/sharp_vty.c b/sharpd/sharp_vty.c
index 2281b3ce26..3853df7cb0 100644
--- a/sharpd/sharp_vty.c
+++ b/sharpd/sharp_vty.c
@@ -234,6 +234,8 @@ DEFPY (install_routes,
memset(&prefix, 0, sizeof(prefix));
memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
+ nexthop_del_srv6_seg6local(&sg.r.nhop);
+ nexthop_del_srv6_seg6(&sg.r.nhop);
memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
@@ -376,6 +378,8 @@ DEFPY (install_seg6_routes,
memset(&prefix, 0, sizeof(prefix));
memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
+ nexthop_del_srv6_seg6local(&sg.r.nhop);
+ nexthop_del_srv6_seg6(&sg.r.nhop);
memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
@@ -467,6 +471,8 @@ DEFPY (install_seg6local_routes,
sg.r.repeat = 0;
memset(&sg.r.orig_prefix, 0, sizeof(sg.r.orig_prefix));
+ nexthop_del_srv6_seg6local(&sg.r.nhop);
+ nexthop_del_srv6_seg6(&sg.r.nhop);
memset(&sg.r.nhop, 0, sizeof(sg.r.nhop));
memset(&sg.r.nhop_group, 0, sizeof(sg.r.nhop_group));
memset(&sg.r.backup_nhop, 0, sizeof(sg.r.nhop));
@@ -924,6 +930,11 @@ DEFPY (import_te,
return CMD_SUCCESS;
}
+static void sharp_srv6_locator_chunk_free(struct prefix_ipv6 *chunk)
+{
+ prefix_ipv6_free((struct prefix_ipv6 **)&chunk);
+}
+
DEFPY (sharp_srv6_manager_get_locator_chunk,
sharp_srv6_manager_get_locator_chunk_cmd,
"sharp srv6-manager get-locator-chunk NAME$locator_name",
@@ -947,6 +958,8 @@ DEFPY (sharp_srv6_manager_get_locator_chunk,
loc = XCALLOC(MTYPE_SRV6_LOCATOR,
sizeof(struct sharp_srv6_locator));
loc->chunks = list_new();
+ loc->chunks->del =
+ (void (*)(void *))sharp_srv6_locator_chunk_free;
snprintf(loc->name, SRV6_LOCNAME_SIZE, "%s", locator_name);
listnode_add(sg.srv6_locators, loc);
}
@@ -1096,6 +1109,7 @@ DEFPY (sharp_srv6_manager_release_locator_chunk,
list_delete_all_node(loc->chunks);
list_delete(&loc->chunks);
listnode_delete(sg.srv6_locators, loc);
+ XFREE(MTYPE_SRV6_LOCATOR, loc);
break;
}
}
diff --git a/staticd/static_nb_config.c b/staticd/static_nb_config.c
index 9ccffe53d9..5a7044e9f9 100644
--- a/staticd/static_nb_config.c
+++ b/staticd/static_nb_config.c
@@ -263,6 +263,7 @@ nexthop_mpls_label_stack_entry_destroy(struct nb_cb_destroy_args *args)
struct static_nexthop *nh;
uint32_t pos;
uint8_t index;
+ uint old_num_labels;
switch (args->event) {
case NB_EV_VALIDATE:
@@ -278,8 +279,12 @@ nexthop_mpls_label_stack_entry_destroy(struct nb_cb_destroy_args *args)
return NB_ERR;
}
index = pos - 1;
+ old_num_labels = nh->snh_label.num_labels;
nh->snh_label.label[index] = 0;
nh->snh_label.num_labels--;
+
+ if (old_num_labels != nh->snh_label.num_labels)
+ nh->state = STATIC_START;
break;
}
@@ -291,6 +296,7 @@ static int static_nexthop_mpls_label_modify(struct nb_cb_modify_args *args)
struct static_nexthop *nh;
uint32_t pos;
uint8_t index;
+ mpls_label_t old_label;
nh = nb_running_get_entry(args->dnode, NULL, true);
pos = yang_get_list_pos(lyd_parent(args->dnode));
@@ -301,8 +307,13 @@ static int static_nexthop_mpls_label_modify(struct nb_cb_modify_args *args)
}
/* Mapping to array = list-index -1 */
index = pos - 1;
+
+ old_label = nh->snh_label.label[index];
nh->snh_label.label[index] = yang_dnode_get_uint32(args->dnode, NULL);
+ if (old_label != nh->snh_label.label[index])
+ nh->state = STATIC_START;
+
return NB_OK;
}
@@ -310,6 +321,7 @@ static int static_nexthop_onlink_modify(struct nb_cb_modify_args *args)
{
struct static_nexthop *nh;
enum static_nh_type nh_type;
+ bool old_onlink;
switch (args->event) {
case NB_EV_VALIDATE:
@@ -327,7 +339,11 @@ static int static_nexthop_onlink_modify(struct nb_cb_modify_args *args)
break;
case NB_EV_APPLY:
nh = nb_running_get_entry(args->dnode, NULL, true);
+ old_onlink = nh->onlink;
nh->onlink = yang_dnode_get_bool(args->dnode, NULL);
+
+ if (old_onlink != nh->onlink)
+ nh->state = STATIC_START;
break;
}
@@ -337,20 +353,30 @@ static int static_nexthop_onlink_modify(struct nb_cb_modify_args *args)
static int static_nexthop_color_modify(struct nb_cb_modify_args *args)
{
struct static_nexthop *nh;
+ uint32_t old_color;
nh = nb_running_get_entry(args->dnode, NULL, true);
+ old_color = nh->color;
nh->color = yang_dnode_get_uint32(args->dnode, NULL);
+ if (old_color != nh->color)
+ nh->state = STATIC_START;
+
return NB_OK;
}
static int static_nexthop_color_destroy(struct nb_cb_destroy_args *args)
{
struct static_nexthop *nh;
+ uint32_t old_color;
nh = nb_running_unset_entry(args->dnode);
+ old_color = nh->color;
nh->color = 0;
+ if (old_color != nh->color)
+ nh->state = STATIC_START;
+
return NB_OK;
}
diff --git a/tests/lib/test_typelist.h b/tests/lib/test_typelist.h
index e3579c67a2..feb42909a8 100644
--- a/tests/lib/test_typelist.h
+++ b/tests/lib/test_typelist.h
@@ -74,7 +74,7 @@ static uint32_t list_hash(const struct item *a)
{
#ifdef SHITTY_HASH
/* crappy hash to get some hash collisions */
- return a->val ^ (a->val << 29) ^ 0x55AA0000U;
+ return (a->val & 0xFF) ^ (a->val << 29) ^ 0x55AA0000U;
#else
return jhash_1word(a->val, 0xdeadbeef);
#endif
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/__init__.py b/tests/topotests/bgp_aggregate_address_matching_med/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/__init__.py
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/r1/bgpd.conf b/tests/topotests/bgp_aggregate_address_matching_med/r1/bgpd.conf
new file mode 100644
index 0000000000..35597602f7
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/r1/bgpd.conf
@@ -0,0 +1,21 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 3 10
+ address-family ipv4 unicast
+ redistribute connected
+ neighbor 192.168.1.2 route-map r2 out
+ exit-address-family
+!
+ip prefix-list p1 seq 5 permit 172.16.255.1/32
+ip prefix-list p1 seq 10 permit 172.16.255.2/32
+ip prefix-list p2 seq 15 permit 172.16.255.3/32
+!
+route-map r2 permit 10
+ match ip address prefix-list p1
+ set metric 300
+route-map r2 permit 20
+ match ip address prefix-list p2
+ set metric 400
+!
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/r1/zebra.conf b/tests/topotests/bgp_aggregate_address_matching_med/r1/zebra.conf
new file mode 100644
index 0000000000..685adb3080
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/r1/zebra.conf
@@ -0,0 +1,11 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+ ip address 172.16.255.2/32
+ ip address 172.16.255.3/32
+!
+interface r1-eth0
+ ip address 192.168.1.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/r2/bgpd.conf b/tests/topotests/bgp_aggregate_address_matching_med/r2/bgpd.conf
new file mode 100644
index 0000000000..9bc9a3132f
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/r2/bgpd.conf
@@ -0,0 +1,11 @@
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 3 10
+ neighbor 192.168.2.1 remote-as external
+ neighbor 192.168.2.1 timers 3 10
+ address-family ipv4 unicast
+ aggregate-address 172.16.255.0/24 summary-only matching-MED-only
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/r2/zebra.conf b/tests/topotests/bgp_aggregate_address_matching_med/r2/zebra.conf
new file mode 100644
index 0000000000..f229954341
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/r2/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface r2-eth0
+ ip address 192.168.1.2/24
+!
+interface r2-eth1
+ ip address 192.168.2.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/r3/bgpd.conf b/tests/topotests/bgp_aggregate_address_matching_med/r3/bgpd.conf
new file mode 100644
index 0000000000..dfb5ac7a3c
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/r3/bgpd.conf
@@ -0,0 +1,6 @@
+!
+router bgp 65003
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers 3 10
+!
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/r3/zebra.conf b/tests/topotests/bgp_aggregate_address_matching_med/r3/zebra.conf
new file mode 100644
index 0000000000..11e06d47cc
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/r3/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r3-eth0
+ ip address 192.168.2.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_aggregate_address_matching_med/test_bgp_aggregate_address_matching_med.py b/tests/topotests/bgp_aggregate_address_matching_med/test_bgp_aggregate_address_matching_med.py
new file mode 100644
index 0000000000..edf50dc9e0
--- /dev/null
+++ b/tests/topotests/bgp_aggregate_address_matching_med/test_bgp_aggregate_address_matching_med.py
@@ -0,0 +1,148 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# 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 aggregate-address command works fine when suppressing summary-only
+and using matching-MED-only together.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+from lib.common_config import (
+ step,
+)
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+
+def build_topo(tgen):
+ for routern in range(1, 5):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r2"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_aggregate_address_matching_med():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r3 = tgen.gears["r3"]
+
+ def _bgp_converge():
+ output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "172.16.255.0/24": None,
+ "172.16.255.1/32": [{"path": "65002 65001"}],
+ "172.16.255.2/32": [{"path": "65002 65001"}],
+ "172.16.255.3/32": [{"path": "65002 65001"}],
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed to see unsuppressed routes from R2"
+
+ step("Change MED for 172.16.255.3/32 from 400 to 300")
+ r1.vtysh_cmd(
+ """
+ configure terminal
+ route-map r2 permit 20
+ set metric 300
+ """
+ )
+
+ step("Check if 172.16.255.0/24 aggregated route was created and others suppressed")
+
+ def _bgp_aggregated_summary_only_med_match():
+ output = json.loads(r3.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "172.16.255.0/24": [{"path": "65002"}],
+ "172.16.255.1/32": None,
+ "172.16.255.2/32": None,
+ "172.16.255.3/32": None,
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_aggregated_summary_only_med_match)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed to see unsuppressed routes from R2"
+
+ step("Change MED for 172.16.255.3/32 back to 400 from 300")
+ r1.vtysh_cmd(
+ """
+ configure terminal
+ route-map r2 permit 20
+ set metric 400
+ """
+ )
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed to see unsuppressed routes from R2"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_as_override/__init__.py b/tests/topotests/bgp_as_override/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_as_override/__init__.py
diff --git a/tests/topotests/bgp_as_override/r1/bgpd.conf b/tests/topotests/bgp_as_override/r1/bgpd.conf
new file mode 100644
index 0000000000..3cfb7a2c90
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r1/bgpd.conf
@@ -0,0 +1,10 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_as_override/r1/zebra.conf b/tests/topotests/bgp_as_override/r1/zebra.conf
new file mode 100644
index 0000000000..63728eb5d5
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r1/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.1.2/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_as_override/r2/bgpd.conf b/tests/topotests/bgp_as_override/r2/bgpd.conf
new file mode 100644
index 0000000000..5e3b0c7f87
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r2/bgpd.conf
@@ -0,0 +1,10 @@
+!
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers 1 3
+ neighbor 192.168.2.2 timers connect 1
+!
diff --git a/tests/topotests/bgp_as_override/r2/zebra.conf b/tests/topotests/bgp_as_override/r2/zebra.conf
new file mode 100644
index 0000000000..5bdfd02224
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r2/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface r2-eth0
+ ip address 192.168.1.1/30
+!
+interface r2-eth1
+ ip address 192.168.2.1/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_as_override/r3/bgpd.conf b/tests/topotests/bgp_as_override/r3/bgpd.conf
new file mode 100644
index 0000000000..6bbe56b678
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r3/bgpd.conf
@@ -0,0 +1,13 @@
+!
+router bgp 65003
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.1 remote-as external
+ neighbor 192.168.2.1 timers 1 3
+ neighbor 192.168.2.1 timers connect 1
+ neighbor 192.168.3.1 remote-as external
+ neighbor 192.168.3.1 timers 1 3
+ neighbor 192.168.3.1 timers connect 1
+ address-family ipv4 unicast
+ neighbor 192.168.3.1 as-override
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_as_override/r3/zebra.conf b/tests/topotests/bgp_as_override/r3/zebra.conf
new file mode 100644
index 0000000000..77782be3a8
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r3/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface r3-eth0
+ ip address 192.168.2.2/30
+!
+interface r3-eth1
+ ip address 192.168.3.2/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_as_override/r4/bgpd.conf b/tests/topotests/bgp_as_override/r4/bgpd.conf
new file mode 100644
index 0000000000..1bdee0800a
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r4/bgpd.conf
@@ -0,0 +1,7 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.3.2 remote-as external
+ neighbor 192.168.3.2 timers 1 3
+ neighbor 192.168.3.2 timers connect 1
+!
diff --git a/tests/topotests/bgp_as_override/r4/zebra.conf b/tests/topotests/bgp_as_override/r4/zebra.conf
new file mode 100644
index 0000000000..71dc595558
--- /dev/null
+++ b/tests/topotests/bgp_as_override/r4/zebra.conf
@@ -0,0 +1,6 @@
+!
+interface r4-eth0
+ ip address 192.168.3.1/30
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_as_override/test_bgp_as_override.py b/tests/topotests/bgp_as_override/test_bgp_as_override.py
new file mode 100644
index 0000000000..40085cd7ec
--- /dev/null
+++ b/tests/topotests/bgp_as_override/test_bgp_as_override.py
@@ -0,0 +1,122 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# 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.
+#
+
+"""
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 7):
+ 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["r3"])
+ switch.add_link(tgen.gears["r4"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for 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_as_override():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r3 = tgen.gears["r3"]
+ r4 = tgen.gears["r4"]
+
+ def _bgp_converge():
+ output = json.loads(r3.vtysh_cmd("show ip bgp neighbor 192.168.2.1 json"))
+ expected = {
+ "192.168.2.1": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_as_override():
+ output = json.loads(r4.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "172.16.255.1/32": [{"valid": True, "path": "65003 65002 65003"}]
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R4"
+
+ step("Check if BGP as-override from R3 works")
+ test_func = functools.partial(_bgp_as_override)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see overriden ASN (65001) from R3"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py b/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py
index 1097be3d70..0e16b97e4a 100644
--- a/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py
+++ b/tests/topotests/bgp_conditional_advertisement/test_bgp_conditional_advertisement.py
@@ -43,10 +43,15 @@ TC21: exist-map routes present in R2's BGP table.
advertise-map routes present in R2's BGP table are advertised to R3.
TC22: exist-map routes not present in R2's BGP table
advertise-map routes present in R2's BGP table are withdrawn from R3.
+TC23: advertise-map with exist-map configuration is removed from a peer
+ send normal BGP update to advertise previously withdrawn routes if any.
+
TC31: non-exist-map routes not present in R2's BGP table
advertise-map routes present in R2's BGP table are advertised to R3.
TC32: non-exist-map routes present in R2's BGP table
advertise-map routes present in R2's BGP table are withdrawn from R3.
+TC33: advertise-map with non-exist-map configuration is removed from a peer
+ send normal BGP update to advertisepreviously withdrawn routes if any.
TC41: non-exist-map route-map configuration removed in R2.
advertise-map routes present in R2's BGP table are advertised to R3.
@@ -221,6 +226,18 @@ def all_routes_withdrawn(router):
return topotest.json_cmp(output, expected)
+def default_route_withdrawn(router):
+ output = json.loads(router.vtysh_cmd("show ip route json"))
+ expected = {
+ "0.0.0.0/0": None,
+ "192.0.2.1/32": [{"protocol": "bgp"}],
+ "192.0.2.5/32": [{"protocol": "bgp"}],
+ "10.139.224.0/20": [{"protocol": "bgp"}],
+ "203.0.113.1/32": [{"protocol": "bgp"}],
+ }
+ return topotest.json_cmp(output, expected)
+
+
# BGP conditional advertisement with route-maps
# EXIST-MAP, ADV-MAP-1 and RMAP-1
def exist_map_routes_present(router):
@@ -252,15 +269,7 @@ def non_exist_map_routes_present(router):
def non_exist_map_routes_not_present(router):
- output = json.loads(router.vtysh_cmd("show ip route json"))
- expected = {
- "0.0.0.0/0": None,
- "192.0.2.1/32": [{"protocol": "bgp"}],
- "192.0.2.5/32": [{"protocol": "bgp"}],
- "10.139.224.0/20": [{"protocol": "bgp"}],
- "203.0.113.1/32": [{"protocol": "bgp"}],
- }
- return topotest.json_cmp(output, expected)
+ return default_route_withdrawn(router)
def exist_map_no_condition_route_map(router):
@@ -389,7 +398,7 @@ passed = "PASSED!!!"
failed = "FAILED!!!"
-def test_bgp_conditional_advertisement_step1():
+def test_bgp_conditional_advertisement_tc_1_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -409,7 +418,7 @@ def test_bgp_conditional_advertisement_step1():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step2():
+def test_bgp_conditional_advertisement_tc_2_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -438,7 +447,7 @@ def test_bgp_conditional_advertisement_step2():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step3():
+def test_bgp_conditional_advertisement_tc_2_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -467,7 +476,36 @@ def test_bgp_conditional_advertisement_step3():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step4():
+def test_bgp_conditional_advertisement_tc_2_3():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
+ # TC23: advertise-map with exist-map configuration is removed from a peer
+ # send normal BGP update to advertise previously withdrawn routes if any.
+ router2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2
+ address-family ipv4 unicast
+ no neighbor 10.10.20.3 advertise-map ADV-MAP-1 exist-map EXIST-MAP
+ """
+ )
+
+ test_func = functools.partial(default_route_withdrawn, router3)
+ success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
+
+ msg = "TC23: advertise-map with exist-map configuration is removed from peer - "
+ assert result is None, msg + failed
+
+ logger.info(msg + passed)
+
+
+def test_bgp_conditional_advertisement_tc_3_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -496,7 +534,7 @@ def test_bgp_conditional_advertisement_step4():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step5():
+def test_bgp_conditional_advertisement_tc_3_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -525,7 +563,38 @@ def test_bgp_conditional_advertisement_step5():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step6():
+def test_bgp_conditional_advertisement_tc_3_3():
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router1 = tgen.gears["r1"]
+ router2 = tgen.gears["r2"]
+ router3 = tgen.gears["r3"]
+
+ # TC33: advertise-map with non-exist-map configuration is removed from a peer
+ # send normal BGP update to advertisepreviously withdrawn routes if any.
+ router2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 2
+ address-family ipv4 unicast
+ no neighbor 10.10.20.3 advertise-map ADV-MAP-1 non-exist-map EXIST-MAP
+ """
+ )
+
+ test_func = functools.partial(all_routes_advertised, router3)
+ success, result = topotest.run_and_expect(test_func, None, count=90, wait=1)
+
+ msg = (
+ "TC33: advertise-map with non-exist-map configuration is removed from a peer - "
+ )
+ assert result is None, msg + failed
+
+ logger.info(msg + passed)
+
+
+def test_bgp_conditional_advertisement_tc_4_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -539,6 +608,9 @@ def test_bgp_conditional_advertisement_step6():
router2.vtysh_cmd(
"""
configure terminal
+ router bgp 2
+ address-family ipv4 unicast
+ neighbor 10.10.20.3 advertise-map ADV-MAP-1 non-exist-map EXIST-MAP
no route-map EXIST-MAP permit 10
"""
)
@@ -552,7 +624,7 @@ def test_bgp_conditional_advertisement_step6():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step7():
+def test_bgp_conditional_advertisement_tc_4_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -581,7 +653,7 @@ def test_bgp_conditional_advertisement_step7():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step8():
+def test_bgp_conditional_advertisement_tc_5_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -614,7 +686,7 @@ def test_bgp_conditional_advertisement_step8():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step9():
+def test_bgp_conditional_advertisement_tc_5_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -643,7 +715,7 @@ def test_bgp_conditional_advertisement_step9():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step10():
+def test_bgp_conditional_advertisement_tc_5_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -673,7 +745,7 @@ def test_bgp_conditional_advertisement_step10():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step11():
+def test_bgp_conditional_advertisement_tc_5_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -702,7 +774,7 @@ def test_bgp_conditional_advertisement_step11():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step12():
+def test_bgp_conditional_advertisement_tc_6_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -740,7 +812,7 @@ def test_bgp_conditional_advertisement_step12():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step13():
+def test_bgp_conditional_advertisement_tc_6_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -769,7 +841,7 @@ def test_bgp_conditional_advertisement_step13():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step14():
+def test_bgp_conditional_advertisement_tc_6_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -799,7 +871,7 @@ def test_bgp_conditional_advertisement_step14():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step15():
+def test_bgp_conditional_advertisement_tc_6_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -830,7 +902,7 @@ def test_bgp_conditional_advertisement_step15():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step16():
+def test_bgp_conditional_advertisement_tc_7_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -868,7 +940,7 @@ def test_bgp_conditional_advertisement_step16():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step17():
+def test_bgp_conditional_advertisement_tc_7_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -897,7 +969,7 @@ def test_bgp_conditional_advertisement_step17():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step18():
+def test_bgp_conditional_advertisement_tc_7_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -927,7 +999,7 @@ def test_bgp_conditional_advertisement_step18():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step19():
+def test_bgp_conditional_advertisement_tc_7_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -956,7 +1028,7 @@ def test_bgp_conditional_advertisement_step19():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step20():
+def test_bgp_conditional_advertisement_tc_8_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -994,7 +1066,7 @@ def test_bgp_conditional_advertisement_step20():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step21():
+def test_bgp_conditional_advertisement_tc_8_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -1023,7 +1095,7 @@ def test_bgp_conditional_advertisement_step21():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step22():
+def test_bgp_conditional_advertisement_tc_8_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -1055,7 +1127,7 @@ def test_bgp_conditional_advertisement_step22():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step23():
+def test_bgp_conditional_advertisement_tc_8_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -1086,7 +1158,7 @@ def test_bgp_conditional_advertisement_step23():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step24():
+def test_bgp_conditional_advertisement_tc_9_1():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -1124,7 +1196,7 @@ def test_bgp_conditional_advertisement_step24():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step25():
+def test_bgp_conditional_advertisement_tc_9_2():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -1153,7 +1225,7 @@ def test_bgp_conditional_advertisement_step25():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step26():
+def test_bgp_conditional_advertisement_tc_9_3():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
@@ -1193,7 +1265,7 @@ def test_bgp_conditional_advertisement_step26():
logger.info(msg + passed)
-def test_bgp_conditional_advertisement_step27():
+def test_bgp_conditional_advertisement_tc_9_4():
tgen = get_topogen()
if tgen.routers_have_failure():
pytest.skip(tgen.errors)
diff --git a/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py b/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py
index c8cdc7ec5c..4d7f436eac 100644
--- a/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py
+++ b/tests/topotests/bgp_default_originate/test_bgp_default_originate_2links.py
@@ -22,6 +22,7 @@
Following tests are covered.
1. Verify default-originate route with default static and network command
2. Verify default-originate route with aggregate summary command
+3. Verfiy default-originate behaviour in ecmp
"""
import os
import sys
@@ -48,7 +49,10 @@ from lib.bgp import (
from lib.common_config import (
verify_fib_routes,
step,
+ create_prefix_lists,
run_frr_cmd,
+ create_route_maps,
+ shutdown_bringup_interface,
get_frr_ipv6_linklocal,
start_topology,
apply_raw_config,
@@ -296,6 +300,78 @@ def verify_the_uptime(time_stamp_before, time_stamp_after, incremented=None):
return True
+def get_best_path_route_in_FIB(tgen, topo, dut, network):
+ """
+ API to verify the best route in FIB and return the ipv4 and ipv6 nexthop for the given route
+ command
+ =======
+ show ip route
+ show ipv6 route
+ params
+ ======
+ dut : device under test :
+ network ; route (ip) to which the best route to be retrieved
+ Returns
+ ========
+ on success : return dict with next hops for the best hop
+ on failure : return error message with boolean False
+ """
+ is_ipv4_best_path_found = False
+ is_ipv6_best_path_found = False
+ rnode = tgen.routers()[dut]
+ ipv4_show_bgp_json = run_frr_cmd(rnode, "sh ip bgp json ", isjson=True)
+ ipv6_show_bgp_json = run_frr_cmd(
+ rnode, "sh ip bgp ipv6 unicast json ", isjson=True
+ )
+ output_dict = {"ipv4": None, "ipv6": None}
+ ipv4_nxt_hop_count = len(ipv4_show_bgp_json["routes"][network["ipv4"]])
+ for index in range(ipv4_nxt_hop_count):
+ if "bestpath" in ipv4_show_bgp_json["routes"][network["ipv4"]][index].keys():
+ best_path_ip = ipv4_show_bgp_json["routes"][network["ipv4"]][index][
+ "nexthops"
+ ][0]["ip"]
+ output_dict["ipv4"] = best_path_ip
+ logger.info(
+ "[DUT [{}]] Best path for the route {} is {} ".format(
+ dut, network["ipv4"], best_path_ip
+ )
+ )
+ is_ipv4_best_path_found = True
+ else:
+ logger.error("ERROR....! No Best Path Found in BGP RIB.... FAILED")
+
+ ipv6_nxt_hop_count = len(ipv6_show_bgp_json["routes"][network["ipv6"]])
+ for index in range(ipv6_nxt_hop_count):
+ if "bestpath" in ipv6_show_bgp_json["routes"][network["ipv6"]][index].keys():
+ ip_add_count = len(
+ ipv6_show_bgp_json["routes"][network["ipv6"]][index]["nexthops"]
+ )
+ for i_index in range(ip_add_count):
+ if (
+ "global"
+ in ipv6_show_bgp_json["routes"][network["ipv6"]][index]["nexthops"][
+ i_index
+ ]["scope"]
+ ):
+ best_path_ip = ipv6_show_bgp_json["routes"][network["ipv6"]][index][
+ "nexthops"
+ ][i_index]["ip"]
+ output_dict["ipv6"] = best_path_ip
+ logger.info(
+ "[DUT [{}]] Best path for the route {} is {} ".format(
+ dut, network["ipv6"], best_path_ip
+ )
+ )
+
+ else:
+ logger.error("ERROR....! No Best Path Found in BGP RIB.... FAILED")
+ if is_ipv4_best_path_found:
+ return output_dict
+ else:
+ logger.error("ERROR...! Unable to find the Best Path in the RIB")
+ return False
+
+
#####################################################
#
# Testcases
@@ -1409,6 +1485,326 @@ def test_verify_bgp_default_originate_with_aggregate_summary_p1(request):
write_test_footer(tc_name)
+def test_verify_default_originate_with_2way_ecmp_p2(request):
+ """
+ Summary: "Verify default-originate route with 3 way ECMP and traffic "
+ """
+
+ tgen = get_topogen()
+ global BGP_CONVERGENCE
+ global DEFAULT_ROUTES
+ DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"}
+
+ if BGP_CONVERGENCE != True:
+ pytest.skip("skipped because of BGP Convergence failure")
+ # test case name
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+ reset_config_on_routers(tgen)
+
+ step("Populating next-hops details")
+ r1_r2_ipv4_neighbor_ips = []
+ r1_r2_ipv6_neighbor_ips = []
+ r1_link = None
+ for index in range(1, 3):
+ r1_link = "r1-link" + str(index)
+ r1_r2_ipv4_neighbor_ips.append(
+ topo["routers"]["r2"]["links"][r1_link]["ipv4"].split("/")[0]
+ )
+ r1_r2_ipv6_neighbor_ips.append(
+ topo["routers"]["r2"]["links"][r1_link]["ipv6"].split("/")[0]
+ )
+
+ step(
+ "Configure default-originate on R1 for all the neighbor of IPv4 and IPv6 peers "
+ )
+ local_as = get_dut_as_number(tgen, dut="r1")
+ for index in range(2):
+ raw_config = {
+ "r1": {
+ "raw_config": [
+ "router bgp {}".format(local_as),
+ "address-family ipv4 unicast",
+ "neighbor {} default-originate".format(
+ r1_r2_ipv4_neighbor_ips[index]
+ ),
+ "exit-address-family",
+ "address-family ipv6 unicast",
+ "neighbor {} default-originate ".format(
+ r1_r2_ipv6_neighbor_ips[index]
+ ),
+ "exit-address-family",
+ ]
+ }
+ }
+ result = apply_raw_config(tgen, raw_config)
+ assert result is True, "Testcase {} : Failed Error: {}".format(tc_name, result)
+
+ step(
+ "After configuring default-originate command , verify default routes are advertised on R2 "
+ )
+
+ r2_link = None
+ for index in range(1, 3):
+ r2_link = "r2-link" + str(index)
+ ipv4_nxt_hop = topo["routers"]["r1"]["links"][r2_link]["ipv4"].split("/")[0]
+ interface = topo["routers"]["r1"]["links"][r2_link]["interface"]
+ ipv6_link_local_nxt_hop = get_frr_ipv6_linklocal(tgen, "r1", intf=interface)
+ DEFAULT_ROUTE_NXT_HOP = {"ipv4": ipv4_nxt_hop, "ipv6": ipv6_link_local_nxt_hop}
+
+ result = verify_rib_default_route(
+ tgen,
+ topo,
+ dut="r2",
+ routes=DEFAULT_ROUTES,
+ expected_nexthop=DEFAULT_ROUTE_NXT_HOP,
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Ping R1 configure IPv4 and IPv6 loopback address from R2")
+ pingaddr = topo["routers"]["r1"]["links"]["lo"]["ipv4"].split("/")[0]
+ router = tgen.gears["r2"]
+ output = router.run("ping -c 4 -w 4 {}".format(pingaddr))
+ assert " 0% packet loss" in output, "Ping R1->R2 FAILED"
+ logger.info("Ping from R1 to R2 ... success")
+
+ step("Shuting up the active route")
+ network = {"ipv4": "0.0.0.0/0", "ipv6": "::/0"}
+ ipv_dict = get_best_path_route_in_FIB(tgen, topo, dut="r2", network=network)
+ dut_links = topo["routers"]["r1"]["links"]
+ active_interface = None
+ for key, values in dut_links.items():
+ ipv4_address = dut_links[key]["ipv4"].split("/")[0]
+ ipv6_address = dut_links[key]["ipv6"].split("/")[0]
+ if ipv_dict["ipv4"] == ipv4_address and ipv_dict["ipv6"] == ipv6_address:
+ active_interface = dut_links[key]["interface"]
+
+ logger.info(
+ "Shutting down the interface {} on router {} ".format(active_interface, "r1")
+ )
+ shutdown_bringup_interface(tgen, "r1", active_interface, False)
+
+ step("Verify the complete convergence to fail after shutting the interface")
+ result = verify_bgp_convergence(tgen, topo, expected=False)
+ assert (
+ result is not True
+ ), " Testcase {} : After shuting down the interface Convergence is expected to be Failed".format(
+ tc_name
+ )
+
+ step(
+ "Verify routes from active best path is not received from r1 after shuting the interface"
+ )
+ r2_link = None
+ for index in range(1, 3):
+ r2_link = "r2-link" + str(index)
+ ipv4_nxt_hop = topo["routers"]["r1"]["links"][r2_link]["ipv4"].split("/")[0]
+ interface = topo["routers"]["r1"]["links"][r2_link]["interface"]
+ ipv6_link_local_nxt_hop = get_frr_ipv6_linklocal(tgen, "r1", intf=interface)
+ DEFAULT_ROUTE_NXT_HOP = {"ipv4": ipv4_nxt_hop, "ipv6": ipv6_link_local_nxt_hop}
+ if index == 1:
+ result = verify_rib_default_route(
+ tgen,
+ topo,
+ dut="r2",
+ routes=DEFAULT_ROUTES,
+ expected_nexthop=DEFAULT_ROUTE_NXT_HOP,
+ expected=False,
+ )
+ assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ else:
+ result = verify_rib_default_route(
+ tgen,
+ topo,
+ dut="r2",
+ routes=DEFAULT_ROUTES,
+ expected_nexthop=DEFAULT_ROUTE_NXT_HOP,
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Ping R1 configure IPv4 and IPv6 loopback address from R2")
+ pingaddr = topo["routers"]["r1"]["links"]["lo"]["ipv4"].split("/")[0]
+ router = tgen.gears["r2"]
+ output = router.run("ping -c 4 -w 4 {}".format(pingaddr))
+ assert " 0% packet loss" in output, "Ping R1->R2 FAILED"
+ logger.info("Ping from R1 to R2 ... success")
+
+ step("No Shuting up the active route")
+
+ shutdown_bringup_interface(tgen, "r1", active_interface, True)
+
+ step("Verify the complete convergence after bringup the interface")
+ result = verify_bgp_convergence(tgen, topo)
+ assert (
+ result is True
+ ), " Testcase {} : After bringing up the interface complete convergence is expected ".format(
+ tc_name
+ )
+
+ step("Verify all the routes are received from r1 after no shuting the interface")
+ r2_link = None
+ for index in range(1, 3):
+ r2_link = "r2-link" + str(index)
+ ipv4_nxt_hop = topo["routers"]["r1"]["links"][r2_link]["ipv4"].split("/")[0]
+ interface = topo["routers"]["r1"]["links"][r2_link]["interface"]
+ ipv6_link_local_nxt_hop = get_frr_ipv6_linklocal(tgen, "r1", intf=interface)
+ DEFAULT_ROUTE_NXT_HOP = {"ipv4": ipv4_nxt_hop, "ipv6": ipv6_link_local_nxt_hop}
+ if index == 1:
+ result = verify_rib_default_route(
+ tgen,
+ topo,
+ dut="r2",
+ routes=DEFAULT_ROUTES,
+ expected_nexthop=DEFAULT_ROUTE_NXT_HOP,
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+ else:
+ result = verify_rib_default_route(
+ tgen,
+ topo,
+ dut="r2",
+ routes=DEFAULT_ROUTES,
+ expected_nexthop=DEFAULT_ROUTE_NXT_HOP,
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Configure IPv4 and IPv6 route-map with deny option on R2 to filter default route 0.0.0.0/0 and 0::0/0"
+ )
+ DEFAULT_ROUTES = {"ipv4": "0.0.0.0/0", "ipv6": "0::0/0"}
+ input_dict_3 = {
+ "r2": {
+ "prefix_lists": {
+ "ipv4": {
+ "Pv4": [
+ {
+ "seqid": "1",
+ "network": DEFAULT_ROUTES["ipv4"],
+ "action": "permit",
+ }
+ ]
+ },
+ "ipv6": {
+ "Pv6": [
+ {
+ "seqid": "1",
+ "network": DEFAULT_ROUTES["ipv6"],
+ "action": "permit",
+ }
+ ]
+ },
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ input_dict_3 = {
+ "r2": {
+ "route_maps": {
+ "RMv4": [
+ {
+ "action": "deny",
+ "seq_id": "1",
+ "match": {"ipv4": {"prefix_lists": "Pv4"}},
+ },
+ ],
+ "RMv6": [
+ {
+ "action": "deny",
+ "seq_id": "1",
+ "match": {"ipv6": {"prefix_lists": "Pv6"}},
+ },
+ ],
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Apply route-map IN direction of R2 ( R2-R1) for IPv4 and IPv6 BGP neighbors")
+ r2_link = None
+ for index in range(1, 3):
+ r2_link = "r2-link" + str(index)
+ input_dict_4 = {
+ "r2": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ r2_link: {
+ "route_maps": [
+ {"name": "RMv4", "direction": "in"}
+ ]
+ },
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ r2_link: {
+ "route_maps": [
+ {"name": "RMv6", "direction": "in"}
+ ]
+ },
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("After applying the route-map the routes are not expected in RIB ")
+ r2_link = None
+ for index in range(1, 3):
+ r2_link = "r2-link" + str(index)
+ ipv4_nxt_hop = topo["routers"]["r1"]["links"][r2_link]["ipv4"].split("/")[0]
+ interface = topo["routers"]["r1"]["links"][r2_link]["interface"]
+ ipv6_link_local_nxt_hop = get_frr_ipv6_linklocal(tgen, "r1", intf=interface)
+ DEFAULT_ROUTE_NXT_HOP = {"ipv4": ipv4_nxt_hop, "ipv6": ipv6_link_local_nxt_hop}
+
+ result = verify_rib_default_route(
+ tgen,
+ topo,
+ dut="r2",
+ routes=DEFAULT_ROUTES,
+ expected_nexthop=DEFAULT_ROUTE_NXT_HOP,
+ expected=False,
+ )
+ assert result is not True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ write_test_footer(tc_name)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_distance_change/bgp_admin_dist.json b/tests/topotests/bgp_distance_change/bgp_admin_dist.json
new file mode 100755
index 0000000000..e6a20a6585
--- /dev/null
+++ b/tests/topotests/bgp_distance_change/bgp_admin_dist.json
@@ -0,0 +1,402 @@
+{
+ "address_types": [
+ "ipv4",
+ "ipv6"
+ ],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 30,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 30,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:DB8:F::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "static_routes": [
+ {
+ "network": "192.168.22.1/32",
+ "no_of_ip": 2,
+ "next_hop": "10.0.0.2"
+ },
+ {
+ "network": "fc07:1::1/128",
+ "no_of_ip": 2,
+ "next_hop": "fd00::2"
+ },
+ {
+ "network": "192.168.21.1/32",
+ "no_of_ip": 2,
+ "next_hop": "blackhole"
+ },
+ {
+ "network": "fc07:150::1/128",
+ "no_of_ip": 2,
+ "next_hop": "blackhole"
+ }
+ ]
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "r3": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r4": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ },
+ "r5": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "100",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ },
+ "r4": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "200",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ }
+ }
+ }
+ },
+ "r5": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto"
+ }
+ },
+ "bgp": {
+ "local_as": "300",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "static_routes": [
+ {
+ "network": "192.168.20.1/32",
+ "no_of_ip": 2,
+ "next_hop": "blackhole"
+ },
+ {
+ "network": "fc07:50::1/128",
+ "no_of_ip": 2,
+ "next_hop": "blackhole"
+ },
+ {
+ "network": "192.168.21.1/32",
+ "no_of_ip": 2,
+ "next_hop": "blackhole"
+ },
+ {
+ "network": "fc07:150::1/128",
+ "no_of_ip": 2,
+ "next_hop": "blackhole"
+ }
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/topotests/bgp_distance_change/bgp_admin_dist_vrf.json b/tests/topotests/bgp_distance_change/bgp_admin_dist_vrf.json
new file mode 100755
index 0000000000..23afa2c911
--- /dev/null
+++ b/tests/topotests/bgp_distance_change/bgp_admin_dist_vrf.json
@@ -0,0 +1,429 @@
+{
+ "address_types": [
+ "ipv4",
+ "ipv6"
+ ],
+ "ipv4base": "10.0.0.0",
+ "ipv4mask": 30,
+ "ipv6base": "fd00::",
+ "ipv6mask": 64,
+ "link_ip_start": {
+ "ipv4": "10.0.0.0",
+ "v4mask": 30,
+ "ipv6": "fd00::",
+ "v6mask": 64
+ },
+ "lo_prefix": {
+ "ipv4": "1.0.",
+ "v4mask": 32,
+ "ipv6": "2001:DB8:F::",
+ "v6mask": 128
+ },
+ "routers": {
+ "r1": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback",
+ "vrf": "RED"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ }
+ },
+ "vrfs": [
+ {
+ "name": "RED",
+ "id": "1"
+ }
+ ],
+ "bgp": [{
+ "local_as": "100",
+ "vrf": "RED",
+
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r2": {
+ "dest_link": {
+ "r1": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r1": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ }
+ }
+ }],
+ "static_routes": [
+ {
+ "network": "192.168.22.1/32",
+ "no_of_ip": 2,
+ "next_hop": "10.0.0.2",
+ "vrf": "RED"
+ },
+ {
+ "network": "fc07:1::1/128",
+ "no_of_ip": 2,
+ "next_hop": "fd00::2",
+ "vrf": "RED"
+ },
+ {
+ "network": "192.168.21.1/32",
+ "no_of_ip": 2,
+ "next_hop": "blackhole",
+ "vrf": "RED"
+ },
+ {
+ "network": "fc07:150::1/128",
+ "no_of_ip": 2,
+ "next_hop": "blackhole",
+ "vrf": "RED"
+ }
+ ]
+ },
+ "r2": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback",
+ "vrf": "RED"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ }
+ },
+ "vrfs": [
+ {
+ "name": "RED",
+ "id": "1"
+ }
+ ],
+ "bgp": [{
+ "local_as": "100",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r2": {}
+ }
+ },
+ "r3": {
+ "dest_link": {
+ "r2": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }]
+ },
+ "r3": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback",
+ "vrf": "RED"
+ },
+ "r1": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ },
+ "r2": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ },
+ "r4": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ },
+ "r5": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ }
+ },
+ "vrfs": [
+ {
+ "name": "RED",
+ "id": "1"
+ }
+ ],
+ "bgp": [{
+ "local_as": "100",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r1": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r2": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r4": {
+ "dest_link": {
+ "r3": {}
+ }
+ },
+ "r5": {
+ "dest_link": {
+ "r3": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }]
+ },
+ "r4": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback",
+ "vrf": "RED"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ }
+ },
+ "vrfs": [
+ {
+ "name": "RED",
+ "id": "1"
+ }
+ ],
+ "bgp": [{
+ "local_as": "200",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r4": {}
+ }
+ }
+ }
+ }
+ }
+ }
+ }]
+ },
+ "r5": {
+ "links": {
+ "lo": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "type": "loopback",
+ "vrf": "RED"
+ },
+ "r3": {
+ "ipv4": "auto",
+ "ipv6": "auto",
+ "vrf": "RED"
+ }
+ },
+ "vrfs": [
+ {
+ "name": "RED",
+ "id": "1"
+ }
+ ],
+ "bgp": [{
+ "local_as": "300",
+ "vrf": "RED",
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r3": {
+ "dest_link": {
+ "r5": {}
+ }
+ }
+ },
+ "redistribute": [
+ {
+ "redist_type": "static"
+ },
+ {
+ "redist_type": "connected"
+ }
+ ]
+ }
+ }
+ }
+ }],
+ "static_routes": [
+ {
+ "network": "192.168.20.1/32",
+ "no_of_ip": 2,
+ "next_hop": "blackhole",
+ "vrf": "RED"
+ },
+ {
+ "network": "fc07:50::1/128",
+ "no_of_ip": 2,
+ "next_hop": "blackhole",
+ "vrf": "RED"
+ },
+ {
+ "network": "192.168.21.1/32",
+ "no_of_ip": 2,
+ "next_hop": "blackhole",
+ "vrf": "RED"
+ },
+ {
+ "network": "fc07:150::1/128",
+ "no_of_ip": 2,
+ "next_hop": "blackhole",
+ "vrf": "RED"
+ }
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/tests/topotests/bgp_distance_change/test_bgp_admin_dist.py b/tests/topotests/bgp_distance_change/test_bgp_admin_dist.py
new file mode 100755
index 0000000000..90c3d22240
--- /dev/null
+++ b/tests/topotests/bgp_distance_change/test_bgp_admin_dist.py
@@ -0,0 +1,1282 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+import sys
+import time
+import pytest
+import inspect
+import os
+
+
+"""Following tests are covered to test bgp admin distance functionality.
+TC_1:
+ Verify bgp admin distance functionality when static route is
+ configured same as ebgp learnt route
+
+TC_2:
+ Verify ebgp admin distance functionality with ECMP.
+
+TC_3:
+ Verify ibgp admin distance functionality when static route is
+ configured same as bgp learnt route.
+TC_4:
+ Verify ibgp admin distance functionality with ECMP.
+
+TC_7: Chaos - Verify bgp admin distance functionality with chaos.
+"""
+
+#################################
+# TOPOLOGY
+#################################
+"""
+
+ +-------+
+ +--------- | R2 |
+ | +-------+
+ |iBGP |
+ +-------+ |
+ | R1 | |iBGP
+ +-------+ |
+ | |
+ | iBGP +-------+ eBGP +-------+
+ +---------- | R3 |----------| R4 |
+ +-------+ +-------+
+ |
+ |eBGP
+ |
+ +-------+
+ | R5 |
+ +-------+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+# Required to instantiate the topology builder class.
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ step,
+ write_test_footer,
+ create_static_routes,
+ verify_rib,
+ create_route_maps,
+ create_prefix_lists,
+ check_address_types,
+ reset_config_on_routers,
+ check_router_status,
+ stop_router,
+ kill_router_daemons,
+ start_router_daemons,
+ start_router,
+ get_frr_ipv6_linklocal,
+ verify_fib_routes,
+)
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_best_path_as_per_admin_distance,
+ clear_bgp,
+)
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topojson import build_config_from_json
+from lib.topolog import logger
+
+# Global variables
+topo = None
+bgp_convergence = False
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+NETWORK = {
+ "ipv4": [
+ "192.168.20.1/32",
+ "192.168.20.2/32",
+ "192.168.21.1/32",
+ "192.168.21.2/32",
+ "192.168.22.1/32",
+ "192.168.22.2/32",
+ ],
+ "ipv6": [
+ "fc07:50::1/128",
+ "fc07:50::2/128",
+ "fc07:150::1/128",
+ "fc07:150::2/128",
+ "fc07:1::1/128",
+ "fc07:1::2/128",
+ ],
+}
+
+ADDR_TYPES = check_address_types()
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global topo
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_admin_dist.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Checking BGP convergence
+ global bgp_convergence
+ global ADDR_TYPES
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Api call verify whether BGP is converged
+ bgp_convergence = verify_bgp_convergence(tgen, topo)
+ assert bgp_convergence is True, "setup_module :Failed \n Error:" " {}".format(
+ bgp_convergence
+ )
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """teardown_module.
+
+ Teardown the pytest environment.
+ * `mod`: module name
+ """
+ logger.info("Running teardown_module to delete topology")
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+# Tests starting
+#####################################################
+def test_bgp_admin_distance_ebgp_ecmp_p0():
+ """
+ TC: 2
+ Verify ebgp admin distance functionality with ECMP.
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ step("Configure base config as per the topology")
+ reset_config_on_routers(tgen)
+
+ step("Configure static route in R4 and R5, redistribute in bgp")
+
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r4": {
+ "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r5": {
+ "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that route is learnt in DUT via ebgp")
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ input_dict = topo["routers"]
+ dut = "r3"
+ nhop = {"ipv4": [], "ipv6": []}
+ nhop["ipv4"].append(topo["routers"]["r4"]["links"]["r3"]["ipv4"].split("/")[0])
+ nhop["ipv4"].append(topo["routers"]["r5"]["links"]["r3"]["ipv4"].split("/")[0])
+ nhop["ipv6"].append(get_frr_ipv6_linklocal(tgen, "r4", "r3-r4-eth1"))
+ nhop["ipv6"].append(get_frr_ipv6_linklocal(tgen, "r5", "r1-r3-eth1"))
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure the static route in R3 (Dut).")
+
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that static route is selected as best route in zebra.")
+
+ # Verifying RIB routes
+ protocol = "static"
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step(" Configure the admin distance of 254 to static route in R3.")
+
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type][0],
+ "next_hop": "Null0",
+ "admin_distance": 254,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that bgp routes are selected as best routes in zebra.")
+ protocol = "bgp"
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+ }
+ },
+ },
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that bgp routes are selected as best routes in zebra.")
+ # Verifying RIB routes
+ protocol = "bgp"
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure bgp admin distance 10 with CLI in dut.")
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {"distance": {"ebgp": 10, "ibgp": 254, "local": 254}}
+ },
+ "ipv6": {
+ "unicast": {"distance": {"ebgp": 10, "ibgp": 254, "local": 254}}
+ },
+ },
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify ebgp routes have admin distance of 10 in dut.")
+
+ protocol = "bgp"
+ input_dict = topo["routers"]
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(
+ tgen, addr_type, dut, input_dict, protocol=protocol, admin_distance=10
+ )
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step(
+ "Configure route map with weight as 200 and apply to one of the "
+ "neighbor (R4 neighbor)."
+ )
+
+ # Create Prefix list
+ input_dict_2 = {
+ "r3": {
+ "prefix_lists": {
+ "ipv4": {
+ "pf_ls_1": [
+ {
+ "seqid": 10,
+ "network": NETWORK["ipv4"][0],
+ "le": "32",
+ "action": "permit",
+ }
+ ]
+ },
+ "ipv6": {
+ "pf_ls_1_ipv6": [
+ {
+ "seqid": 100,
+ "network": NETWORK["ipv6"][0],
+ "le": "128",
+ "action": "permit",
+ }
+ ]
+ },
+ }
+ }
+ }
+ result = create_prefix_lists(tgen, input_dict_2)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ # Create route map
+ input_dict_3 = {
+ "r3": {
+ "route_maps": {
+ "RMAP_WEIGHT": [
+ {
+ "action": "permit",
+ "match": {"ipv4": {"prefix_lists": "pf_ls_1"}},
+ "set": {"weight": 200},
+ },
+ {
+ "action": "permit",
+ "match": {"ipv6": {"prefix_lists": "pf_ls_1_ipv6"}},
+ "set": {"weight": 200},
+ },
+ ]
+ }
+ }
+ }
+ result = create_route_maps(tgen, input_dict_3)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {
+ "name": "RMAP_WEIGHT",
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {
+ "name": "RMAP_WEIGHT",
+ "direction": "in",
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that bgp route is selected as best on by zebra in r3.")
+
+ protocol = "bgp"
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(
+ tgen, addr_type, dut, input_dict, protocol=protocol, admin_distance=10
+ )
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Static route should not be selected as best route.")
+ protocol = "static"
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_fib_routes(
+ tgen, addr_type, dut, input_dict, protocol=protocol, expected=False
+ )
+ assert (
+ result4 is not True
+ ), "Testcase {} : Failed. Wrong route is selected as best route.\n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Reconfigure the static route without admin distance")
+
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type][0],
+ "next_hop": "Null0",
+ "admin_distance": 254,
+ "delete": True,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that static route is installed as best route.")
+ protocol = "static"
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(
+ tgen, addr_type, dut, input_dict, protocol=protocol, fib=True
+ )
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Unconfigure the static route in R3.")
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type][0],
+ "next_hop": "Null0",
+ "delete": True,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that bgp route is selected as best on by zebra in r3.")
+
+ protocol = "bgp"
+ dut = "r3"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Un configure the route map on R3.")
+
+ # Configure neighbor for route map
+ input_dict_4 = {
+ "r3": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {
+ "name": "RMAP_WEIGHT",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "neighbor": {
+ "r4": {
+ "dest_link": {
+ "r3": {
+ "route_maps": [
+ {
+ "name": "RMAP_WEIGHT",
+ "direction": "in",
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ }
+ }
+ },
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, input_dict_4)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("verify bgp routes installed in zebra.")
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ input_dict = topo["routers"]
+ dut = "r3"
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type][0], "next_hop": "Null0"}
+ ]
+ }
+ }
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_bgp_admin_distance_ibgp_p0():
+ """
+ TC: 3
+ Verify bgp admin distance functionality when static route is
+ configured same as ibgp learnt route
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ step("Configure base config as per the topology")
+ reset_config_on_routers(tgen)
+
+ step("Configure bgp admin distance 200 with CLI in dut.")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ },
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have admin distance of 200 in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": "192.168.22.1/32",
+ "admin_distance": 200,
+ },
+ {
+ "network": "192.168.22.2/32",
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": "fc07:1::1/128",
+ "admin_distance": 200,
+ },
+ {
+ "network": "fc07:1::2/128",
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Modify the admin distance value to 150.")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+ }
+ },
+ },
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have admin distance of 150 in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": "192.168.22.1/32",
+ "admin_distance": 150,
+ },
+ {
+ "network": "192.168.22.2/32",
+ "admin_distance": 150,
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": "fc07:1::1/128",
+ "admin_distance": 150,
+ },
+ {
+ "network": "fc07:1::2/128",
+ "admin_distance": 150,
+ },
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Un configure the admin distance value on DUT")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {
+ "ebgp": 150,
+ "ibgp": 150,
+ "local": 150,
+ "delete": True,
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {
+ "ebgp": 150,
+ "ibgp": 150,
+ "local": 150,
+ "delete": True,
+ }
+ }
+ },
+ },
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have default admin distance in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": "192.168.22.1/32",
+ "admin_distance": 20,
+ },
+ {
+ "network": "192.168.22.2/32",
+ "admin_distance": 20,
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": "fc07:1::1/128",
+ "admin_distance": 20,
+ },
+ {
+ "network": "fc07:1::2/128",
+ "admin_distance": 20,
+ },
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Learn the same route via ebgp and ibgp peer. Configure admin "
+ "distance of 200 in DUT for both ebgp and ibgp peer. "
+ )
+
+ step("Verify that ebgp route is preferred over ibgp.")
+
+ # Verifying RIB routes
+ protocol = "bgp"
+ input_dict = topo["routers"]
+
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure static route Without any admin distance")
+
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r3": {
+ "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that zebra selects static route.")
+ protocol = "static"
+
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r3": {
+ "static_routes": [{"network": NETWORK[addr_type], "next_hop": "Null0"}]
+ }
+ }
+
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure static route with admin distance of 253")
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "admin_distance": 253,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that zebra selects bgp route.")
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure admin distance of 254 in bgp for route.")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+ }
+ },
+ },
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that zebra selects static route.")
+ protocol = "static"
+
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Delete the static route.")
+ for addr_type in ADDR_TYPES:
+
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "admin_distance": 253,
+ "delete": True,
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that zebra selects bgp route.")
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_bgp_admin_distance_chaos_p2():
+ """
+ TC: 7
+ Chaos - Verify bgp admin distance functionality with chaos.
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ step("Configure base config as per the topology")
+ reset_config_on_routers(tgen)
+
+ step("Configure bgp admin distance 200 with CLI in dut.")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ },
+ }
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have admin distance of 200 in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][0],
+ "admin_distance": 200,
+ },
+ {
+ "network": NETWORK["ipv4"][1],
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv6"][0],
+ "admin_distance": 200,
+ },
+ {
+ "network": NETWORK["ipv6"][1],
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Restart frr on R3")
+ stop_router(tgen, "r3")
+ start_router(tgen, "r3")
+
+ bgp_convergence = verify_bgp_convergence(tgen, topo)
+ assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, bgp_convergence
+ )
+
+ step("Verify ebgp and ibgp routes have admin distance of 200 in dut.")
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Restart bgpd process on R3")
+ kill_router_daemons(tgen, "r3", ["bgpd"])
+ start_router_daemons(tgen, "r3", ["bgpd"])
+
+ bgp_convergence = verify_bgp_convergence(tgen, topo)
+ assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, bgp_convergence
+ )
+
+ step("Verify ebgp and ibgp routes have admin distance of 200 in dut.")
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Clear BGP")
+ for rtr in topo["routers"]:
+ clear_bgp(tgen, "ipv4", rtr)
+ clear_bgp(tgen, "ipv6", rtr)
+
+ bgp_convergence = verify_bgp_convergence(tgen, topo)
+ assert bgp_convergence is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, bgp_convergence
+ )
+
+ step("Verify that zebra selects bgp route.")
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_distance_change/test_bgp_admin_dist_vrf.py b/tests/topotests/bgp_distance_change/test_bgp_admin_dist_vrf.py
new file mode 100755
index 0000000000..559dc93aa0
--- /dev/null
+++ b/tests/topotests/bgp_distance_change/test_bgp_admin_dist_vrf.py
@@ -0,0 +1,900 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+import sys
+import time
+import pytest
+import inspect
+import os
+
+"""Following tests are covered to test bgp admin distance functionality.
+TC_5:
+ Verify bgp admin distance functionality when static route is configured
+ same as bgp learnt route in user vrf.
+
+TC_6: Verify bgp admin distance functionality with ECMP in user vrf.
+
+TC_7:
+ Verify bgp admin distance functionality when routes are
+ imported between VRFs.
+"""
+
+#################################
+# TOPOLOGY
+#################################
+"""
+
+ +-------+
+ +--------- | R2 |
+ | +-------+
+ |iBGP |
+ +-------+ |
+ | R1 | |iBGP
+ +-------+ |
+ | |
+ | iBGP +-------+ eBGP +-------+
+ +---------- | R3 |----------| R4 |
+ +-------+ +-------+
+ |
+ |eBGP
+ |
+ +-------+
+ | R5 |
+ +-------+
+
+
+"""
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+
+# Required to instantiate the topology builder class.
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ step,
+ write_test_footer,
+ create_static_routes,
+ verify_rib,
+ check_address_types,
+ reset_config_on_routers,
+ check_router_status,
+)
+from lib.topolog import logger
+from lib.bgp import (
+ verify_bgp_convergence,
+ create_router_bgp,
+ verify_best_path_as_per_admin_distance,
+)
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+from lib.topogen import Topogen, get_topogen
+from lib.topojson import build_config_from_json
+from lib.topolog import logger
+
+# Global variables
+topo = None
+bgp_convergence = False
+pytestmark = [pytest.mark.bgpd, pytest.mark.staticd]
+
+NETWORK = {
+ "ipv4": [
+ "192.168.20.1/32",
+ "192.168.20.2/32",
+ "192.168.21.1/32",
+ "192.168.21.2/32",
+ "192.168.22.1/32",
+ "192.168.22.2/32",
+ ],
+ "ipv6": [
+ "fc07:50::1/128",
+ "fc07:50::2/128",
+ "fc07:150::1/128",
+ "fc07:150::2/128",
+ "fc07:1::1/128",
+ "fc07:1::2/128",
+ ],
+}
+ADDR_TYPES = check_address_types()
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ global topo
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: {}".format(testsuite_run_time))
+ logger.info("=" * 40)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/bgp_admin_dist_vrf.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global topo
+ topo = tgen.json_topo
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start deamons and then start routers
+ start_topology(tgen)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, topo)
+
+ # Checking BGP convergence
+ global bgp_convergence
+ global ADDR_TYPES
+
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Api call verify whether BGP is converged
+ bgp_convergence = verify_bgp_convergence(tgen, topo)
+ assert bgp_convergence is True, "setup_module :Failed \n Error:" " {}".format(
+ bgp_convergence
+ )
+ logger.info("Running setup_module() done")
+
+
+def teardown_module(mod):
+ """teardown_module.
+
+ Teardown the pytest environment.
+ * `mod`: module name
+ """
+ logger.info("Running teardown_module to delete topology")
+ tgen = get_topogen()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info(
+ "Testsuite end time: {}".format(time.asctime(time.localtime(time.time())))
+ )
+ logger.info("=" * 40)
+
+
+#####################################################
+# Tests starting
+#####################################################
+
+
+def test_bgp_admin_distance_ebgp_vrf_p0():
+ """
+ TC: 5
+ Verify bgp admin distance functionality when static route is
+ configured same as ebgp learnt route
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ step("Configure base config as per the topology")
+ reset_config_on_routers(tgen)
+
+ step("Configure bgp admin distance 200 with CLI in dut.")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": [
+ {
+ "vrf": "RED",
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ },
+ }
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have admin distance of 200 in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][0],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ {
+ "network": NETWORK["ipv4"][1],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv6"][0],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ {
+ "network": NETWORK["ipv6"][1],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Modify the admin distance value to 150.")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": [
+ {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 150, "ibgp": 150, "local": 150}
+ }
+ },
+ },
+ }
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have admin distance of 150 in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][0],
+ "admin_distance": 150,
+ "vrf": "RED",
+ },
+ {
+ "network": NETWORK["ipv4"][1],
+ "admin_distance": 150,
+ "vrf": "RED",
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv6"][0],
+ "admin_distance": 150,
+ "vrf": "RED",
+ },
+ {
+ "network": NETWORK["ipv6"][1],
+ "admin_distance": 150,
+ "vrf": "RED",
+ },
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Un configure the admin distance value on DUT")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": [
+ {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {
+ "ebgp": 150,
+ "ibgp": 150,
+ "local": 150,
+ "delete": True,
+ }
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {
+ "ebgp": 150,
+ "ibgp": 150,
+ "local": 150,
+ "delete": True,
+ }
+ }
+ },
+ },
+ }
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have default admin distance in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK["ipv4"][0], "admin_distance": 20, "vrf": "RED"},
+ {"network": NETWORK["ipv4"][1], "admin_distance": 20, "vrf": "RED"},
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK["ipv6"][0], "admin_distance": 20, "vrf": "RED"},
+ {"network": NETWORK["ipv6"][1], "admin_distance": 20, "vrf": "RED"},
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Configure static route Without any admin distance")
+
+ for addr_type in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": "Null0", "vrf": "RED"}
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that zebra selects static route.")
+ protocol = "static"
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {"network": NETWORK[addr_type], "next_hop": "Null0", "vrf": "RED"}
+ ]
+ }
+ }
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure static route with admin distance of 253")
+ for addr_type in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "admin_distance": 253,
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that zebra selects bgp route.")
+ protocol = "bgp"
+
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "admin_distance": 253,
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure admin distance of 254 in bgp for route .")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": [
+ {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 254, "ibgp": 254, "local": 254}
+ }
+ },
+ },
+ }
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that zebra selects static route.")
+ protocol = "static"
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "admin_distance": 253,
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Configure admin distance of 255 in bgp for route in vrf red")
+
+ input_dict_1 = {
+ "r3": {
+ "bgp": [
+ {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 255, "ibgp": 255, "local": 255}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 255, "ibgp": 255, "local": 255}
+ }
+ },
+ },
+ }
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify that zebra selects static route.")
+ protocol = "static"
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "admin_distance": 253,
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step("Delete the static route.")
+ for addr_type in ADDR_TYPES:
+ # Create Static routes
+ input_dict = {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK[addr_type],
+ "next_hop": "Null0",
+ "admin_distance": 253,
+ "delete": True,
+ "vrf": "RED",
+ }
+ ]
+ }
+ }
+
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("Verify that zebra selects bgp route.")
+ protocol = "bgp"
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_bgp_admin_distance_ebgp_with_imported_rtes_vrf_p0():
+ """
+ TC: 5
+ Verify bgp admin distance functionality when static route is configured
+ same as bgp learnt route in user vrf.
+ """
+ tgen = get_topogen()
+ global bgp_convergence
+
+ if bgp_convergence is not True:
+ pytest.skip("skipping test case because of BGP Convergence failure at setup")
+
+ # test case name
+ tc_name = inspect.stack()[0][3]
+ write_test_header(tc_name)
+ if tgen.routers_have_failure():
+ check_router_status(tgen)
+
+ step("Configure base config as per the topology")
+ reset_config_on_routers(tgen)
+ step("Configure bgp admin distance 200 with CLI in dut.")
+ step(" Import route from vrf to default vrf")
+ input_dict_1 = {
+ "r3": {
+ "bgp": [
+ {
+ "vrf": "RED",
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ },
+ },
+ {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+ "import": {"vrf": "RED"},
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+ "import": {
+ "vrf": "RED",
+ },
+ }
+ },
+ },
+ },
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ step("Verify bgp routes have admin distance of 200 in dut.")
+ # Verifying best path
+ dut = "r3"
+ attribute = "admin_distance"
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][0],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ {
+ "network": NETWORK["ipv4"][1],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv6"][0],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ {
+ "network": NETWORK["ipv6"][1],
+ "admin_distance": 200,
+ "vrf": "RED",
+ },
+ ]
+ }
+ },
+ }
+
+ for addr_type in ADDR_TYPES:
+ result = verify_best_path_as_per_admin_distance(
+ tgen, addr_type, dut, input_dict[addr_type], attribute, vrf="RED"
+ )
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Verify that routes are getting imported without any issues and "
+ "routes are calculated and installed in rib."
+ )
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][0],
+ "admin_distance": 200,
+ },
+ {
+ "network": NETWORK["ipv4"][1],
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv6"][0],
+ "admin_distance": 200,
+ },
+ {
+ "network": NETWORK["ipv6"][1],
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ }
+
+ step("Verify that zebra selects bgp route.")
+ protocol = "bgp"
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(tgen, addr_type, dut, input_dict, protocol=protocol)
+ assert result4 is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result4
+ )
+
+ step(" Un configure import route vrf red inside default vrf.")
+ input_dict_1 = {
+ "r3": {
+ "bgp": [
+ {
+ "vrf": "RED",
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200}
+ }
+ },
+ },
+ },
+ {
+ "local_as": 100,
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+ "import": {"vrf": "RED", "delete": True},
+ }
+ },
+ "ipv6": {
+ "unicast": {
+ "distance": {"ebgp": 200, "ibgp": 200, "local": 200},
+ "import": {"vrf": "RED", "delete": True},
+ }
+ },
+ },
+ },
+ ]
+ }
+ }
+
+ result = create_router_bgp(tgen, topo, input_dict_1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ input_dict = {
+ "ipv4": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][0],
+ "admin_distance": 200,
+ },
+ {
+ "network": NETWORK["ipv4"][1],
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ "ipv6": {
+ "r3": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv6"][0],
+ "admin_distance": 200,
+ },
+ {
+ "network": NETWORK["ipv6"][1],
+ "admin_distance": 200,
+ },
+ ]
+ }
+ },
+ }
+
+ step("Verify that route withdrawal happens properly.")
+ protocol = "bgp"
+ # dual stack changes
+ for addr_type in ADDR_TYPES:
+ result4 = verify_rib(
+ tgen,
+ addr_type,
+ dut,
+ input_dict[addr_type],
+ protocol=protocol,
+ expected=False,
+ )
+ assert (
+ result4 is not True
+ ), "Testcase {} : Failed \n Route is not withdrawn. Error: {}".format(
+ tc_name, result4
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/__init__.py b/tests/topotests/bgp_gr_restart_retain_routes/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/__init__.py
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf
new file mode 100644
index 0000000000..50d1583873
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r1/bgpd.conf
@@ -0,0 +1,11 @@
+router bgp 65001
+ no bgp ebgp-requires-policy
+ bgp graceful-restart
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.255.2 remote-as external
+ neighbor 192.168.255.2 timers 1 3
+ neighbor 192.168.255.2 timers connect 1
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf
new file mode 100644
index 0000000000..e65bfb2c3a
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r1/zebra.conf
@@ -0,0 +1,7 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.255.1/24
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf
new file mode 100644
index 0000000000..97418ca9a0
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r2/bgpd.conf
@@ -0,0 +1,8 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ bgp graceful-restart
+ bgp graceful-restart preserve-fw-state
+ neighbor 192.168.255.1 remote-as external
+ neighbor 192.168.255.1 timers 1 3
+ neighbor 192.168.255.1 timers connect 1
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf b/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf
new file mode 100644
index 0000000000..758d797ad6
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/r2/zebra.conf
@@ -0,0 +1,5 @@
+no zebra nexthop kernel enable
+!
+interface r2-eth0
+ ip address 192.168.255.2/24
+!
diff --git a/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
new file mode 100644
index 0000000000..52ce0d5b57
--- /dev/null
+++ b/tests/topotests/bgp_gr_restart_retain_routes/test_bgp_gr_restart_retain_routes.py
@@ -0,0 +1,131 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# 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 routes are retained during BGP restarts.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step, stop_router
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 3):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_gr_restart_retain_routes():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 neighbors 192.168.255.1 json"))
+ expected = {
+ "192.168.255.1": {
+ "bgpState": "Established",
+ "addressFamilyInfo": {"ipv4Unicast": {"acceptedPrefixCounter": 2}},
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_bgp_retained_routes():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast 172.16.255.1/32 json"))
+ expected = {"paths": [{"stale": True}]}
+ return topotest.json_cmp(output, expected)
+
+ def _bgp_check_kernel_retained_routes():
+ output = (
+ r2.cmd("ip route show 172.16.255.1/32 proto bgp dev r2-eth0")
+ .replace("\n", "")
+ .rstrip()
+ )
+ expected = "172.16.255.1 via 192.168.255.1 metric 20"
+ diff = topotest.get_textdiff(
+ output, expected, "Actual IP Routing Table", "Expected IP RoutingTable"
+ )
+ if diff:
+ return False
+ return True
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_converge)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP convergence on R2"
+
+ step("Restart R1")
+ stop_router(tgen, "r1")
+
+ step("Check if routes (BGP) are retained at R2")
+ test_func = functools.partial(_bgp_check_bgp_retained_routes)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP retained routes on R2"
+
+ step("Check if routes (Kernel) are retained at R2")
+ assert _bgp_check_kernel_retained_routes() == True
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py b/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py
index 4105c3fe63..c070904353 100644
--- a/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py
+++ b/tests/topotests/bgp_ipv4_over_ipv6/test_rfc5549_ebgp_unnumbered_nbr.py
@@ -26,13 +26,17 @@ import os
import sys
import time
import pytest
+import functools
+import json
# Save the Current Working Directory to find configuration files.
CWD = os.path.dirname(os.path.realpath(__file__))
sys.path.append(os.path.join(CWD, "../"))
sys.path.append(os.path.join(CWD, "../../"))
-from lib.topogen import Topogen, get_topogen
+
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
from lib.common_config import (
write_test_header,
@@ -288,7 +292,6 @@ def test_unnumbered_loopback_ebgp_nbr_p0(request):
" received on R2 BGP and routing table , "
"verify using show ip bgp, show ip route for IPv4 routes ."
)
-
llip = get_llip("r1", "r2-link0")
assert llip is not None, "Testcase {} : Failed \n Error: {}".format(tc_name, llip)
@@ -582,6 +585,195 @@ def test_restart_frr_p2(request):
write_test_footer(tc_name)
+def test_configure_gua_on_unnumbered_intf(request):
+ """
+ Configure a global V6 address on an unnumbered interface on R1
+
+ """
+ tc_name = request.node.name
+ write_test_header(tc_name)
+ tgen = get_topogen()
+ # Don't run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+ reset_config_on_routers(tgen)
+
+ step("Configure IPv6 EBGP Unnumbered session between R1 and R2")
+ step("Enable capability extended-nexthop on both the IPv6 BGP peers")
+ step("Activate same IPv6 nbr from IPv4 unicast family")
+ step("Enable cap ext nh on r1 and r2 and activate in ipv4 addr family")
+ step("Verify bgp convergence as ipv6 nbr is enabled on ipv4 addr family.")
+ bgp_convergence = verify_bgp_convergence(tgen, topo)
+ assert bgp_convergence is True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, bgp_convergence
+ )
+
+ step(" Configure 5 IPv4 static" " routes on R1, Nexthop as different links of R0")
+ for rte in range(0, NO_OF_RTES):
+ # Create Static routes
+ input_dict = {
+ "r1": {
+ "static_routes": [
+ {
+ "network": NETWORK["ipv4"][rte],
+ "no_of_ip": 1,
+ "next_hop": NEXT_HOP["ipv4"][rte],
+ }
+ ]
+ }
+ }
+ result = create_static_routes(tgen, input_dict)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step(
+ "Advertise static routes from IPv4 unicast family and IPv6 "
+ "unicast family respectively from R1 using red static cmd "
+ "Advertise loopback from IPv4 unicast family using network command "
+ "from R1"
+ )
+
+ configure_bgp_on_r1 = {
+ "r1": {
+ "bgp": {
+ "address_family": {
+ "ipv4": {
+ "unicast": {
+ "redistribute": [{"redist_type": "static"}],
+ "advertise_networks": [
+ {"network": NETWORK_CMD_IP, "no_of_network": 1}
+ ],
+ }
+ },
+ "ipv6": {"unicast": {"redistribute": [{"redist_type": "static"}]}},
+ }
+ }
+ }
+ }
+ result = create_router_bgp(tgen, topo, configure_bgp_on_r1)
+ assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
+
+ r2 = tgen.gears["r2"]
+
+ def bgp_prefix_received_gua_nh(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast 11.0.20.1/32 json"))
+ expected = {
+ "prefix": "11.0.20.1/32",
+ "paths": [
+ {
+ "nexthops": [
+ {
+ "ip": "5001:dead:beef::1",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "scope": "global",
+ }
+ ]
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ def bgp_prefix_received_v4_mapped_v6_nh(router):
+ output = json.loads(router.vtysh_cmd("show bgp ipv4 unicast 11.0.20.1/32 json"))
+ expected = {
+ "prefix": "11.0.20.1/32",
+ "paths": [
+ {
+ "nexthops": [
+ {
+ "ip": "::ffff:a00:501",
+ "hostname": "r1",
+ "afi": "ipv6",
+ "scope": "global",
+ }
+ ]
+ }
+ ],
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Configure a global V6 address on an unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ ipv6 address 5001:dead:beef::1/126
+ !
+ """
+ )
+
+ # verify that r2 has received prefix with GUA as nexthop
+ test_func = functools.partial(bgp_prefix_received_gua_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not 5001:dead:beef::1".format(
+ tc_name
+ )
+
+ step("Configure a secondary global V6 address on an unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ ipv6 address 7771:dead:beef::1/126
+ !
+ """
+ )
+ # verify that r1 did not readvertise the prefix with secondary V6 address as the nexthop
+ test_func = functools.partial(bgp_prefix_received_gua_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not 5001:dead:beef::1".format(
+ tc_name
+ )
+
+ step("Unconfigure the secondary global V6 address from unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ no ipv6 address 7771:dead:beef::1/126
+ !
+ """
+ )
+ # verify that r1 still has the prefix with primary GUA as the nexthop
+ test_func = functools.partial(bgp_prefix_received_gua_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not 5001:dead:beef::1".format(
+ tc_name
+ )
+
+ step("Unconfigure the primary global V6 address from unnumbered interface on R1")
+ output = tgen.gears["r1"].vtysh_cmd(
+ """
+ configure terminal
+ interface r1-r2-eth5
+ no ipv6 address 5001:dead:beef::1/126
+ !
+ """
+ )
+ # verify that r1 has rcvd the prefix with v4-mapped-v6 address as the nexthop
+ test_func = functools.partial(bgp_prefix_received_v4_mapped_v6_nh, r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert (
+ result is None
+ ), "Testcase {} : Failed \n Error: Nexthop for prefix 11.0.20.1 \
+ is not ::ffff:a00:501".format(
+ tc_name
+ )
+
+ write_test_footer(tc_name)
+
+
if __name__ == "__main__":
args = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py
index 36bfdfe068..c0a5c7ad9c 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/customize.py
@@ -137,22 +137,6 @@ def ltemplatePreRouterStartHook():
if tgen.hasmpls != True:
logger.info("MPLS not available, skipping setup")
return False
- # configure r2 mpls interfaces
- intfs = ["lo", "r2-eth0", "r2-eth1", "r2-eth2"]
- for intf in intfs:
- cc.doCmd(tgen, "r2", "echo 1 > /proc/sys/net/mpls/conf/{}/input".format(intf))
- # configure MPLS
- rtrs = ["r1", "r3", "r4"]
- cmds = ["echo 1 > /proc/sys/net/mpls/conf/lo/input"]
- for rtr in rtrs:
- router = tgen.gears[rtr]
- for cmd in cmds:
- cc.doCmd(tgen, rtr, cmd)
- intfs = ["lo", rtr + "-eth0", rtr + "-eth4"]
- for intf in intfs:
- cc.doCmd(
- tgen, rtr, "echo 1 > /proc/sys/net/mpls/conf/{}/input".format(intf)
- )
logger.info("setup mpls input")
return True
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf
index 18f61e0c54..767e17e62c 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r1/zebra.conf
@@ -3,15 +3,18 @@ log file zebra.log
hostname r1
!
interface lo
+ mpls
ip address 1.1.1.1/32
!
interface r1-eth0
description to sw0
+ mpls
ip address 10.0.1.1/24
no link-detect
!
interface r1-eth4
description to ce1
+ mpls
ip address 192.168.1.1/24
no link-detect
!
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf
index dd1dbac32b..829ac969e3 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r2/zebra.conf
@@ -3,20 +3,24 @@ log file zebra.log
hostname r2
!
interface lo
+ mpls
ip address 2.2.2.2/32
!
interface r2-eth0
description to sw0
+ mpls
ip address 10.0.1.2/24
no link-detect
!
interface r2-eth1
description to sw1
+ mpls
ip address 10.0.2.2/24
no link-detect
!
interface r2-eth2
description to sw2
+ mpls
ip address 10.0.3.2/24
no link-detect
!
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf
index 9dbc290243..916dabf37d 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r3/zebra.conf
@@ -3,10 +3,12 @@ log file zebra.log
hostname r3
!
interface lo
+ mpls
ip address 3.3.3.3/32
!
interface r3-eth0
description to sw1
+ mpls
ip address 10.0.2.3/24
no link-detect
!
@@ -17,6 +19,7 @@ interface r3-eth1
!
interface r3-eth4
description to ce2
+ mpls
ip address 192.168.1.1/24
no link-detect
!
diff --git a/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf b/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf
index 415f03df51..e08ac86aec 100644
--- a/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf
+++ b/tests/topotests/bgp_l3vpn_to_bgp_direct/r4/zebra.conf
@@ -3,15 +3,18 @@ log file zebra.log
hostname r4
!
interface lo
+ mpls
ip address 4.4.4.4/32
!
interface r4-eth0
description to sw1
+ mpls
ip address 10.0.2.4/24
no link-detect
!
interface r4-eth4
description to ce3
+ mpls
ip address 192.168.1.1/24
no link-detect
!
diff --git a/tests/topotests/bgp_local_as/__init__.py b/tests/topotests/bgp_local_as/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_local_as/__init__.py
diff --git a/tests/topotests/bgp_local_as/r1/bgpd.conf b/tests/topotests/bgp_local_as/r1/bgpd.conf
new file mode 100644
index 0000000000..fa147d8673
--- /dev/null
+++ b/tests/topotests/bgp_local_as/r1/bgpd.conf
@@ -0,0 +1,14 @@
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as 65002
+ neighbor 192.168.1.2 local-as 65002
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ neighbor PG peer-group
+ neighbor PG remote-as 65003
+ neighbor PG local-as 65003
+ neighbor 192.168.2.2 peer-group PG
+ address-family ipv4
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_local_as/r1/zebra.conf b/tests/topotests/bgp_local_as/r1/zebra.conf
new file mode 100644
index 0000000000..5b32faeb44
--- /dev/null
+++ b/tests/topotests/bgp_local_as/r1/zebra.conf
@@ -0,0 +1,10 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface r1-eth0
+ ip address 192.168.1.1/24
+!
+interface r1-eth1
+ ip address 192.168.2.1/24
+!
diff --git a/tests/topotests/bgp_local_as/r2/bgpd.conf b/tests/topotests/bgp_local_as/r2/bgpd.conf
new file mode 100644
index 0000000000..9c25bdfdd3
--- /dev/null
+++ b/tests/topotests/bgp_local_as/r2/bgpd.conf
@@ -0,0 +1,6 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as internal
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+!
diff --git a/tests/topotests/bgp_local_as/r2/zebra.conf b/tests/topotests/bgp_local_as/r2/zebra.conf
new file mode 100644
index 0000000000..0c95656663
--- /dev/null
+++ b/tests/topotests/bgp_local_as/r2/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r2-eth0
+ ip address 192.168.1.2/24
+!
diff --git a/tests/topotests/bgp_local_as/r3/bgpd.conf b/tests/topotests/bgp_local_as/r3/bgpd.conf
new file mode 100644
index 0000000000..54ccd90f3f
--- /dev/null
+++ b/tests/topotests/bgp_local_as/r3/bgpd.conf
@@ -0,0 +1,6 @@
+router bgp 65003
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.1 remote-as internal
+ neighbor 192.168.2.1 timers 1 3
+ neighbor 192.168.2.1 timers connect 1
+!
diff --git a/tests/topotests/bgp_local_as/r3/zebra.conf b/tests/topotests/bgp_local_as/r3/zebra.conf
new file mode 100644
index 0000000000..d28deddfcd
--- /dev/null
+++ b/tests/topotests/bgp_local_as/r3/zebra.conf
@@ -0,0 +1,4 @@
+!
+interface r3-eth0
+ ip address 192.168.2.2/24
+!
diff --git a/tests/topotests/bgp_local_as/test_bgp_local_as.py b/tests/topotests/bgp_local_as/test_bgp_local_as.py
new file mode 100644
index 0000000000..525d44220f
--- /dev/null
+++ b/tests/topotests/bgp_local_as/test_bgp_local_as.py
@@ -0,0 +1,134 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# 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.
+#
+
+"""
+
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ for routern in range(1, 4):
+ tgen.add_router("r{}".format(routern))
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r2"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["r1"])
+ switch.add_link(tgen.gears["r3"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_local_as_same_remote_as():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_check_local_as_same_remote_as():
+ output = json.loads(
+ tgen.gears["r2"].vtysh_cmd("show bgp ipv4 unicast 172.16.255.1/32 json")
+ )
+ expected = {
+ "paths": [
+ {
+ "valid": True,
+ "aspath": {"string": "Local"},
+ "nexthops": [{"ip": "192.168.1.1", "hostname": "r1"}],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Check if iBGP works when local-as == remote-as")
+ test_func = functools.partial(_bgp_check_local_as_same_remote_as)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP prefixes on R2"
+
+
+def test_bgp_peer_group_local_as_same_remote_as():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_check_local_as_same_remote_as():
+ output = json.loads(
+ tgen.gears["r3"].vtysh_cmd("show bgp ipv4 unicast 172.16.255.1/32 json")
+ )
+ expected = {
+ "paths": [
+ {
+ "valid": True,
+ "aspath": {"string": "Local"},
+ "nexthops": [{"ip": "192.168.2.1", "hostname": "r1"}],
+ }
+ ]
+ }
+ return topotest.json_cmp(output, expected)
+
+ step("Initial BGP converge")
+ test_func = functools.partial(_bgp_check_local_as_same_remote_as)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Failed to see BGP prefixes on R3"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_lu_topo1/R1/labelpool.summ.json b/tests/topotests/bgp_lu_topo1/R1/labelpool.summ.json
index 29e6c2cbf7..e2eee513e6 100644
--- a/tests/topotests/bgp_lu_topo1/R1/labelpool.summ.json
+++ b/tests/topotests/bgp_lu_topo1/R1/labelpool.summ.json
@@ -2,7 +2,7 @@
"Ledger":506,
"InUse":506,
"Requests":0,
- "LabelChunks":11,
+ "LabelChunks":3,
"Pending":0,
"Reconnects":0
}
diff --git a/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json
index 77705e8d35..0dc59b58cf 100644
--- a/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json
+++ b/tests/topotests/bgp_lu_topo2/R1/labelpool.summ.json
@@ -2,7 +2,7 @@
"Ledger":51,
"InUse":51,
"Requests":0,
- "LabelChunks":2,
+ "LabelChunks":1,
"Pending":0,
"Reconnects":0
}
diff --git a/tests/topotests/bgp_orf/__init__.py b/tests/topotests/bgp_orf/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_orf/__init__.py
diff --git a/tests/topotests/bgp_orf/r1/bgpd.conf b/tests/topotests/bgp_orf/r1/bgpd.conf
new file mode 100644
index 0000000000..800bf1b7ab
--- /dev/null
+++ b/tests/topotests/bgp_orf/r1/bgpd.conf
@@ -0,0 +1,9 @@
+!
+router bgp 65001
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ address-family ipv4 unicast
+ redistribute connected
+ neighbor 192.168.1.2 capability orf prefix-list both
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_orf/r1/zebra.conf b/tests/topotests/bgp_orf/r1/zebra.conf
new file mode 100644
index 0000000000..85ab53102f
--- /dev/null
+++ b/tests/topotests/bgp_orf/r1/zebra.conf
@@ -0,0 +1,8 @@
+!
+int lo
+ ip address 10.10.10.1/32
+ ip address 10.10.10.2/32
+!
+int r1-eth0
+ ip address 192.168.1.1/24
+!
diff --git a/tests/topotests/bgp_orf/r2/bgpd.conf b/tests/topotests/bgp_orf/r2/bgpd.conf
new file mode 100644
index 0000000000..8c488aa106
--- /dev/null
+++ b/tests/topotests/bgp_orf/r2/bgpd.conf
@@ -0,0 +1,9 @@
+router bgp 65002
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ address-family ipv4 unicast
+ neighbor 192.168.1.1 capability orf prefix-list both
+ neighbor 192.168.1.1 prefix-list r1 in
+ exit-address-family
+!
+ip prefix-list r1 seq 5 permit 10.10.10.1/32
diff --git a/tests/topotests/bgp_orf/r2/zebra.conf b/tests/topotests/bgp_orf/r2/zebra.conf
new file mode 100644
index 0000000000..cffe827363
--- /dev/null
+++ b/tests/topotests/bgp_orf/r2/zebra.conf
@@ -0,0 +1,4 @@
+!
+int r2-eth0
+ ip address 192.168.1.2/24
+!
diff --git a/tests/topotests/bgp_orf/test_bgp_orf.py b/tests/topotests/bgp_orf/test_bgp_orf.py
new file mode 100644
index 0000000000..cb74b85b76
--- /dev/null
+++ b/tests/topotests/bgp_orf/test_bgp_orf.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# 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 ORF filtering is working correctly when modifying
+prefix-list.
+
+Initially advertise 10.10.10.1/32 from R1 to R2. Add new prefix
+10.10.10.2/32 to r1 prefix list on R2. Test if we updated ORF
+prefix-list correctly.
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+pytestmark = pytest.mark.bgpd
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def setup_module(mod):
+ topodef = {"s1": ("r1", "r2")}
+ tgen = Topogen(topodef, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+
+ for i, (rname, router) in enumerate(router_list.items(), 1):
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_orf():
+ tgen = get_topogen()
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ r1 = tgen.gears["r1"]
+ r2 = tgen.gears["r2"]
+
+ def _bgp_converge_r1():
+ output = json.loads(
+ r1.vtysh_cmd(
+ "show bgp ipv4 unicast neighbor 192.168.1.2 advertised-routes json"
+ )
+ )
+ expected = {"advertisedRoutes": {"10.10.10.1/32": {}, "10.10.10.2/32": None}}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge_r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't apply ORF from R1 to R2"
+
+ def _bgp_converge_r2():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast summary json"))
+ expected = {
+ "peers": {
+ "192.168.1.1": {
+ "pfxRcd": 1,
+ "pfxSnt": 1,
+ "state": "Established",
+ "peerState": "OK",
+ }
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_converge_r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "ORF filtering is not working from R1 to R2"
+
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ ip prefix-list r1 seq 10 permit 10.10.10.2/32
+ """
+ )
+
+ def _bgp_orf_changed_r1():
+ output = json.loads(
+ r1.vtysh_cmd(
+ "show bgp ipv4 unicast neighbor 192.168.1.2 advertised-routes json"
+ )
+ )
+ expected = {"advertisedRoutes": {"10.10.10.1/32": {}, "10.10.10.2/32": {}}}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_orf_changed_r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't apply new ORF from R1 to R2"
+
+ def _bgp_orf_changed_r2():
+ output = json.loads(r2.vtysh_cmd("show bgp ipv4 unicast json"))
+ expected = {
+ "routes": {
+ "10.10.10.1/32": [{"valid": True}],
+ "10.10.10.2/32": [{"valid": True}],
+ }
+ }
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_orf_changed_r2)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "New ORF filtering is not working from R1 to R2"
+
+ r2.vtysh_cmd(
+ """
+ configure terminal
+ no ip prefix-list r1 seq 10 permit 10.10.10.2/32
+ """
+ )
+
+ test_func = functools.partial(_bgp_converge_r1)
+ _, result = topotest.run_and_expect(test_func, None, count=60, wait=0.5)
+ assert result is None, "Can't apply initial ORF from R1 to R2"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py b/tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py
index 7d52048ebe..1108919e13 100644
--- a/tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py
+++ b/tests/topotests/bgp_remove_private_as/test_bgp_remove_private_as.py
@@ -361,13 +361,6 @@ def test_bgp_remove_private_as():
return True
return False
- def _get_pfx_path_from_nh(router, prefix, nh):
- """Return as-path for a specific route + path."""
- output = json.loads(tgen.gears[router].vtysh_cmd(f"show ip bgp {prefix} json"))
- for path in output[prefix]:
- if path["nexthops"]["ip"] == nh:
- return path["aspath"]["string"]
-
def _routers_up(tx_rtrs, rx_rtrs):
"""Ensure all BGP sessions are up and all routes are installed."""
# all sessions go through tx_routers, so ensure all their peers are up
@@ -408,11 +401,7 @@ def test_bgp_remove_private_as():
for pfx in prefixes:
good_path = expected_paths[rtr][remove_type][peer][pfx]
real_path = adj_rib_in["receivedRoutes"][pfx]["path"]
- msg = (
- f"{rtr} received incorrect AS-Path from {peer} "
- f'({p_ip}) for {pfx}. remove_type: "{remove_type}"'
- )
- assert real_path == good_path, msg
+ return real_path == good_path
#######################
# Begin Test
@@ -424,7 +413,11 @@ def test_bgp_remove_private_as():
# test each variation of remove-private-AS
for rmv_type in remove_types:
_change_remove_type(rmv_type, "add")
- _validate_paths(rmv_type)
+
+ test_func = partial(_validate_paths, rmv_type)
+ _, result = topotest.run_and_expect(test_func, True, count=60, wait=0.5)
+ assert result == True, "Not all routes have correct AS-Path values!"
+
# each variation sets a separate peer flag in bgpd. we need to clear
# the old flag after each iteration so we only test the flags we expect.
_change_remove_type(rmv_type, "del")
diff --git a/tests/topotests/bgp_soo/__init__.py b/tests/topotests/bgp_soo/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_soo/__init__.py
diff --git a/tests/topotests/bgp_soo/cpe1/bgpd.conf b/tests/topotests/bgp_soo/cpe1/bgpd.conf
new file mode 100644
index 0000000000..a8984d4e8b
--- /dev/null
+++ b/tests/topotests/bgp_soo/cpe1/bgpd.conf
@@ -0,0 +1,10 @@
+router bgp 65000
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.2 remote-as external
+ neighbor 192.168.1.2 timers 1 3
+ neighbor 192.168.1.2 timers connect 1
+ neighbor 10.0.0.2 remote-as internal
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_soo/cpe1/zebra.conf b/tests/topotests/bgp_soo/cpe1/zebra.conf
new file mode 100644
index 0000000000..669cb91295
--- /dev/null
+++ b/tests/topotests/bgp_soo/cpe1/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface lo
+ ip address 172.16.255.1/32
+!
+interface cpe1-eth0
+ ip address 192.168.1.1/24
+!
+interface cpe1-eth1
+ ip address 10.0.0.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_soo/cpe2/bgpd.conf b/tests/topotests/bgp_soo/cpe2/bgpd.conf
new file mode 100644
index 0000000000..19f7a24e2b
--- /dev/null
+++ b/tests/topotests/bgp_soo/cpe2/bgpd.conf
@@ -0,0 +1,10 @@
+router bgp 65000
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.2 remote-as external
+ neighbor 192.168.2.2 timers 1 3
+ neighbor 192.168.2.2 timers connect 1
+ neighbor 10.0.0.1 remote-as internal
+ address-family ipv4 unicast
+ redistribute connected
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_soo/cpe2/zebra.conf b/tests/topotests/bgp_soo/cpe2/zebra.conf
new file mode 100644
index 0000000000..52f36c06e8
--- /dev/null
+++ b/tests/topotests/bgp_soo/cpe2/zebra.conf
@@ -0,0 +1,9 @@
+!
+interface cpe2-eth0
+ ip address 192.168.2.1/24
+!
+interface cpe2-eth1
+ ip address 10.0.0.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_soo/pe1/bgpd.conf b/tests/topotests/bgp_soo/pe1/bgpd.conf
new file mode 100644
index 0000000000..04a6857c7c
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe1/bgpd.conf
@@ -0,0 +1,27 @@
+router bgp 65001
+ bgp router-id 10.10.10.10
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 10.10.10.20 remote-as internal
+ neighbor 10.10.10.20 update-source 10.10.10.10
+ address-family ipv4 vpn
+ neighbor 10.10.10.20 activate
+ exit-address-family
+!
+router bgp 65001 vrf RED
+ bgp router-id 192.168.1.2
+ no bgp ebgp-requires-policy
+ neighbor 192.168.1.1 remote-as external
+ neighbor 192.168.1.1 timers 1 3
+ neighbor 192.168.1.1 timers connect 1
+ address-family ipv4 unicast
+ neighbor 192.168.1.1 as-override
+ neighbor 192.168.1.1 soo 65000:1
+ label vpn export 1111
+ rd vpn export 192.168.1.2:2
+ rt vpn import 192.168.2.2:2 192.168.1.2:2
+ rt vpn export 192.168.1.2:2
+ export vpn
+ import vpn
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_soo/pe1/ldpd.conf b/tests/topotests/bgp_soo/pe1/ldpd.conf
new file mode 100644
index 0000000000..fb40f06fa7
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe1/ldpd.conf
@@ -0,0 +1,10 @@
+mpls ldp
+ router-id 10.10.10.10
+ !
+ address-family ipv4
+ discovery transport-address 10.10.10.10
+ !
+ interface pe1-eth1
+ !
+ !
+!
diff --git a/tests/topotests/bgp_soo/pe1/ospfd.conf b/tests/topotests/bgp_soo/pe1/ospfd.conf
new file mode 100644
index 0000000000..34f0899c95
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe1/ospfd.conf
@@ -0,0 +1,7 @@
+interface pe1-eth1
+ ip ospf dead-interval 4
+ ip ospf hello-interval 1
+!
+router ospf
+ router-id 10.10.10.10
+ network 0.0.0.0/0 area 0
diff --git a/tests/topotests/bgp_soo/pe1/zebra.conf b/tests/topotests/bgp_soo/pe1/zebra.conf
new file mode 100644
index 0000000000..cc8ff1983a
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe1/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface lo
+ ip address 10.10.10.10/32
+!
+interface pe1-eth0 vrf RED
+ ip address 192.168.1.2/24
+!
+interface pe1-eth1
+ ip address 10.0.1.1/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_soo/pe2/bgpd.conf b/tests/topotests/bgp_soo/pe2/bgpd.conf
new file mode 100644
index 0000000000..efebc02f27
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe2/bgpd.conf
@@ -0,0 +1,31 @@
+router bgp 65001
+ bgp router-id 10.10.10.20
+ no bgp ebgp-requires-policy
+ no bgp default ipv4-unicast
+ neighbor 10.10.10.10 remote-as internal
+ neighbor 10.10.10.10 update-source 10.10.10.20
+ address-family ipv4 vpn
+ neighbor 10.10.10.10 activate
+ exit-address-family
+!
+router bgp 65001 vrf RED
+ bgp router-id 192.168.2.2
+ no bgp ebgp-requires-policy
+ neighbor 192.168.2.1 remote-as external
+ neighbor 192.168.2.1 timers 1 3
+ neighbor 192.168.2.1 timers connect 1
+ address-family ipv4 unicast
+ neighbor 192.168.2.1 as-override
+ neighbor 192.168.2.1 route-map cpe2-in in
+ label vpn export 2222
+ rd vpn export 192.168.2.2:2
+ rt vpn import 192.168.2.2:2 192.168.1.2:2
+ rt vpn export 192.168.2.2:2
+ export vpn
+ import vpn
+ exit-address-family
+!
+! To prefer internal MPLS route over eBGP
+route-map cpe2-in permit 10
+ set local-preference 50
+exit
diff --git a/tests/topotests/bgp_soo/pe2/ldpd.conf b/tests/topotests/bgp_soo/pe2/ldpd.conf
new file mode 100644
index 0000000000..e2b5359993
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe2/ldpd.conf
@@ -0,0 +1,10 @@
+mpls ldp
+ router-id 10.10.10.20
+ !
+ address-family ipv4
+ discovery transport-address 10.10.10.20
+ !
+ interface pe2-eth0
+ !
+ !
+!
diff --git a/tests/topotests/bgp_soo/pe2/ospfd.conf b/tests/topotests/bgp_soo/pe2/ospfd.conf
new file mode 100644
index 0000000000..4c4b1374d1
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe2/ospfd.conf
@@ -0,0 +1,7 @@
+interface pe2-eth0
+ ip ospf dead-interval 4
+ ip ospf hello-interval 1
+!
+router ospf
+ router-id 10.10.10.20
+ network 0.0.0.0/0 area 0
diff --git a/tests/topotests/bgp_soo/pe2/zebra.conf b/tests/topotests/bgp_soo/pe2/zebra.conf
new file mode 100644
index 0000000000..8049a74601
--- /dev/null
+++ b/tests/topotests/bgp_soo/pe2/zebra.conf
@@ -0,0 +1,12 @@
+!
+interface lo
+ ip address 10.10.10.20/32
+!
+interface pe2-eth1 vrf RED
+ ip address 192.168.2.2/24
+!
+interface pe2-eth0
+ ip address 10.0.1.2/24
+!
+ip forwarding
+!
diff --git a/tests/topotests/bgp_soo/test_bgp_soo.py b/tests/topotests/bgp_soo/test_bgp_soo.py
new file mode 100644
index 0000000000..e3a7334c60
--- /dev/null
+++ b/tests/topotests/bgp_soo/test_bgp_soo.py
@@ -0,0 +1,186 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2022 by
+# Donatas Abraitis <donatas@opensourcerouting.org>
+#
+# 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 SoO per neighbor works correctly. Routes having SoO
+extended community MUST be rejected if the neighbor is configured
+with soo (neighbor soo).
+"""
+
+import os
+import sys
+import json
+import pytest
+import functools
+
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+
+# pylint: disable=C0413
+from lib import topotest
+from lib.topogen import Topogen, TopoRouter, get_topogen
+from lib.common_config import step
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ tgen.add_router("cpe1")
+ tgen.add_router("cpe2")
+ tgen.add_router("pe1")
+ tgen.add_router("pe2")
+
+ switch = tgen.add_switch("s1")
+ switch.add_link(tgen.gears["cpe1"])
+ switch.add_link(tgen.gears["pe1"])
+
+ switch = tgen.add_switch("s2")
+ switch.add_link(tgen.gears["pe1"])
+ switch.add_link(tgen.gears["pe2"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["pe2"])
+ switch.add_link(tgen.gears["cpe2"])
+
+ switch = tgen.add_switch("s4")
+ switch.add_link(tgen.gears["cpe2"])
+ switch.add_link(tgen.gears["cpe1"])
+
+
+def setup_module(mod):
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ pe1 = tgen.gears["pe1"]
+ pe2 = tgen.gears["pe2"]
+
+ pe1.run("ip link add RED type vrf table 1001")
+ pe1.run("ip link set up dev RED")
+ pe2.run("ip link add RED type vrf table 1001")
+ pe2.run("ip link set up dev RED")
+ pe1.run("ip link set pe1-eth0 master RED")
+ pe2.run("ip link set pe2-eth1 master RED")
+
+ pe1.run("sysctl -w net.ipv4.ip_forward=1")
+ pe2.run("sysctl -w net.ipv4.ip_forward=1")
+ pe1.run("sysctl -w net.mpls.conf.pe1-eth0.input=1")
+ pe2.run("sysctl -w net.mpls.conf.pe2-eth1.input=1")
+
+ 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))
+ )
+ router.load_config(
+ TopoRouter.RD_OSPF, os.path.join(CWD, "{}/ospfd.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_LDP, os.path.join(CWD, "{}/ldpd.conf".format(rname))
+ )
+
+ tgen.start_router()
+
+
+def teardown_module(mod):
+ tgen = get_topogen()
+ tgen.stop_topology()
+
+
+def test_bgp_soo():
+ tgen = get_topogen()
+
+ pe2 = tgen.gears["pe2"]
+
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ def _bgp_soo_unconfigured():
+ output = json.loads(
+ pe2.vtysh_cmd(
+ "show bgp vrf RED ipv4 unicast neighbors 192.168.2.1 advertised-routes json"
+ )
+ )
+ expected = {"advertisedRoutes": {"172.16.255.1/32": {"path": "65001"}}}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_soo_unconfigured)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "Failed to see BGP convergence in pe2"
+
+ step("Configure SoO (65000:1) for PE2 -- CPE2 session")
+ pe2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65001 vrf RED
+ address-family ipv4 unicast
+ neighbor 192.168.2.1 soo 65000:1
+ """
+ )
+
+ def _bgp_soo_configured():
+ output = json.loads(
+ pe2.vtysh_cmd(
+ "show bgp vrf RED ipv4 unicast neighbors 192.168.2.1 advertised-routes json"
+ )
+ )
+ expected = {"advertisedRoutes": {"172.16.255.1/32": None}}
+ return topotest.json_cmp(output, expected)
+
+ test_func = functools.partial(_bgp_soo_configured)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "SoO filtering does not work from pe2"
+
+ step("Configure SoO (65000:2) for PE2 -- CPE2 session")
+ pe2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65001 vrf RED
+ address-family ipv4 unicast
+ neighbor 192.168.2.1 soo 65000:2
+ """
+ )
+
+ test_func = functools.partial(_bgp_soo_unconfigured)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "SoO filtering does not work from pe2"
+
+ step("Unconfigure SoO for PE2 -- CPE2 session")
+ pe2.vtysh_cmd(
+ """
+ configure terminal
+ router bgp 65001 vrf RED
+ address-family ipv4 unicast
+ no neighbor 192.168.2.1 soo
+ """
+ )
+
+ test_func = functools.partial(_bgp_soo_unconfigured)
+ _, result = topotest.run_and_expect(test_func, None, count=30, wait=0.5)
+ assert result is None, "SoO filtering does not work from pe2"
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vpnv4_ebgp/__init__.py b/tests/topotests/bgp_vpnv4_ebgp/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/__init__.py
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf
new file mode 100644
index 0000000000..2eebe5e6dd
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r1/bgpd.conf
@@ -0,0 +1,25 @@
+router bgp 65500
+ bgp router-id 1.1.1.1
+ no bgp ebgp-requires-policy
+ neighbor 10.125.0.2 remote-as 65501
+ address-family ipv4 unicast
+ no neighbor 10.125.0.2 activate
+ exit-address-family
+ address-family ipv4 vpn
+ neighbor 10.125.0.2 activate
+ exit-address-family
+!
+router bgp 65500 vrf vrf1
+ bgp router-id 1.1.1.1
+ address-family ipv4 unicast
+ redistribute connected
+ label vpn export 101
+ rd vpn export 444:1
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+!
+interface r1-eth0
+ mpls bgp forwarding
+! \ No newline at end of file
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json
new file mode 100644
index 0000000000..da7d281833
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r1/ipv4_routes.json
@@ -0,0 +1,50 @@
+{
+ "10.200.0.0/24": [
+ {
+ "prefix": "10.200.0.0/24",
+ "prefixLen": 24,
+ "protocol": "bgp",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "10.125.0.2",
+ "afi": "ipv4",
+ "interfaceName": "r1-eth0",
+ "vrf": "default",
+ "active": true,
+ "labels":[
+ 102
+ ]
+ }
+ ]
+ }
+ ],
+ "10.201.0.0/24": [
+ {
+ "prefix": "10.201.0.0/24",
+ "prefixLen": 24,
+ "protocol": "connected",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "nexthops":[
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r1-eth1",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf
new file mode 100644
index 0000000000..e9ae4e9831
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r1/zebra.conf
@@ -0,0 +1,7 @@
+log stdout
+interface r1-eth1 vrf vrf1
+ ip address 10.201.0.1/24
+!
+interface r1-eth0
+ ip address 10.125.0.1/24
+!
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json
new file mode 100644
index 0000000000..19797dd561
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgp_ipv4_routes.json
@@ -0,0 +1,38 @@
+{
+ "vrfName": "vrf1",
+ "localAS": 65501,
+ "routes":
+ {
+ "10.201.0.0/24": [
+ {
+ "prefix": "10.201.0.0",
+ "prefixLen": 24,
+ "network": "10.201.0.0\/24",
+ "nhVrfName": "default",
+ "nexthops": [
+ {
+ "ip": "10.125.0.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "10.200.0.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "prefix": "10.200.0.0",
+ "prefixLen": 24,
+ "network": "10.200.0.0\/24",
+ "nexthops": [
+ {
+ "ip": "0.0.0.0",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf b/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf
new file mode 100644
index 0000000000..e38c99d69c
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/bgpd.conf
@@ -0,0 +1,25 @@
+router bgp 65501
+ bgp router-id 2.2.2.2
+ no bgp ebgp-requires-policy
+ neighbor 10.125.0.1 remote-as 65500
+ address-family ipv4 unicast
+ no neighbor 10.125.0.1 activate
+ exit-address-family
+ address-family ipv4 vpn
+ neighbor 10.125.0.1 activate
+ exit-address-family
+!
+router bgp 65501 vrf vrf1
+ bgp router-id 2.2.2.2
+ address-family ipv4 unicast
+ redistribute connected
+ label vpn export 102
+ rd vpn export 444:2
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+!
+interface r2-eth0
+ mpls bgp forwarding
+!
diff --git a/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf b/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf
new file mode 100644
index 0000000000..6c433aef2b
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/r2/zebra.conf
@@ -0,0 +1,7 @@
+log stdout
+interface r2-eth1 vrf vrf1
+ ip address 10.200.0.2/24
+!
+interface r2-eth0
+ ip address 10.125.0.2/24
+!
diff --git a/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
new file mode 100644
index 0000000000..cd8a9b6d6f
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_ebgp/test_bgp_vpnv4_ebgp.py
@@ -0,0 +1,187 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_vpnv4_ebgp.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2022 by 6WIND
+#
+# 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_bgp_vpnv4_ebgp.py: Test the FRR BGP daemon with EBGP direct connection
+"""
+
+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.
+
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 2 routers.
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+
+ 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["r1"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r2"])
+
+def _populate_iface():
+ tgen = get_topogen()
+ cmds_list = [
+ 'ip link add vrf1 type vrf table 10',
+ 'echo 100000 > /proc/sys/net/mpls/platform_labels',
+ 'ip link set dev vrf1 up',
+ 'ip link set dev {0}-eth1 master vrf1',
+ 'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input',
+ ]
+
+ for cmd in cmds_list:
+ input = cmd.format('r1', '1', '2')
+ logger.info('input: ' + cmd)
+ output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2'))
+ logger.info('output: ' + output)
+
+ for cmd in cmds_list:
+ input = cmd.format('r2', '2', '1')
+ logger.info('input: ' + cmd)
+ output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
+ logger.info('output: ' + output)
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ _populate_iface()
+
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears['r1']
+ logger.info("Dump some context for r1")
+ router.vtysh_cmd("show bgp ipv4 vpn")
+ router.vtysh_cmd("show bgp summary")
+ router.vtysh_cmd("show bgp vrf vrf1 ipv4")
+ router.vtysh_cmd("show running-config")
+ router = tgen.gears['r2']
+ logger.info("Dump some context for r2")
+ router.vtysh_cmd("show bgp ipv4 vpn")
+ router.vtysh_cmd("show bgp summary")
+ router.vtysh_cmd("show bgp vrf vrf1 ipv4")
+ router.vtysh_cmd("show running-config")
+
+ # Check IPv4 routing tables on r1
+ logger.info("Checking IPv4 routes for convergence on r1")
+ router = tgen.gears['r1']
+ json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info("skipping file {}".format(json_file))
+ assert 0, 'ipv4_routes.json file not found'
+ return
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip route vrf vrf1 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check BGP IPv4 routing tables on r2 not installed
+ logger.info("Checking BGP IPv4 routes for convergence on r2")
+ router = tgen.gears['r2']
+ json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ assert 0, 'bgp_ipv4_routes.json file not found'
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp vrf vrf1 ipv4 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/bgp_vpnv4_gre/__init__.py b/tests/topotests/bgp_vpnv4_gre/__init__.py
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/__init__.py
diff --git a/tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf b/tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf
new file mode 100644
index 0000000000..0e2d3a8248
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/r1/bgpd.conf
@@ -0,0 +1,26 @@
+router bgp 65500
+ bgp router-id 192.0.2.1
+ neighbor 192.0.2.2 remote-as 65500
+ neighbor 192.0.2.2 update-source 192.0.2.1
+ address-family ipv4 unicast
+ no neighbor 192.0.2.2 activate
+ exit-address-family
+ address-family ipv4 vpn
+ neighbor 192.0.2.2 activate
+ neighbor 192.0.2.2 route-map rmap in
+ exit-address-family
+!
+router bgp 65500 vrf vrf1
+ bgp router-id 192.0.2.1
+ address-family ipv4 unicast
+ redistribute connected
+ label vpn export 101
+ rd vpn export 444:1
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+!
+route-map rmap permit 1
+ set l3vpn next-hop encapsulation gre
+!
diff --git a/tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json b/tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json
new file mode 100644
index 0000000000..5f2732aab0
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/r1/ipv4_routes.json
@@ -0,0 +1,50 @@
+{
+ "10.200.0.0/24": [
+ {
+ "prefix": "10.200.0.0/24",
+ "prefixLen": 24,
+ "protocol": "bgp",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 20,
+ "metric": 0,
+ "nexthops": [
+ {
+ "flags": 3,
+ "fib": true,
+ "ip": "192.168.0.2",
+ "afi": "ipv4",
+ "interfaceName": "r1-gre0",
+ "vrf": "default",
+ "active": true,
+ "labels":[
+ 102
+ ]
+ }
+ ]
+ }
+ ],
+ "10.201.0.0/24": [
+ {
+ "prefix": "10.201.0.0/24",
+ "prefixLen": 24,
+ "protocol": "connected",
+ "vrfName": "vrf1",
+ "selected": true,
+ "destSelected": true,
+ "distance": 0,
+ "metric": 0,
+ "installed": true,
+ "nexthops":[
+ {
+ "flags": 3,
+ "fib": true,
+ "directlyConnected": true,
+ "interfaceName": "r1-eth1",
+ "active": true
+ }
+ ]
+ }
+ ]
+}
diff --git a/tests/topotests/bgp_vpnv4_gre/r1/zebra.conf b/tests/topotests/bgp_vpnv4_gre/r1/zebra.conf
new file mode 100644
index 0000000000..11780a874c
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/r1/zebra.conf
@@ -0,0 +1,14 @@
+log stdout
+ip route 192.0.2.2/32 192.168.0.2
+interface lo
+ ip address 192.0.2.1/32
+!
+interface r1-gre0
+ ip address 192.168.0.1/24
+!
+interface r1-eth1 vrf vrf1
+ ip address 10.201.0.1/24
+!
+interface r1-eth0
+ ip address 10.125.0.1/24
+!
diff --git a/tests/topotests/bgp_vpnv4_gre/r2/bgp_ipv4_routes.json b/tests/topotests/bgp_vpnv4_gre/r2/bgp_ipv4_routes.json
new file mode 100644
index 0000000000..e50d5dd084
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/r2/bgp_ipv4_routes.json
@@ -0,0 +1,38 @@
+{
+ "vrfName": "vrf1",
+ "localAS": 65500,
+ "routes":
+ {
+ "10.201.0.0/24": [
+ {
+ "prefix": "10.201.0.0",
+ "prefixLen": 24,
+ "network": "10.201.0.0\/24",
+ "nhVrfName": "default",
+ "nexthops": [
+ {
+ "ip": "192.0.2.1",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ],
+ "10.200.0.0/24": [
+ {
+ "valid": true,
+ "bestpath": true,
+ "prefix": "10.200.0.0",
+ "prefixLen": 24,
+ "network": "10.200.0.0\/24",
+ "nexthops": [
+ {
+ "ip": "0.0.0.0",
+ "afi": "ipv4",
+ "used": true
+ }
+ ]
+ }
+ ]
+ }
+}
diff --git a/tests/topotests/bgp_vpnv4_gre/r2/bgpd.conf b/tests/topotests/bgp_vpnv4_gre/r2/bgpd.conf
new file mode 100644
index 0000000000..bf05866da4
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/r2/bgpd.conf
@@ -0,0 +1,22 @@
+router bgp 65500
+ bgp router-id 192.0.2.2
+ neighbor 192.0.2.1 remote-as 65500
+ neighbor 192.0.2.1 update-source 192.0.2.2
+ address-family ipv4 unicast
+ no neighbor 192.0.2.1 activate
+ exit-address-family
+ address-family ipv4 vpn
+ neighbor 192.0.2.1 activate
+ exit-address-family
+!
+router bgp 65500 vrf vrf1
+ bgp router-id 192.0.2.2
+ address-family ipv4 unicast
+ redistribute connected
+ label vpn export 102
+ rd vpn export 444:2
+ rt vpn both 52:100
+ export vpn
+ import vpn
+ exit-address-family
+!
diff --git a/tests/topotests/bgp_vpnv4_gre/r2/zebra.conf b/tests/topotests/bgp_vpnv4_gre/r2/zebra.conf
new file mode 100644
index 0000000000..de88a4b64e
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/r2/zebra.conf
@@ -0,0 +1,14 @@
+log stdout
+ip route 192.0.2.1/32 192.168.0.1
+interface lo
+ ip address 192.0.2.2/32
+!
+interface r2-gre0
+ ip address 192.168.0.2/24
+!
+interface r2-eth1 vrf vrf1
+ ip address 10.200.0.2/24
+!
+interface r2-eth0
+ ip address 10.125.0.2/24
+!
diff --git a/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
new file mode 100644
index 0000000000..f562f44179
--- /dev/null
+++ b/tests/topotests/bgp_vpnv4_gre/test_bgp_vpnv4_gre.py
@@ -0,0 +1,191 @@
+#!/usr/bin/env python
+
+#
+# test_bgp_vpnv4_gre.py
+# Part of NetDEF Topology Tests
+#
+# Copyright (c) 2021 by 6WIND
+#
+# 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_bgp_vpnv4_gre.py: Test the FRR BGP daemon with BGP IPv6 interface
+ with route advertisements on a separate netns.
+"""
+
+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.
+
+
+pytestmark = [pytest.mark.bgpd]
+
+
+def build_topo(tgen):
+ "Build function"
+
+ # Create 2 routers.
+ tgen.add_router("r1")
+ tgen.add_router("r2")
+
+ 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["r1"])
+
+ switch = tgen.add_switch("s3")
+ switch.add_link(tgen.gears["r2"])
+
+def _populate_iface():
+ tgen = get_topogen()
+ cmds_list = [
+ 'ip link add vrf1 type vrf table 10',
+ 'echo 10 > /proc/sys/net/mpls/platform_labels',
+ 'ip link set dev vrf1 up',
+ 'ip link set dev {0}-eth1 master vrf1',
+ 'echo 1 > /proc/sys/net/mpls/conf/{0}-eth0/input',
+ 'ip tunnel add {0}-gre0 mode gre ttl 64 dev {0}-eth0 local 10.125.0.{1} remote 10.125.0.{2}',
+ 'ip link set dev {0}-gre0 up',
+ 'echo 1 > /proc/sys/net/mpls/conf/{0}-gre0/input',
+ ]
+
+ for cmd in cmds_list:
+ input = cmd.format('r1', '1', '2')
+ logger.info('input: ' + cmd)
+ output = tgen.net['r1'].cmd(cmd.format('r1', '1', '2'))
+ logger.info('output: ' + output)
+
+ for cmd in cmds_list:
+ input = cmd.format('r2', '2', '1')
+ logger.info('input: ' + cmd)
+ output = tgen.net['r2'].cmd(cmd.format('r2', '2', '1'))
+ logger.info('output: ' + output)
+
+def setup_module(mod):
+ "Sets up the pytest environment"
+ tgen = Topogen(build_topo, mod.__name__)
+ tgen.start_topology()
+
+ router_list = tgen.routers()
+ _populate_iface()
+
+ for rname, router in router_list.items():
+ router.load_config(
+ TopoRouter.RD_ZEBRA, os.path.join(CWD, "{}/zebra.conf".format(rname))
+ )
+ router.load_config(
+ TopoRouter.RD_BGP, os.path.join(CWD, "{}/bgpd.conf".format(rname))
+ )
+
+ # Initialize all routers.
+ tgen.start_router()
+
+
+def teardown_module(_mod):
+ "Teardown the pytest environment"
+ tgen = get_topogen()
+
+ tgen.stop_topology()
+
+
+def test_protocols_convergence():
+ """
+ Assert that all protocols have converged
+ statuses as they depend on it.
+ """
+ tgen = get_topogen()
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ router = tgen.gears['r1']
+ logger.info("Dump some context for r1")
+ router.vtysh_cmd("show bgp ipv4 vpn")
+ router.vtysh_cmd("show bgp summary")
+ router.vtysh_cmd("show bgp vrf vrf1 ipv4")
+ router.vtysh_cmd("show running-config")
+ router = tgen.gears['r2']
+ logger.info("Dump some context for r2")
+ router.vtysh_cmd("show bgp ipv4 vpn")
+ router.vtysh_cmd("show bgp summary")
+ router.vtysh_cmd("show bgp vrf vrf1 ipv4")
+ router.vtysh_cmd("show running-config")
+
+ # Check IPv4 routing tables on r1
+ logger.info("Checking IPv4 routes for convergence on r1")
+ router = tgen.gears['r1']
+ json_file = "{}/{}/ipv4_routes.json".format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ logger.info("skipping file {}".format(json_file))
+ assert 0, 'ipv4_routes.json file not found'
+ return
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show ip route vrf vrf1 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+ # Check BGP IPv4 routing tables on r2 not installed
+ logger.info("Checking BGP IPv4 routes for convergence on r2")
+ router = tgen.gears['r2']
+ json_file = "{}/{}/bgp_ipv4_routes.json".format(CWD, router.name)
+ if not os.path.isfile(json_file):
+ assert 0, 'bgp_ipv4_routes.json file not found'
+
+ expected = json.loads(open(json_file).read())
+ test_func = partial(
+ topotest.router_json_cmp,
+ router,
+ "show bgp vrf vrf1 ipv4 json",
+ expected,
+ )
+ _, result = topotest.run_and_expect(test_func, None, count=40, wait=2)
+ assertmsg = '"{}" JSON output mismatches'.format(router.name)
+ assert result is None, assertmsg
+
+def test_memory_leak():
+ "Run the memory leak test and report results."
+ tgen = get_topogen()
+ if not tgen.is_memleak_enabled():
+ pytest.skip("Memory leak test/report is disabled")
+
+ tgen.report_memory_leaks()
+
+
+if __name__ == "__main__":
+ args = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(args))
diff --git a/tests/topotests/conftest.py b/tests/topotests/conftest.py
index 120a3e82e4..2a57f6c26e 100755
--- a/tests/topotests/conftest.py
+++ b/tests/topotests/conftest.py
@@ -232,6 +232,9 @@ def pytest_configure(config):
Assert that the environment is correctly configured, and get extra config.
"""
+ if config.getoption("--collect-only"):
+ return
+
if "PYTEST_XDIST_WORKER" not in os.environ:
os.environ["PYTEST_XDIST_MODE"] = config.getoption("dist", "no")
os.environ["PYTEST_TOPOTEST_WORKER"] = ""
@@ -363,7 +366,7 @@ def pytest_configure(config):
# Check environment now that we have config
if not diagnose_env(rundir):
- pytest.exit("environment has errors, please read the logs")
+ pytest.exit("environment has errors, please read the logs in %s" % rundir)
@pytest.fixture(autouse=True, scope="session")
diff --git a/tests/topotests/lib/bgp.py b/tests/topotests/lib/bgp.py
index 341ec25a19..7ab36c4fcd 100644
--- a/tests/topotests/lib/bgp.py
+++ b/tests/topotests/lib/bgp.py
@@ -491,6 +491,25 @@ def __create_bgp_unicast_neighbor(
cmd = "no {}".format(cmd)
config_data.append(cmd)
+ admin_dist_data = addr_data.setdefault("distance", {})
+ if admin_dist_data:
+ if len(admin_dist_data) < 2:
+ logger.debug(
+ "Router %s: pass the admin distance values for "
+ "ebgp, ibgp and local routes",
+ router,
+ )
+ cmd = "distance bgp {} {} {}".format(
+ admin_dist_data["ebgp"],
+ admin_dist_data["ibgp"],
+ admin_dist_data["local"],
+ )
+
+ del_action = admin_dist_data.setdefault("delete", False)
+ if del_action:
+ cmd = "no distance bgp"
+ config_data.append(cmd)
+
import_vrf_data = addr_data.setdefault("import", {})
if import_vrf_data:
cmd = "import vrf {}".format(import_vrf_data["vrf"])
@@ -2662,7 +2681,7 @@ def verify_best_path_as_per_bgp_attribute(
@retry(retry_timeout=10)
def verify_best_path_as_per_admin_distance(
- tgen, addr_type, router, input_dict, attribute, expected=True
+ tgen, addr_type, router, input_dict, attribute, expected=True, vrf=None
):
"""
API is to verify best path according to admin distance for given
@@ -2678,6 +2697,7 @@ def verify_best_path_as_per_admin_distance(
* `input_dict`: defines different routes with different admin distance
to calculate for which route best path is selected
* `expected` : expected results from API, by-default True
+ * `vrf`: Pass vrf name check for perticular vrf.
Usage
-----
@@ -2710,9 +2730,14 @@ def verify_best_path_as_per_admin_distance(
# Show ip route cmd
if addr_type == "ipv4":
- command = "show ip route json"
+ command = "show ip route"
+ else:
+ command = "show ipv6 route"
+
+ if vrf:
+ command = "{} vrf {} json".format(command, vrf)
else:
- command = "show ipv6 route json"
+ command = "{} json".format(command)
for routes_from_router in input_dict.keys():
sh_ip_route_json = router_list[routes_from_router].vtysh_cmd(
diff --git a/tests/topotests/lib/common_config.py b/tests/topotests/lib/common_config.py
index fa33b02ed1..5f4c280715 100644
--- a/tests/topotests/lib/common_config.py
+++ b/tests/topotests/lib/common_config.py
@@ -3339,6 +3339,7 @@ def verify_rib(
metric=None,
fib=None,
count_only=False,
+ admin_distance=None,
):
"""
Data will be read from input_dict or input JSON file, API will generate
@@ -3611,6 +3612,30 @@ def verify_rib(
)
return errormsg
+ if admin_distance is not None:
+ if "distance" not in rib_routes_json[st_rt][0]:
+ errormsg = (
+ "[DUT: {}]: admin distance is"
+ " not present for"
+ " route {} in RIB \n".format(dut, st_rt)
+ )
+ return errormsg
+
+ if (
+ admin_distance
+ != rib_routes_json[st_rt][0]["distance"]
+ ):
+ errormsg = (
+ "[DUT: {}]: admin distance value "
+ "{} is not matched for "
+ "route {} in RIB \n".format(
+ dut,
+ admin_distance,
+ st_rt,
+ )
+ )
+ return errormsg
+
if metric is not None:
if "metric" not in rib_routes_json[st_rt][0]:
errormsg = (
@@ -3764,7 +3789,7 @@ def verify_rib(
@retry(retry_timeout=12)
-def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
+def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None, protocol=None):
"""
Data will be read from input_dict or input JSON file, API will generate
same prefixes, which were redistributed by either create_static_routes() or
@@ -3822,6 +3847,9 @@ def verify_fib_routes(tgen, addr_type, dut, input_dict, next_hop=None):
found_routes = []
missing_routes = []
+ if protocol:
+ command = "{} {}".format(command, protocol)
+
if "static_routes" in input_dict[routerInput]:
static_routes = input_dict[routerInput]["static_routes"]
@@ -5039,7 +5067,7 @@ def verify_ip_nht(tgen, input_dict):
for nh in nh_list:
if nh in show_ip_nht:
- nht = run_frr_cmd(rnode, f"show ip nht {nh}")
+ nht = run_frr_cmd(rnode, "show ip nht {}".format(nh))
if "unresolved" in nht:
errormsg = "Nexthop {} became unresolved on {}".format(nh, router)
return errormsg
diff --git a/tests/topotests/lib/topogen.py b/tests/topotests/lib/topogen.py
index c51a187f28..04712eda87 100644
--- a/tests/topotests/lib/topogen.py
+++ b/tests/topotests/lib/topogen.py
@@ -1293,7 +1293,7 @@ def diagnose_env_linux(rundir):
)
continue
- logger.warning("could not find {} in {}".format(fname, frrdir))
+ logger.error("could not find {} in {}".format(fname, frrdir))
ret = False
else:
if fname != "zebra":
diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
index eafad06e96..2a9fe32b08 100755
--- a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
+++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp.py
@@ -1391,2531 +1391,6 @@ def test_send_join_on_higher_preffered_rp_p1(request):
write_test_footer(tc_name)
-def test_RP_configured_as_LHR_1_p1(request):
- """
- TC_21_1_P1: Verify OIF and RPF for (*,G) and (S,G) when static RP configure
- in LHR router
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
-
- r1 : LHR/RP
- r3 : FHR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface")
- step("Configure RP on r1 (loopback interface) for the group range" " 224.0.0.0/4")
- step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
- step("Send the IGMP join from r0")
- step("Send multicast traffic from r5")
-
- step("r1 , r2, r3, r4: Delete existing RP configuration" "configure r1(LHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Configure r1(LHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- shutdown_bringup_interface(tgen, "r1", "lo", False)
- sleep(5)
- shutdown_bringup_interface(tgen, "r1", "lo", True)
- sleep(5)
-
- step("r1: Verify RP info")
- dut = "r1"
- rp_address = "1.0.1.17"
- iif = "lo"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S, G) upstream join state is joined and join"
- " timer is running \n Error: {}".format(tc_name, result)
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- # Uncomment next line for debugging
- # tgen.mininet_cli()
-
- write_test_footer(tc_name)
-
-
-def test_RP_configured_as_LHR_2_p1(request):
- """
- TC_21_2_P1: Verify OIF and RPF for (*,G) and (S,G) when static RP configure
- in LHR router
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
-
- r1 : LHR/RP
- r3 : FHR
-
- """
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface")
- step("Configure RP on r1 (loopback interface) for the group range" " 224.0.0.0/4")
- step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
- step("Send multicast traffic from r5")
- step("Send the IGMP join from r0")
-
- step("r1, r2, r3, r4: Delete existing RP configuration," "configure r1(LHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1, r2, r3, r4: Configure r1(LHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.1.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify RP info")
- dut = "r1"
- rp_address = "1.0.1.17"
- iif = "lo"
- result = verify_pim_rp_info(tgen, TOPO, dut, GROUP_ADDRESS, iif, rp_address, SOURCE)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- # Uncomment next line for debugging
- # tgen.mininet_cli()
-
- write_test_footer(tc_name)
-
-
-def test_RP_configured_as_FHR_1_p1(request):
- """
- TC_22_1_P1: Verify OIF and RFP for (*,G) and (S,G) when static RP configure
- in FHR router
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
-
- r1 : LHR
- r3 : FHR/RP
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface")
- step("Configure RP on r2 (loopback interface) for the group range" " 225.1.1.0/24")
- step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
- step("Send the IGMP join from r0")
- step("Send multicast traffic from r5")
-
- step("r1, r2, r3, r4: Delete existing RP configuration" "configure r3(FHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- }
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1, r2, r3, r4: Configure r3(FHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify RP info")
- dut = "r1"
- rp_address = "1.0.3.17"
- iif = "r1-r3-eth2"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Verify IGMP groups")
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- # Uncomment next line for debugging
- # tgen.mininet_cli()
-
- write_test_footer(tc_name)
-
-
-def test_RP_configured_as_FHR_2_p2(request):
- """
- TC_22_2_P2: Verify OIF and RFP for (*,G) and (S,G) when static RP configure
- in FHR router
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
-
- r1 : LHR
- r3 : FHR/RP
- """
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface")
- step("Configure RP on r2 (loopback interface) for the group range" " 225.1.1.0/24")
- step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
- step("Send multicast traffic from r5")
- step("Send the IGMP join from r0")
-
- step("r1, r2, r3, r4: Delete existing RP configuration" "configure r3(FHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- },
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1, r2, r3, r4: Configure r3(FHR) as RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r3": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.3.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- },
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify RP info")
- dut = "r1"
- rp_address = "1.0.3.17"
- iif = "r1-r3-eth2"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Verify IGMP groups")
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- # Uncomment next line for debugging
- # tgen.mininet_cli()
-
- write_test_footer(tc_name)
-
-
-def test_SPT_RPT_path_different_p1(request):
- """
- TC_23_P1: Verify (*,G) and (S,G) populated correctly when RPT and SPT path
- are different
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
-
- r1: LHR
- r2: RP
- r3: FHR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface and send IGMP join (225.1.1.1) to r1")
- step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
- step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
- step("Send multicast traffic from r3")
-
- step("r2: Verify RP info")
- dut = "r2"
- rp_address = "1.0.2.17"
- iif = "lo"
- result = verify_pim_rp_info(tgen, TOPO, dut, GROUP_ADDRESS, iif, rp_address, SOURCE)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- dut = "r1"
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream IIF interface")
- dut = "r2"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream IIF interface")
- dut = "r2"
- iif = "r2-r3-eth1"
- result = verify_upstream_iif(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, joinState="NotJoined"
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (S, G) ip mroutes")
- oif = "none"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- # Uncomment next line for debugging
- # tgen.mininet_cli()
-
- write_test_footer(tc_name)
-
-
-def test_clear_pim_configuration_p1(request):
- """
- TC_25_P1: Verify (*,G) and (S,G) populated correctly after clearing the
- PIM,IGMP and mroutes joins
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
- | |
- |_____________|
- r4
- r1 : LHR
- r2 : RP
- r3 : FHR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface")
- step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
- step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
- step("Send the IGMP join from r0")
- step("Send multicast traffic from r5")
-
- step("r2: Verify RP info")
- dut = "r2"
- rp_address = "1.0.2.17"
- oif = "lo"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, oif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- dut = "r1"
- iif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, iif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- dut = "r1"
- iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups timer restarted")
- result = clear_igmp_interfaces(tgen, dut)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify PIM neighbor timer restarted")
- result = clear_pim_interfaces(tgen, dut)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify PIM mroute timer restarted")
- result = clear_mroute_verify(tgen, dut)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- # Uncomment next line for debugging
- # tgen.mininet_cli()
-
- write_test_footer(tc_name)
-
-
-def test_restart_pimd_process_p2(request):
- """
- TC_26_P2: Restart the PIMd process and verify PIM upstream and mroutes
- entries
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
- | |
- |_____________|
- r4
- r1 : LHR
- r2 : RP
- r3 : FHR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface and send IGMP join (225.1.1.1) to R1")
- step("Configure RP on r3 (loopback interface) for the group range" " 224.0.0.0/4")
- step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
- step("Send multicast traffic from R3")
- step("Restart the PIMd process")
-
- step("r2: Verify RP info")
- dut = "r2"
- rp_address = "1.0.2.17"
- oif = "lo"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, oif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- dut = "r1"
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream IIF interface")
- dut = "r2"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- dut = "r1"
- iif = "r1-r2-eth1"
- oil = "r1-r0-eth0"
- logger.info("waiting for 10 sec to make sure old mroute time is higher")
- sleep(10)
- # Why do we then wait 60 seconds below before checking the routes?
- uptime_before = verify_mroutes(
- tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=60
- )
- assert isinstance(uptime_before, dict), "Testcase{} : Failed Error: {}".format(
- tc_name, result
- )
-
- step("r1: Kill pimd process")
- kill_router_daemons(tgen, "r1", ["pimd"])
-
- step("r1 : Start pimd process")
- start_router_daemons(tgen, "r1", ["pimd"])
-
- logger.info("Waiting for 5sec to get PIMd restarted and mroute" " re-learned..")
- sleep(5)
-
- # Why do we then wait 10 seconds below before checking the routes?
- uptime_after = verify_mroutes(
- tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=10
- )
- assert isinstance(uptime_after, dict), "Testcase{} : Failed Error: {}".format(
- tc_name, result
- )
-
- result = verify_mroute_repopulated(uptime_before, uptime_after)
- assert result is True, "Testcase{} : Failed Error: {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_multiple_groups_same_RP_address_p2(request):
- """
- TC_27_P2: Configure multiple groups (10 grps) with same RP address
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
-
- r1 : LHR
- r2 : RP
- r3 : FHR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface and send IGMP join (225.1.1.1) to r1")
- step("Configure RP on r2 (loopback interface) for the group range" "225.1.1.0/24")
- step("Enable the PIM on all the interfaces of r1-r2-r3")
- step("Send multicast traffic from r5 to all the groups")
- step("r1 : Remove the groups to RP mapping one by one")
- step("r1: Shut the upstream interfaces")
- step("r1: No shut the upstream interfaces")
- step("r1: Configure the RP again")
- step("r1: Shut the receiver interfaces")
- step("r1: No Shut the receiver interfaces")
- step("r2: Verify RP info")
-
- step("r2: verify rp-info")
- dut = "r2"
- rp_address = "1.0.2.17"
- oif = "lo"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, oif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- group_address_list = GROUP_ADDRESS_LIST_1 + GROUP_ADDRESS_LIST_2
- step("r0: Send IGMP join for 10 groups")
- result = app_helper.run_join("r0", group_address_list, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- dut = "r1"
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", group_address_list, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- dut = "r1"
- iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream IIF interface")
- dut = "r2"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream IIF interface")
- dut = "r2"
- iif = "r2-r3-eth1"
- result = verify_upstream_iif(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list, joinState="NotJoined"
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (S, G) ip mroutes")
- oif = "none"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Delete RP configuration")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- }
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: No Shut the interface r1-r2-eth1 from R1 to R2")
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Configure RP")
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- }
- ]
- }
- }
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Shut the interface r1-r0-eth0 from R1 to R2")
- intf = "r1-r0-eth0"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: No Shut the interface r1-r0-eth0 from R1 to R2")
- intf = "r1-r0-eth0"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Verify (*, G) upstream IIF interface")
- dut = "r1"
- iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream IIF interface")
- dut = "r2"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream IIF interface")
- dut = "r2"
- iif = "r2-r3-eth1"
- result = verify_upstream_iif(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list, joinState="NotJoined"
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (S, G) ip mroutes")
- oif = "none"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_multiple_groups_different_RP_address_p2(request):
- """
- TC_28_P2: Verify IIF and OIL in updated in mroute when upstream interface
- configure as RP
-
- Topology used:
- ________r2_____
- | |
- iperf | | iperf
- r0-----r1-------------r3-----r5
- | |
- |_____________|
- r4
- r1 : LHR
- r2 & r4 : RP
- r3 : FHR
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Delete existing RP configuration")
- input_dict = {
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- }
- }
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- input_dict = {
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_LIST_1,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.4.17",
- "group_addr_range": GROUP_RANGE_LIST_2,
- }
- ]
- }
- },
- }
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify RP info")
- dut = "r2"
- rp_address = "1.0.2.17"
- oif = "lo"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_LIST_1, oif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify RP info")
- dut = "r4"
- rp_address = "1.0.4.17"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_LIST_2, oif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- group_address_list = GROUP_ADDRESS_LIST_1 + GROUP_ADDRESS_LIST_2
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", group_address_list, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- dut = "r1"
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, group_address_list)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r5: Send multicast traffic for group 225.1.1.1")
- result = app_helper.run_traffic("r5", group_address_list, "r3")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- dut = "r1"
- iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream IIF interface")
- dut = "r2"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream IIF interface")
- iif = "r2-r3-eth1"
- result = verify_upstream_iif(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, joinState="NotJoined"
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (S, G) ip mroutes")
- oif = "none"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- dut = "r1"
- iif = "r1-r4-eth3"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (*, G) upstream IIF interface")
- dut = "r4"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (*, G) ip mroutes")
- oif = "r4-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (S, G) upstream IIF interface")
- iif = "r4-r3-eth1"
- result = verify_upstream_iif(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, joinState="NotJoined"
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r4: Verify (S, G) ip mroutes")
- oif = "none"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
- )
- assert result is not True, "Testcase {} :Failed \n Error: {}".format(
- tc_name, result
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("Delete RP configuration")
- input_dict = {
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_LIST_1,
- "delete": True,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.4.17",
- "group_addr_range": GROUP_RANGE_LIST_2,
- "delete": True,
- }
- ]
- }
- },
- }
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1, r2, r3, r4: Re-configure RP")
- input_dict = {
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_LIST_1,
- }
- ]
- }
- },
- "r4": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.4.17",
- "group_addr_range": GROUP_RANGE_LIST_2,
- }
- ]
- }
- },
- }
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: No shut the interface r1-r2-eth1 from R1 to R2")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Shut the interface r1-r2-eth1 from R1 to R4")
- dut = "r1"
- intf = "r1-r4-eth3"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: No shut the interface r1-r2-eth1 from R1 to r4")
- dut = "r1"
- intf = "r1-r4-eth3"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Shut the interface r1-r0-eth0 from R1 to R0")
- dut = "r1"
- intf = "r1-r0-eth0"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: No Shut the interface r1-r0-eth0 from R1 to R0")
- dut = "r1"
- intf = "r1-r0-eth0"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Verify (*, G) upstream IIF interface")
- dut = "r1"
- iif = "r1-r2-eth1"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream IIF interface")
- dut = "r2"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream IIF interface")
- iif = "r2-r3-eth1"
- result = verify_upstream_iif(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, joinState="NotJoined"
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (S, G) ip mroutes")
- oif = "none"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream IIF interface")
- dut = "r1"
- iif = "r1-r4-eth3"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream IIF interface")
- iif = "r1-r3-eth2"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (S, G) ip mroutes")
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (*, G) upstream IIF interface")
- dut = "r4"
- iif = "lo"
- result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (*, G) upstream join state and join timer")
- result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (*, G) ip mroutes")
- oif = "r4-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (S, G) upstream IIF interface")
- iif = "r4-r3-eth1"
- result = verify_upstream_iif(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, joinState="NotJoined"
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r4: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r4: Verify (S, G) ip mroutes")
- oif = "none"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream IIF interface")
- dut = "r3"
- iif = "r3-r5-eth3"
- result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (S, G) upstream join state and join timer")
- result = verify_join_state_and_timer(
- tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
- )
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (S, G) ip mroutes")
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_shutdown_primary_path_p1(request):
- """
- TC_30_P1: Verify IIF and OIL change to other path after shut the primary
- path
-
- Topology used:
- ________r2_____
- | |
- iperf | |
- r0-----r1-------------r3
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- # Steps to execute
- step("Enable IGMP on r1 interface")
- step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
- step("r1: Shut the link from r1 to r2")
- step("r3: Shut the link from r1 to r3")
- step("r1: No shut the link from r1 to r2")
- step("r3: No shut the link from r1 to r3")
-
- step("r1: Verify RP info")
- dut = "r1"
- rp_address = "1.0.2.17"
- iif = "r1-r2-eth1"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- dut = "r2"
- iif = "lo"
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step(
- "Verify after shut the R1 to R2 link , verify join is reaching to RP"
- "via other path"
- )
-
- logger.info("Waiting for 110 sec only if test run with crucible")
-
- step("r1: Verify (*, G) ip mroutes")
- dut = "r1"
- iif = "r1-r3-eth2"
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- dut = "r2"
- iif = "lo"
- oif = "r2-r3-eth1"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (*, G) ip mroutes")
- dut = "r3"
- iif = "r3-r2-eth1"
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Shut the link from R1 to R3 from R3 node")
- dut = "r3"
- intf = "r3-r1-eth0"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step(
- "Verify after shut of R1 to R3 link , verify (*,G) entries got"
- " cleared from all the node R1, R2, R3"
- )
-
- step("r1: Verify (*, G) ip mroutes")
- dut = "r1"
- iif = "r1-r3-eth2"
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (*, G) ip mroutes")
- dut = "r2"
- iif = "lo"
- oif = "r2-r3-eth1"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: Verify (*, G) ip mroutes")
- dut = "r3"
- iif = "r3-r2-eth1"
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r3: No shutdown the link from R1 to R3 from R3 node")
- dut = "r3"
- intf = "r3-r1-eth0"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Verify (*, G) ip mroutes")
- dut = "r1"
- iif = "r1-r3-eth2"
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- dut = "r2"
- iif = "lo"
- oif = "r2-r3-eth1"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r3: Verify (*, G) ip mroutes")
- dut = "r3"
- iif = "r3-r2-eth1"
- oif = "r3-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: No shutdown the link from R1 to R2 from R1 node")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Verify (*, G) ip mroutes")
- dut = "r1"
- iif = "r1-r2-eth1"
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes")
- dut = "r2"
- iif = "lo"
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- write_test_footer(tc_name)
-
-
-def test_delete_RP_shut_noshut_upstream_interface_p1(request):
- """
- TC_31_P1: Verify RP info and (*,G) mroute after deleting the RP and shut /
- no shut the RPF interface.
- Topology used:
- ________r2_____
- | |
- iperf | |
- r0-----r1-------------r3
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface")
- step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
- step("r1: Delete the RP config")
- step("r1: Shut and no shut the upstream interface (R1-R2) connected link")
- step("r1: Shut and no shut the OIL interface")
-
- step("r1: Verify RP info")
- dut = "r1"
- rp_address = "1.0.2.17"
- iif = "r1-r2-eth1"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- dut = "r1"
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes created")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes created")
- dut = "r2"
- iif = "lo"
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Delete RP configuration")
-
- # Delete RP configuration
- input_dict = {
- "r1": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- }
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: No shutdown the interface r1-r2-eth1 from R1 to R2")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Shutdown the OIL interface r1-r0-eth0 from R1 to R0 ")
- dut = "r1"
- intf = "r1-r0-eth0"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: No shutdown the OIL interface r1-r0-eth0 from R1 to R0")
- dut = "r1"
- intf = "r1-r0-eth0"
- shutdown_bringup_interface(tgen, dut, intf, True)
-
- step("r1: Verify (*, G) ip mroutes cleared")
- dut = "r1"
- iif = "r1-r2-eth1"
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (*, G) ip mroutes cleared")
- dut = "r2"
- iif = "lo"
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
- tc_name, result
- )
- )
-
- write_test_footer(tc_name)
-
-
-def test_delete_RP_shut_noshut_RP_interface_p1(request):
- """
- TC_32_P1: Verify RP info and (*,G) mroute after deleting the RP and shut/
- no shut the RPF interface
-
- Topology used:
- ________r2_____
- | |
- iperf | |
- r0-----r1-------------r3
- """
-
- tgen = get_topogen()
- tc_name = request.node.name
- write_test_header(tc_name)
-
- # Don"t run this test if we have any failure.
- if tgen.routers_have_failure():
- pytest.skip(tgen.errors)
-
- step("Creating configuration from JSON")
- reset_config_on_routers(tgen)
- app_helper.stop_all_hosts()
- clear_mroute(tgen)
- clear_pim_interface_traffic(tgen, TOPO)
-
- step("Enable IGMP on r1 interface")
- step("Configure RP on r2 (lo) for the group range" " 224.0.0.0/4")
- step("r2: Delete the RP configuration")
- step("r2: Shut the RP interface (lo)")
- step("r1: Shut the interface(r1-r2-eth1, r1-r3-eth2) towards rp")
-
- step("r1: Verify RP info")
- dut = "r1"
- rp_address = "1.0.2.17"
- iif = "r1-r2-eth1"
- result = verify_pim_rp_info(
- tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
- )
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r0: Send IGMP join")
- result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify IGMP groups")
- oif = "r1-r0-eth0"
- result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r1: Verify (*, G) ip mroutes created")
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Verify (*, G) ip mroutes created")
- dut = "r2"
- iif = "lo"
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Delete RP configuration")
-
- # Delete RP configuration
- input_dict = {
- "r2": {
- "pim": {
- "rp": [
- {
- "rp_addr": "1.0.2.17",
- "group_addr_range": GROUP_RANGE_ALL,
- "delete": True,
- }
- ]
- }
- }
- }
-
- result = create_pim_config(tgen, TOPO, input_dict)
- assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
-
- step("r2: Shut the RP interface lo")
- dut = "r2"
- intf = "lo"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: Shut the interface r1-r2-eth1 towards RP")
- dut = "r1"
- intf = "r1-r2-eth1"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: Shut the interface r1-r3-eth2 towards RP")
- dut = "r1"
- intf = "r1-r3-eth2"
- shutdown_bringup_interface(tgen, dut, intf, False)
-
- step("r1: Verify (*, G) ip mroutes cleared")
- dut = "r1"
- iif = "r1-r2-eth1"
- oif = "r1-r0-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r1: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- )
- )
-
- step("r2: Verify (*, G) ip mroutes cleared")
- dut = "r2"
- iif = "lo"
- oif = "r2-r1-eth0"
- result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
- assert result is not True, (
- "Testcase {} : Failed \n "
- "r2: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
- tc_name, result
- )
- )
-
- write_test_footer(tc_name)
-
-
if __name__ == "__main__":
ARGS = ["-s"] + sys.argv[1:]
sys.exit(pytest.main(ARGS))
diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py
new file mode 100755
index 0000000000..35303c3f2c
--- /dev/null
+++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp1.py
@@ -0,0 +1,1424 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test Multicast basic functionality:
+
+Topology:
+
+ _______r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+ | |
+ |_____________|
+ r4
+
+Test steps
+- Create topology (setup module)
+- Bring up topology
+
+TC_1 : Verify upstream interfaces(IIF) and join state are updated properly
+ after adding and deleting the static RP
+TC_2 : Verify IIF and OIL in "show ip pim state" updated properly after
+ adding and deleting the static RP
+TC_3: (*, G) Mroute entry are cleared when static RP gets deleted
+TC_4: Verify (*,G) prune is send towards the RP after deleting the static RP
+TC_5: Verify OIF entry for RP is cleared when RP becomes unreachable
+TC_6: Verify IIF and OIL in "show ip pim state" updated properly when RP
+ becomes unreachable
+TC_7 : Verify upstream interfaces(IIF) and join state are updated properly
+ after adding and deleting the static RP
+TC_8: Verify (*,G) prune is send towards the RP when RP becomes unreachable
+TC_9 : Verify RP configured after IGMP join received, PIM join towards RP is
+ sent immediately
+TC_10 : Verify RP becomes reachable after IGMP join received, PIM join
+ towards RP is sent immediately
+TC_11 : Verify PIM join send towards the higher preferred RP
+TC_12 : Verify PIM prune send towards the lower preferred RP
+TC_13 : Verify RPF interface is updated in mroute (kernel) when higher
+ preferred overlapping RP configured
+TC_14 : Verify IIF and OIL in "show ip pim state" updated properly when higher
+ preferred overlapping RP configured
+TC_15 : Verify upstream interfaces(IIF) and join state are updated when higher
+ preferred overlapping RP is configured
+TC_16 : Verify join is send to lower preferred RP, when higher preferred RP
+ gets deleted
+TC_17 : Verify prune is send to higher preferred RP when higher preferred RP
+ gets deleted
+TC_18 : Verify RPF interface updated in mroute when higher preferred RP gets
+ deleted
+TC_19 : Verify IIF and OIL in "show ip pim state" updated when higher
+ preferred overlapping RP is deleted
+TC_20 : Verify PIM upstream IIF updated when higher preferred overlapping RP
+ deleted
+TC_21_1 : Verify OIF and RFP for (*,G) and (S,G) when static RP configure in
+ LHR router
+TC_21_2 : Verify OIF and RFP for (*,G) and (S,G) when static RP configure in
+ LHR router
+TC_22_1 : Verify OIF and RPF for (*,G) and (S,G) when static RP configure in
+ FHR router
+TC_22_2 : Verify OIF and RPF for (*,G) and (S,G) when static RP configure in
+ FHR router
+TC_23 : Verify (*,G) and (S,G) populated correctly when RPT and SPT path are
+ different
+TC_24 : Verify (*,G) and (S,G) populated correctly when SPT and RPT share the
+ same path
+TC_25 : Verify (*,G) and (S,G) populated correctly after clearing the PIM ,
+ IGMP and mroutes joins
+TC_26 : Restart the PIMd process and verify PIM joins , and mroutes entries
+TC_27 : Configure multiple groups (10 grps) with same RP address
+TC_28 : Configure multiple groups (10 grps) with different RP address
+TC_29 : Verify IIF and OIL in updated in mroute when upstream interface
+ configure as RP
+TC_30 : Verify IIF and OIL change to other path after shut the primary path
+TC_31 : Verify RP info and (*,G) mroute after deleting the RP and shut / no
+ shut the RPF interface.
+TC_32 : Verify RP info and (*,G) mroute after deleting the RP and shut / no
+ shut the RPF interface
+"""
+
+import os
+import sys
+import time
+from time import sleep
+import datetime
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ reset_config_on_routers,
+ step,
+ shutdown_bringup_interface,
+ kill_router_daemons,
+ start_router_daemons,
+ create_static_routes,
+ topo_daemons,
+)
+from lib.pim import (
+ create_pim_config,
+ verify_igmp_groups,
+ verify_upstream_iif,
+ verify_join_state_and_timer,
+ verify_mroutes,
+ verify_pim_neighbors,
+ get_pim_interface_traffic,
+ verify_pim_rp_info,
+ verify_pim_state,
+ clear_pim_interface_traffic,
+ clear_igmp_interfaces,
+ clear_pim_interfaces,
+ clear_mroute,
+ clear_mroute_verify,
+ McastTesterHelper,
+)
+
+pytestmark = [pytest.mark.pimd, pytest.mark.staticd]
+
+
+# Global variables
+GROUP_RANGE_ALL = "224.0.0.0/4"
+GROUP_RANGE = "225.1.1.1/32"
+GROUP_RANGE_LIST_1 = [
+ "225.1.1.1/32",
+ "225.1.1.2/32",
+ "225.1.1.3/32",
+ "225.1.1.4/32",
+ "225.1.1.5/32",
+]
+GROUP_RANGE_LIST_2 = [
+ "225.1.1.6/32",
+ "225.1.1.7/32",
+ "225.1.1.8/32",
+ "225.1.1.9/32",
+ "225.1.1.10/32",
+]
+GROUP_ADDRESS = "225.1.1.1"
+GROUP_ADDRESS_LIST_1 = ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"]
+GROUP_ADDRESS_LIST_2 = [
+ "225.1.1.6",
+ "225.1.1.7",
+ "225.1.1.8",
+ "225.1.1.9",
+ "225.1.1.10",
+]
+STAR = "*"
+SOURCE_ADDRESS = "10.0.6.2"
+SOURCE = "Static"
+
+
+def build_topo(tgen):
+ """Build function"""
+
+ # Building topology from json file
+ build_topo_from_json(tgen, TOPO)
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: %s", testsuite_run_time)
+ logger.info("=" * 40)
+
+ topology = """
+
+ _______r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+ | |
+ |_____________|
+ r4
+
+ """
+ logger.info("Master Topology: \n %s", topology)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/multicast_pim_static_rp.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global TOPO
+ TOPO = tgen.json_topo
+
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, TOPO)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start daemons and then start routers
+ start_topology(tgen, daemons)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, TOPO)
+
+ # Verify PIM neighbors
+ result = verify_pim_neighbors(tgen, TOPO)
+ assert result is True, "setup_module :Failed \n Error:" " {}".format(result)
+
+ # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
+ global app_helper
+ app_helper = McastTesterHelper(tgen)
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ app_helper.cleanup()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info("Testsuite end time: %s", time.asctime(time.localtime(time.time())))
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def verify_mroute_repopulated(uptime_before, uptime_after):
+ """
+ API to compare uptime for mroutes
+
+ Parameters
+ ----------
+ * `uptime_before` : Uptime dictionary for any particular instance
+ * `uptime_after` : Uptime dictionary for any particular instance
+ """
+
+ for group in uptime_before.keys():
+ for source in uptime_before[group].keys():
+ if set(uptime_before[group]) != set(uptime_after[group]):
+ errormsg = (
+ "mroute (%s, %s) has not come"
+ " up after mroute clear [FAILED!!]" % (source, group)
+ )
+ return errormsg
+
+ d_1 = datetime.datetime.strptime(uptime_before[group][source], "%H:%M:%S")
+ d_2 = datetime.datetime.strptime(uptime_after[group][source], "%H:%M:%S")
+ if d_2 >= d_1:
+ errormsg = "mroute (%s, %s) is not " "repopulated [FAILED!!]" % (
+ source,
+ group,
+ )
+ return errormsg
+
+ logger.info("mroute (%s, %s) is " "repopulated [PASSED!!]", source, group)
+
+ return True
+
+
+def verify_state_incremented(state_before, state_after):
+ """
+ API to compare interface traffic state incrementing
+
+ Parameters
+ ----------
+ * `state_before` : State dictionary for any particular instance
+ * `state_after` : State dictionary for any particular instance
+ """
+
+ for router, state_data in state_before.items():
+ for state, _ in state_data.items():
+ if state_before[router][state] >= state_after[router][state]:
+ errormsg = (
+ "[DUT: %s]: state %s value has not"
+ " incremented, Initial value: %s, "
+ "Current value: %s [FAILED!!]"
+ % (
+ router,
+ state,
+ state_before[router][state],
+ state_after[router][state],
+ )
+ )
+ return errormsg
+
+ logger.info(
+ "[DUT: %s]: State %s value is "
+ "incremented, Initial value: %s, Current value: %s"
+ " [PASSED!!]",
+ router,
+ state,
+ state_before[router][state],
+ state_after[router][state],
+ )
+
+ return True
+
+
+def test_RP_configured_as_LHR_1_p1(request):
+ """
+ TC_21_1_P1: Verify OIF and RPF for (*,G) and (S,G) when static RP configure
+ in LHR router
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+
+ r1 : LHR/RP
+ r3 : FHR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r1 (loopback interface) for the group range" " 224.0.0.0/4")
+ step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
+ step("Send the IGMP join from r0")
+ step("Send multicast traffic from r5")
+
+ step("r1 , r2, r3, r4: Delete existing RP configuration" "configure r1(LHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Configure r1(LHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ shutdown_bringup_interface(tgen, "r1", "lo", False)
+ sleep(5)
+ shutdown_bringup_interface(tgen, "r1", "lo", True)
+ sleep(5)
+
+ step("r1: Verify RP info")
+ dut = "r1"
+ rp_address = "1.0.1.17"
+ iif = "lo"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S, G) upstream join state is joined and join"
+ " timer is running \n Error: {}".format(tc_name, result)
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+ write_test_footer(tc_name)
+
+
+def test_RP_configured_as_LHR_2_p1(request):
+ """
+ TC_21_2_P1: Verify OIF and RPF for (*,G) and (S,G) when static RP configure
+ in LHR router
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+
+ r1 : LHR/RP
+ r3 : FHR
+
+ """
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r1 (loopback interface) for the group range" " 224.0.0.0/4")
+ step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
+ step("Send multicast traffic from r5")
+ step("Send the IGMP join from r0")
+
+ step("r1, r2, r3, r4: Delete existing RP configuration," "configure r1(LHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1, r2, r3, r4: Configure r1(LHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.1.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify RP info")
+ dut = "r1"
+ rp_address = "1.0.1.17"
+ iif = "lo"
+ result = verify_pim_rp_info(tgen, TOPO, dut, GROUP_ADDRESS, iif, rp_address, SOURCE)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+ write_test_footer(tc_name)
+
+
+def test_RP_configured_as_FHR_1_p1(request):
+ """
+ TC_22_1_P1: Verify OIF and RFP for (*,G) and (S,G) when static RP configure
+ in FHR router
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+
+ r1 : LHR
+ r3 : FHR/RP
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r2 (loopback interface) for the group range" " 225.1.1.0/24")
+ step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
+ step("Send the IGMP join from r0")
+ step("Send multicast traffic from r5")
+
+ step("r1, r2, r3, r4: Delete existing RP configuration" "configure r3(FHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ }
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1, r2, r3, r4: Configure r3(FHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify RP info")
+ dut = "r1"
+ rp_address = "1.0.3.17"
+ iif = "r1-r3-eth2"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Verify IGMP groups")
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+ write_test_footer(tc_name)
+
+
+def test_RP_configured_as_FHR_2_p2(request):
+ """
+ TC_22_2_P2: Verify OIF and RFP for (*,G) and (S,G) when static RP configure
+ in FHR router
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+
+ r1 : LHR
+ r3 : FHR/RP
+ """
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r2 (loopback interface) for the group range" " 225.1.1.0/24")
+ step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
+ step("Send multicast traffic from r5")
+ step("Send the IGMP join from r0")
+
+ step("r1, r2, r3, r4: Delete existing RP configuration" "configure r3(FHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1, r2, r3, r4: Configure r3(FHR) as RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r3": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.3.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ },
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify RP info")
+ dut = "r1"
+ rp_address = "1.0.3.17"
+ iif = "r1-r3-eth2"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Verify IGMP groups")
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+ write_test_footer(tc_name)
+
+
+def test_SPT_RPT_path_different_p1(request):
+ """
+ TC_23_P1: Verify (*,G) and (S,G) populated correctly when RPT and SPT path
+ are different
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+
+ r1: LHR
+ r2: RP
+ r3: FHR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface and send IGMP join (225.1.1.1) to r1")
+ step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
+ step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
+ step("Send multicast traffic from r3")
+
+ step("r2: Verify RP info")
+ dut = "r2"
+ rp_address = "1.0.2.17"
+ iif = "lo"
+ result = verify_pim_rp_info(tgen, TOPO, dut, GROUP_ADDRESS, iif, rp_address, SOURCE)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ dut = "r1"
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ iif = "r1-r2-eth1"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream IIF interface")
+ dut = "r2"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream IIF interface")
+ dut = "r2"
+ iif = "r2-r3-eth1"
+ result = verify_upstream_iif(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, joinState="NotJoined"
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (S, G) ip mroutes")
+ oif = "none"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+ write_test_footer(tc_name)
+
+
+def test_clear_pim_configuration_p1(request):
+ """
+ TC_25_P1: Verify (*,G) and (S,G) populated correctly after clearing the
+ PIM,IGMP and mroutes joins
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+ | |
+ |_____________|
+ r4
+ r1 : LHR
+ r2 : RP
+ r3 : FHR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
+ step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
+ step("Send the IGMP join from r0")
+ step("Send multicast traffic from r5")
+
+ step("r2: Verify RP info")
+ dut = "r2"
+ rp_address = "1.0.2.17"
+ oif = "lo"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, oif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ dut = "r1"
+ iif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, iif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups timer restarted")
+ result = clear_igmp_interfaces(tgen, dut)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify PIM neighbor timer restarted")
+ result = clear_pim_interfaces(tgen, dut)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify PIM mroute timer restarted")
+ result = clear_mroute_verify(tgen, dut)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ # Uncomment next line for debugging
+ # tgen.mininet_cli()
+
+ write_test_footer(tc_name)
+
+
+
+
+if __name__ == "__main__":
+ ARGS = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(ARGS))
diff --git a/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py
new file mode 100755
index 0000000000..991d7d5fb6
--- /dev/null
+++ b/tests/topotests/multicast_pim_static_rp_topo1/test_multicast_pim_static_rp2.py
@@ -0,0 +1,1799 @@
+#!/usr/bin/env python
+
+#
+# Copyright (c) 2019 by VMware, Inc. ("VMware")
+# Used Copyright (c) 2018 by Network Device Education Foundation,
+# Inc. ("NetDEF") in this file.
+#
+# Permission to use, copy, modify, and/or distribute this software
+# for any purpose with or without fee is hereby granted, provided
+# that the above copyright notice and this permission notice appear
+# in all copies.
+#
+# THE SOFTWARE IS PROVIDED "AS IS" AND VMWARE DISCLAIMS ALL WARRANTIES
+# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL VMWARE BE LIABLE FOR
+# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+# DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+# WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+# ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
+# OF THIS SOFTWARE.
+#
+
+"""
+Following tests are covered to test Multicast basic functionality:
+
+Topology:
+
+ _______r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+ | |
+ |_____________|
+ r4
+
+Test steps
+- Create topology (setup module)
+- Bring up topology
+
+TC_1 : Verify upstream interfaces(IIF) and join state are updated properly
+ after adding and deleting the static RP
+TC_2 : Verify IIF and OIL in "show ip pim state" updated properly after
+ adding and deleting the static RP
+TC_3: (*, G) Mroute entry are cleared when static RP gets deleted
+TC_4: Verify (*,G) prune is send towards the RP after deleting the static RP
+TC_5: Verify OIF entry for RP is cleared when RP becomes unreachable
+TC_6: Verify IIF and OIL in "show ip pim state" updated properly when RP
+ becomes unreachable
+TC_7 : Verify upstream interfaces(IIF) and join state are updated properly
+ after adding and deleting the static RP
+TC_8: Verify (*,G) prune is send towards the RP when RP becomes unreachable
+TC_9 : Verify RP configured after IGMP join received, PIM join towards RP is
+ sent immediately
+TC_10 : Verify RP becomes reachable after IGMP join received, PIM join
+ towards RP is sent immediately
+TC_11 : Verify PIM join send towards the higher preferred RP
+TC_12 : Verify PIM prune send towards the lower preferred RP
+TC_13 : Verify RPF interface is updated in mroute (kernel) when higher
+ preferred overlapping RP configured
+TC_14 : Verify IIF and OIL in "show ip pim state" updated properly when higher
+ preferred overlapping RP configured
+TC_15 : Verify upstream interfaces(IIF) and join state are updated when higher
+ preferred overlapping RP is configured
+TC_16 : Verify join is send to lower preferred RP, when higher preferred RP
+ gets deleted
+TC_17 : Verify prune is send to higher preferred RP when higher preferred RP
+ gets deleted
+TC_18 : Verify RPF interface updated in mroute when higher preferred RP gets
+ deleted
+TC_19 : Verify IIF and OIL in "show ip pim state" updated when higher
+ preferred overlapping RP is deleted
+TC_20 : Verify PIM upstream IIF updated when higher preferred overlapping RP
+ deleted
+TC_21_1 : Verify OIF and RFP for (*,G) and (S,G) when static RP configure in
+ LHR router
+TC_21_2 : Verify OIF and RFP for (*,G) and (S,G) when static RP configure in
+ LHR router
+TC_22_1 : Verify OIF and RPF for (*,G) and (S,G) when static RP configure in
+ FHR router
+TC_22_2 : Verify OIF and RPF for (*,G) and (S,G) when static RP configure in
+ FHR router
+TC_23 : Verify (*,G) and (S,G) populated correctly when RPT and SPT path are
+ different
+TC_24 : Verify (*,G) and (S,G) populated correctly when SPT and RPT share the
+ same path
+TC_25 : Verify (*,G) and (S,G) populated correctly after clearing the PIM ,
+ IGMP and mroutes joins
+TC_26 : Restart the PIMd process and verify PIM joins , and mroutes entries
+TC_27 : Configure multiple groups (10 grps) with same RP address
+TC_28 : Configure multiple groups (10 grps) with different RP address
+TC_29 : Verify IIF and OIL in updated in mroute when upstream interface
+ configure as RP
+TC_30 : Verify IIF and OIL change to other path after shut the primary path
+TC_31 : Verify RP info and (*,G) mroute after deleting the RP and shut / no
+ shut the RPF interface.
+TC_32 : Verify RP info and (*,G) mroute after deleting the RP and shut / no
+ shut the RPF interface
+"""
+
+import os
+import sys
+import time
+from time import sleep
+import datetime
+import pytest
+
+# Save the Current Working Directory to find configuration files.
+CWD = os.path.dirname(os.path.realpath(__file__))
+sys.path.append(os.path.join(CWD, "../"))
+sys.path.append(os.path.join(CWD, "../lib/"))
+
+# Required to instantiate the topology builder class.
+
+# pylint: disable=C0413
+# Import topogen and topotest helpers
+
+from lib.topogen import Topogen, get_topogen
+from lib.topolog import logger
+from lib.topojson import build_topo_from_json, build_config_from_json
+
+from lib.common_config import (
+ start_topology,
+ write_test_header,
+ write_test_footer,
+ reset_config_on_routers,
+ step,
+ shutdown_bringup_interface,
+ kill_router_daemons,
+ start_router_daemons,
+ create_static_routes,
+ topo_daemons,
+)
+from lib.pim import (
+ create_pim_config,
+ verify_igmp_groups,
+ verify_upstream_iif,
+ verify_join_state_and_timer,
+ verify_mroutes,
+ verify_pim_neighbors,
+ get_pim_interface_traffic,
+ verify_pim_rp_info,
+ verify_pim_state,
+ clear_pim_interface_traffic,
+ clear_igmp_interfaces,
+ clear_pim_interfaces,
+ clear_mroute,
+ clear_mroute_verify,
+ McastTesterHelper,
+)
+
+pytestmark = [pytest.mark.pimd, pytest.mark.staticd]
+
+
+# Global variables
+GROUP_RANGE_ALL = "224.0.0.0/4"
+GROUP_RANGE = "225.1.1.1/32"
+GROUP_RANGE_LIST_1 = [
+ "225.1.1.1/32",
+ "225.1.1.2/32",
+ "225.1.1.3/32",
+ "225.1.1.4/32",
+ "225.1.1.5/32",
+]
+GROUP_RANGE_LIST_2 = [
+ "225.1.1.6/32",
+ "225.1.1.7/32",
+ "225.1.1.8/32",
+ "225.1.1.9/32",
+ "225.1.1.10/32",
+]
+GROUP_ADDRESS = "225.1.1.1"
+GROUP_ADDRESS_LIST_1 = ["225.1.1.1", "225.1.1.2", "225.1.1.3", "225.1.1.4", "225.1.1.5"]
+GROUP_ADDRESS_LIST_2 = [
+ "225.1.1.6",
+ "225.1.1.7",
+ "225.1.1.8",
+ "225.1.1.9",
+ "225.1.1.10",
+]
+STAR = "*"
+SOURCE_ADDRESS = "10.0.6.2"
+SOURCE = "Static"
+
+
+def build_topo(tgen):
+ """Build function"""
+
+ # Building topology from json file
+ build_topo_from_json(tgen, TOPO)
+
+
+def setup_module(mod):
+ """
+ Sets up the pytest environment
+
+ * `mod`: module name
+ """
+
+ testsuite_run_time = time.asctime(time.localtime(time.time()))
+ logger.info("Testsuite start time: %s", testsuite_run_time)
+ logger.info("=" * 40)
+
+ topology = """
+
+ _______r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+ | |
+ |_____________|
+ r4
+
+ """
+ logger.info("Master Topology: \n %s", topology)
+
+ logger.info("Running setup_module to create topology")
+
+ # This function initiates the topology build with Topogen...
+ json_file = "{}/multicast_pim_static_rp.json".format(CWD)
+ tgen = Topogen(json_file, mod.__name__)
+ global TOPO
+ TOPO = tgen.json_topo
+
+ # ... and here it calls Mininet initialization functions.
+
+ # get list of daemons needs to be started for this suite.
+ daemons = topo_daemons(tgen, TOPO)
+
+ # Starting topology, create tmp files which are loaded to routers
+ # to start daemons and then start routers
+ start_topology(tgen, daemons)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ # Creating configuration from JSON
+ build_config_from_json(tgen, TOPO)
+
+ # Verify PIM neighbors
+ result = verify_pim_neighbors(tgen, TOPO)
+ assert result is True, "setup_module :Failed \n Error:" " {}".format(result)
+
+ # XXX Replace this using "with McastTesterHelper()... " in each test if possible.
+ global app_helper
+ app_helper = McastTesterHelper(tgen)
+
+ logger.info("Running setup_module() done")
+
+
+def teardown_module():
+ """Teardown the pytest environment"""
+
+ logger.info("Running teardown_module to delete topology")
+
+ tgen = get_topogen()
+
+ app_helper.cleanup()
+
+ # Stop toplogy and Remove tmp files
+ tgen.stop_topology()
+
+ logger.info("Testsuite end time: %s", time.asctime(time.localtime(time.time())))
+ logger.info("=" * 40)
+
+
+#####################################################
+#
+# Testcases
+#
+#####################################################
+
+
+def verify_mroute_repopulated(uptime_before, uptime_after):
+ """
+ API to compare uptime for mroutes
+
+ Parameters
+ ----------
+ * `uptime_before` : Uptime dictionary for any particular instance
+ * `uptime_after` : Uptime dictionary for any particular instance
+ """
+
+ for group in uptime_before.keys():
+ for source in uptime_before[group].keys():
+ if set(uptime_before[group]) != set(uptime_after[group]):
+ errormsg = (
+ "mroute (%s, %s) has not come"
+ " up after mroute clear [FAILED!!]" % (source, group)
+ )
+ return errormsg
+
+ d_1 = datetime.datetime.strptime(uptime_before[group][source], "%H:%M:%S")
+ d_2 = datetime.datetime.strptime(uptime_after[group][source], "%H:%M:%S")
+ if d_2 >= d_1:
+ errormsg = "mroute (%s, %s) is not " "repopulated [FAILED!!]" % (
+ source,
+ group,
+ )
+ return errormsg
+
+ logger.info("mroute (%s, %s) is " "repopulated [PASSED!!]", source, group)
+
+ return True
+
+
+def verify_state_incremented(state_before, state_after):
+ """
+ API to compare interface traffic state incrementing
+
+ Parameters
+ ----------
+ * `state_before` : State dictionary for any particular instance
+ * `state_after` : State dictionary for any particular instance
+ """
+
+ for router, state_data in state_before.items():
+ for state, _ in state_data.items():
+ if state_before[router][state] >= state_after[router][state]:
+ errormsg = (
+ "[DUT: %s]: state %s value has not"
+ " incremented, Initial value: %s, "
+ "Current value: %s [FAILED!!]"
+ % (
+ router,
+ state,
+ state_before[router][state],
+ state_after[router][state],
+ )
+ )
+ return errormsg
+
+ logger.info(
+ "[DUT: %s]: State %s value is "
+ "incremented, Initial value: %s, Current value: %s"
+ " [PASSED!!]",
+ router,
+ state,
+ state_before[router][state],
+ state_after[router][state],
+ )
+
+ return True
+
+
+def test_restart_pimd_process_p2(request):
+ """
+ TC_26_P2: Restart the PIMd process and verify PIM upstream and mroutes
+ entries
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+ | |
+ |_____________|
+ r4
+ r1 : LHR
+ r2 : RP
+ r3 : FHR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface and send IGMP join (225.1.1.1) to R1")
+ step("Configure RP on r3 (loopback interface) for the group range" " 224.0.0.0/4")
+ step("Enable the PIM on all the interfaces of r1, r2, r3 and r4 routers")
+ step("Send multicast traffic from R3")
+ step("Restart the PIMd process")
+
+ step("r2: Verify RP info")
+ dut = "r2"
+ rp_address = "1.0.2.17"
+ oif = "lo"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, oif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ dut = "r1"
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", GROUP_ADDRESS, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ iif = "r1-r2-eth1"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream IIF interface")
+ dut = "r2"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ oil = "r1-r0-eth0"
+ logger.info("waiting for 10 sec to make sure old mroute time is higher")
+ sleep(10)
+ # Why do we then wait 60 seconds below before checking the routes?
+ uptime_before = verify_mroutes(
+ tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=60
+ )
+ assert isinstance(uptime_before, dict), "Testcase{} : Failed Error: {}".format(
+ tc_name, result
+ )
+
+ step("r1: Kill pimd process")
+ kill_router_daemons(tgen, "r1", ["pimd"])
+
+ step("r1 : Start pimd process")
+ start_router_daemons(tgen, "r1", ["pimd"])
+
+ logger.info("Waiting for 5sec to get PIMd restarted and mroute" " re-learned..")
+ sleep(5)
+
+ # Why do we then wait 10 seconds below before checking the routes?
+ uptime_after = verify_mroutes(
+ tgen, dut, STAR, GROUP_ADDRESS, iif, oil, return_uptime=True, mwait=10
+ )
+ assert isinstance(uptime_after, dict), "Testcase{} : Failed Error: {}".format(
+ tc_name, result
+ )
+
+ result = verify_mroute_repopulated(uptime_before, uptime_after)
+ assert result is True, "Testcase{} : Failed Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_multiple_groups_same_RP_address_p2(request):
+ """
+ TC_27_P2: Configure multiple groups (10 grps) with same RP address
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+
+ r1 : LHR
+ r2 : RP
+ r3 : FHR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface and send IGMP join (225.1.1.1) to r1")
+ step("Configure RP on r2 (loopback interface) for the group range" "225.1.1.0/24")
+ step("Enable the PIM on all the interfaces of r1-r2-r3")
+ step("Send multicast traffic from r5 to all the groups")
+ step("r1 : Remove the groups to RP mapping one by one")
+ step("r1: Shut the upstream interfaces")
+ step("r1: No shut the upstream interfaces")
+ step("r1: Configure the RP again")
+ step("r1: Shut the receiver interfaces")
+ step("r1: No Shut the receiver interfaces")
+ step("r2: Verify RP info")
+
+ step("r2: verify rp-info")
+ dut = "r2"
+ rp_address = "1.0.2.17"
+ oif = "lo"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, oif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ group_address_list = GROUP_ADDRESS_LIST_1 + GROUP_ADDRESS_LIST_2
+ step("r0: Send IGMP join for 10 groups")
+ result = app_helper.run_join("r0", group_address_list, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ dut = "r1"
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", group_address_list, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream IIF interface")
+ dut = "r2"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream IIF interface")
+ dut = "r2"
+ iif = "r2-r3-eth1"
+ result = verify_upstream_iif(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, joinState="NotJoined"
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (S, G) ip mroutes")
+ oif = "none"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Delete RP configuration")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: No Shut the interface r1-r2-eth1 from R1 to R2")
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Configure RP")
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Shut the interface r1-r0-eth0 from R1 to R2")
+ intf = "r1-r0-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: No Shut the interface r1-r0-eth0 from R1 to R2")
+ intf = "r1-r0-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream IIF interface")
+ dut = "r2"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream IIF interface")
+ dut = "r2"
+ iif = "r2-r3-eth1"
+ result = verify_upstream_iif(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, joinState="NotJoined"
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (S, G) ip mroutes")
+ oif = "none"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, group_address_list, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, group_address_list, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_multiple_groups_different_RP_address_p2(request):
+ """
+ TC_28_P2: Verify IIF and OIL in updated in mroute when upstream interface
+ configure as RP
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | | iperf
+ r0-----r1-------------r3-----r5
+ | |
+ |_____________|
+ r4
+ r1 : LHR
+ r2 & r4 : RP
+ r3 : FHR
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Delete existing RP configuration")
+ input_dict = {
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ input_dict = {
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_LIST_1,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.4.17",
+ "group_addr_range": GROUP_RANGE_LIST_2,
+ }
+ ]
+ }
+ },
+ }
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify RP info")
+ dut = "r2"
+ rp_address = "1.0.2.17"
+ oif = "lo"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_LIST_1, oif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify RP info")
+ dut = "r4"
+ rp_address = "1.0.4.17"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_LIST_2, oif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ group_address_list = GROUP_ADDRESS_LIST_1 + GROUP_ADDRESS_LIST_2
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", group_address_list, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ dut = "r1"
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, group_address_list)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r5: Send multicast traffic for group 225.1.1.1")
+ result = app_helper.run_traffic("r5", group_address_list, "r3")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream IIF interface")
+ dut = "r2"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream IIF interface")
+ iif = "r2-r3-eth1"
+ result = verify_upstream_iif(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, joinState="NotJoined"
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (S, G) ip mroutes")
+ oif = "none"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ dut = "r1"
+ iif = "r1-r4-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (*, G) upstream IIF interface")
+ dut = "r4"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (*, G) ip mroutes")
+ oif = "r4-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (S, G) upstream IIF interface")
+ iif = "r4-r3-eth1"
+ result = verify_upstream_iif(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, joinState="NotJoined"
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r4: Verify (S, G) ip mroutes")
+ oif = "none"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
+ )
+ assert result is not True, "Testcase {} :Failed \n Error: {}".format(
+ tc_name, result
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("Delete RP configuration")
+ input_dict = {
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_LIST_1,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.4.17",
+ "group_addr_range": GROUP_RANGE_LIST_2,
+ "delete": True,
+ }
+ ]
+ }
+ },
+ }
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1, r2, r3, r4: Re-configure RP")
+ input_dict = {
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_LIST_1,
+ }
+ ]
+ }
+ },
+ "r4": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.4.17",
+ "group_addr_range": GROUP_RANGE_LIST_2,
+ }
+ ]
+ }
+ },
+ }
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: No shut the interface r1-r2-eth1 from R1 to R2")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Shut the interface r1-r2-eth1 from R1 to R4")
+ dut = "r1"
+ intf = "r1-r4-eth3"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: No shut the interface r1-r2-eth1 from R1 to r4")
+ dut = "r1"
+ intf = "r1-r4-eth3"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Shut the interface r1-r0-eth0 from R1 to R0")
+ dut = "r1"
+ intf = "r1-r0-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: No Shut the interface r1-r0-eth0 from R1 to R0")
+ dut = "r1"
+ intf = "r1-r0-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream IIF interface")
+ dut = "r2"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream IIF interface")
+ iif = "r2-r3-eth1"
+ result = verify_upstream_iif(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, joinState="NotJoined"
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (S, G) ip mroutes")
+ oif = "none"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_1, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream IIF interface")
+ dut = "r1"
+ iif = "r1-r4-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream IIF interface")
+ iif = "r1-r3-eth2"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (S, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (*, G) upstream IIF interface")
+ dut = "r4"
+ iif = "lo"
+ result = verify_upstream_iif(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (*, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(tgen, dut, iif, STAR, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (*, G) ip mroutes")
+ oif = "r4-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (S, G) upstream IIF interface")
+ iif = "r4-r3-eth1"
+ result = verify_upstream_iif(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, joinState="NotJoined"
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r4: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r4: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r4: Verify (S, G) ip mroutes")
+ oif = "none"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream IIF interface")
+ dut = "r3"
+ iif = "r3-r5-eth3"
+ result = verify_upstream_iif(tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (S, G) upstream join state and join timer")
+ result = verify_join_state_and_timer(
+ tgen, dut, iif, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, expected=False
+ )
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (S,G) upstream state is joined and join timer is running\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (S, G) ip mroutes")
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, SOURCE_ADDRESS, GROUP_ADDRESS_LIST_2, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_shutdown_primary_path_p1(request):
+ """
+ TC_30_P1: Verify IIF and OIL change to other path after shut the primary
+ path
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | |
+ r0-----r1-------------r3
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ # Steps to execute
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
+ step("r1: Shut the link from r1 to r2")
+ step("r3: Shut the link from r1 to r3")
+ step("r1: No shut the link from r1 to r2")
+ step("r3: No shut the link from r1 to r3")
+
+ step("r1: Verify RP info")
+ dut = "r1"
+ rp_address = "1.0.2.17"
+ iif = "r1-r2-eth1"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step(
+ "Verify after shut the R1 to R2 link , verify join is reaching to RP"
+ "via other path"
+ )
+
+ logger.info("Waiting for 110 sec only if test run with crucible")
+
+ step("r1: Verify (*, G) ip mroutes")
+ dut = "r1"
+ iif = "r1-r3-eth2"
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r3-eth1"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (*, G) ip mroutes")
+ dut = "r3"
+ iif = "r3-r2-eth1"
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Shut the link from R1 to R3 from R3 node")
+ dut = "r3"
+ intf = "r3-r1-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step(
+ "Verify after shut of R1 to R3 link , verify (*,G) entries got"
+ " cleared from all the node R1, R2, R3"
+ )
+
+ step("r1: Verify (*, G) ip mroutes")
+ dut = "r1"
+ iif = "r1-r3-eth2"
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (*, G) ip mroutes")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r3-eth1"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: Verify (*, G) ip mroutes")
+ dut = "r3"
+ iif = "r3-r2-eth1"
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r3: (*,G) mroutes are not cleared after shut of R1 to R3 link\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r3: No shutdown the link from R1 to R3 from R3 node")
+ dut = "r3"
+ intf = "r3-r1-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Verify (*, G) ip mroutes")
+ dut = "r1"
+ iif = "r1-r3-eth2"
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r3-eth1"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r3: Verify (*, G) ip mroutes")
+ dut = "r3"
+ iif = "r3-r2-eth1"
+ oif = "r3-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: No shutdown the link from R1 to R2 from R1 node")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Verify (*, G) ip mroutes")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ write_test_footer(tc_name)
+
+
+def test_delete_RP_shut_noshut_upstream_interface_p1(request):
+ """
+ TC_31_P1: Verify RP info and (*,G) mroute after deleting the RP and shut /
+ no shut the RPF interface.
+ Topology used:
+ ________r2_____
+ | |
+ iperf | |
+ r0-----r1-------------r3
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r2 (loopback interface) for the group range" " 224.0.0.0/4")
+ step("r1: Delete the RP config")
+ step("r1: Shut and no shut the upstream interface (R1-R2) connected link")
+ step("r1: Shut and no shut the OIL interface")
+
+ step("r1: Verify RP info")
+ dut = "r1"
+ rp_address = "1.0.2.17"
+ iif = "r1-r2-eth1"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ dut = "r1"
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes created")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes created")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Delete RP configuration")
+
+ # Delete RP configuration
+ input_dict = {
+ "r1": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Shut the interface r1-r2-eth1 from R1 to R2")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: No shutdown the interface r1-r2-eth1 from R1 to R2")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Shutdown the OIL interface r1-r0-eth0 from R1 to R0 ")
+ dut = "r1"
+ intf = "r1-r0-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: No shutdown the OIL interface r1-r0-eth0 from R1 to R0")
+ dut = "r1"
+ intf = "r1-r0-eth0"
+ shutdown_bringup_interface(tgen, dut, intf, True)
+
+ step("r1: Verify (*, G) ip mroutes cleared")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (*, G) ip mroutes cleared")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (*,G) mroutes are not cleared after shut of R1 to R0 link\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ write_test_footer(tc_name)
+
+
+def test_delete_RP_shut_noshut_RP_interface_p1(request):
+ """
+ TC_32_P1: Verify RP info and (*,G) mroute after deleting the RP and shut/
+ no shut the RPF interface
+
+ Topology used:
+ ________r2_____
+ | |
+ iperf | |
+ r0-----r1-------------r3
+ """
+
+ tgen = get_topogen()
+ tc_name = request.node.name
+ write_test_header(tc_name)
+
+ # Don"t run this test if we have any failure.
+ if tgen.routers_have_failure():
+ pytest.skip(tgen.errors)
+
+ step("Creating configuration from JSON")
+ reset_config_on_routers(tgen)
+ app_helper.stop_all_hosts()
+ clear_mroute(tgen)
+ clear_pim_interface_traffic(tgen, TOPO)
+
+ step("Enable IGMP on r1 interface")
+ step("Configure RP on r2 (lo) for the group range" " 224.0.0.0/4")
+ step("r2: Delete the RP configuration")
+ step("r2: Shut the RP interface (lo)")
+ step("r1: Shut the interface(r1-r2-eth1, r1-r3-eth2) towards rp")
+
+ step("r1: Verify RP info")
+ dut = "r1"
+ rp_address = "1.0.2.17"
+ iif = "r1-r2-eth1"
+ result = verify_pim_rp_info(
+ tgen, TOPO, dut, GROUP_RANGE_ALL, iif, rp_address, SOURCE
+ )
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r0: Send IGMP join")
+ result = app_helper.run_join("r0", GROUP_ADDRESS, "r1")
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify IGMP groups")
+ oif = "r1-r0-eth0"
+ result = verify_igmp_groups(tgen, dut, oif, GROUP_ADDRESS)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r1: Verify (*, G) ip mroutes created")
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Verify (*, G) ip mroutes created")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Delete RP configuration")
+
+ # Delete RP configuration
+ input_dict = {
+ "r2": {
+ "pim": {
+ "rp": [
+ {
+ "rp_addr": "1.0.2.17",
+ "group_addr_range": GROUP_RANGE_ALL,
+ "delete": True,
+ }
+ ]
+ }
+ }
+ }
+
+ result = create_pim_config(tgen, TOPO, input_dict)
+ assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
+
+ step("r2: Shut the RP interface lo")
+ dut = "r2"
+ intf = "lo"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: Shut the interface r1-r2-eth1 towards RP")
+ dut = "r1"
+ intf = "r1-r2-eth1"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: Shut the interface r1-r3-eth2 towards RP")
+ dut = "r1"
+ intf = "r1-r3-eth2"
+ shutdown_bringup_interface(tgen, dut, intf, False)
+
+ step("r1: Verify (*, G) ip mroutes cleared")
+ dut = "r1"
+ iif = "r1-r2-eth1"
+ oif = "r1-r0-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r1: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ step("r2: Verify (*, G) ip mroutes cleared")
+ dut = "r2"
+ iif = "lo"
+ oif = "r2-r1-eth0"
+ result = verify_mroutes(tgen, dut, STAR, GROUP_ADDRESS, iif, oif, expected=False)
+ assert result is not True, (
+ "Testcase {} : Failed \n "
+ "r2: (*,G) mroutes are not cleared after shut of R1 to R2 and R3 link\n Error: {}".format(
+ tc_name, result
+ )
+ )
+
+ write_test_footer(tc_name)
+
+
+if __name__ == "__main__":
+ ARGS = ["-s"] + sys.argv[1:]
+ sys.exit(pytest.main(ARGS))
diff --git a/tests/topotests/ospf_topo1/test_ospf_topo1.py b/tests/topotests/ospf_topo1/test_ospf_topo1.py
index e2a6ff64a4..37facfc5da 100644
--- a/tests/topotests/ospf_topo1/test_ospf_topo1.py
+++ b/tests/topotests/ospf_topo1/test_ospf_topo1.py
@@ -316,17 +316,26 @@ def test_ospf6_kernel_route():
for router in rlist:
logger.info('Checking OSPF IPv6 kernel routes in "%s"', router.name)
- routes = topotest.ip6_route(router)
- expected = {
- "2001:db8:1::/64": {},
- "2001:db8:2::/64": {},
- "2001:db8:3::/64": {},
- "2001:db8:100::/64": {},
- "2001:db8:200::/64": {},
- "2001:db8:300::/64": {},
- }
+ def _routes_in_fib6():
+ routes = topotest.ip6_route(router)
+ expected = {
+ "2001:db8:1::/64": {},
+ "2001:db8:2::/64": {},
+ "2001:db8:3::/64": {},
+ "2001:db8:100::/64": {},
+ "2001:db8:200::/64": {},
+ "2001:db8:300::/64": {},
+ }
+ logger.info("Routes:")
+ logger.info(routes)
+ logger.info(topotest.json_cmp(routes, expected))
+ logger.info("ENd:")
+ return topotest.json_cmp(routes, expected)
+
+ _, result = topotest.run_and_expect(_routes_in_fib6, None, count=20, wait=1)
+
assertmsg = 'OSPF IPv6 route mismatch in router "{}"'.format(router.name)
- assert topotest.json_cmp(routes, expected) is None, assertmsg
+ assert result is None, assertmsg
def test_ospf_json():
@@ -337,6 +346,7 @@ def test_ospf_json():
for rnum in range(1, 5):
router = tgen.gears["r{}".format(rnum)]
+ logger.info(router.vtysh_cmd("show ip ospf database"))
logger.info('Comparing router "%s" "show ip ospf json" output', router.name)
expected = {
"routerId": "10.0.255.{}".format(rnum),
diff --git a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
index c9824e79c5..d318ec0906 100644
--- a/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
+++ b/tests/topotests/ospfv3_basic_functionality/test_ospfv3_single_area.py
@@ -183,7 +183,7 @@ def test_ospfv3_p2p_tc3_p0(request):
step("Verify that interface is enabled in ospf.")
step("Verify that config is successful.")
dut = "r0"
- input_dict = {"r0": {"links": {"r3": {"ospf6": {"ospf6Enabled": True}}}}}
+ input_dict = {"r0": {"links": {"r3": {"ospf6": {}}}}}
result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
@@ -339,7 +339,7 @@ def test_ospfv3_p2p_tc3_p0(request):
assert result is True, "Testcase {} :Failed \n Error: {}".format(tc_name, result)
step("Verify that interface is enabled in ospf.")
dut = "r0"
- input_dict = {"r0": {"links": {"r3": {"ospf6": {"ospf6Enabled": True}}}}}
+ input_dict = {"r0": {"links": {"r3": {"ospf6": {}}}}}
result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
@@ -374,7 +374,7 @@ def test_ospfv3_p2p_tc3_p0(request):
step("Verify that interface is enabled in ospf.")
dut = "r0"
- input_dict = {"r0": {"links": {"r3": {"ospf6": {"ospf6Enabled": True}}}}}
+ input_dict = {"r0": {"links": {"r3": {"ospf6": {}}}}}
result = verify_ospf6_interface(tgen, topo, dut=dut, input_dict=input_dict)
assert result is True, "Testcase {} : Failed \n Error: {}".format(tc_name, result)
@@ -1172,7 +1172,6 @@ def test_ospfv3_show_p1(request):
"ospf6": {
"status": "up",
"type": "BROADCAST",
- "ospf6Enabled": True,
"attachedToArea": True,
"instanceId": 0,
"interfaceMtu": 1500,
diff --git a/tools/coccinelle/route_map_apply.cocci b/tools/coccinelle/route_map_apply.cocci
new file mode 100644
index 0000000000..ccca619d7e
--- /dev/null
+++ b/tools/coccinelle/route_map_apply.cocci
@@ -0,0 +1,15 @@
+@rmap@
+identifier ret;
+position p;
+@@
+
+int ret@p;
+...
+* ret = route_map_apply(...);
+
+@script:python@
+p << rmap.p;
+@@
+
+msg = "ERROR: Invalid type of return value variable for route_map_apply_ext()"
+coccilib.report.print_report(p[0], msg)
diff --git a/tools/etc/frr/daemons b/tools/etc/frr/daemons
index 860c4980b6..8aa08871e3 100644
--- a/tools/etc/frr/daemons
+++ b/tools/etc/frr/daemons
@@ -21,6 +21,7 @@ ripd=no
ripngd=no
isisd=no
pimd=no
+pim6d=no
ldpd=no
nhrpd=no
eigrpd=no
@@ -46,6 +47,7 @@ ripd_options=" -A 127.0.0.1"
ripngd_options=" -A ::1"
isisd_options=" -A 127.0.0.1"
pimd_options=" -A 127.0.0.1"
+pim6d_options=" -A ::1"
ldpd_options=" -A 127.0.0.1"
nhrpd_options=" -A 127.0.0.1"
eigrpd_options=" -A 127.0.0.1"
diff --git a/tools/etc/rsyslog.d/45-frr.conf b/tools/etc/rsyslog.d/45-frr.conf
index 9da15b9f92..6e14eb7abc 100644
--- a/tools/etc/rsyslog.d/45-frr.conf
+++ b/tools/etc/rsyslog.d/45-frr.conf
@@ -15,6 +15,7 @@ if $programname == 'babeld' or
$programname == 'ospf6d' or
$programname == 'ospfd' or
$programname == 'pimd' or
+ $programname == 'pim6d' or
$programname == 'pathd' or
$programname == 'ripd' or
$programname == 'ripngd' or
@@ -35,6 +36,7 @@ if $programname == 'babeld' or
$programname == 'ospf6d' or
$programname == 'ospfd' or
$programname == 'pimd' or
+ $programname == 'pim6d' or
$programname == 'pathd' or
$programname == 'ripd' or
$programname == 'ripngd' or
diff --git a/tools/frr-reload.py b/tools/frr-reload.py
index 743d32d5e2..32f9a78841 100755
--- a/tools/frr-reload.py
+++ b/tools/frr-reload.py
@@ -1886,6 +1886,7 @@ if __name__ == "__main__":
"ospfd",
"pbrd",
"pimd",
+ "pim6d",
"ripd",
"ripngd",
"sharpd",
diff --git a/tools/frr.in b/tools/frr.in
index 889c075f81..27b2c0ab84 100755
--- a/tools/frr.in
+++ b/tools/frr.in
@@ -27,7 +27,7 @@ FRR_DEFAULT_PROFILE="@DFLT_NAME@" # traditional / datacenter
# Local Daemon selection may be done by using /etc/frr/daemons.
# See /usr/share/doc/frr/README.Debian.gz for further information.
# Keep zebra first and do not list watchfrr!
-DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd pathd"
+DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd pim6d ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd pathd"
MAX_INSTANCES=5
RELOAD_SCRIPT="$D_PATH/frr-reload.py"
diff --git a/tools/frr.service.in b/tools/frr.service.in
index df1e4f3b08..1e958dd93e 100644
--- a/tools/frr.service.in
+++ b/tools/frr.service.in
@@ -15,7 +15,7 @@ StartLimitBurst=3
TimeoutSec=@TIMEOUT_MIN@m
WatchdogSec=60s
RestartSec=5
-Restart=on-abnormal
+Restart=always
LimitNOFILE=1024
PIDFile=@CFG_STATE@/watchfrr.pid
ExecStart=@CFG_SBIN@/frrinit.sh start
diff --git a/tools/frr@.service.in b/tools/frr@.service.in
index 1cbef1b18c..85408a0cc7 100644
--- a/tools/frr@.service.in
+++ b/tools/frr@.service.in
@@ -15,7 +15,7 @@ StartLimitBurst=3
TimeoutSec=@TIMEOUT_MIN@m
WatchdogSec=60s
RestartSec=5
-Restart=on-abnormal
+Restart=always
LimitNOFILE=1024
PIDFile=@CFG_STATE@/%I/watchfrr.pid
ExecStart=@CFG_SBIN@/frrinit.sh start %I
diff --git a/tools/frrcommon.sh.in b/tools/frrcommon.sh.in
index 6eb3223faa..b589ced965 100755
--- a/tools/frrcommon.sh.in
+++ b/tools/frrcommon.sh.in
@@ -35,7 +35,7 @@ FRR_DEFAULT_PROFILE="@DFLT_NAME@" # traditional / datacenter
# - keep zebra first
# - watchfrr does NOT belong in this list
-DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd pathd"
+DAEMONS="zebra bgpd ripd ripngd ospfd ospf6d isisd babeld pimd pim6d ldpd nhrpd eigrpd sharpd pbrd staticd bfdd fabricd vrrpd pathd"
RELOAD_SCRIPT="$D_PATH/frr-reload.py"
#
@@ -272,7 +272,7 @@ all_start() {
}
all_stop() {
- local pids reversed
+ local pids reversed need_zebra
daemon_list enabled_daemons disabled_daemons
[ "$1" = "--reallyall" ] && enabled_daemons="$enabled_daemons $disabled_daemons"
@@ -282,13 +282,23 @@ all_stop() {
reversed="$dmninst $reversed"
done
+ # Stop zebra last, after trying to stop the other daemons
for dmninst in $reversed; do
+ if [ "$dmninst" = "zebra" ]; then
+ need_zebra="yes"
+ continue
+ fi
+
daemon_stop "$dmninst" "$1" &
pids="$pids $!"
done
for pid in $pids; do
wait $pid
done
+
+ if [ -n "$need_zebra" ]; then
+ daemon_stop "zebra"
+ fi
}
all_status() {
diff --git a/vtysh/vtysh.h b/vtysh/vtysh.h
index 1f02efee20..68841e2d38 100644
--- a/vtysh/vtysh.h
+++ b/vtysh/vtysh.h
@@ -60,8 +60,13 @@ extern struct thread_master *master;
#define VTYSH_ALL VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_LDPD|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_SHARPD|VTYSH_PBRD|VTYSH_STATICD|VTYSH_BFDD|VTYSH_FABRICD|VTYSH_VRRPD|VTYSH_PATHD
#define VTYSH_ACL VTYSH_BFDD|VTYSH_BABELD|VTYSH_BGPD|VTYSH_EIGRPD|VTYSH_ISISD|VTYSH_FABRICD|VTYSH_LDPD|VTYSH_NHRPD|VTYSH_OSPF6D|VTYSH_OSPFD|VTYSH_PBRD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_VRRPD|VTYSH_ZEBRA
#define VTYSH_RMAP VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_BGPD|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_EIGRPD|VTYSH_FABRICD
-#define VTYSH_INTERFACE VTYSH_ZEBRA|VTYSH_RIPD|VTYSH_RIPNGD|VTYSH_OSPFD|VTYSH_OSPF6D|VTYSH_ISISD|VTYSH_PIMD|VTYSH_PIM6D|VTYSH_NHRPD|VTYSH_EIGRPD|VTYSH_BABELD|VTYSH_PBRD|VTYSH_FABRICD|VTYSH_VRRPD
-#define VTYSH_VRF VTYSH_INTERFACE|VTYSH_STATICD
+#define VTYSH_INTERFACE_SUBSET \
+ VTYSH_ZEBRA | VTYSH_RIPD | VTYSH_RIPNGD | VTYSH_OSPFD | VTYSH_OSPF6D | \
+ VTYSH_ISISD | VTYSH_PIMD | VTYSH_PIM6D | VTYSH_NHRPD | \
+ VTYSH_EIGRPD | VTYSH_BABELD | VTYSH_PBRD | VTYSH_FABRICD | \
+ VTYSH_VRRPD
+#define VTYSH_INTERFACE VTYSH_INTERFACE_SUBSET | VTYSH_BGPD
+#define VTYSH_VRF VTYSH_INTERFACE_SUBSET | VTYSH_STATICD
#define VTYSH_KEYS VTYSH_RIPD | VTYSH_EIGRPD | VTYSH_OSPF6D
/* Daemons who can process nexthop-group configs */
#define VTYSH_NH_GROUP VTYSH_PBRD|VTYSH_SHARPD
diff --git a/vtysh/vtysh_config.c b/vtysh/vtysh_config.c
index a7ec2a93c2..d98f83dbf6 100644
--- a/vtysh/vtysh_config.c
+++ b/vtysh/vtysh_config.c
@@ -483,13 +483,21 @@ void vtysh_config_parse_line(void *arg, const char *line)
0 ||
strncmp(line, "domainname", strlen("domainname")) ==
0 ||
+ strncmp(line, "allow-reserved-ranges",
+ strlen("allow-reserved-ranges")) == 0 ||
strncmp(line, "frr", strlen("frr")) == 0 ||
strncmp(line, "agentx", strlen("agentx")) == 0 ||
strncmp(line, "no log", strlen("no log")) == 0 ||
strncmp(line, "no ip prefix-list",
strlen("no ip prefix-list")) == 0 ||
strncmp(line, "no ipv6 prefix-list",
- strlen("no ipv6 prefix-list")) == 0)
+ strlen("no ipv6 prefix-list")) == 0 ||
+ strncmp(line, "service cputime-stats",
+ strlen("service cputime-stats")) == 0 ||
+ strncmp(line, "no service cputime-stats",
+ strlen("no service cputime-stats")) == 0 ||
+ strncmp(line, "service cputime-warning",
+ strlen("service cputime-warning")) == 0)
config_add_line_uniq(config_top, line);
else
config_add_line(config_top, line);
diff --git a/vtysh/vtysh_main.c b/vtysh/vtysh_main.c
index 04eb47feeb..ca119eb900 100644
--- a/vtysh/vtysh_main.c
+++ b/vtysh/vtysh_main.c
@@ -78,36 +78,56 @@ int execute_flag = 0;
/* Flag to indicate if in user/unprivileged mode. */
int user_mode;
-/* For sigsetjmp() & siglongjmp(). */
-static sigjmp_buf jmpbuf;
-
-/* Flag for avoid recursive siglongjmp() call. */
-static int jmpflag = 0;
-
/* Master of threads. */
struct thread_master *master;
/* Command logging */
FILE *logfile;
+static void vtysh_rl_callback(char *line_read)
+{
+ HIST_ENTRY *last;
+
+ rl_callback_handler_remove();
+
+ if (!line_read) {
+ vtysh_loop_exited = true;
+ return;
+ }
+
+ /* If the line has any text in it, save it on the history. But only if
+ * last command in history isn't the same one.
+ */
+ if (*line_read) {
+ using_history();
+ last = previous_history();
+ if (!last || strcmp(last->line, line_read) != 0) {
+ add_history(line_read);
+ append_history(1, history_file);
+ }
+ }
+
+ vtysh_execute(line_read);
+
+ if (!vtysh_loop_exited)
+ rl_callback_handler_install(vtysh_prompt(), vtysh_rl_callback);
+}
+
/* SIGTSTP handler. This function care user's ^Z input. */
static void sigtstp(int sig)
{
+ rl_callback_handler_remove();
+
/* Execute "end" command. */
vtysh_execute("end");
+ if (!vtysh_loop_exited)
+ rl_callback_handler_install(vtysh_prompt(), vtysh_rl_callback);
+
/* Initialize readline. */
rl_initialize();
printf("\n");
-
- /* Check jmpflag for duplicate siglongjmp(). */
- if (!jmpflag)
- return;
-
- jmpflag = 0;
-
- /* Back to main command loop. */
- siglongjmp(jmpbuf, 1);
+ rl_forced_update_display();
}
/* SIGINT handler. This function care user's ^Z input. */
@@ -207,34 +227,6 @@ struct option longopts[] = {
bool vtysh_loop_exited;
-static void vtysh_rl_callback(char *line_read)
-{
- HIST_ENTRY *last;
-
- rl_callback_handler_remove();
-
- if (!line_read) {
- vtysh_loop_exited = true;
- return;
- }
-
- /* If the line has any text in it, save it on the history. But only if
- * last command in history isn't the same one. */
- if (*line_read) {
- using_history();
- last = previous_history();
- if (!last || strcmp(last->line, line_read) != 0) {
- add_history(line_read);
- append_history(1, history_file);
- }
- }
-
- vtysh_execute(line_read);
-
- if (!vtysh_loop_exited)
- rl_callback_handler_install(vtysh_prompt(), vtysh_rl_callback);
-}
-
static struct thread *vtysh_rl_read_thread;
static void vtysh_rl_read(struct thread *thread)
@@ -752,10 +744,6 @@ int main(int argc, char **argv, char **env)
vtysh_add_timestamp = ts_flag;
- /* Preparation for longjmp() in sigtstp(). */
- sigsetjmp(jmpbuf, 1);
- jmpflag = 1;
-
/* Main command loop. */
vtysh_rl_run();
diff --git a/watchfrr/watchfrr.c b/watchfrr/watchfrr.c
index fc285c748a..423f25faa2 100644
--- a/watchfrr/watchfrr.c
+++ b/watchfrr/watchfrr.c
@@ -1429,7 +1429,7 @@ int main(int argc, char **argv)
if ((sscanf(optarg, "%ld%1s", &gs.operational_timeout,
garbage) != 1) ||
- (gs.max_restart_interval < 0)) {
+ (gs.operational_timeout < 0)) {
fprintf(stderr,
"Invalid Operational_timeout argument: %s\n",
optarg);
diff --git a/yang/frr-bgp-route-map.yang b/yang/frr-bgp-route-map.yang
index eaa7891f0c..3f3d829211 100644
--- a/yang/frr-bgp-route-map.yang
+++ b/yang/frr-bgp-route-map.yang
@@ -66,6 +66,12 @@ module frr-bgp-route-map {
"Control rpki specific settings";
}
+ identity rpki-extcommunity {
+ base frr-route-map:rmap-match-type;
+ description
+ "Control rpki specific settings derived from extended community";
+ }
+
identity probability {
base frr-route-map:rmap-match-type;
description
@@ -330,6 +336,12 @@ module frr-bgp-route-map {
"Set EVPN gateway IP overlay index IPv6";
}
+ identity set-l3vpn-nexthop-encapsulation {
+ base frr-route-map:rmap-set-type;
+ description
+ "Accept L3VPN traffic over other than LSP encapsulation";
+ }
+
grouping extcommunity-non-transitive-types {
leaf two-octet-as-specific {
type boolean;
@@ -430,6 +442,29 @@ module frr-bgp-route-map {
}
}
+ case rpki-extcommunity {
+ when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:rpki-extcommunity')";
+ leaf rpki-extcommunity {
+ type enumeration {
+ enum "valid" {
+ value 0;
+ description
+ "Valid prefix";
+ }
+ enum "notfound" {
+ value 1;
+ description
+ "Prefix not found";
+ }
+ enum "invalid" {
+ value 2;
+ description
+ "Invalid prefix";
+ }
+ }
+ }
+ }
+
case probability {
when "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:match-condition/frr-route-map:condition, 'frr-bgp-route-map:probability')";
leaf probability {
@@ -902,5 +937,21 @@ module frr-bgp-route-map {
type inet:ipv6-address;
}
}
+ case l3vpn-nexthop-encapsulation {
+ when
+ "derived-from-or-self(/frr-route-map:lib/frr-route-map:route-map/frr-route-map:entry/frr-route-map:set-action/frr-route-map:action,
+ 'frr-bgp-route-map:set-l3vpn-nexthop-encapsulation')";
+ description
+ "Accept L3VPN traffic over other than LSP encapsulation";
+ leaf l3vpn-nexthop-encapsulation {
+ type enumeration {
+ enum "gre" {
+ value 0;
+ description
+ "GRE protocol";
+ }
+ }
+ }
+ }
}
}
diff --git a/zebra/debug_nl.c b/zebra/debug_nl.c
index a16d442521..afefab6674 100644
--- a/zebra/debug_nl.c
+++ b/zebra/debug_nl.c
@@ -1536,6 +1536,24 @@ next_rta:
goto next_rta;
}
+static const char *tcm_nltype2str(int nltype)
+{
+ switch (nltype) {
+ case RTM_NEWQDISC:
+ case RTM_DELQDISC:
+ return "qdisc";
+ case RTM_NEWTCLASS:
+ case RTM_DELTCLASS:
+ return "tclass";
+ case RTM_NEWTFILTER:
+ case RTM_DELTFILTER:
+ return "tfilter";
+ default:
+ /* should never hit */
+ return "unknown";
+ }
+}
+
static void nlncm_dump(const struct netconfmsg *ncm, size_t msglen)
{
const struct rtattr *rta;
@@ -1595,6 +1613,8 @@ void nl_dump(void *msg, size_t msglen)
struct ifinfomsg *ifi;
struct tunnel_msg *tnlm;
struct fib_rule_hdr *frh;
+ struct tcmsg *tcm;
+
char fbuf[128];
char ibuf[128];
@@ -1730,6 +1750,21 @@ next_header:
nlncm_dump(ncm, nlmsg->nlmsg_len - NLMSG_LENGTH(sizeof(*ncm)));
break;
+ case RTM_NEWQDISC:
+ case RTM_DELQDISC:
+ case RTM_NEWTCLASS:
+ case RTM_DELTCLASS:
+ case RTM_NEWTFILTER:
+ case RTM_DELTFILTER:
+ tcm = NLMSG_DATA(nlmsg);
+ zlog_debug(
+ " tcm [type=%s family=%s (%d) ifindex=%d handle=%04x:%04x]",
+ tcm_nltype2str(nlmsg->nlmsg_type),
+ af_type2str(tcm->tcm_family), tcm->tcm_family,
+ tcm->tcm_ifindex, tcm->tcm_handle >> 16,
+ tcm->tcm_handle & 0xffff);
+ break;
+
default:
break;
}
diff --git a/zebra/dplane_fpm_nl.c b/zebra/dplane_fpm_nl.c
index ec4ea372f1..d07c4c6332 100644
--- a/zebra/dplane_fpm_nl.c
+++ b/zebra/dplane_fpm_nl.c
@@ -815,6 +815,9 @@ static int fpm_nl_enqueue(struct fpm_nl_ctx *fnc, struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
case DPLANE_OP_NONE:
break;
diff --git a/zebra/if_ioctl.c b/zebra/if_ioctl.c
index 4e4ebc9cda..e02f3d5624 100644
--- a/zebra/if_ioctl.c
+++ b/zebra/if_ioctl.c
@@ -199,7 +199,7 @@ static int if_getaddrs(void)
ifp = if_lookup_by_name(ifap->ifa_name, VRF_DEFAULT);
if (ifp == NULL) {
flog_err(EC_LIB_INTERFACE,
- "if_getaddrs(): Can't lookup interface %s\n",
+ "%s: Can't lookup interface %s", __func__,
ifap->ifa_name);
continue;
}
@@ -290,7 +290,7 @@ static void interface_info_ioctl()
void interface_list(struct zebra_ns *zns)
{
- zlog_info("interface_list: NS %u", zns->ns_id);
+ zlog_info("%s: NS %u", __func__, zns->ns_id);
/* Linux can do both proc & ioctl, ioctl is the only way to get
interface aliases in 2.2 series kernels. */
diff --git a/zebra/if_netlink.c b/zebra/if_netlink.c
index 7a4e1304bd..b28c468a96 100644
--- a/zebra/if_netlink.c
+++ b/zebra/if_netlink.c
@@ -423,7 +423,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
ecmd.cmd = ETHTOOL_GSET; /* ETHTOOL_GLINK */
ifdata.ifr_data = (caddr_t)&ecmd;
- /* use ioctl to get IP address of an interface */
+ /* use ioctl to get speed of an interface */
frr_with_privs(&zserv_privs) {
sd = vrf_socket(PF_INET, SOCK_DGRAM, IPPROTO_IP,
interface->vrf->vrf_id, NULL);
@@ -436,7 +436,7 @@ static uint32_t get_iflink_speed(struct interface *interface, int *error)
*error = -1;
return 0;
}
- /* Get the current link state for the interface */
+ /* Get the current link state for the interface */
rc = vrf_ioctl(interface->vrf->vrf_id, sd, SIOCETHTOOL,
(char *)&ifdata);
}
@@ -1182,13 +1182,19 @@ int interface_lookup_netlink(struct zebra_ns *zns)
if (ret < 0)
return ret;
+ /*
+ * So netlink_tunneldump_read will initiate a request
+ * per tunnel to get data. If we are on a kernel that
+ * does not support this then we will get X error messages
+ * (one per tunnel request )back which netlink_parse_info will
+ * stop after the first one. So we need to read equivalent
+ * error messages per tunnel then we can continue.
+ * if we do not gather all the read failures then
+ * later requests will not work right.
+ */
ret = netlink_tunneldump_read(zns);
if (ret < 0)
return ret;
- ret = netlink_parse_info(netlink_interface, netlink_cmd, &dp_info, 0,
- true);
- if (ret < 0)
- return ret;
/* fixup linkages */
zebra_if_update_all_links(zns);
@@ -1443,7 +1449,7 @@ int netlink_interface_addr(struct nlmsghdr *h, ns_id_t ns_id, int startup)
if (IS_ZEBRA_DEBUG_KERNEL) /* remove this line to see initial ifcfg */
{
char buf[BUFSIZ];
- zlog_debug("netlink_interface_addr %s %s flags 0x%x:",
+ zlog_debug("%s %s %s flags 0x%x:", __func__,
nl_msg_type_to_str(h->nlmsg_type), ifp->name,
kernel_flags);
if (tb[IFA_LOCAL])
@@ -1818,7 +1824,7 @@ int netlink_link_change(struct nlmsghdr *h, ns_id_t ns_id, int startup)
/* assume if not default zns, then new VRF */
if (!(h->nlmsg_type == RTM_NEWLINK || h->nlmsg_type == RTM_DELLINK)) {
/* If this is not link add/delete message so print warning. */
- zlog_debug("netlink_link_change: wrong kernel message %s",
+ zlog_debug("%s: wrong kernel message %s", __func__,
nl_msg_type_to_str(h->nlmsg_type));
return 0;
}
@@ -2322,6 +2328,7 @@ int netlink_tunneldump_read(struct zebra_ns *zns)
struct route_node *rn;
struct interface *tmp_if = NULL;
struct zebra_if *zif;
+ struct nlsock *netlink_cmd = &zns->netlink_cmd;
zebra_dplane_info_from_zns(&dp_info, zns, true /*is_cmd*/);
@@ -2337,7 +2344,14 @@ int netlink_tunneldump_read(struct zebra_ns *zns)
tmp_if->ifindex);
if (ret < 0)
return ret;
+
+ ret = netlink_parse_info(netlink_interface, netlink_cmd,
+ &dp_info, 0, true);
+
+ if (ret < 0)
+ return ret;
}
+
return 0;
}
#endif /* GNU_LINUX */
diff --git a/zebra/if_socket.c b/zebra/if_socket.c
index 309d5a3f3e..da9fadf7c7 100644
--- a/zebra/if_socket.c
+++ b/zebra/if_socket.c
@@ -38,4 +38,15 @@ enum zebra_dplane_result kernel_intf_update(struct zebra_dplane_ctx *ctx)
return ZEBRA_DPLANE_REQUEST_FAILURE;
}
+enum zebra_dplane_result
+kernel_intf_netconf_update(struct zebra_dplane_ctx *ctx)
+{
+ const char *ifname = dplane_ctx_get_ifname(ctx);
+ enum dplane_netconf_status_e mpls_on = dplane_ctx_get_netconf_mpls(ctx);
+
+ zlog_warn("%s: Unable to set kernel mpls state for interface %s(%d)",
+ __func__, ifname, mpls_on);
+
+ return ZEBRA_DPLANE_REQUEST_SUCCESS;
+}
#endif
diff --git a/zebra/if_sysctl.c b/zebra/if_sysctl.c
index 38729c8d38..70d11646c3 100644
--- a/zebra/if_sysctl.c
+++ b/zebra/if_sysctl.c
@@ -97,7 +97,7 @@ void interface_list(struct zebra_ns *zns)
NET_RT_IFLIST, 0};
if (zns->ns_id != NS_DEFAULT) {
- zlog_debug("interface_list: ignore NS %u", zns->ns_id);
+ zlog_debug("%s: ignore NS %u", __func__, zns->ns_id);
return;
}
@@ -132,7 +132,7 @@ void interface_list(struct zebra_ns *zns)
ifam_read((struct ifa_msghdr *)ifm);
break;
default:
- zlog_info("interfaces_list(): unexpected message type");
+ zlog_info("%s: unexpected message type", __func__);
XFREE(MTYPE_TMP, ref);
return;
break;
diff --git a/zebra/interface.c b/zebra/interface.c
index de7db2d48f..c674b499ac 100644
--- a/zebra/interface.c
+++ b/zebra/interface.c
@@ -147,8 +147,8 @@ static int if_zebra_new_hook(struct interface *ifp)
zebra_if = XCALLOC(MTYPE_ZINFO, sizeof(struct zebra_if));
zebra_if->ifp = ifp;
- zebra_if->multicast = IF_ZEBRA_MULTICAST_UNSPEC;
- zebra_if->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
+ zebra_if->multicast = IF_ZEBRA_DATA_UNSPEC;
+ zebra_if->shutdown = IF_ZEBRA_DATA_OFF;
zebra_if_nhg_dependents_init(zebra_if);
@@ -583,9 +583,9 @@ void if_add_update(struct interface *ifp)
if_data = ifp->info;
assert(if_data);
- if (if_data->multicast == IF_ZEBRA_MULTICAST_ON)
+ if (if_data->multicast == IF_ZEBRA_DATA_ON)
if_set_flags(ifp, IFF_MULTICAST);
- else if (if_data->multicast == IF_ZEBRA_MULTICAST_OFF)
+ else if (if_data->multicast == IF_ZEBRA_DATA_OFF)
if_unset_flags(ifp, IFF_MULTICAST);
zebra_ptm_if_set_ptm_state(ifp, if_data);
@@ -595,7 +595,7 @@ void if_add_update(struct interface *ifp)
if (!CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)) {
SET_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE);
- if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON) {
+ if (if_data->shutdown == IF_ZEBRA_DATA_ON) {
if (IS_ZEBRA_DEBUG_KERNEL) {
zlog_debug(
"interface %s vrf %s(%u) index %d is shutdown. Won't wake it up.",
@@ -848,10 +848,6 @@ void if_handle_vrf_change(struct interface *ifp, vrf_id_t vrf_id)
/* Send out notification on interface VRF change. */
/* This is to issue an ADD, if needed. */
zebra_interface_vrf_update_add(ifp, old_vrf_id);
-
- /* Install connected routes (in new VRF). */
- if (if_is_operative(ifp))
- if_install_connected(ifp);
}
static void ipv6_ll_address_to_mac(struct in6_addr *address, uint8_t *mac)
@@ -1453,9 +1449,10 @@ static void zebra_if_netconf_update_ctx(struct zebra_dplane_ctx *ctx,
/*
* mpls netconf data is neither v4 or v6 it's AF_MPLS!
*/
- if (mpls == DPLANE_NETCONF_STATUS_ENABLED)
+ if (mpls == DPLANE_NETCONF_STATUS_ENABLED) {
zif->mpls = true;
- else if (mpls == DPLANE_NETCONF_STATUS_DISABLED)
+ zebra_mpls_turned_on();
+ } else if (mpls == DPLANE_NETCONF_STATUS_DISABLED)
zif->mpls = false;
}
@@ -1576,6 +1573,9 @@ void zebra_if_dplane_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_IPSET_ENTRY_DELETE:
case DPLANE_OP_NEIGH_TABLE_UPDATE:
case DPLANE_OP_GRE_SET:
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
break; /* should never hit here */
}
}
@@ -2908,7 +2908,7 @@ int if_multicast_set(struct interface *ifp)
if_refresh(ifp);
}
if_data = ifp->info;
- if_data->multicast = IF_ZEBRA_MULTICAST_ON;
+ if_data->multicast = IF_ZEBRA_DATA_ON;
return 0;
}
@@ -2931,7 +2931,28 @@ DEFUN (multicast,
if_refresh(ifp);
}
if_data = ifp->info;
- if_data->multicast = IF_ZEBRA_MULTICAST_ON;
+ if_data->multicast = IF_ZEBRA_DATA_ON;
+
+ return CMD_SUCCESS;
+}
+
+DEFPY (mpls,
+ mpls_cmd,
+ "[no] mpls enable",
+ NO_STR
+ MPLS_STR
+ "Set mpls to be on for the interface\n")
+{
+ VTY_DECLVAR_CONTEXT(interface, ifp);
+ struct zebra_if *if_data = ifp->info;
+
+ if (no) {
+ dplane_intf_mpls_modify_state(ifp, false);
+ if_data->mpls = IF_ZEBRA_DATA_UNSPEC;
+ } else {
+ dplane_intf_mpls_modify_state(ifp, true);
+ if_data->mpls = IF_ZEBRA_DATA_ON;
+ }
return CMD_SUCCESS;
}
@@ -2949,7 +2970,7 @@ int if_multicast_unset(struct interface *ifp)
if_refresh(ifp);
}
if_data = ifp->info;
- if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
+ if_data->multicast = IF_ZEBRA_DATA_OFF;
return 0;
}
@@ -2973,7 +2994,7 @@ DEFUN (no_multicast,
if_refresh(ifp);
}
if_data = ifp->info;
- if_data->multicast = IF_ZEBRA_MULTICAST_OFF;
+ if_data->multicast = IF_ZEBRA_DATA_OFF;
return CMD_SUCCESS;
}
@@ -3039,7 +3060,7 @@ int if_shutdown(struct interface *ifp)
if_refresh(ifp);
}
if_data = ifp->info;
- if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
+ if_data->shutdown = IF_ZEBRA_DATA_ON;
return 0;
}
@@ -3064,7 +3085,7 @@ DEFUN (shutdown_if,
if_refresh(ifp);
}
if_data = ifp->info;
- if_data->shutdown = IF_ZEBRA_SHUTDOWN_ON;
+ if_data->shutdown = IF_ZEBRA_DATA_ON;
return CMD_SUCCESS;
}
@@ -3088,7 +3109,7 @@ int if_no_shutdown(struct interface *ifp)
}
if_data = ifp->info;
- if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
+ if_data->shutdown = IF_ZEBRA_DATA_OFF;
return 0;
}
@@ -3119,7 +3140,7 @@ DEFUN (no_shutdown_if,
}
if_data = ifp->info;
- if_data->shutdown = IF_ZEBRA_SHUTDOWN_OFF;
+ if_data->shutdown = IF_ZEBRA_DATA_OFF;
return CMD_SUCCESS;
}
@@ -3906,9 +3927,9 @@ int if_ip_address_install(struct interface *ifp, struct prefix *prefix,
SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
/* In case of this route need to install kernel. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
- && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
- && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
+ !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
/* Some system need to up the interface to set IP address. */
if (!if_is_up(ifp)) {
if_set_flags(ifp, IFF_UP | IFF_RUNNING);
@@ -4001,9 +4022,9 @@ static int ip_address_install(struct vty *vty, struct interface *ifp,
SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
/* In case of this route need to install kernel. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
- && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
- && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
+ !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
/* Some system need to up the interface to set IP address. */
if (!if_is_up(ifp)) {
if_set_flags(ifp, IFF_UP | IFF_RUNNING);
@@ -4264,9 +4285,9 @@ int if_ipv6_address_install(struct interface *ifp, struct prefix *prefix,
SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
/* In case of this route need to install kernel. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
- && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
- && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
+ !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
/* Some system need to up the interface to set IP address. */
if (!if_is_up(ifp)) {
if_set_flags(ifp, IFF_UP | IFF_RUNNING);
@@ -4337,9 +4358,9 @@ static int ipv6_address_install(struct vty *vty, struct interface *ifp,
SET_FLAG(ifc->conf, ZEBRA_IFC_CONFIGURED);
/* In case of this route need to install kernel. */
- if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED)
- && CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE)
- && !(if_data && if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)) {
+ if (!CHECK_FLAG(ifc->conf, ZEBRA_IFC_QUEUED) &&
+ CHECK_FLAG(ifp->status, ZEBRA_INTERFACE_ACTIVE) &&
+ !(if_data && if_data->shutdown == IF_ZEBRA_DATA_ON)) {
/* Some system need to up the interface to set IP address. */
if (!if_is_up(ifp)) {
if_set_flags(ifp, IFF_UP | IFF_RUNNING);
@@ -4524,7 +4545,7 @@ static int if_config_write(struct vty *vty)
if_vty_config_start(vty, ifp);
if (if_data) {
- if (if_data->shutdown == IF_ZEBRA_SHUTDOWN_ON)
+ if (if_data->shutdown == IF_ZEBRA_DATA_ON)
vty_out(vty, " shutdown\n");
zebra_ptm_if_write(vty, if_data);
@@ -4574,13 +4595,14 @@ static int if_config_write(struct vty *vty)
}
if (if_data) {
- if (if_data->multicast
- != IF_ZEBRA_MULTICAST_UNSPEC)
+ if (if_data->multicast != IF_ZEBRA_DATA_UNSPEC)
vty_out(vty, " %smulticast\n",
- if_data->multicast
- == IF_ZEBRA_MULTICAST_ON
+ if_data->multicast ==
+ IF_ZEBRA_DATA_ON
? ""
: "no ");
+ if (if_data->mpls == IF_ZEBRA_DATA_ON)
+ vty_out(vty, " mpls\n");
}
hook_call(zebra_if_config_wr, vty, ifp);
@@ -4617,6 +4639,7 @@ void zebra_if_init(void)
install_element(ENABLE_NODE, &show_interface_desc_vrf_all_cmd);
install_element(INTERFACE_NODE, &multicast_cmd);
install_element(INTERFACE_NODE, &no_multicast_cmd);
+ install_element(INTERFACE_NODE, &mpls_cmd);
install_element(INTERFACE_NODE, &linkdetect_cmd);
install_element(INTERFACE_NODE, &no_linkdetect_cmd);
install_element(INTERFACE_NODE, &shutdown_if_cmd);
diff --git a/zebra/interface.h b/zebra/interface.h
index f3f41b90c5..801078e83d 100644
--- a/zebra/interface.h
+++ b/zebra/interface.h
@@ -36,14 +36,10 @@
extern "C" {
#endif
-/* For interface multicast configuration. */
-#define IF_ZEBRA_MULTICAST_UNSPEC 0
-#define IF_ZEBRA_MULTICAST_ON 1
-#define IF_ZEBRA_MULTICAST_OFF 2
-
-/* For interface shutdown configuration. */
-#define IF_ZEBRA_SHUTDOWN_OFF 0
-#define IF_ZEBRA_SHUTDOWN_ON 1
+/* For interface configuration. */
+#define IF_ZEBRA_DATA_UNSPEC 0
+#define IF_ZEBRA_DATA_ON 1
+#define IF_ZEBRA_DATA_OFF 2
#define IF_VLAN_BITMAP_MAX 4096
diff --git a/zebra/kernel_netlink.c b/zebra/kernel_netlink.c
index 5c8aca9691..a8b56bb8f2 100644
--- a/zebra/kernel_netlink.c
+++ b/zebra/kernel_netlink.c
@@ -47,6 +47,7 @@
#include "zebra/rt_netlink.h"
#include "zebra/if_netlink.h"
#include "zebra/rule_netlink.h"
+#include "zebra/tc_netlink.h"
#include "zebra/netconf_netlink.h"
#include "zebra/zebra_errors.h"
@@ -114,6 +115,15 @@ static const struct message nlmsg_str[] = {{RTM_NEWROUTE, "RTM_NEWROUTE"},
{RTM_NEWTUNNEL, "RTM_NEWTUNNEL"},
{RTM_DELTUNNEL, "RTM_DELTUNNEL"},
{RTM_GETTUNNEL, "RTM_GETTUNNEL"},
+ {RTM_NEWQDISC, "RTM_NEWQDISC"},
+ {RTM_DELQDISC, "RTM_DELQDISC"},
+ {RTM_GETQDISC, "RTM_GETQDISC"},
+ {RTM_NEWTCLASS, "RTM_NEWTCLASS"},
+ {RTM_DELTCLASS, "RTM_DELTCLASS"},
+ {RTM_GETTCLASS, "RTM_GETTCLASS"},
+ {RTM_NEWTFILTER, "RTM_NEWTFILTER"},
+ {RTM_DELTFILTER, "RTM_DELTFILTER"},
+ {RTM_GETTFILTER, "RTM_GETTFILTER"},
{0}};
static const struct message rtproto_str[] = {
@@ -1023,12 +1033,18 @@ static int netlink_parse_error(const struct nlsock *nl, struct nlmsghdr *h,
return 1;
}
- /* Deal with errors that occur because of races in link handling. */
- if (is_cmd
- && ((msg_type == RTM_DELROUTE
- && (-errnum == ENODEV || -errnum == ESRCH))
- || (msg_type == RTM_NEWROUTE
- && (-errnum == ENETDOWN || -errnum == EEXIST)))) {
+ /*
+ * Deal with errors that occur because of races in link handling
+ * or types are not supported in kernel.
+ */
+ if (is_cmd &&
+ ((msg_type == RTM_DELROUTE &&
+ (-errnum == ENODEV || -errnum == ESRCH)) ||
+ (msg_type == RTM_NEWROUTE &&
+ (-errnum == ENETDOWN || -errnum == EEXIST)) ||
+ ((msg_type == RTM_NEWTUNNEL || msg_type == RTM_DELTUNNEL ||
+ msg_type == RTM_GETTUNNEL) &&
+ (-errnum == EOPNOTSUPP)))) {
if (IS_ZEBRA_DEBUG_KERNEL)
zlog_debug("%s: error: %s type=%s(%u), seq=%u, pid=%u",
nl->name, safe_strerror(-errnum),
@@ -1613,14 +1629,21 @@ static enum netlink_msg_status nl_put_msg(struct nl_batch *bth,
case DPLANE_OP_INTF_ADDR_ADD:
case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_NETCONFIG:
case DPLANE_OP_NONE:
return FRR_NETLINK_ERROR;
+ case DPLANE_OP_INTF_NETCONFIG:
+ return netlink_put_intf_netconfig(bth, ctx);
+
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
return netlink_put_intf_update_msg(bth, ctx);
+
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
+ return netlink_put_tc_update_msg(bth, ctx);
}
return FRR_NETLINK_ERROR;
diff --git a/zebra/kernel_socket.c b/zebra/kernel_socket.c
index 2741a23242..e76d8c0cc4 100644
--- a/zebra/kernel_socket.c
+++ b/zebra/kernel_socket.c
@@ -534,7 +534,7 @@ int ifm_read(struct if_msghdr *ifm)
/* paranoia: sanity check structure */
if (ifm->ifm_msglen < sizeof(struct if_msghdr)) {
flog_err(EC_ZEBRA_NETLINK_LENGTH_ERROR,
- "ifm_read: ifm->ifm_msglen %d too short",
+ "%s: ifm->ifm_msglen %d too short", __func__,
ifm->ifm_msglen);
return -1;
}
@@ -1112,14 +1112,6 @@ void rtm_read(struct rt_msghdr *rtm)
} else
return;
- /*
- * CHANGE: delete the old prefix, we have no further information
- * to specify the route really
- */
- if (rtm->rtm_type == RTM_CHANGE)
- rib_delete(afi, SAFI_UNICAST, VRF_DEFAULT, ZEBRA_ROUTE_KERNEL,
- 0, zebra_flags, &p, NULL, NULL, 0, RT_TABLE_MAIN, 0,
- 0, true);
if (rtm->rtm_type == RTM_GET || rtm->rtm_type == RTM_ADD
|| rtm->rtm_type == RTM_CHANGE)
rib_add(afi, SAFI_UNICAST, VRF_DEFAULT, proto, 0, zebra_flags,
@@ -1396,9 +1388,8 @@ static void kernel_read(struct thread *thread)
* can assume they have the whole message.
*/
if (rtm->rtm_msglen != nbytes) {
- zlog_debug(
- "kernel_read: rtm->rtm_msglen %d, nbytes %d, type %d",
- rtm->rtm_msglen, nbytes, rtm->rtm_type);
+ zlog_debug("%s: rtm->rtm_msglen %d, nbytes %d, type %d",
+ __func__, rtm->rtm_msglen, nbytes, rtm->rtm_type);
return;
}
@@ -1529,7 +1520,7 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
{
struct zebra_dplane_ctx *ctx;
struct dplane_ctx_q handled_list;
- enum zebra_dplane_result res;
+ enum zebra_dplane_result res = ZEBRA_DPLANE_REQUEST_SUCCESS;
TAILQ_INIT(&handled_list);
@@ -1603,6 +1594,12 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
res = kernel_intf_update(ctx);
break;
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
+ res = kernel_tc_update(ctx);
+ break;
+
/* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
@@ -1611,9 +1608,27 @@ void kernel_update_multi(struct dplane_ctx_q *ctx_list)
res = ZEBRA_DPLANE_REQUEST_SUCCESS;
break;
- default:
- res = ZEBRA_DPLANE_REQUEST_FAILURE;
+ case DPLANE_OP_INTF_NETCONFIG:
+ res = kernel_intf_netconf_update(ctx);
break;
+
+ case DPLANE_OP_NONE:
+ case DPLANE_OP_BR_PORT_UPDATE:
+ case DPLANE_OP_IPTABLE_ADD:
+ case DPLANE_OP_IPTABLE_DELETE:
+ case DPLANE_OP_IPSET_ADD:
+ case DPLANE_OP_IPSET_DELETE:
+ case DPLANE_OP_IPSET_ENTRY_ADD:
+ case DPLANE_OP_IPSET_ENTRY_DELETE:
+ case DPLANE_OP_NEIGH_IP_INSTALL:
+ case DPLANE_OP_NEIGH_IP_DELETE:
+ case DPLANE_OP_NEIGH_TABLE_UPDATE:
+ case DPLANE_OP_GRE_SET:
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
+ zlog_err("Unhandled dplane data for %s",
+ dplane_op2str(dplane_ctx_get_op(ctx)));
+ res = ZEBRA_DPLANE_REQUEST_FAILURE;
}
skip_one:
diff --git a/zebra/netconf_netlink.c b/zebra/netconf_netlink.c
index f9cb37a3cf..56f56bfe66 100644
--- a/zebra/netconf_netlink.c
+++ b/zebra/netconf_netlink.c
@@ -29,6 +29,7 @@
#include "linux/netconf.h"
+#include "lib/lib_errors.h"
#include "zebra/zebra_ns.h"
#include "zebra/zebra_dplane.h"
#include "zebra/kernel_netlink.h"
@@ -185,4 +186,56 @@ int netlink_request_netconf(int sockfd)
return netlink_request(nls, &req);
}
+extern struct zebra_privs_t zserv_privs;
+/*
+ * Currently netconf has no ability to set from netlink.
+ * So we've received a request to do this work in the data plane.
+ * as such we need to set the value via the /proc system
+ */
+enum netlink_msg_status netlink_put_intf_netconfig(struct nl_batch *bth,
+ struct zebra_dplane_ctx *ctx)
+{
+ const char *ifname = dplane_ctx_get_ifname(ctx);
+ enum dplane_netconf_status_e mpls_on = dplane_ctx_get_netconf_mpls(ctx);
+ char set[64];
+ char mpls_proc[PATH_MAX];
+ int fd, ret = FRR_NETLINK_ERROR;
+
+ snprintf(mpls_proc, sizeof(mpls_proc),
+ "/proc/sys/net/mpls/conf/%s/input", ifname);
+
+ if (mpls_on == DPLANE_NETCONF_STATUS_ENABLED)
+ snprintf(set, sizeof(set), "1\n");
+ else if (mpls_on == DPLANE_NETCONF_STATUS_DISABLED)
+ snprintf(set, sizeof(set), "0\n");
+ else {
+ flog_err_sys(
+ EC_LIB_DEVELOPMENT,
+ "%s: Expected interface %s to be set to ENABLED or DISABLED was %d",
+ __func__, ifname, mpls_on);
+ return ret;
+ }
+
+ frr_with_privs (&zserv_privs) {
+ fd = open(mpls_proc, O_WRONLY);
+ if (fd < 0) {
+ flog_err_sys(
+ EC_LIB_SOCKET,
+ "%s: Unable to open %s for writing: %s(%d)",
+ __func__, mpls_proc, safe_strerror(errno),
+ errno);
+ return ret;
+ }
+ if (write(fd, set, 2) == 2)
+ ret = FRR_NETLINK_SUCCESS;
+ else
+ flog_err_sys(EC_LIB_SOCKET,
+ "%s: Unsuccessful write to %s: %s(%d)",
+ __func__, mpls_proc, safe_strerror(errno),
+ errno);
+ close(fd);
+ }
+ return ret;
+}
+
#endif /* HAVE_NETLINK */
diff --git a/zebra/netconf_netlink.h b/zebra/netconf_netlink.h
index 3f2e7af768..1b3450bcb5 100644
--- a/zebra/netconf_netlink.h
+++ b/zebra/netconf_netlink.h
@@ -38,6 +38,10 @@ extern int netlink_netconf_change(struct nlmsghdr *h, ns_id_t ns_id,
/* Request info from the host OS. */
int netlink_request_netconf(int sockfd);
+struct nl_batch;
+
+extern enum netlink_msg_status
+netlink_put_intf_netconfig(struct nl_batch *bth, struct zebra_dplane_ctx *ctx);
#ifdef __cplusplus
}
diff --git a/zebra/redistribute.c b/zebra/redistribute.c
index 1a28f8ceec..4a8fe938ed 100644
--- a/zebra/redistribute.c
+++ b/zebra/redistribute.c
@@ -685,15 +685,10 @@ int zebra_add_import_table_entry(struct zebra_vrf *zvrf, struct route_node *rn,
zebra_del_import_table_entry(zvrf, rn, same);
}
- newre = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
- newre->type = ZEBRA_ROUTE_TABLE;
- newre->distance = zebra_import_table_distance[afi][re->table];
- newre->flags = re->flags;
- newre->metric = re->metric;
- newre->mtu = re->mtu;
- newre->table = zvrf->table_id;
- newre->uptime = monotime(NULL);
- newre->instance = re->table;
+ newre = zebra_rib_route_entry_new(
+ 0, ZEBRA_ROUTE_TABLE, re->table, re->flags, re->nhe_id,
+ zvrf->table_id, re->metric, re->mtu,
+ zebra_import_table_distance[afi][re->table], re->tag);
ng = nexthop_group_new();
copy_nexthops(&ng->nexthop, re->nhe->nhg.nexthop, NULL);
diff --git a/zebra/rib.h b/zebra/rib.h
index 60092c9632..99f52bcd4e 100644
--- a/zebra/rib.h
+++ b/zebra/rib.h
@@ -178,15 +178,17 @@ struct route_entry {
/* meta-queue structure:
* sub-queue 0: nexthop group objects
* sub-queue 1: EVPN/VxLAN objects
- * sub-queue 2: connected
- * sub-queue 3: kernel
- * sub-queue 4: static
- * sub-queue 5: RIP, RIPng, OSPF, OSPF6, IS-IS, EIGRP, NHRP
- * sub-queue 6: iBGP, eBGP
- * sub-queue 7: any other origin (if any) typically those that
+ * sub-queue 2: Early Route Processing
+ * sub-queue 3: Early Label Processing
+ * sub-queue 4: connected
+ * sub-queue 5: kernel
+ * sub-queue 6: static
+ * sub-queue 7: RIP, RIPng, OSPF, OSPF6, IS-IS, EIGRP, NHRP
+ * sub-queue 8: iBGP, eBGP
+ * sub-queue 9: any other origin (if any) typically those that
* don't generate routes
*/
-#define MQ_SIZE 8
+#define MQ_SIZE 10
struct meta_queue {
struct list *subq[MQ_SIZE];
uint32_t size; /* sum of lengths of all subqueues */
@@ -342,6 +344,12 @@ extern void _route_entry_dump(const char *func, union prefixconstptr pp,
union prefixconstptr src_pp,
const struct route_entry *re);
+struct route_entry *
+zebra_rib_route_entry_new(vrf_id_t vrf_id, int type, uint8_t instance,
+ uint32_t flags, uint32_t nhe_id, uint32_t table_id,
+ uint32_t metric, uint32_t mtu, uint8_t distance,
+ route_tag_t tag);
+
#define ZEBRA_RIB_LOOKUP_ERROR -1
#define ZEBRA_RIB_FOUND_EXACT 0
#define ZEBRA_RIB_FOUND_NOGATE 1
@@ -454,9 +462,7 @@ int zebra_rib_queue_evpn_rem_vtep_add(vrf_id_t vrf_id, vni_t vni,
int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
struct in_addr vtep_ip);
-extern void meta_queue_free(struct meta_queue *mq);
-extern void rib_meta_queue_free_vrf(struct meta_queue *mq,
- struct zebra_vrf *zvrf);
+extern void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf);
extern int zebra_rib_labeled_unicast(struct route_entry *re);
extern struct route_table *rib_table_ipv6;
@@ -579,6 +585,7 @@ static inline void rib_tables_iter_cleanup(rib_tables_iter_t *iter)
DECLARE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
+DECLARE_HOOK(rib_shutdown, (struct route_node * rn), (rn));
/*
* Access installed/fib nexthops, which may be a subset of the
diff --git a/zebra/rt.h b/zebra/rt.h
index 4952c3eb1a..d8a22d2cfc 100644
--- a/zebra/rt.h
+++ b/zebra/rt.h
@@ -69,6 +69,10 @@ kernel_pbr_rule_update(struct zebra_dplane_ctx *ctx);
extern enum zebra_dplane_result
kernel_intf_update(struct zebra_dplane_ctx *ctx);
+extern enum zebra_dplane_result
+kernel_intf_netconf_update(struct zebra_dplane_ctx *ctx);
+extern enum zebra_dplane_result kernel_tc_update(struct zebra_dplane_ctx *ctx);
+
#endif /* !HAVE_NETLINK */
extern int kernel_neigh_update(int cmd, int ifindex, void *addr, char *lla,
diff --git a/zebra/rt_netlink.c b/zebra/rt_netlink.c
index 0eab1fa850..e883033d59 100644
--- a/zebra/rt_netlink.c
+++ b/zebra/rt_netlink.c
@@ -937,44 +937,38 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
afi = AFI_IP6;
if (h->nlmsg_type == RTM_NEWROUTE) {
+ struct route_entry *re;
+ struct nexthop_group *ng = NULL;
+
+ re = zebra_rib_route_entry_new(vrf_id, proto, 0, flags, nhe_id,
+ table, metric, mtu, distance,
+ tag);
+ if (!nhe_id)
+ ng = nexthop_group_new();
if (!tb[RTA_MULTIPATH]) {
- struct nexthop nh = {0};
+ struct nexthop *nexthop, nh;
if (!nhe_id) {
nh = parse_nexthop_unicast(
ns_id, rtm, tb, bh_type, index, prefsrc,
gate, afi, vrf_id);
+
+ nexthop = nexthop_new();
+ *nexthop = nh;
+ nexthop_group_add_sorted(ng, nexthop);
}
- rib_add(afi, SAFI_UNICAST, vrf_id, proto, 0, flags, &p,
- &src_p, &nh, nhe_id, table, metric, mtu,
- distance, tag, startup);
} else {
/* This is a multipath route */
- struct route_entry *re;
- struct nexthop_group *ng = NULL;
struct rtnexthop *rtnh =
(struct rtnexthop *)RTA_DATA(tb[RTA_MULTIPATH]);
- re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
- re->type = proto;
- re->distance = distance;
- re->flags = flags;
- re->metric = metric;
- re->mtu = mtu;
- re->vrf_id = vrf_id;
- re->table = table;
- re->uptime = monotime(NULL);
- re->tag = tag;
- re->nhe_id = nhe_id;
-
if (!nhe_id) {
uint8_t nhop_num;
/* Use temporary list of nexthops; parse
* message payload's nexthops.
*/
- ng = nexthop_group_new();
nhop_num =
parse_multipath_nexthops_unicast(
ns_id, ng, rtm, rtnh, tb,
@@ -989,23 +983,22 @@ static int netlink_route_change_read_unicast(struct nlmsghdr *h, ns_id_t ns_id,
ng = NULL;
}
}
-
- if (nhe_id || ng)
- rib_add_multipath(afi, SAFI_UNICAST, &p,
- &src_p, re, ng, startup);
- else {
- /*
- * I really don't see how this is possible
- * but since we are testing for it let's
- * let the end user know why the route
- * that was just received was swallowed
- * up and forgotten
- */
- zlog_err(
- "%s: %pFX multipath RTM_NEWROUTE has a invalid nexthop group from the kernel",
- __func__, &p);
- XFREE(MTYPE_RE, re);
- }
+ }
+ if (nhe_id || ng)
+ rib_add_multipath(afi, SAFI_UNICAST, &p, &src_p, re, ng,
+ startup);
+ else {
+ /*
+ * I really don't see how this is possible
+ * but since we are testing for it let's
+ * let the end user know why the route
+ * that was just received was swallowed
+ * up and forgotten
+ */
+ zlog_err(
+ "%s: %pFX multipath RTM_NEWROUTE has a invalid nexthop group from the kernel",
+ __func__, &p);
+ XFREE(MTYPE_RE, re);
}
} else {
if (nhe_id) {
diff --git a/zebra/rtadv.c b/zebra/rtadv.c
index bf959980be..127888d655 100644
--- a/zebra/rtadv.c
+++ b/zebra/rtadv.c
@@ -227,8 +227,7 @@ static void rtadv_send_packet(int sock, struct interface *ifp,
adata = calloc(1, CMSG_SPACE(sizeof(struct in6_pktinfo)));
if (adata == NULL) {
- zlog_debug(
- "rtadv_send_packet: can't malloc control data");
+ zlog_debug("%s: can't malloc control data", __func__);
exit(-1);
}
}
@@ -665,8 +664,9 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
zif->rtadv.lastadvcurhoplimit.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvCurHopLimit doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvCurHopLimit (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvCurHopLimit,
+ addr_str, radvert->nd_ra_curhoplimit);
monotime(&zif->rtadv.lastadvcurhoplimit);
}
@@ -677,8 +677,11 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
zif->rtadv.lastadvmanagedflag.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvManagedFlag doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvManagedFlag (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvManagedFlag,
+ addr_str,
+ !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
+ ND_RA_FLAG_MANAGED));
monotime(&zif->rtadv.lastadvmanagedflag);
}
@@ -689,8 +692,11 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
zif->rtadv.lastadvotherconfigflag.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvOtherConfigFlag doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvOtherConfigFlag (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvOtherConfigFlag,
+ addr_str,
+ !!CHECK_FLAG(radvert->nd_ra_flags_reserved,
+ ND_RA_FLAG_OTHER));
monotime(&zif->rtadv.lastadvotherconfigflag);
}
@@ -701,20 +707,23 @@ static void rtadv_process_advert(uint8_t *msg, unsigned int len,
zif->rtadv.lastadvreachabletime.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvReachableTime doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvReachableTime (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvReachableTime,
+ addr_str, ntohl(radvert->nd_ra_reachable));
monotime(&zif->rtadv.lastadvreachabletime);
}
- if ((ntohl(radvert->nd_ra_retransmit) !=
+ if ((radvert->nd_ra_retransmit && zif->rtadv.AdvRetransTimer) &&
+ (ntohl(radvert->nd_ra_retransmit) !=
(unsigned int)zif->rtadv.AdvRetransTimer) &&
(monotime_since(&zif->rtadv.lastadvretranstimer, NULL) >
SIXHOUR2USEC ||
zif->rtadv.lastadvretranstimer.tv_sec == 0)) {
flog_warn(
EC_ZEBRA_RA_PARAM_MISMATCH,
- "%s(%u): Rx RA - our AdvRetransTimer doesn't agree with %s",
- ifp->name, ifp->ifindex, addr_str);
+ "%s(%u): Rx RA - our AdvRetransTimer (%u) doesn't agree with %s (%u)",
+ ifp->name, ifp->ifindex, zif->rtadv.AdvRetransTimer,
+ addr_str, ntohl(radvert->nd_ra_retransmit));
monotime(&zif->rtadv.lastadvretranstimer);
}
diff --git a/zebra/subdir.am b/zebra/subdir.am
index a926c14adf..298b71598c 100644
--- a/zebra/subdir.am
+++ b/zebra/subdir.am
@@ -82,6 +82,8 @@ zebra_zebra_SOURCES = \
zebra/rule_netlink.c \
zebra/rule_socket.c \
zebra/table_manager.c \
+ zebra/tc_netlink.c \
+ zebra/tc_socket.c \
zebra/zapi_msg.c \
zebra/zebra_dplane.c \
zebra/zebra_errors.c \
@@ -163,6 +165,7 @@ noinst_HEADERS += \
zebra/rtadv.h \
zebra/rule_netlink.h \
zebra/table_manager.h \
+ zebra/tc_netlink.h \
zebra/zapi_msg.h \
zebra/zebra_dplane.h \
zebra/zebra_errors.h \
diff --git a/zebra/tc_netlink.c b/zebra/tc_netlink.c
new file mode 100644
index 0000000000..4fb0241d1d
--- /dev/null
+++ b/zebra/tc_netlink.c
@@ -0,0 +1,468 @@
+/*
+ * Zebra Traffic Control (TC) interaction with the kernel using netlink.
+ *
+ * Copyright (C) 2022 Shichu Yang
+ *
+ * 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 FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#ifdef HAVE_NETLINK
+
+#include <linux/if_ether.h>
+#include <sys/socket.h>
+
+#include "if.h"
+#include "prefix.h"
+#include "vrf.h"
+
+#include <linux/fib_rules.h>
+#include <linux/pkt_cls.h>
+#include <linux/pkt_sched.h>
+#include "zebra/zserv.h"
+#include "zebra/zebra_ns.h"
+#include "zebra/zebra_vrf.h"
+#include "zebra/rt.h"
+#include "zebra/interface.h"
+#include "zebra/debug.h"
+#include "zebra/rtadv.h"
+#include "zebra/kernel_netlink.h"
+#include "zebra/tc_netlink.h"
+#include "zebra/zebra_errors.h"
+#include "zebra/zebra_dplane.h"
+#include "zebra/zebra_trace.h"
+
+/* TODO: move these bitflags to zebra_tc.h */
+#define TC_FILTER_SRC_IP (1 << 0)
+#define TC_FILTER_DST_IP (1 << 1)
+#define TC_FILTER_IP_PROTOCOL (1 << 9)
+
+#define TC_FREQ_DEFAULT (100)
+
+#define TC_MAJOR_BASE (0x1000u)
+#define TC_MINOR_NOCLASS (0xffffu)
+
+#define TC_FILTER_MASK (0x8000u)
+
+#define TIME_UNITS_PER_SEC (1000000)
+#define xmittime(r, s) (TIME_UNITS_PER_SEC * ((double)(s) / (double)(r)))
+
+static uint32_t tc_get_freq(void)
+{
+ int freq = 0;
+ FILE *fp = fopen("/proc/net/psched", "r");
+
+ if (fp) {
+ uint32_t nom, denom;
+
+ if (fscanf(fp, "%*08x%*08x%08x%08x", &nom, &denom) == 2) {
+ if (nom == 1000000)
+ freq = denom;
+ }
+ fclose(fp);
+ }
+
+ return freq == 0 ? TC_FREQ_DEFAULT : freq;
+}
+
+static inline uint32_t tc_make_handle(uint16_t major, uint16_t minor)
+{
+ return (major) << 16 | (minor);
+}
+
+static inline uint32_t tc_get_handle(struct zebra_dplane_ctx *ctx,
+ uint16_t minor)
+{
+ uint16_t major = TC_MAJOR_BASE + (uint16_t)dplane_ctx_get_ifindex(ctx);
+
+ return tc_make_handle(major, minor);
+}
+
+static void tc_calc_rate_table(struct tc_ratespec *ratespec, uint32_t *table,
+ uint32_t mtu)
+{
+ if (mtu == 0)
+ mtu = 2047;
+
+ int cell_log = -1;
+
+ if (cell_log < 0) {
+ cell_log = 0;
+ while ((mtu >> cell_log) > 255)
+ cell_log++;
+ }
+
+ for (int i = 0; i < 256; i++)
+ table[i] = xmittime(ratespec->rate, (i + 1) << cell_log);
+
+ ratespec->cell_align = -1;
+ ratespec->cell_log = cell_log;
+ ratespec->linklayer = TC_LINKLAYER_ETHERNET;
+}
+
+static int tc_flower_get_inet_prefix(const struct prefix *prefix,
+ struct inet_prefix *addr)
+{
+ addr->family = prefix->family;
+
+ if (addr->family == AF_INET) {
+ addr->bytelen = 4;
+ addr->bitlen = prefix->prefixlen;
+ addr->flags = 0;
+ addr->flags |= PREFIXLEN_SPECIFIED;
+ addr->flags |= ADDRTYPE_INET;
+ memcpy(addr->data, prefix->u.val32, sizeof(prefix->u.val32));
+ } else if (addr->family == AF_INET6) {
+ addr->bytelen = 16;
+ addr->bitlen = prefix->prefixlen;
+ addr->flags = 0;
+ addr->flags |= PREFIXLEN_SPECIFIED;
+ addr->flags |= ADDRTYPE_INET;
+ memcpy(addr->data, prefix->u.val, sizeof(prefix->u.val));
+ } else {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int tc_flower_get_inet_mask(const struct prefix *prefix,
+ struct inet_prefix *addr)
+{
+ addr->family = prefix->family;
+
+ if (addr->family == AF_INET) {
+ addr->bytelen = 4;
+ addr->bitlen = prefix->prefixlen;
+ addr->flags = 0;
+ addr->flags |= PREFIXLEN_SPECIFIED;
+ addr->flags |= ADDRTYPE_INET;
+ } else if (addr->family == AF_INET6) {
+ addr->bytelen = 16;
+ addr->bitlen = prefix->prefixlen;
+ addr->flags = 0;
+ addr->flags |= PREFIXLEN_SPECIFIED;
+ addr->flags |= ADDRTYPE_INET;
+ } else {
+ return -1;
+ }
+
+ memset(addr->data, 0xff, addr->bytelen);
+
+ int rest = prefix->prefixlen;
+
+ for (int i = 0; i < addr->bytelen / 4; i++) {
+ if (!rest) {
+ addr->data[i] = 0;
+ } else if (rest / 32 >= 1) {
+ rest -= 32;
+ } else {
+ addr->data[i] <<= 32 - rest;
+ addr->data[i] = htonl(addr->data[i]);
+ rest = 0;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * Traffic control queue discipline encoding (only "htb" supported)
+ */
+static ssize_t netlink_qdisc_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
+ void *data, size_t datalen)
+{
+ struct nlsock *nl;
+
+ const char *kind = "htb";
+
+ struct tc_htb_glob htb_glob = {
+ .rate2quantum = 10, .version = 3, .defcls = TC_MINOR_NOCLASS};
+
+ struct rtattr *nest;
+
+ struct {
+ struct nlmsghdr n;
+ struct tcmsg t;
+ char buf[0];
+ } *req = (void *)data;
+
+ if (datalen < sizeof(*req))
+ return 0;
+
+ nl = kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
+
+ memset(req, 0, sizeof(*req));
+
+ req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
+ req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+
+ req->n.nlmsg_flags |= NLM_F_REPLACE;
+
+ req->n.nlmsg_type = cmd;
+
+ req->n.nlmsg_pid = nl->snl.nl_pid;
+
+ req->t.tcm_family = AF_UNSPEC;
+ req->t.tcm_ifindex = dplane_ctx_get_ifindex(ctx);
+ req->t.tcm_handle = tc_get_handle(ctx, 0);
+ req->t.tcm_parent = TC_H_ROOT;
+
+ nl_attr_put(&req->n, datalen, TCA_KIND, kind, strlen(kind) + 1);
+
+ nest = nl_attr_nest(&req->n, datalen, TCA_OPTIONS);
+
+ nl_attr_put(&req->n, datalen, TCA_HTB_INIT, &htb_glob,
+ sizeof(htb_glob));
+ nl_attr_nest_end(&req->n, nest);
+
+ return NLMSG_ALIGN(req->n.nlmsg_len);
+}
+
+/*
+ * Traffic control class encoding
+ */
+static ssize_t netlink_tclass_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
+ void *data, size_t datalen)
+{
+ struct nlsock *nl;
+ struct tc_htb_opt htb_opt = {};
+
+ uint64_t rate, ceil;
+ uint64_t buffer, cbuffer;
+
+ /* TODO: fetch mtu from interface */
+ uint32_t mtu = 0;
+
+ uint32_t rtab[256];
+ uint32_t ctab[256];
+
+ struct rtattr *nest;
+
+ struct {
+ struct nlmsghdr n;
+ struct tcmsg t;
+ char buf[0];
+ } *req = (void *)data;
+
+ if (datalen < sizeof(*req))
+ return 0;
+
+ nl = kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
+
+ memset(req, 0, sizeof(*req));
+
+ req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
+ req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+
+ req->n.nlmsg_type = cmd;
+
+ req->n.nlmsg_pid = nl->snl.nl_pid;
+
+ req->t.tcm_family = AF_UNSPEC;
+ req->t.tcm_ifindex = dplane_ctx_get_ifindex(ctx);
+ req->t.tcm_handle = tc_get_handle(ctx, 1);
+ req->t.tcm_parent = tc_get_handle(ctx, 0);
+
+ rate = dplane_ctx_tc_get_rate(ctx);
+ ceil = dplane_ctx_tc_get_ceil(ctx);
+
+ ceil = ceil < rate ? rate : ceil;
+
+ htb_opt.rate.rate = (rate >> 32 != 0) ? ~0U : rate;
+ htb_opt.ceil.rate = (ceil >> 32 != 0) ? ~0U : ceil;
+
+ buffer = rate / tc_get_freq(), cbuffer = ceil / tc_get_freq();
+
+ htb_opt.buffer = buffer;
+ htb_opt.cbuffer = cbuffer;
+
+ tc_calc_rate_table(&htb_opt.rate, rtab, mtu);
+ tc_calc_rate_table(&htb_opt.ceil, ctab, mtu);
+
+ htb_opt.ceil.mpu = htb_opt.rate.mpu = 0;
+ htb_opt.ceil.overhead = htb_opt.rate.overhead = 0;
+
+ nest = nl_attr_nest(&req->n, datalen, TCA_OPTIONS);
+
+ if (rate >> 32 != 0) {
+ nl_attr_put(&req->n, datalen, TCA_HTB_CEIL64, &rate,
+ sizeof(rate));
+ }
+
+ if (ceil >> 32 != 0) {
+ nl_attr_put(&req->n, datalen, TCA_HTB_CEIL64, &ceil,
+ sizeof(ceil));
+ }
+
+ nl_attr_put(&req->n, datalen, TCA_HTB_PARMS, &htb_opt, sizeof(htb_opt));
+
+ nl_attr_put(&req->n, datalen, TCA_HTB_RTAB, rtab, sizeof(rtab));
+ nl_attr_put(&req->n, datalen, TCA_HTB_CTAB, ctab, sizeof(ctab));
+ nl_attr_nest_end(&req->n, nest);
+
+ return NLMSG_ALIGN(req->n.nlmsg_len);
+}
+
+/*
+ * Traffic control filter encoding (only "flower" supported)
+ */
+static ssize_t netlink_tfilter_msg_encode(int cmd, struct zebra_dplane_ctx *ctx,
+ void *data, size_t datalen)
+{
+ struct nlsock *nl;
+ struct rtattr *nest;
+
+ const char *kind = "flower";
+
+ uint16_t priority;
+ uint16_t protocol;
+ uint32_t classid;
+ uint32_t filter_bm;
+ uint32_t flags = 0;
+
+ struct inet_prefix addr;
+
+ struct {
+ struct nlmsghdr n;
+ struct tcmsg t;
+ char buf[0];
+ } *req = (void *)data;
+
+ if (datalen < sizeof(*req))
+ return 0;
+
+ nl = kernel_netlink_nlsock_lookup(dplane_ctx_get_ns_sock(ctx));
+
+ memset(req, 0, sizeof(*req));
+
+ req->n.nlmsg_len = NLMSG_LENGTH(sizeof(struct tcmsg));
+ req->n.nlmsg_flags = NLM_F_CREATE | NLM_F_REQUEST;
+
+ req->n.nlmsg_flags |= NLM_F_EXCL;
+
+ req->n.nlmsg_type = cmd;
+
+ req->n.nlmsg_pid = nl->snl.nl_pid;
+
+ req->t.tcm_family = AF_UNSPEC;
+ req->t.tcm_ifindex = dplane_ctx_get_ifindex(ctx);
+
+ /* TODO: priority and layer-3 protocol support */
+ priority = 0;
+ protocol = htons(ETH_P_IP);
+ classid = tc_get_handle(ctx, 1);
+ filter_bm = dplane_ctx_tc_get_filter_bm(ctx);
+
+ req->t.tcm_info = tc_make_handle(priority, protocol);
+
+ req->t.tcm_handle = 1;
+ req->t.tcm_parent = tc_get_handle(ctx, 0);
+
+ nl_attr_put(&req->n, datalen, TCA_KIND, kind, strlen(kind) + 1);
+ nest = nl_attr_nest(&req->n, datalen, TCA_OPTIONS);
+
+ nl_attr_put(&req->n, datalen, TCA_FLOWER_CLASSID, &classid,
+ sizeof(classid));
+
+ if (filter_bm & TC_FILTER_SRC_IP) {
+ const struct prefix *src_p = dplane_ctx_tc_get_src_ip(ctx);
+
+ if (tc_flower_get_inet_prefix(src_p, &addr) != 0)
+ return 0;
+
+ nl_attr_put(&req->n, datalen,
+ (addr.family == AF_INET) ? TCA_FLOWER_KEY_IPV4_SRC
+ : TCA_FLOWER_KEY_IPV6_SRC,
+ addr.data, addr.bytelen);
+
+ if (tc_flower_get_inet_mask(src_p, &addr) != 0)
+ return 0;
+
+ nl_attr_put(&req->n, datalen,
+ (addr.family == AF_INET)
+ ? TCA_FLOWER_KEY_IPV4_SRC_MASK
+ : TCA_FLOWER_KEY_IPV6_SRC_MASK,
+ addr.data, addr.bytelen);
+ }
+
+ if (filter_bm & TC_FILTER_DST_IP) {
+ const struct prefix *dst_p = dplane_ctx_tc_get_dst_ip(ctx);
+
+ if (tc_flower_get_inet_prefix(dst_p, &addr) != 0)
+ return 0;
+
+ nl_attr_put(&req->n, datalen,
+ (addr.family == AF_INET) ? TCA_FLOWER_KEY_IPV4_DST
+ : TCA_FLOWER_KEY_IPV6_DST,
+ addr.data, addr.bytelen);
+
+ if (tc_flower_get_inet_mask(dst_p, &addr) != 0)
+ return 0;
+
+ nl_attr_put(&req->n, datalen,
+ (addr.family == AF_INET)
+ ? TCA_FLOWER_KEY_IPV4_DST_MASK
+ : TCA_FLOWER_KEY_IPV6_DST_MASK,
+ addr.data, addr.bytelen);
+ }
+
+ if (filter_bm & TC_FILTER_IP_PROTOCOL) {
+ nl_attr_put8(&req->n, datalen, TCA_FLOWER_KEY_IP_PROTO,
+ dplane_ctx_tc_get_ip_proto(ctx));
+ }
+
+ nl_attr_put32(&req->n, datalen, TCA_FLOWER_FLAGS, flags);
+
+ nl_attr_put16(&req->n, datalen, TCA_FLOWER_KEY_ETH_TYPE, protocol);
+ nl_attr_nest_end(&req->n, nest);
+
+ return NLMSG_ALIGN(req->n.nlmsg_len);
+}
+
+static ssize_t netlink_newqdisc_msg_encoder(struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen)
+{
+ return netlink_qdisc_msg_encode(RTM_NEWQDISC, ctx, buf, buflen);
+}
+
+static ssize_t netlink_newtclass_msg_encoder(struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen)
+{
+ return netlink_tclass_msg_encode(RTM_NEWTCLASS, ctx, buf, buflen);
+}
+
+static ssize_t netlink_newtfilter_msg_encoder(struct zebra_dplane_ctx *ctx,
+ void *buf, size_t buflen)
+{
+ return netlink_tfilter_msg_encode(RTM_NEWTFILTER, ctx, buf, buflen);
+}
+
+enum netlink_msg_status netlink_put_tc_update_msg(struct nl_batch *bth,
+ struct zebra_dplane_ctx *ctx)
+{
+ /* TODO: error handling and other actions (delete, replace, ...) */
+
+ netlink_batch_add_msg(bth, ctx, netlink_newqdisc_msg_encoder, false);
+ netlink_batch_add_msg(bth, ctx, netlink_newtclass_msg_encoder, false);
+ return netlink_batch_add_msg(bth, ctx, netlink_newtfilter_msg_encoder,
+ false);
+}
+
+#endif /* HAVE_NETLINK */
diff --git a/zebra/tc_netlink.h b/zebra/tc_netlink.h
new file mode 100644
index 0000000000..2190bca4f9
--- /dev/null
+++ b/zebra/tc_netlink.h
@@ -0,0 +1,62 @@
+/*
+ * Zebra Traffic Control (TC) interaction with the kernel using netlink.
+ *
+ * Copyright (C) 2022 Shichu Yang
+ *
+ * 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 FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#ifndef _ZEBRA_TC_NETLINK_H
+#define _ZEBRA_TC_NETLINK_H
+
+#ifdef HAVE_NETLINK
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Represent a prefixed address in flower filter */
+
+struct inet_prefix {
+ uint16_t flags;
+ uint16_t bytelen;
+ uint16_t bitlen;
+ uint16_t family;
+ uint32_t data[64];
+};
+
+enum {
+ PREFIXLEN_SPECIFIED = (1 << 0),
+ ADDRTYPE_INET = (1 << 1),
+ ADDRTYPE_UNSPEC = (1 << 2),
+ ADDRTYPE_MULTI = (1 << 3),
+
+ ADDRTYPE_INET_UNSPEC = ADDRTYPE_INET | ADDRTYPE_UNSPEC,
+ ADDRTYPE_INET_MULTI = ADDRTYPE_INET | ADDRTYPE_MULTI
+};
+
+extern enum netlink_msg_status
+netlink_put_tc_update_msg(struct nl_batch *bth, struct zebra_dplane_ctx *ctx);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* HAVE_NETLINK */
+
+#endif /* _ZEBRA_TC_NETLINK_H */
diff --git a/zebra/tc_socket.c b/zebra/tc_socket.c
new file mode 100644
index 0000000000..0bf9e487b0
--- /dev/null
+++ b/zebra/tc_socket.c
@@ -0,0 +1,41 @@
+/*
+ * Zebra Traffic Control (TC) interaction with the kernel using socket.
+ *
+ * Copyright (C) 2022 Shichu Yang
+ *
+ * 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 FRR; see the file COPYING. If not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ */
+
+#include <zebra.h>
+
+#ifndef HAVE_NETLINK
+
+#include "lib_errors.h"
+
+#include "zebra/rt.h"
+#include "zebra/zebra_dplane.h"
+#include "zebra/zebra_errors.h"
+
+enum zebra_dplane_result kernel_tc_update(struct zebra_dplane_ctx *ctx)
+{
+ flog_err(EC_LIB_UNAVAILABLE, "%s not Implemented for this platform",
+ __func__);
+ return ZEBRA_DPLANE_REQUEST_FAILURE;
+}
+
+#endif /* !HAVE_NETLINK */
diff --git a/zebra/zapi_msg.c b/zebra/zapi_msg.c
index 9895943016..761ba789b8 100644
--- a/zebra/zapi_msg.c
+++ b/zebra/zapi_msg.c
@@ -2034,7 +2034,7 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
struct nhg_backup_info *bnhg = NULL;
int ret;
vrf_id_t vrf_id;
- struct nhg_hash_entry nhe;
+ struct nhg_hash_entry nhe, *n = NULL;
s = msg;
if (zapi_route_decode(s, &api) < 0) {
@@ -2052,17 +2052,10 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
(int)api.message, api.flags);
/* Allocate new route. */
- re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
- re->type = api.type;
- re->instance = api.instance;
- re->flags = api.flags;
- re->uptime = monotime(NULL);
- re->vrf_id = vrf_id;
-
- if (api.tableid)
- re->table = api.tableid;
- else
- re->table = zvrf->table_id;
+ re = zebra_rib_route_entry_new(
+ vrf_id, api.type, api.instance, api.flags, api.nhgid,
+ api.tableid ? api.tableid : zvrf->table_id, api.metric, api.mtu,
+ api.distance, api.tag);
if (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NHG)
&& (!CHECK_FLAG(api.message, ZAPI_MESSAGE_NEXTHOP)
@@ -2087,9 +2080,6 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
&api.prefix);
}
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_NHG))
- re->nhe_id = api.nhgid;
-
if (!re->nhe_id
&& (!zapi_read_nexthops(client, &api.prefix, api.nexthops,
api.flags, api.message, api.nexthop_num,
@@ -2105,15 +2095,6 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
return;
}
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_DISTANCE))
- re->distance = api.distance;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_METRIC))
- re->metric = api.metric;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_TAG))
- re->tag = api.tag;
- if (CHECK_FLAG(api.message, ZAPI_MESSAGE_MTU))
- re->mtu = api.mtu;
-
if (CHECK_FLAG(api.message, ZAPI_MESSAGE_OPAQUE)) {
re->opaque =
XMALLOC(MTYPE_RE_OPAQUE,
@@ -2161,9 +2142,10 @@ static void zread_route_add(ZAPI_HANDLER_ARGS)
zebra_nhe_init(&nhe, afi, ng->nexthop);
nhe.nhg.nexthop = ng->nexthop;
nhe.backup_info = bnhg;
+ n = zebra_nhe_copy(&nhe, 0);
}
- ret = rib_add_multipath_nhe(afi, api.safi, &api.prefix, src_p,
- re, &nhe, false);
+ ret = rib_add_multipath_nhe(afi, api.safi, &api.prefix, src_p, re, n,
+ false);
/*
* rib_add_multipath_nhe only fails in a couple spots
@@ -2492,7 +2474,6 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_labels zl;
- int ret;
/* Get input stream. */
s = msg;
@@ -2510,12 +2491,7 @@ static void zread_mpls_labels_add(ZAPI_HANDLER_ARGS)
if (zapi_labels_validate(&zl) < 0)
return;
- ret = mpls_zapi_labels_process(true, zvrf, &zl);
- if (ret < 0) {
- if (IS_ZEBRA_DEBUG_RECV)
- zlog_debug("%s: Error processing zapi request",
- __func__);
- }
+ mpls_zapi_labels_process(true, zvrf, &zl);
}
/*
@@ -2532,7 +2508,6 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
{
struct stream *s;
struct zapi_labels zl;
- int ret;
/* Get input stream. */
s = msg;
@@ -2547,12 +2522,7 @@ static void zread_mpls_labels_delete(ZAPI_HANDLER_ARGS)
return;
if (zl.nexthop_num > 0) {
- ret = mpls_zapi_labels_process(false /*delete*/, zvrf, &zl);
- if (ret < 0) {
- if (IS_ZEBRA_DEBUG_RECV)
- zlog_debug("%s: Error processing zapi request",
- __func__);
- }
+ mpls_zapi_labels_process(false /*delete*/, zvrf, &zl);
} else {
mpls_lsp_uninstall_all_vrf(zvrf, zl.type, zl.local_label);
diff --git a/zebra/zebra_dplane.c b/zebra/zebra_dplane.c
index a4330a3200..6a691a222f 100644
--- a/zebra/zebra_dplane.c
+++ b/zebra/zebra_dplane.c
@@ -314,6 +314,25 @@ struct dplane_netconf_info {
};
/*
+ * Traffic control contexts for the dplane
+ */
+struct dplane_tc_info {
+ /* Rate spec (unit: Bytes/s) */
+ uint64_t rate;
+ uint64_t ceil;
+
+ /* TODO: custom burst */
+
+ /* Filter components for "tfilter" */
+ uint32_t filter_bm;
+ struct prefix src_ip;
+ struct prefix dst_ip;
+ uint8_t ip_proto;
+
+ /* TODO: more filter components */
+};
+
+/*
* The context block used to exchange info about route updates across
* the boundary between the zebra main context (and pthread) and the
* dataplane layer (and pthread).
@@ -362,6 +381,7 @@ struct zebra_dplane_ctx {
struct dplane_mac_info macinfo;
struct dplane_neigh_info neigh;
struct dplane_rule_info rule;
+ struct dplane_tc_info tc;
struct zebra_pbr_iptable iptable;
struct zebra_pbr_ipset ipset;
struct {
@@ -509,6 +529,8 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_intf_addrs_in;
_Atomic uint32_t dg_intf_addr_errors;
+ _Atomic uint32_t dg_intf_changes;
+ _Atomic uint32_t dg_intf_changes_errors;
_Atomic uint32_t dg_macs_in;
_Atomic uint32_t dg_mac_errors;
@@ -538,6 +560,9 @@ static struct zebra_dplane_globals {
_Atomic uint32_t dg_intfs_in;
_Atomic uint32_t dg_intf_errors;
+ _Atomic uint32_t dg_tcs_in;
+ _Atomic uint32_t dg_tcs_errors;
+
/* Dataplane pthread */
struct frr_pthread *dg_pthread;
@@ -775,6 +800,9 @@ static void dplane_ctx_free_internal(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
break;
case DPLANE_OP_IPSET_ENTRY_ADD:
@@ -1098,6 +1126,16 @@ const char *dplane_op2str(enum dplane_op_e op)
case DPLANE_OP_INTF_DELETE:
ret = "INTF_DELETE";
break;
+
+ case DPLANE_OP_TC_INSTALL:
+ ret = "TC_INSTALL";
+ break;
+ case DPLANE_OP_TC_UPDATE:
+ ret = "TC_UPDATE";
+ break;
+ case DPLANE_OP_TC_DELETE:
+ ret = "TC_DELETE";
+ break;
}
return ret;
@@ -1417,6 +1455,50 @@ uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx)
return ctx->u.rinfo.zd_old_distance;
}
+uint64_t dplane_ctx_tc_get_rate(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.tc.rate;
+}
+
+uint64_t dplane_ctx_tc_get_ceil(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.tc.ceil;
+}
+
+uint32_t dplane_ctx_tc_get_filter_bm(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.tc.filter_bm;
+}
+
+const struct prefix *
+dplane_ctx_tc_get_src_ip(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.tc.src_ip);
+}
+
+const struct prefix *
+dplane_ctx_tc_get_dst_ip(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return &(ctx->u.tc.dst_ip);
+}
+
+uint8_t dplane_ctx_tc_get_ip_proto(const struct zebra_dplane_ctx *ctx)
+{
+ DPLANE_CTX_VALID(ctx);
+
+ return ctx->u.tc.ip_proto;
+}
+
/*
* Set the nexthops associated with a context: note that processing code
* may well expect that nexthops are in canonical (sorted) order, so we
@@ -2689,6 +2771,25 @@ done:
return ret;
}
+int dplane_ctx_tc_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op)
+{
+ int ret = EINVAL;
+
+ struct zebra_ns *zns = NULL;
+
+ ctx->zd_op = op;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+
+ /* TODO: init traffic control qdisc */
+ zns = zebra_ns_lookup(NS_DEFAULT);
+
+ dplane_ctx_ns_init(ctx, zns, true);
+
+ ret = AOK;
+
+ return ret;
+}
+
/**
* dplane_ctx_nexthop_init() - Initialize a context block for a nexthop update
*
@@ -3408,6 +3509,47 @@ dplane_route_update_internal(struct route_node *rn,
return result;
}
+static enum zebra_dplane_result dplane_tc_update_internal(enum dplane_op_e op)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ int ret;
+ struct zebra_dplane_ctx *ctx = NULL;
+
+ /* Obtain context block */
+ ctx = dplane_ctx_alloc();
+
+ if (!ctx) {
+ ret = ENOMEM;
+ goto done;
+ }
+
+ /* Init context with info from zebra data structs */
+ ret = dplane_ctx_tc_init(ctx, op);
+
+ if (ret == AOK)
+ ret = dplane_update_enqueue(ctx);
+
+done:
+ /* Update counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_tcs_in, 1,
+ memory_order_relaxed);
+ if (ret == AOK) {
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ } else {
+ atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors, 1,
+ memory_order_relaxed);
+ if (ctx)
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
+enum zebra_dplane_result dplane_tc_update(void)
+{
+ return dplane_tc_update_internal(DPLANE_OP_TC_UPDATE);
+}
+
/**
* dplane_nexthop_update_internal() - Helper for enqueuing nexthop changes
*
@@ -3420,7 +3562,7 @@ static enum zebra_dplane_result
dplane_nexthop_update_internal(struct nhg_hash_entry *nhe, enum dplane_op_e op)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
- int ret = EINVAL;
+ int ret;
struct zebra_dplane_ctx *ctx = NULL;
/* Obtain context block */
@@ -3698,7 +3840,7 @@ dplane_lsp_notif_update(struct zebra_lsp *lsp, enum dplane_op_e op,
struct zebra_dplane_ctx *notif_ctx)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
- int ret = EINVAL;
+ int ret;
struct zebra_dplane_ctx *ctx = NULL;
struct nhlfe_list_head *head;
struct zebra_nhlfe *nhlfe, *new_nhlfe;
@@ -3913,6 +4055,47 @@ dplane_br_port_update(const struct interface *ifp, bool non_df,
return result;
}
+enum zebra_dplane_result
+dplane_intf_mpls_modify_state(const struct interface *ifp, bool set)
+{
+ enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
+ struct zebra_dplane_ctx *ctx;
+ struct zebra_ns *zns;
+ int ret = EINVAL;
+
+ ctx = dplane_ctx_alloc();
+ ctx->zd_op = DPLANE_OP_INTF_NETCONFIG;
+ ctx->zd_status = ZEBRA_DPLANE_REQUEST_SUCCESS;
+ ctx->zd_vrf_id = ifp->vrf->vrf_id;
+ strlcpy(ctx->zd_ifname, ifp->name, sizeof(ctx->zd_ifname));
+
+ zns = zebra_ns_lookup(ifp->vrf->vrf_id);
+ dplane_ctx_ns_init(ctx, zns, false);
+
+ ctx->zd_ifindex = ifp->ifindex;
+ if (set)
+ dplane_ctx_set_netconf_mpls(ctx, DPLANE_NETCONF_STATUS_ENABLED);
+ else
+ dplane_ctx_set_netconf_mpls(ctx,
+ DPLANE_NETCONF_STATUS_DISABLED);
+ /* Increment counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_intf_changes, 1,
+ memory_order_relaxed);
+
+ ret = dplane_update_enqueue(ctx);
+
+ if (ret == AOK)
+ result = ZEBRA_DPLANE_REQUEST_QUEUED;
+ else {
+ /* Error counter */
+ atomic_fetch_add_explicit(&zdplane_info.dg_intf_changes_errors,
+ 1, memory_order_relaxed);
+ dplane_ctx_free(&ctx);
+ }
+
+ return result;
+}
+
/*
* Enqueue interface address add for the dataplane.
*/
@@ -4032,7 +4215,7 @@ static enum zebra_dplane_result
dplane_intf_update_internal(const struct interface *ifp, enum dplane_op_e op)
{
enum zebra_dplane_result result = ZEBRA_DPLANE_REQUEST_FAILURE;
- int ret = EINVAL;
+ int ret;
struct zebra_dplane_ctx *ctx = NULL;
/* Obtain context block */
@@ -4900,6 +5083,13 @@ int dplane_show_helper(struct vty *vty, bool detailed)
vty_out(vty, "Intf addr updates: %"PRIu64"\n", incoming);
vty_out(vty, "Intf addr errors: %"PRIu64"\n", errs);
+ incoming = atomic_load_explicit(&zdplane_info.dg_intf_changes,
+ memory_order_relaxed);
+ errs = atomic_load_explicit(&zdplane_info.dg_intf_changes_errors,
+ memory_order_relaxed);
+ vty_out(vty, "Intf change updates: %" PRIu64 "\n", incoming);
+ vty_out(vty, "Intf change errors: %" PRIu64 "\n", errs);
+
incoming = atomic_load_explicit(&zdplane_info.dg_macs_in,
memory_order_relaxed);
errs = atomic_load_explicit(&zdplane_info.dg_mac_errors,
@@ -5541,6 +5731,13 @@ static void kernel_dplane_log_detail(struct zebra_dplane_ctx *ctx)
dplane_ctx_get_ifindex(ctx),
dplane_ctx_intf_is_protodown(ctx));
break;
+
+ /* TODO: more detailed log */
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
+ zlog_debug("Dplane tc ifidx %u", dplane_ctx_get_ifindex(ctx));
+ break;
}
}
@@ -5684,6 +5881,14 @@ static void kernel_dplane_handle_result(struct zebra_dplane_ctx *ctx)
1, memory_order_relaxed);
break;
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
+ if (res != ZEBRA_DPLANE_REQUEST_SUCCESS)
+ atomic_fetch_add_explicit(&zdplane_info.dg_tcs_errors,
+ 1, memory_order_relaxed);
+ break;
+
/* Ignore 'notifications' - no-op */
case DPLANE_OP_SYS_ROUTE_ADD:
case DPLANE_OP_SYS_ROUTE_DELETE:
diff --git a/zebra/zebra_dplane.h b/zebra/zebra_dplane.h
index d940bd9568..8b239a9ba1 100644
--- a/zebra/zebra_dplane.h
+++ b/zebra/zebra_dplane.h
@@ -193,6 +193,11 @@ enum dplane_op_e {
DPLANE_OP_INTF_INSTALL,
DPLANE_OP_INTF_UPDATE,
DPLANE_OP_INTF_DELETE,
+
+ /* Traffic control */
+ DPLANE_OP_TC_INSTALL,
+ DPLANE_OP_TC_UPDATE,
+ DPLANE_OP_TC_DELETE,
};
/*
@@ -378,6 +383,16 @@ uint8_t dplane_ctx_get_distance(const struct zebra_dplane_ctx *ctx);
void dplane_ctx_set_distance(struct zebra_dplane_ctx *ctx, uint8_t distance);
uint8_t dplane_ctx_get_old_distance(const struct zebra_dplane_ctx *ctx);
+/* Accessors for traffic control context */
+uint64_t dplane_ctx_tc_get_rate(const struct zebra_dplane_ctx *ctx);
+uint64_t dplane_ctx_tc_get_ceil(const struct zebra_dplane_ctx *ctx);
+uint32_t dplane_ctx_tc_get_filter_bm(const struct zebra_dplane_ctx *ctx);
+const struct prefix *
+dplane_ctx_tc_get_src_ip(const struct zebra_dplane_ctx *ctx);
+const struct prefix *
+dplane_ctx_tc_get_dst_ip(const struct zebra_dplane_ctx *ctx);
+uint8_t dplane_ctx_tc_get_ip_proto(const struct zebra_dplane_ctx *ctx);
+
void dplane_ctx_set_nexthops(struct zebra_dplane_ctx *ctx, struct nexthop *nh);
void dplane_ctx_set_backup_nhg(struct zebra_dplane_ctx *ctx,
const struct nexthop_group *nhg);
@@ -690,6 +705,8 @@ enum zebra_dplane_result dplane_lsp_notif_update(struct zebra_lsp *lsp,
enum zebra_dplane_result dplane_pw_install(struct zebra_pw *pw);
enum zebra_dplane_result dplane_pw_uninstall(struct zebra_pw *pw);
+enum zebra_dplane_result
+dplane_intf_mpls_modify_state(const struct interface *ifp, const bool set);
/*
* Enqueue interface address changes for the dataplane.
*/
@@ -706,6 +723,13 @@ enum zebra_dplane_result dplane_intf_update(const struct interface *ifp);
enum zebra_dplane_result dplane_intf_delete(const struct interface *ifp);
/*
+ * Enqueue interface link changes for the dataplane.
+ */
+enum zebra_dplane_result dplane_tc_add(void);
+enum zebra_dplane_result dplane_tc_update(void);
+enum zebra_dplane_result dplane_tc_delete(void);
+
+/*
* Link layer operations for the dataplane.
*/
enum zebra_dplane_result dplane_neigh_ip_update(enum dplane_op_e op,
@@ -847,6 +871,9 @@ int dplane_ctx_nexthop_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
int dplane_ctx_intf_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op,
const struct interface *ifp);
+/* Encode traffic control information into data plane context. */
+int dplane_ctx_tc_init(struct zebra_dplane_ctx *ctx, enum dplane_op_e op);
+
/* Retrieve the limit on the number of pending, unprocessed updates. */
uint32_t dplane_get_in_queue_limit(void);
diff --git a/zebra/zebra_fpm.c b/zebra/zebra_fpm.c
index 21acaa823c..1b2753377b 100644
--- a/zebra/zebra_fpm.c
+++ b/zebra/zebra_fpm.c
@@ -1478,6 +1478,32 @@ static int zfpm_trigger_update(struct route_node *rn, const char *reason)
}
/*
+ * zfpm_trigger_remove
+ *
+ * The zebra code invokes this function to indicate that we should
+ * send an remove to the FPM about the given route_node.
+ */
+
+static int zfpm_trigger_remove(struct route_node *rn)
+{
+ rib_dest_t *dest;
+
+ if (!zfpm_conn_is_up())
+ return 0;
+
+ dest = rib_dest_from_rnode(rn);
+ if (!CHECK_FLAG(dest->flags, RIB_DEST_UPDATE_FPM))
+ return 0;
+
+ zfpm_debug("%pRN Removing from update queue shutting down", rn);
+
+ UNSET_FLAG(dest->flags, RIB_DEST_UPDATE_FPM);
+ TAILQ_REMOVE(&zfpm_g->dest_q, dest, fpm_q_entries);
+
+ return 0;
+}
+
+/*
* Generate Key for FPM MAC info hash entry
*/
static unsigned int zfpm_mac_info_hash_keymake(const void *p)
@@ -2036,6 +2062,7 @@ static int zfpm_fini(void)
static int zebra_fpm_module_init(void)
{
hook_register(rib_update, zfpm_trigger_update);
+ hook_register(rib_shutdown, zfpm_trigger_remove);
hook_register(zebra_rmac_update, zfpm_trigger_rmac_update);
hook_register(frr_late_init, zfpm_init);
hook_register(frr_early_fini, zfpm_fini);
diff --git a/zebra/zebra_mpls.c b/zebra/zebra_mpls.c
index 41f85af635..9756d9ba08 100644
--- a/zebra/zebra_mpls.c
+++ b/zebra/zebra_mpls.c
@@ -53,7 +53,7 @@ DEFINE_MTYPE_STATIC(ZEBRA, LSP, "MPLS LSP object");
DEFINE_MTYPE_STATIC(ZEBRA, FEC, "MPLS FEC object");
DEFINE_MTYPE_STATIC(ZEBRA, NHLFE, "MPLS nexthop object");
-int mpls_enabled;
+bool mpls_enabled;
bool mpls_pw_reach_strict; /* Strict reachability checking */
/* static function declarations */
@@ -1035,15 +1035,12 @@ static void lsp_processq_del(struct work_queue *wq, void *data)
struct zebra_lsp *lsp;
struct hash *lsp_table;
struct zebra_nhlfe *nhlfe;
- bool in_shutdown = false;
/* If zebra is shutting down, don't delete any structs,
* just ignore this callback. The LSPs will be cleaned up
* during the shutdown processing.
*/
- in_shutdown = atomic_load_explicit(&zrouter.in_shutdown,
- memory_order_relaxed);
- if (in_shutdown)
+ if (zebra_router_in_shutdown())
return;
zvrf = vrf_info_lookup(VRF_DEFAULT);
@@ -1751,14 +1748,9 @@ static int lsp_cmp(const struct zebra_lsp *lsp1, const struct zebra_lsp *lsp2)
/*
* Initialize work queue for processing changed LSPs.
*/
-static int mpls_processq_init(void)
+static void mpls_processq_init(void)
{
zrouter.lsp_process_q = work_queue_new(zrouter.master, "LSP processing");
- if (!zrouter.lsp_process_q) {
- flog_err(EC_ZEBRA_WQ_NONEXISTENT,
- "%s: could not initialise work queue!", __func__);
- return -1;
- }
zrouter.lsp_process_q->spec.workfunc = &lsp_process;
zrouter.lsp_process_q->spec.del_item_data = &lsp_processq_del;
@@ -1766,8 +1758,6 @@ static int mpls_processq_init(void)
zrouter.lsp_process_q->spec.completion_func = &lsp_processq_complete;
zrouter.lsp_process_q->spec.max_retries = 0;
zrouter.lsp_process_q->spec.hold = 10;
-
- return 0;
}
@@ -2757,9 +2747,9 @@ static bool ftn_update_nexthop(bool add_p, struct nexthop *nexthop,
return true;
}
-int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
- struct prefix *prefix, uint8_t route_type,
- unsigned short route_instance)
+void zebra_mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ struct prefix *prefix, uint8_t route_type,
+ uint8_t route_instance)
{
struct route_table *table;
struct route_node *rn;
@@ -2771,7 +2761,7 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
/* Lookup table. */
table = zebra_vrf_table(afi, SAFI_UNICAST, zvrf_id(zvrf));
if (!table)
- return -1;
+ return;
/* Lookup existing route */
rn = route_node_get(table, prefix);
@@ -2782,7 +2772,7 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
break;
}
if (re == NULL)
- return -1;
+ return;
/*
* Nexthops are now shared by multiple routes, so we have to make
@@ -2811,8 +2801,6 @@ int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
zebra_nhg_free(new_nhe);
rib_queue_add(rn);
-
- return 0;
}
/*
@@ -2894,8 +2882,8 @@ static bool ftn_update_znh(bool add_p, enum lsp_types_t type,
* There are several changes that need to be made, in several zebra
* data structures, so we want to do all the work required at once.
*/
-int mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
- const struct zapi_labels *zl)
+void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+ const struct zapi_labels *zl)
{
int i, counter, ret = 0;
char buf[NEXTHOP_STRLEN];
@@ -2916,7 +2904,7 @@ int mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
/* Lookup table. */
lsp_table = zvrf->lsp_table;
if (!lsp_table)
- return -1;
+ return;
/* Find or create LSP object */
tmp_ile.in_label = zl->local_label;
@@ -3080,8 +3068,6 @@ znh_done:
if (new_nhe)
zebra_nhg_free(new_nhe);
-
- return ret;
}
/*
@@ -4064,12 +4050,23 @@ void zebra_mpls_init_tables(struct zebra_vrf *zvrf)
zvrf->mpls_srgb.end_label = MPLS_DEFAULT_MAX_SRGB_LABEL;
}
+void zebra_mpls_turned_on(void)
+{
+ if (!mpls_enabled) {
+ mpls_processq_init();
+ mpls_enabled = true;
+ }
+
+ hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client);
+ hook_register(zserv_client_close, zebra_mpls_cleanup_zclient_labels);
+}
+
/*
* Global MPLS initialization.
*/
void zebra_mpls_init(void)
{
- mpls_enabled = 0;
+ mpls_enabled = false;
mpls_pw_reach_strict = false;
if (mpls_kernel_init() < 0) {
@@ -4078,9 +4075,5 @@ void zebra_mpls_init(void)
return;
}
- if (!mpls_processq_init())
- mpls_enabled = 1;
-
- hook_register(zserv_client_close, zebra_mpls_cleanup_fecs_for_client);
- hook_register(zserv_client_close, zebra_mpls_cleanup_zclient_labels);
+ zebra_mpls_turned_on();
}
diff --git a/zebra/zebra_mpls.h b/zebra/zebra_mpls.h
index a8c4e1a60c..cf247861f8 100644
--- a/zebra/zebra_mpls.h
+++ b/zebra/zebra_mpls.h
@@ -260,17 +260,30 @@ void zebra_mpls_print_fec(struct vty *vty, struct zebra_vrf *zvrf,
/*
* Handle zapi request to install/uninstall LSP and
* (optionally) FEC-To-NHLFE (FTN) bindings.
+ *
+ * mpls_zapi_labels_process -> Installs for future processing
+ * in the meta-q
+ * zebra_mpls_labels_process -> called by the meta-q
*/
-int mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
- const struct zapi_labels *zl);
+void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+ const struct zapi_labels *zl);
+void zebra_mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+ const struct zapi_labels *zl);
/*
* Uninstall all NHLFEs bound to a single FEC.
- */
-int mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
- struct prefix *prefix, uint8_t route_type,
- unsigned short route_instance);
-
+ *
+ * mpls_ftn_uninstall -> Called to enqueue into early label processing
+ * via the metaq
+ * zebra_mpls_ftn_uninstall -> Called when we process the meta q
+ * for this item
+ */
+void mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ struct prefix *prefix, uint8_t route_type,
+ uint8_t route_instance);
+void zebra_mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ struct prefix *prefix, uint8_t route_type,
+ uint8_t route_instance);
/*
* Install/update a NHLFE for an LSP in the forwarding table. This may be
* a new LSP entry or a new NHLFE for an existing in-label or an update of
@@ -395,6 +408,13 @@ void zebra_mpls_close_tables(struct zebra_vrf *zvrf);
void zebra_mpls_init_tables(struct zebra_vrf *zvrf);
/*
+ * If mpls is turned on *after* FRR is brought
+ * up let's actually notice this and turn on
+ * the relevant bits to make it work.
+ */
+void zebra_mpls_turned_on(void);
+
+/*
* Global MPLS initialization.
*/
void zebra_mpls_init(void);
@@ -569,7 +589,7 @@ static inline int mpls_should_lsps_be_processed(struct route_node *rn)
}
/* Global variables. */
-extern int mpls_enabled;
+extern bool mpls_enabled;
extern bool mpls_pw_reach_strict; /* Strict pseudowire reachability checking */
#ifdef __cplusplus
diff --git a/zebra/zebra_nhg.c b/zebra/zebra_nhg.c
index f846164834..1964c763c5 100644
--- a/zebra/zebra_nhg.c
+++ b/zebra/zebra_nhg.c
@@ -1058,7 +1058,7 @@ static void zebra_nhg_set_invalid(struct nhg_hash_entry *nhe)
/* If we're in shutdown, this interface event needs to clean
* up installed NHGs, so don't clear that flag directly.
*/
- if (!zrouter.in_shutdown)
+ if (!zebra_router_in_shutdown())
UNSET_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED);
/* Update validity of nexthops depending on it */
@@ -1613,18 +1613,66 @@ void zebra_nhg_free(struct nhg_hash_entry *nhe)
THREAD_OFF(nhe->timer);
- if (nhe->refcnt)
- zlog_debug("nhe_id=%pNG hash refcnt=%d", nhe, nhe->refcnt);
-
zebra_nhg_free_members(nhe);
XFREE(MTYPE_NHG, nhe);
}
+/*
+ * Let's just drop the memory associated with each item
+ */
void zebra_nhg_hash_free(void *p)
{
- zebra_nhg_release_all_deps((struct nhg_hash_entry *)p);
- zebra_nhg_free((struct nhg_hash_entry *)p);
+ struct nhg_hash_entry *nhe = p;
+
+ if (IS_ZEBRA_DEBUG_NHG_DETAIL) {
+ /* Group or singleton? */
+ if (nhe->nhg.nexthop && nhe->nhg.nexthop->next)
+ zlog_debug("%s: nhe %p (%u), refcnt %d", __func__, nhe,
+ nhe->id, nhe->refcnt);
+ else
+ zlog_debug("%s: nhe %p (%pNG), refcnt %d, NH %pNHv",
+ __func__, nhe, nhe, nhe->refcnt,
+ nhe->nhg.nexthop);
+ }
+
+ THREAD_OFF(nhe->timer);
+
+ nexthops_free(nhe->nhg.nexthop);
+
+ XFREE(MTYPE_NHG, nhe);
+}
+
+/*
+ * On cleanup there are nexthop groups that have not
+ * been resolved at all( a nhe->id of 0 ). As such
+ * zebra needs to clean up the memory associated with
+ * those entries.
+ */
+void zebra_nhg_hash_free_zero_id(struct hash_bucket *b, void *arg)
+{
+ struct nhg_hash_entry *nhe = b->data;
+ struct nhg_connected *dep;
+
+ while ((dep = nhg_connected_tree_pop(&nhe->nhg_depends))) {
+ if (dep->nhe->id == 0)
+ zebra_nhg_hash_free(dep->nhe);
+
+ nhg_connected_free(dep);
+ }
+
+ while ((dep = nhg_connected_tree_pop(&nhe->nhg_dependents)))
+ nhg_connected_free(dep);
+
+ if (nhe->backup_info && nhe->backup_info->nhe->id == 0) {
+ while ((dep = nhg_connected_tree_pop(
+ &nhe->backup_info->nhe->nhg_depends)))
+ nhg_connected_free(dep);
+
+ zebra_nhg_hash_free(nhe->backup_info->nhe);
+
+ XFREE(MTYPE_NHG, nhe->backup_info);
+ }
}
static void zebra_nhg_timer(struct thread *thread)
@@ -1646,13 +1694,14 @@ void zebra_nhg_decrement_ref(struct nhg_hash_entry *nhe)
nhe->refcnt--;
- if (!zrouter.in_shutdown && nhe->refcnt <= 0 &&
+ if (!zebra_router_in_shutdown() && nhe->refcnt <= 0 &&
CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_INSTALLED) &&
!CHECK_FLAG(nhe->flags, NEXTHOP_GROUP_KEEP_AROUND)) {
nhe->refcnt = 1;
SET_FLAG(nhe->flags, NEXTHOP_GROUP_KEEP_AROUND);
thread_add_timer(zrouter.master, zebra_nhg_timer, nhe,
zrouter.nhg_keep, &nhe->timer);
+ return;
}
if (!zebra_nhg_depends_is_empty(nhe))
@@ -3076,6 +3125,9 @@ void zebra_nhg_dplane_result(struct zebra_dplane_ctx *ctx)
case DPLANE_OP_INTF_INSTALL:
case DPLANE_OP_INTF_UPDATE:
case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
break;
}
}
diff --git a/zebra/zebra_nhg.h b/zebra/zebra_nhg.h
index 6d2ab248f9..62f71f943f 100644
--- a/zebra/zebra_nhg.h
+++ b/zebra/zebra_nhg.h
@@ -256,6 +256,7 @@ struct nhg_hash_entry *zebra_nhg_alloc(void);
void zebra_nhg_free(struct nhg_hash_entry *nhe);
/* In order to clear a generic hash, we need a generic api, sigh. */
void zebra_nhg_hash_free(void *p);
+void zebra_nhg_hash_free_zero_id(struct hash_bucket *b, void *arg);
/* Init an nhe, for use in a hash lookup for example. There's some fuzziness
* if the nhe represents only a single nexthop, so we try to capture that
diff --git a/zebra/zebra_pw.c b/zebra/zebra_pw.c
index 6dde513f40..be089fc759 100644
--- a/zebra/zebra_pw.c
+++ b/zebra/zebra_pw.c
@@ -101,13 +101,15 @@ void zebra_pw_del(struct zebra_vrf *zvrf, struct zebra_pw *pw)
if (pw->status == PW_FORWARDING) {
hook_call(pw_uninstall, pw);
dplane_pw_uninstall(pw);
- } else if (pw->install_retry_timer)
- THREAD_OFF(pw->install_retry_timer);
+ }
+
+ THREAD_OFF(pw->install_retry_timer);
/* unlink and release memory */
RB_REMOVE(zebra_pw_head, &zvrf->pseudowires, pw);
if (pw->protocol == ZEBRA_ROUTE_STATIC)
RB_REMOVE(zebra_static_pw_head, &zvrf->static_pseudowires, pw);
+
XFREE(MTYPE_PW, pw);
}
@@ -230,7 +232,6 @@ static void zebra_pw_install_retry(struct thread *thread)
{
struct zebra_pw *pw = THREAD_ARG(thread);
- pw->install_retry_timer = NULL;
zebra_pw_install(pw);
}
diff --git a/zebra/zebra_rib.c b/zebra/zebra_rib.c
index d0babbb9e4..fceaaaa9f0 100644
--- a/zebra/zebra_rib.c
+++ b/zebra/zebra_rib.c
@@ -76,52 +76,70 @@ static struct dplane_ctx_q rib_dplane_q;
DEFINE_HOOK(rib_update, (struct route_node * rn, const char *reason),
(rn, reason));
+DEFINE_HOOK(rib_shutdown, (struct route_node * rn), (rn));
+
+
+/* Meta Q's specific names */
+enum meta_queue_indexes {
+ META_QUEUE_NHG,
+ META_QUEUE_EVPN,
+ META_QUEUE_EARLY_ROUTE,
+ META_QUEUE_EARLY_LABEL,
+ META_QUEUE_CONNECTED,
+ META_QUEUE_KERNEL,
+ META_QUEUE_STATIC,
+ META_QUEUE_NOTBGP,
+ META_QUEUE_BGP,
+ META_QUEUE_OTHER,
+};
/* Each route type's string and default distance value. */
static const struct {
int key;
uint8_t distance;
- uint8_t meta_q_map;
+ enum meta_queue_indexes meta_q_map;
} route_info[ZEBRA_ROUTE_MAX] = {
- [ZEBRA_ROUTE_NHG] = {ZEBRA_ROUTE_NHG, 255 /* Unneeded for nhg's */, 0},
- [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, 7},
- [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0, 3},
- [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0, 2},
- [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1, 4},
- [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120, 5},
- [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120, 5},
- [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110, 5},
- [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110, 5},
- [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115, 5},
- [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */, 6},
- [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255, 7},
- [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90, 5},
- [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10, 5},
- [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255, 7},
- [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255, 7},
- [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150, 4},
- [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150, 7},
- [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20, 6},
- [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20, 6},
- [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20, 6},
- [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20, 6},
- [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20, 6},
- [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, 5},
- [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, 7},
- [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, 7},
- [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, 7},
- [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115, 5},
- [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, 7},
- [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, 7},
- [ZEBRA_ROUTE_ALL] = {ZEBRA_ROUTE_ALL, 255, 7},
+ [ZEBRA_ROUTE_NHG] = {ZEBRA_ROUTE_NHG, 255 /* Unneeded for nhg's */,
+ META_QUEUE_NHG},
+ [ZEBRA_ROUTE_SYSTEM] = {ZEBRA_ROUTE_SYSTEM, 0, META_QUEUE_KERNEL},
+ [ZEBRA_ROUTE_KERNEL] = {ZEBRA_ROUTE_KERNEL, 0, META_QUEUE_KERNEL},
+ [ZEBRA_ROUTE_CONNECT] = {ZEBRA_ROUTE_CONNECT, 0, META_QUEUE_CONNECTED},
+ [ZEBRA_ROUTE_STATIC] = {ZEBRA_ROUTE_STATIC, 1, META_QUEUE_STATIC},
+ [ZEBRA_ROUTE_RIP] = {ZEBRA_ROUTE_RIP, 120, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_RIPNG] = {ZEBRA_ROUTE_RIPNG, 120, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_OSPF] = {ZEBRA_ROUTE_OSPF, 110, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_OSPF6] = {ZEBRA_ROUTE_OSPF6, 110, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_ISIS] = {ZEBRA_ROUTE_ISIS, 115, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_BGP] = {ZEBRA_ROUTE_BGP, 20 /* IBGP is 200. */,
+ META_QUEUE_BGP},
+ [ZEBRA_ROUTE_PIM] = {ZEBRA_ROUTE_PIM, 255, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_EIGRP] = {ZEBRA_ROUTE_EIGRP, 90, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_NHRP] = {ZEBRA_ROUTE_NHRP, 10, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_HSLS] = {ZEBRA_ROUTE_HSLS, 255, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_OLSR] = {ZEBRA_ROUTE_OLSR, 255, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_TABLE] = {ZEBRA_ROUTE_TABLE, 150, META_QUEUE_STATIC},
+ [ZEBRA_ROUTE_LDP] = {ZEBRA_ROUTE_LDP, 150, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_VNC] = {ZEBRA_ROUTE_VNC, 20, META_QUEUE_BGP},
+ [ZEBRA_ROUTE_VNC_DIRECT] = {ZEBRA_ROUTE_VNC_DIRECT, 20, META_QUEUE_BGP},
+ [ZEBRA_ROUTE_VNC_DIRECT_RH] = {ZEBRA_ROUTE_VNC_DIRECT_RH, 20,
+ META_QUEUE_BGP},
+ [ZEBRA_ROUTE_BGP_DIRECT] = {ZEBRA_ROUTE_BGP_DIRECT, 20, META_QUEUE_BGP},
+ [ZEBRA_ROUTE_BGP_DIRECT_EXT] = {ZEBRA_ROUTE_BGP_DIRECT_EXT, 20,
+ META_QUEUE_BGP},
+ [ZEBRA_ROUTE_BABEL] = {ZEBRA_ROUTE_BABEL, 100, META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_SHARP] = {ZEBRA_ROUTE_SHARP, 150, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_PBR] = {ZEBRA_ROUTE_PBR, 200, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_BFD] = {ZEBRA_ROUTE_BFD, 255, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_OPENFABRIC] = {ZEBRA_ROUTE_OPENFABRIC, 115,
+ META_QUEUE_NOTBGP},
+ [ZEBRA_ROUTE_VRRP] = {ZEBRA_ROUTE_VRRP, 255, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_SRTE] = {ZEBRA_ROUTE_SRTE, 255, META_QUEUE_OTHER},
+ [ZEBRA_ROUTE_ALL] = {ZEBRA_ROUTE_ALL, 255, META_QUEUE_OTHER},
/* Any new route type added to zebra, should be mirrored here */
/* no entry/default: 150 */
};
-/* EVPN/VXLAN subqueue is number 1 */
-#define META_QUEUE_EVPN 1
-
/* Wrapper struct for nhg workqueue items; a 'ctx' is an incoming update
* from the OS, and an 'nhe' is a nhe update.
*/
@@ -159,29 +177,56 @@ struct wq_evpn_wrapper {
#define WQ_EVPN_WRAPPER_TYPE_REM_MACIP 0x03
#define WQ_EVPN_WRAPPER_TYPE_REM_VTEP 0x04
+enum wq_label_types {
+ WQ_LABEL_FTN_UNINSTALL,
+ WQ_LABEL_LABELS_PROCESS,
+};
+
+struct wq_label_wrapper {
+ enum wq_label_types type;
+ vrf_id_t vrf_id;
+
+ struct prefix p;
+ enum lsp_types_t ltype;
+ uint8_t route_type;
+ uint8_t route_instance;
+
+ bool add_p;
+ struct zapi_labels zl;
+
+ int afi;
+};
+
+static void rib_addnode(struct route_node *rn, struct route_entry *re,
+ int process);
+
/* %pRN is already a printer for route_nodes that just prints the prefix */
#ifdef _FRR_ATTRIBUTE_PRINTFRR
#pragma FRR printfrr_ext "%pZN" (struct route_node *)
#endif
-static const char *subqueue2str(uint8_t index)
+static const char *subqueue2str(enum meta_queue_indexes index)
{
switch (index) {
- case 0:
+ case META_QUEUE_NHG:
return "NHG Objects";
- case 1:
+ case META_QUEUE_EVPN:
return "EVPN/VxLan Objects";
- case 2:
+ case META_QUEUE_EARLY_ROUTE:
+ return "Early Route Processing";
+ case META_QUEUE_EARLY_LABEL:
+ return "Early Label Handling";
+ case META_QUEUE_CONNECTED:
return "Connected Routes";
- case 3:
+ case META_QUEUE_KERNEL:
return "Kernel Routes";
- case 4:
+ case META_QUEUE_STATIC:
return "Static Routes";
- case 5:
+ case META_QUEUE_NOTBGP:
return "RIP/OSPF/ISIS/EIGRP/NHRP Routes";
- case 6:
+ case META_QUEUE_BGP:
return "BGP Routes";
- case 7:
+ case META_QUEUE_OTHER:
return "Other Routes";
}
@@ -901,6 +946,9 @@ void zebra_rtable_node_cleanup(struct route_table *table,
if (node->info) {
rib_dest_t *dest = node->info;
+ /* Remove from update queue of FPM module */
+ hook_call(rib_shutdown, node);
+
rnh_list_fini(&dest->nht);
XFREE(MTYPE_RIB_DEST, node->info);
}
@@ -2407,7 +2455,7 @@ static void process_subq_nhg(struct listnode *lnode)
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;
+ uint8_t qindex = META_QUEUE_NHG;
w = listgetdata(lnode);
@@ -2454,6 +2502,33 @@ static void process_subq_nhg(struct listnode *lnode)
XFREE(MTYPE_WQ_WRAPPER, w);
}
+static void process_subq_early_label(struct listnode *lnode)
+{
+ struct wq_label_wrapper *w = listgetdata(lnode);
+ struct zebra_vrf *zvrf;
+
+ if (!w)
+ return;
+
+ zvrf = vrf_info_lookup(w->vrf_id);
+ if (!zvrf) {
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ return;
+ }
+
+ switch (w->type) {
+ case WQ_LABEL_FTN_UNINSTALL:
+ zebra_mpls_ftn_uninstall(zvrf, w->ltype, &w->p, w->route_type,
+ w->route_instance);
+ break;
+ case WQ_LABEL_LABELS_PROCESS:
+ zebra_mpls_zapi_labels_process(w->add_p, zvrf, &w->zl);
+ break;
+ }
+
+ XFREE(MTYPE_WQ_WRAPPER, w);
+}
+
static void process_subq_route(struct listnode *lnode, uint8_t qindex)
{
struct route_node *rnode = NULL;
@@ -2492,23 +2567,494 @@ static void process_subq_route(struct listnode *lnode, uint8_t qindex)
route_unlock_node(rnode);
}
+static void rib_re_nhg_free(struct route_entry *re)
+{
+ if (re->nhe && re->nhe_id) {
+ assert(re->nhe->id == re->nhe_id);
+ route_entry_update_nhe(re, NULL);
+ } else if (re->nhe && re->nhe->nhg.nexthop)
+ nexthops_free(re->nhe->nhg.nexthop);
+
+ nexthops_free(re->fib_ng.nexthop);
+}
+
+struct zebra_early_route {
+ afi_t afi;
+ safi_t safi;
+ struct prefix p;
+ struct prefix_ipv6 src_p;
+ bool src_p_provided;
+ struct route_entry *re;
+ struct nhg_hash_entry *re_nhe;
+ bool startup;
+ bool deletion;
+ bool fromkernel;
+};
+
+static void early_route_memory_free(struct zebra_early_route *ere)
+{
+ if (ere->re_nhe)
+ zebra_nhg_free(ere->re_nhe);
+
+ XFREE(MTYPE_RE, ere->re);
+ XFREE(MTYPE_WQ_WRAPPER, ere);
+}
+
+static void process_subq_early_route_add(struct zebra_early_route *ere)
+{
+ struct route_entry *re = ere->re;
+ struct route_table *table;
+ struct nhg_hash_entry *nhe = NULL;
+ struct route_node *rn;
+ struct route_entry *same = NULL, *first_same = NULL;
+ int same_count = 0;
+ rib_dest_t *dest;
+
+ /* Lookup table. */
+ table = zebra_vrf_get_table_with_table_id(ere->afi, ere->safi,
+ re->vrf_id, re->table);
+ if (!table) {
+ early_route_memory_free(ere);
+ return;
+ }
+
+ if (re->nhe_id > 0) {
+ nhe = zebra_nhg_lookup_id(re->nhe_id);
+
+ if (!nhe) {
+ /*
+ * We've received from the kernel a nexthop id
+ * that we don't have saved yet. More than likely
+ * it has not been processed and is on the
+ * queue to be processed. Let's stop what we
+ * are doing and cause the meta q to be processed
+ * storing this for later.
+ *
+ * This is being done this way because zebra
+ * runs with the assumption t
+ */
+ flog_err(
+ EC_ZEBRA_TABLE_LOOKUP_FAILED,
+ "Zebra failed to find the nexthop hash entry for id=%u in a route entry %pFX",
+ re->nhe_id, &ere->p);
+
+ early_route_memory_free(ere);
+ return;
+ }
+ } else {
+ /* Lookup nhe from route information */
+ nhe = zebra_nhg_rib_find_nhe(ere->re_nhe, ere->afi);
+ if (!nhe) {
+ char buf2[PREFIX_STRLEN] = "";
+
+ flog_err(
+ EC_ZEBRA_TABLE_LOOKUP_FAILED,
+ "Zebra failed to find or create a nexthop hash entry for %pFX%s%s",
+ &ere->p, ere->src_p_provided ? " from " : "",
+ ere->src_p_provided
+ ? prefix2str(&ere->src_p, buf2,
+ sizeof(buf2))
+ : "");
+
+ early_route_memory_free(ere);
+ return;
+ }
+ }
+
+ /*
+ * Attach the re to the nhe's nexthop group.
+ *
+ * TODO: This will need to change when we start getting IDs from upper
+ * level protocols, as the refcnt might be wrong, since it checks
+ * if old_id != new_id.
+ */
+ route_entry_update_nhe(re, nhe);
+
+ /* Make it sure prefixlen is applied to the prefix. */
+ apply_mask(&ere->p);
+ if (ere->src_p_provided)
+ apply_mask_ipv6(&ere->src_p);
+
+ /* Set default distance by route type. */
+ if (re->distance == 0)
+ re->distance = route_distance(re->type);
+
+ /* Lookup route node.*/
+ rn = srcdest_rnode_get(table, &ere->p,
+ ere->src_p_provided ? &ere->src_p : NULL);
+
+ /*
+ * If same type of route are installed, treat it as a implicit
+ * withdraw. If the user has specified the No route replace semantics
+ * for the install don't do a route replace.
+ */
+ RNODE_FOREACH_RE (rn, same) {
+ if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) {
+ same_count++;
+ continue;
+ }
+
+ /* Compare various route_entry properties */
+ if (rib_compare_routes(re, same)) {
+ same_count++;
+
+ if (first_same == NULL)
+ first_same = same;
+ }
+ }
+
+ same = first_same;
+
+ if (!ere->startup && (re->flags & ZEBRA_FLAG_SELFROUTE) &&
+ zrouter.asic_offloaded) {
+ if (!same) {
+ if (IS_ZEBRA_DEBUG_RIB)
+ zlog_debug(
+ "prefix: %pRN is a self route where we do not have an entry for it. Dropping this update, it's useless",
+ rn);
+ /*
+ * We are not on startup, this is a self route
+ * and we have asic offload. Which means
+ * we are getting a callback for a entry
+ * that was already deleted to the kernel
+ * but an earlier response was just handed
+ * back. Drop it on the floor
+ */
+ early_route_memory_free(ere);
+ return;
+ }
+ }
+
+ /* If this route is kernel/connected route, notify the dataplane. */
+ if (RIB_SYSTEM_ROUTE(re)) {
+ /* Notify dataplane */
+ dplane_sys_route_add(rn, re);
+ }
+
+ /* Link new re to node.*/
+ if (IS_ZEBRA_DEBUG_RIB) {
+ rnode_debug(
+ rn, re->vrf_id,
+ "Inserting route rn %p, re %p (%s) existing %p, same_count %d",
+ rn, re, zebra_route_string(re->type), same, same_count);
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ route_entry_dump(
+ &ere->p,
+ ere->src_p_provided ? &ere->src_p : NULL, re);
+ }
+
+ SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
+ rib_addnode(rn, re, 1);
+
+ /* Free implicit route.*/
+ if (same)
+ rib_delnode(rn, same);
+
+ /* See if we can remove some RE entries that are queued for
+ * removal, but won't be considered in rib processing.
+ */
+ dest = rib_dest_from_rnode(rn);
+ RNODE_FOREACH_RE_SAFE (rn, re, same) {
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
+ /* If the route was used earlier, must retain it. */
+ if (dest && re == dest->selected_fib)
+ continue;
+
+ if (IS_ZEBRA_DEBUG_RIB)
+ rnode_debug(rn, re->vrf_id,
+ "rn %p, removing unneeded re %p",
+ rn, re);
+
+ rib_unlink(rn, re);
+ }
+ }
+
+ route_unlock_node(rn);
+ if (ere->re_nhe)
+ zebra_nhg_free(ere->re_nhe);
+ XFREE(MTYPE_WQ_WRAPPER, ere);
+}
+
+static void process_subq_early_route_delete(struct zebra_early_route *ere)
+{
+ struct route_table *table;
+ struct route_node *rn;
+ struct route_entry *re;
+ struct route_entry *fib = NULL;
+ struct route_entry *same = NULL;
+ struct nexthop *rtnh;
+ char buf2[INET6_ADDRSTRLEN];
+ rib_dest_t *dest;
+
+ if (ere->src_p_provided)
+ assert(!ere->src_p.prefixlen || ere->afi == AFI_IP6);
+
+ /* Lookup table. */
+ table = zebra_vrf_lookup_table_with_table_id(
+ ere->afi, ere->safi, ere->re->vrf_id, ere->re->table);
+ if (!table) {
+ early_route_memory_free(ere);
+ return;
+ }
+
+ /* Apply mask. */
+ apply_mask(&ere->p);
+ if (ere->src_p_provided)
+ apply_mask_ipv6(&ere->src_p);
+
+ /* Lookup route node. */
+ rn = srcdest_rnode_lookup(table, &ere->p,
+ ere->src_p_provided ? &ere->src_p : NULL);
+ if (!rn) {
+ if (IS_ZEBRA_DEBUG_RIB) {
+ char src_buf[PREFIX_STRLEN];
+ struct vrf *vrf = vrf_lookup_by_id(ere->re->vrf_id);
+
+ if (ere->src_p_provided && ere->src_p.prefixlen)
+ prefix2str(&ere->src_p, src_buf,
+ sizeof(src_buf));
+ else
+ src_buf[0] = '\0';
+
+ zlog_debug("%s[%d]:%pRN%s%s doesn't exist in rib",
+ vrf->name, ere->re->table, rn,
+ (src_buf[0] != '\0') ? " from " : "",
+ src_buf);
+ }
+ early_route_memory_free(ere);
+ return;
+ }
+
+ dest = rib_dest_from_rnode(rn);
+ fib = dest->selected_fib;
+
+ struct nexthop *nh = NULL;
+
+ if (ere->re->nhe)
+ nh = ere->re->nhe->nhg.nexthop;
+
+ /* Lookup same type route. */
+ RNODE_FOREACH_RE (rn, re) {
+ if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
+ continue;
+
+ if (re->type != ere->re->type)
+ continue;
+ if (re->instance != ere->re->instance)
+ continue;
+ if (CHECK_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE) &&
+ ere->re->distance != re->distance)
+ continue;
+
+ if (re->type == ZEBRA_ROUTE_KERNEL &&
+ re->metric != ere->re->metric)
+ continue;
+ if (re->type == ZEBRA_ROUTE_CONNECT && (rtnh = nh) &&
+ rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
+ if (rtnh->ifindex != nh->ifindex)
+ continue;
+ same = re;
+ break;
+ }
+
+ /* Make sure that the route found has the same gateway. */
+ if (ere->re->nhe_id && re->nhe_id == ere->re->nhe_id) {
+ same = re;
+ break;
+ }
+
+ if (nh == NULL) {
+ same = re;
+ break;
+ }
+ for (ALL_NEXTHOPS(re->nhe->nhg, rtnh)) {
+ /*
+ * No guarantee all kernel send nh with labels
+ * on delete.
+ */
+ if (nexthop_same_no_labels(rtnh, nh)) {
+ same = re;
+ break;
+ }
+ }
+
+ if (same)
+ break;
+ }
+ /*
+ * If same type of route can't be found and this message is from
+ * kernel.
+ */
+ if (!same) {
+ /*
+ * In the past(HA!) we could get here because
+ * we were receiving a route delete from the
+ * kernel and we're not marking the proto
+ * as coming from it's appropriate originator.
+ * Now that we are properly noticing the fact
+ * that the kernel has deleted our route we
+ * are not going to get called in this path
+ * I am going to leave this here because
+ * this might still work this way on non-linux
+ * platforms as well as some weird state I have
+ * not properly thought of yet.
+ * If we can show that this code path is
+ * dead then we can remove it.
+ */
+ if (fib && CHECK_FLAG(ere->re->flags, ZEBRA_FLAG_SELFROUTE)) {
+ if (IS_ZEBRA_DEBUG_RIB) {
+ rnode_debug(
+ rn, ere->re->vrf_id,
+ "rn %p, re %p (%s) was deleted from kernel, adding",
+ rn, fib, zebra_route_string(fib->type));
+ }
+ if (zrouter.allow_delete ||
+ CHECK_FLAG(dest->flags, RIB_ROUTE_ANY_QUEUED)) {
+ UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
+ /* Unset flags. */
+ for (rtnh = fib->nhe->nhg.nexthop; rtnh;
+ rtnh = rtnh->next)
+ UNSET_FLAG(rtnh->flags,
+ NEXTHOP_FLAG_FIB);
+
+ /*
+ * This is a non FRR route
+ * as such we should mark
+ * it as deleted
+ */
+ dest->selected_fib = NULL;
+ } else {
+ /*
+ * This means someone else, other than Zebra,
+ * has deleted a Zebra router from the kernel.
+ * We will add it back
+ */
+ rib_install_kernel(rn, fib, NULL);
+ }
+ } else {
+ if (IS_ZEBRA_DEBUG_RIB) {
+ if (nh)
+ rnode_debug(
+ rn, ere->re->vrf_id,
+ "via %s ifindex %d type %d doesn't exist in rib",
+ inet_ntop(afi2family(ere->afi),
+ &nh->gate, buf2,
+ sizeof(buf2)),
+ nh->ifindex, ere->re->type);
+ else
+ rnode_debug(
+ rn, ere->re->vrf_id,
+ "type %d doesn't exist in rib",
+ ere->re->type);
+ }
+ route_unlock_node(rn);
+ early_route_memory_free(ere);
+ return;
+ }
+ }
+
+ if (same) {
+ struct nexthop *tmp_nh;
+
+ if (ere->fromkernel &&
+ CHECK_FLAG(ere->re->flags, ZEBRA_FLAG_SELFROUTE) &&
+ !zrouter.allow_delete) {
+ rib_install_kernel(rn, same, NULL);
+ route_unlock_node(rn);
+
+ early_route_memory_free(ere);
+ return;
+ }
+
+ /* Special handling for IPv4 or IPv6 routes sourced from
+ * EVPN - the nexthop (and associated MAC) need to be
+ * uninstalled if no more refs.
+ */
+ for (ALL_NEXTHOPS(re->nhe->nhg, tmp_nh)) {
+ struct ipaddr vtep_ip;
+
+ if (CHECK_FLAG(tmp_nh->flags, NEXTHOP_FLAG_EVPN)) {
+ memset(&vtep_ip, 0, sizeof(struct ipaddr));
+ if (ere->afi == AFI_IP) {
+ vtep_ip.ipa_type = IPADDR_V4;
+ memcpy(&(vtep_ip.ipaddr_v4),
+ &(tmp_nh->gate.ipv4),
+ sizeof(struct in_addr));
+ } else {
+ vtep_ip.ipa_type = IPADDR_V6;
+ memcpy(&(vtep_ip.ipaddr_v6),
+ &(tmp_nh->gate.ipv6),
+ sizeof(struct in6_addr));
+ }
+ zebra_rib_queue_evpn_route_del(
+ re->vrf_id, &vtep_ip, &ere->p);
+ }
+ }
+
+ /* Notify dplane if system route changes */
+ if (RIB_SYSTEM_ROUTE(re))
+ dplane_sys_route_del(rn, same);
+
+ rib_delnode(rn, same);
+ }
+
+ route_unlock_node(rn);
+
+ early_route_memory_free(ere);
+}
+
+/*
+ * When FRR receives a route we need to match the route up to
+ * nexthop groups. That we also may have just received
+ * place the data on this queue so that this work of finding
+ * the nexthop group entries for the route entry is always
+ * done after the nexthop group has had a chance to be processed
+ */
+static void process_subq_early_route(struct listnode *lnode)
+{
+ struct zebra_early_route *ere = listgetdata(lnode);
+
+ if (ere->deletion)
+ process_subq_early_route_delete(ere);
+ else
+ process_subq_early_route_add(ere);
+}
+
/*
* Examine the specified subqueue; process one entry and return 1 if
* there is a node, return 0 otherwise.
*/
-static unsigned int process_subq(struct list *subq, uint8_t qindex)
+static unsigned int process_subq(struct list *subq,
+ enum meta_queue_indexes qindex)
{
struct listnode *lnode = listhead(subq);
if (!lnode)
return 0;
- if (qindex == META_QUEUE_EVPN)
+ switch (qindex) {
+ case META_QUEUE_EVPN:
process_subq_evpn(lnode);
- else if (qindex == route_info[ZEBRA_ROUTE_NHG].meta_q_map)
+ break;
+ case META_QUEUE_NHG:
process_subq_nhg(lnode);
- else
+ break;
+ case META_QUEUE_EARLY_ROUTE:
+ process_subq_early_route(lnode);
+ break;
+ case META_QUEUE_EARLY_LABEL:
+ process_subq_early_label(lnode);
+ break;
+ case META_QUEUE_CONNECTED:
+ case META_QUEUE_KERNEL:
+ case META_QUEUE_STATIC:
+ case META_QUEUE_NOTBGP:
+ case META_QUEUE_BGP:
+ case META_QUEUE_OTHER:
process_subq_route(lnode, qindex);
+ break;
+ }
list_delete_node(subq, lnode);
@@ -2530,8 +3076,9 @@ static wq_item_status meta_queue_process(struct work_queue *dummy, void *data)
queue_len = dplane_get_in_queue_len();
if (queue_len > queue_limit) {
if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- zlog_debug("rib queue: dplane queue len %u, limit %u, retrying",
- queue_len, queue_limit);
+ zlog_debug(
+ "rib queue: dplane queue len %u, limit %u, retrying",
+ queue_len, queue_limit);
/* Ensure that the meta-queue is actually enqueued */
if (work_queue_empty(zrouter.ribq))
@@ -2610,10 +3157,17 @@ static int rib_meta_queue_add(struct meta_queue *mq, void *data)
return 0;
}
+static int early_label_meta_queue_add(struct meta_queue *mq, void *data)
+{
+ listnode_add(mq->subq[META_QUEUE_EARLY_LABEL], data);
+ mq->size++;
+ return 0;
+}
+
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;
+ uint8_t qindex = META_QUEUE_NHG;
struct wq_nhg_wrapper *w;
ctx = (struct nhg_ctx *)data;
@@ -2639,7 +3193,7 @@ static int rib_meta_queue_nhg_ctx_add(struct meta_queue *mq, void *data)
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;
+ uint8_t qindex = META_QUEUE_NHG;
struct wq_nhg_wrapper *w;
nhe = (struct nhg_hash_entry *)data;
@@ -2693,6 +3247,44 @@ static int mq_add_handler(void *data,
return mq_add_func(zrouter.mq, data);
}
+void mpls_ftn_uninstall(struct zebra_vrf *zvrf, enum lsp_types_t type,
+ struct prefix *prefix, uint8_t route_type,
+ uint8_t route_instance)
+{
+ struct wq_label_wrapper *w;
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_label_wrapper));
+
+ w->type = WQ_LABEL_FTN_UNINSTALL;
+ w->vrf_id = zvrf->vrf->vrf_id;
+ w->p = *prefix;
+ w->ltype = type;
+ w->route_type = route_type;
+ w->route_instance = route_instance;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("Early Label Handling for %pFX", prefix);
+
+ mq_add_handler(w, early_label_meta_queue_add);
+}
+
+void mpls_zapi_labels_process(bool add_p, struct zebra_vrf *zvrf,
+ const struct zapi_labels *zl)
+{
+ struct wq_label_wrapper *w;
+
+ w = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(struct wq_label_wrapper));
+ w->type = WQ_LABEL_LABELS_PROCESS;
+ w->vrf_id = zvrf->vrf->vrf_id;
+ w->add_p = add_p;
+ w->zl = *zl;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug("Early Label Handling: Labels Process");
+
+ mq_add_handler(w, early_label_meta_queue_add);
+}
+
/* Add route_node to work queue and schedule processing */
int rib_queue_add(struct route_node *rn)
{
@@ -2933,131 +3525,174 @@ int zebra_rib_queue_evpn_rem_vtep_del(vrf_id_t vrf_id, vni_t vni,
return mq_add_handler(w, rib_meta_queue_evpn_add);
}
+/* Create new meta queue.
+ A destructor function doesn't seem to be necessary here.
+ */
+static struct meta_queue *meta_queue_new(void)
+{
+ struct meta_queue *new;
+ unsigned i;
+
+ new = XCALLOC(MTYPE_WORK_QUEUE, sizeof(struct meta_queue));
+
+ for (i = 0; i < MQ_SIZE; i++) {
+ new->subq[i] = list_new();
+ assert(new->subq[i]);
+ }
+
+ return new;
+}
+
/* Clean up the EVPN meta-queue list */
-static void evpn_meta_queue_free(struct list *l)
+static void evpn_meta_queue_free(struct meta_queue *mq, struct list *l,
+ struct zebra_vrf *zvrf)
{
- struct listnode *node;
+ struct listnode *node, *nnode;
struct wq_evpn_wrapper *w;
/* Free the node wrapper object, and the struct it wraps */
- while ((node = listhead(l)) != NULL) {
- w = node->data;
+ for (ALL_LIST_ELEMENTS(l, node, nnode, w)) {
+ if (zvrf) {
+ vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+
+ if (w->vrf_id != vrf_id)
+ continue;
+ }
+
node->data = NULL;
XFREE(MTYPE_WQ_WRAPPER, w);
list_delete_node(l, node);
+ mq->size--;
}
}
/* Clean up the nhg meta-queue list */
-static void nhg_meta_queue_free(struct list *l)
+static void nhg_meta_queue_free(struct meta_queue *mq, struct list *l,
+ struct zebra_vrf *zvrf)
{
struct wq_nhg_wrapper *w;
- struct listnode *node;
+ struct listnode *node, *nnode;
/* Free the node wrapper object, and the struct it wraps */
- while ((node = listhead(l)) != NULL) {
- w = node->data;
- node->data = NULL;
+ for (ALL_LIST_ELEMENTS(l, node, nnode, w)) {
+ if (zvrf) {
+ vrf_id_t vrf_id = zvrf->vrf->vrf_id;
+ if (w->type == WQ_NHG_WRAPPER_TYPE_CTX &&
+ w->u.ctx->vrf_id != vrf_id)
+ continue;
+ else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG &&
+ w->u.nhe->vrf_id != vrf_id)
+ continue;
+ }
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);
+ node->data = NULL;
XFREE(MTYPE_WQ_WRAPPER, w);
list_delete_node(l, node);
+ mq->size--;
}
}
-/* Create new meta queue.
- A destructor function doesn't seem to be necessary here.
- */
-static struct meta_queue *meta_queue_new(void)
+static void early_label_meta_queue_free(struct meta_queue *mq, struct list *l,
+ struct zebra_vrf *zvrf)
{
- struct meta_queue *new;
- unsigned i;
+ struct wq_label_wrapper *w;
+ struct listnode *node, *nnode;
- new = XCALLOC(MTYPE_WORK_QUEUE, sizeof(struct meta_queue));
+ for (ALL_LIST_ELEMENTS(l, node, nnode, w)) {
+ if (zvrf && zvrf->vrf->vrf_id != w->vrf_id)
+ continue;
- for (i = 0; i < MQ_SIZE; i++) {
- new->subq[i] = list_new();
- assert(new->subq[i]);
- }
+ switch (w->type) {
+ case WQ_LABEL_FTN_UNINSTALL:
+ case WQ_LABEL_LABELS_PROCESS:
+ break;
+ }
- return new;
+ node->data = NULL;
+ XFREE(MTYPE_WQ_WRAPPER, w);
+ list_delete_node(l, node);
+ mq->size--;
+ }
}
-void meta_queue_free(struct meta_queue *mq)
+static void rib_meta_queue_free(struct meta_queue *mq, struct list *l,
+ struct zebra_vrf *zvrf)
{
- unsigned i;
+ struct route_node *rnode;
+ struct listnode *node, *nnode;
- 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]);
- else if (i == META_QUEUE_EVPN)
- evpn_meta_queue_free(mq->subq[i]);
+ for (ALL_LIST_ELEMENTS(l, node, nnode, rnode)) {
+ rib_dest_t *dest = rib_dest_from_rnode(rnode);
- list_delete(&mq->subq[i]);
- }
+ if (dest && rib_dest_vrf(dest) != zvrf)
+ continue;
- XFREE(MTYPE_WORK_QUEUE, mq);
+ route_unlock_node(rnode);
+ node->data = NULL;
+ list_delete_node(l, node);
+ mq->size--;
+ }
}
-void rib_meta_queue_free_vrf(struct meta_queue *mq, struct zebra_vrf *zvrf)
+static void early_route_meta_queue_free(struct meta_queue *mq, struct list *l,
+ struct zebra_vrf *zvrf)
{
- vrf_id_t vrf_id = zvrf->vrf->vrf_id;
- unsigned int i;
-
- for (i = 0; i < MQ_SIZE; i++) {
- struct listnode *lnode, *nnode;
- void *data;
- bool del;
+ struct zebra_early_route *zer;
+ struct listnode *node, *nnode;
- for (ALL_LIST_ELEMENTS(mq->subq[i], lnode, nnode, data)) {
- del = false;
-
- if (i == META_QUEUE_EVPN) {
- struct wq_evpn_wrapper *w = data;
+ for (ALL_LIST_ELEMENTS(l, node, nnode, zer)) {
+ if (zvrf && zer->re->vrf_id != zvrf->vrf->vrf_id)
+ continue;
- if (w->vrf_id == vrf_id) {
- XFREE(MTYPE_WQ_WRAPPER, w);
- del = true;
- }
- } else if (i ==
- route_info[ZEBRA_ROUTE_NHG].meta_q_map) {
- struct wq_nhg_wrapper *w = data;
-
- if (w->type == WQ_NHG_WRAPPER_TYPE_CTX &&
- w->u.ctx->vrf_id == vrf_id) {
- nhg_ctx_free(&w->u.ctx);
- XFREE(MTYPE_WQ_WRAPPER, w);
- del = true;
- } else if (w->type == WQ_NHG_WRAPPER_TYPE_NHG &&
- w->u.nhe->vrf_id == vrf_id) {
- zebra_nhg_free(w->u.nhe);
- XFREE(MTYPE_WQ_WRAPPER, w);
- del = true;
- }
- } else {
- struct route_node *rnode = data;
- rib_dest_t *dest = rib_dest_from_rnode(rnode);
+ XFREE(MTYPE_RE, zer);
+ node->data = NULL;
+ list_delete_node(l, node);
+ mq->size--;
+ }
+}
- if (dest && rib_dest_vrf(dest) == zvrf) {
- route_unlock_node(rnode);
- del = true;
- }
- }
+void meta_queue_free(struct meta_queue *mq, struct zebra_vrf *zvrf)
+{
+ enum meta_queue_indexes i;
- if (del) {
- list_delete_node(mq->subq[i], lnode);
- mq->size--;
- }
+ for (i = 0; i < MQ_SIZE; i++) {
+ /* Some subqueues may need cleanup - nhgs for example */
+ switch (i) {
+ case META_QUEUE_NHG:
+ nhg_meta_queue_free(mq, mq->subq[i], zvrf);
+ break;
+ case META_QUEUE_EVPN:
+ evpn_meta_queue_free(mq, mq->subq[i], zvrf);
+ break;
+ case META_QUEUE_EARLY_ROUTE:
+ early_route_meta_queue_free(mq, mq->subq[i], zvrf);
+ break;
+ case META_QUEUE_EARLY_LABEL:
+ early_label_meta_queue_free(mq, mq->subq[i], zvrf);
+ break;
+ case META_QUEUE_CONNECTED:
+ case META_QUEUE_KERNEL:
+ case META_QUEUE_STATIC:
+ case META_QUEUE_NOTBGP:
+ case META_QUEUE_BGP:
+ case META_QUEUE_OTHER:
+ rib_meta_queue_free(mq, mq->subq[i], zvrf);
+ break;
}
+ if (!zvrf)
+ list_delete(&mq->subq[i]);
}
+
+ if (!zvrf)
+ XFREE(MTYPE_WORK_QUEUE, mq);
}
/* initialise zebra rib work queue */
@@ -3186,17 +3821,6 @@ static void rib_addnode(struct route_node *rn,
rib_link(rn, re, process);
}
-static void rib_re_nhg_free(struct route_entry *re)
-{
- if (re->nhe && re->nhe_id) {
- assert(re->nhe->id == re->nhe_id);
- route_entry_update_nhe(re, NULL);
- } else if (re->nhe && re->nhe->nhg.nexthop)
- nexthops_free(re->nhe->nhg.nexthop);
-
- nexthops_free(re->fib_ng.nexthop);
-}
-
/*
* rib_unlink
*
@@ -3402,6 +4026,46 @@ void _route_entry_dump(const char *func, union prefixconstptr pp,
zlog_debug("%s: dump complete", straddr);
}
+static int rib_meta_queue_early_route_add(struct meta_queue *mq, void *data)
+{
+ struct zebra_early_route *ere = data;
+
+ listnode_add(mq->subq[META_QUEUE_EARLY_ROUTE], data);
+ mq->size++;
+
+ if (IS_ZEBRA_DEBUG_RIB_DETAILED)
+ zlog_debug(
+ "Route %pFX(%u) queued for processing into sub-queue %s",
+ &ere->p, ere->re->vrf_id,
+ subqueue2str(META_QUEUE_EARLY_ROUTE));
+
+ return 0;
+}
+
+struct route_entry *zebra_rib_route_entry_new(vrf_id_t vrf_id, int type,
+ uint8_t instance, uint32_t flags,
+ uint32_t nhe_id,
+ uint32_t table_id,
+ uint32_t metric, uint32_t mtu,
+ uint8_t distance, route_tag_t tag)
+{
+ struct route_entry *re;
+
+ re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
+ re->type = type;
+ re->instance = instance;
+ re->distance = distance;
+ re->flags = flags;
+ re->metric = metric;
+ re->mtu = mtu;
+ re->table = table_id;
+ re->vrf_id = vrf_id;
+ re->uptime = monotime(NULL);
+ re->tag = tag;
+ re->nhe_id = nhe_id;
+
+ return re;
+}
/*
* Internal route-add implementation; there are a couple of different public
* signatures. Callers in this path are responsible for the memory they
@@ -3417,162 +4081,25 @@ int rib_add_multipath_nhe(afi_t afi, safi_t safi, struct prefix *p,
struct prefix_ipv6 *src_p, struct route_entry *re,
struct nhg_hash_entry *re_nhe, bool startup)
{
- struct nhg_hash_entry *nhe = NULL;
- struct route_table *table;
- struct route_node *rn;
- struct route_entry *same = NULL, *first_same = NULL;
- int ret = 0;
- int same_count = 0;
- rib_dest_t *dest;
+ struct zebra_early_route *ere;
- if (!re || !re_nhe)
+ if (!re)
return -1;
assert(!src_p || !src_p->prefixlen || afi == AFI_IP6);
- /* Lookup table. */
- table = zebra_vrf_get_table_with_table_id(afi, safi, re->vrf_id,
- re->table);
- if (!table)
- return -1;
-
- if (re->nhe_id > 0) {
- nhe = zebra_nhg_lookup_id(re->nhe_id);
-
- if (!nhe) {
- flog_err(
- EC_ZEBRA_TABLE_LOOKUP_FAILED,
- "Zebra failed to find the nexthop hash entry for id=%u in a route entry",
- re->nhe_id);
-
- return -1;
- }
- } else {
- /* Lookup nhe from route information */
- nhe = zebra_nhg_rib_find_nhe(re_nhe, afi);
- if (!nhe) {
- char buf2[PREFIX_STRLEN] = "";
-
- flog_err(
- EC_ZEBRA_TABLE_LOOKUP_FAILED,
- "Zebra failed to find or create a nexthop hash entry for %pFX%s%s",
- p, src_p ? " from " : "",
- src_p ? prefix2str(src_p, buf2, sizeof(buf2))
- : "");
-
- return -1;
- }
- }
-
- /*
- * Attach the re to the nhe's nexthop group.
- *
- * TODO: This will need to change when we start getting IDs from upper
- * level protocols, as the refcnt might be wrong, since it checks
- * if old_id != new_id.
- */
- route_entry_update_nhe(re, nhe);
-
- /* Make it sure prefixlen is applied to the prefix. */
- apply_mask(p);
+ ere = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(*ere));
+ ere->afi = afi;
+ ere->safi = safi;
+ ere->p = *p;
if (src_p)
- apply_mask_ipv6(src_p);
-
- /* Set default distance by route type. */
- if (re->distance == 0)
- re->distance = route_distance(re->type);
-
- /* Lookup route node.*/
- rn = srcdest_rnode_get(table, p, src_p);
-
- /*
- * If same type of route are installed, treat it as a implicit
- * withdraw. If the user has specified the No route replace semantics
- * for the install don't do a route replace.
- */
- RNODE_FOREACH_RE (rn, same) {
- if (CHECK_FLAG(same->status, ROUTE_ENTRY_REMOVED)) {
- same_count++;
- continue;
- }
-
- /* Compare various route_entry properties */
- if (rib_compare_routes(re, same)) {
- same_count++;
-
- if (first_same == NULL)
- first_same = same;
- }
- }
-
- same = first_same;
-
- if (!startup &&
- (re->flags & ZEBRA_FLAG_SELFROUTE) && zrouter.asic_offloaded) {
- if (!same) {
- if (IS_ZEBRA_DEBUG_RIB)
- zlog_debug("prefix: %pRN is a self route where we do not have an entry for it. Dropping this update, it's useless", rn);
- /*
- * We are not on startup, this is a self route
- * and we have asic offload. Which means
- * we are getting a callback for a entry
- * that was already deleted to the kernel
- * but an earlier response was just handed
- * back. Drop it on the floor
- */
- rib_re_nhg_free(re);
-
- XFREE(MTYPE_RE, re);
- return ret;
- }
- }
-
- /* If this route is kernel/connected route, notify the dataplane. */
- if (RIB_SYSTEM_ROUTE(re)) {
- /* Notify dataplane */
- dplane_sys_route_add(rn, re);
- }
-
- /* Link new re to node.*/
- if (IS_ZEBRA_DEBUG_RIB) {
- rnode_debug(rn, re->vrf_id,
- "Inserting route rn %p, re %p (%s) existing %p, same_count %d",
- rn, re, zebra_route_string(re->type), same,
- same_count);
-
- if (IS_ZEBRA_DEBUG_RIB_DETAILED)
- route_entry_dump(p, src_p, re);
- }
-
- SET_FLAG(re->status, ROUTE_ENTRY_CHANGED);
- rib_addnode(rn, re, 1);
-
- /* Free implicit route.*/
- if (same) {
- ret = 1;
- rib_delnode(rn, same);
- }
+ ere->src_p = *src_p;
+ ere->src_p_provided = !!src_p;
+ ere->re = re;
+ ere->re_nhe = re_nhe;
+ ere->startup = startup;
- /* See if we can remove some RE entries that are queued for
- * removal, but won't be considered in rib processing.
- */
- dest = rib_dest_from_rnode(rn);
- RNODE_FOREACH_RE_SAFE (rn, re, same) {
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED)) {
- /* If the route was used earlier, must retain it. */
- if (dest && re == dest->selected_fib)
- continue;
-
- if (IS_ZEBRA_DEBUG_RIB)
- rnode_debug(rn, re->vrf_id, "rn %p, removing unneeded re %p",
- rn, re);
-
- rib_unlink(rn, re);
- }
- }
-
- route_unlock_node(rn);
- return ret;
+ return mq_add_handler(ere, rib_meta_queue_early_route_add);
}
/*
@@ -3583,7 +4110,7 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
struct nexthop_group *ng, bool startup)
{
int ret;
- struct nhg_hash_entry nhe;
+ struct nhg_hash_entry nhe, *n;
if (!re)
return -1;
@@ -3601,10 +4128,8 @@ int rib_add_multipath(afi_t afi, safi_t safi, struct prefix *p,
else if (re->nhe_id > 0)
nhe.id = re->nhe_id;
- ret = rib_add_multipath_nhe(afi, safi, p, src_p, re, &nhe, startup);
-
- /* In this path, the callers expect memory to be freed. */
- nexthop_group_delete(&ng);
+ n = zebra_nhe_copy(&nhe, 0);
+ ret = rib_add_multipath_nhe(afi, safi, p, src_p, re, n, startup);
/* In error cases, free the route also */
if (ret < 0)
@@ -3619,212 +4144,32 @@ void rib_delete(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
uint32_t nhe_id, uint32_t table_id, uint32_t metric,
uint8_t distance, bool fromkernel)
{
- struct route_table *table;
- struct route_node *rn;
- struct route_entry *re;
- struct route_entry *fib = NULL;
- struct route_entry *same = NULL;
- struct nexthop *rtnh;
- char buf2[INET6_ADDRSTRLEN];
- rib_dest_t *dest;
-
- assert(!src_p || !src_p->prefixlen || afi == AFI_IP6);
-
- /* Lookup table. */
- table = zebra_vrf_lookup_table_with_table_id(afi, safi, vrf_id,
- table_id);
- if (!table)
- return;
-
- /* Apply mask. */
- apply_mask(p);
- if (src_p)
- apply_mask_ipv6(src_p);
-
- /* Lookup route node. */
- rn = srcdest_rnode_lookup(table, p, src_p);
- if (!rn) {
- if (IS_ZEBRA_DEBUG_RIB) {
- char src_buf[PREFIX_STRLEN];
- struct vrf *vrf = vrf_lookup_by_id(vrf_id);
-
- if (src_p && src_p->prefixlen)
- prefix2str(src_p, src_buf, sizeof(src_buf));
- else
- src_buf[0] = '\0';
-
- zlog_debug("%s[%d]:%pRN%s%s doesn't exist in rib",
- vrf->name, table_id, rn,
- (src_buf[0] != '\0') ? " from " : "",
- src_buf);
- }
- return;
- }
-
- dest = rib_dest_from_rnode(rn);
- fib = dest->selected_fib;
-
- /* Lookup same type route. */
- RNODE_FOREACH_RE (rn, re) {
- if (CHECK_FLAG(re->status, ROUTE_ENTRY_REMOVED))
- continue;
-
- if (re->type != type)
- continue;
- if (re->instance != instance)
- continue;
- if (CHECK_FLAG(re->flags, ZEBRA_FLAG_RR_USE_DISTANCE) &&
- distance != re->distance)
- continue;
-
- if (re->type == ZEBRA_ROUTE_KERNEL && re->metric != metric)
- continue;
- if (re->type == ZEBRA_ROUTE_CONNECT &&
- (rtnh = re->nhe->nhg.nexthop)
- && rtnh->type == NEXTHOP_TYPE_IFINDEX && nh) {
- if (rtnh->ifindex != nh->ifindex)
- continue;
- same = re;
- break;
- }
-
- /* Make sure that the route found has the same gateway. */
- if (nhe_id && re->nhe_id == nhe_id) {
- same = re;
- break;
- }
-
- if (nh == NULL) {
- same = re;
- break;
- }
- for (ALL_NEXTHOPS(re->nhe->nhg, rtnh)) {
- /*
- * No guarantee all kernel send nh with labels
- * on delete.
- */
- if (nexthop_same_no_labels(rtnh, nh)) {
- same = re;
- break;
- }
- }
-
- if (same)
- break;
- }
- /* If same type of route can't be found and this message is from
- kernel. */
- if (!same) {
- /*
- * In the past(HA!) we could get here because
- * we were receiving a route delete from the
- * kernel and we're not marking the proto
- * as coming from it's appropriate originator.
- * Now that we are properly noticing the fact
- * that the kernel has deleted our route we
- * are not going to get called in this path
- * I am going to leave this here because
- * this might still work this way on non-linux
- * platforms as well as some weird state I have
- * not properly thought of yet.
- * If we can show that this code path is
- * dead then we can remove it.
- */
- if (fib && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE)) {
- if (IS_ZEBRA_DEBUG_RIB) {
- rnode_debug(rn, vrf_id,
- "rn %p, re %p (%s) was deleted from kernel, adding",
- rn, fib,
- zebra_route_string(fib->type));
- }
- if (zrouter.allow_delete ||
- CHECK_FLAG(dest->flags, RIB_ROUTE_ANY_QUEUED)) {
- UNSET_FLAG(fib->status, ROUTE_ENTRY_INSTALLED);
- /* Unset flags. */
- for (rtnh = fib->nhe->nhg.nexthop; rtnh;
- rtnh = rtnh->next)
- UNSET_FLAG(rtnh->flags,
- NEXTHOP_FLAG_FIB);
-
- /*
- * This is a non FRR route
- * as such we should mark
- * it as deleted
- */
- dest->selected_fib = NULL;
- } else {
- /* This means someone else, other than Zebra,
- * has deleted
- * a Zebra router from the kernel. We will add
- * it back */
- rib_install_kernel(rn, fib, NULL);
- }
- } else {
- if (IS_ZEBRA_DEBUG_RIB) {
- if (nh)
- rnode_debug(
- rn, vrf_id,
- "via %s ifindex %d type %d doesn't exist in rib",
- inet_ntop(afi2family(afi),
- &nh->gate, buf2,
- sizeof(buf2)),
- nh->ifindex, type);
- else
- rnode_debug(
- rn, vrf_id,
- "type %d doesn't exist in rib",
- type);
- }
- route_unlock_node(rn);
- return;
- }
- }
-
- if (same) {
- struct nexthop *tmp_nh;
-
- if (fromkernel && CHECK_FLAG(flags, ZEBRA_FLAG_SELFROUTE) &&
- !zrouter.allow_delete) {
- rib_install_kernel(rn, same, NULL);
- route_unlock_node(rn);
-
- return;
- }
-
- /* Special handling for IPv4 or IPv6 routes sourced from
- * EVPN - the nexthop (and associated MAC) need to be
- * uninstalled if no more refs.
- */
- for (ALL_NEXTHOPS(re->nhe->nhg, tmp_nh)) {
- struct ipaddr vtep_ip;
-
- if (CHECK_FLAG(tmp_nh->flags, NEXTHOP_FLAG_EVPN)) {
- memset(&vtep_ip, 0, sizeof(struct ipaddr));
- if (afi == AFI_IP) {
- vtep_ip.ipa_type = IPADDR_V4;
- memcpy(&(vtep_ip.ipaddr_v4),
- &(tmp_nh->gate.ipv4),
- sizeof(struct in_addr));
- } else {
- vtep_ip.ipa_type = IPADDR_V6;
- memcpy(&(vtep_ip.ipaddr_v6),
- &(tmp_nh->gate.ipv6),
- sizeof(struct in6_addr));
- }
- zebra_rib_queue_evpn_route_del(re->vrf_id,
- &vtep_ip, p);
- }
- }
+ struct zebra_early_route *ere;
+ struct route_entry *re = NULL;
+ struct nhg_hash_entry *nhe = NULL;
- /* Notify dplane if system route changes */
- if (RIB_SYSTEM_ROUTE(re))
- dplane_sys_route_del(rn, same);
+ re = zebra_rib_route_entry_new(vrf_id, type, instance, flags, nhe_id,
+ table_id, metric, 0, distance, 0);
- rib_delnode(rn, same);
+ if (nh) {
+ nhe = zebra_nhg_alloc();
+ nhe->nhg.nexthop = nexthop_dup(nh, NULL);
}
- route_unlock_node(rn);
- return;
+ ere = XCALLOC(MTYPE_WQ_WRAPPER, sizeof(*ere));
+ ere->afi = afi;
+ ere->safi = safi;
+ ere->p = *p;
+ if (src_p)
+ ere->src_p = *src_p;
+ ere->src_p_provided = !!src_p;
+ ere->re = re;
+ ere->re_nhe = nhe;
+ ere->startup = false;
+ ere->deletion = true;
+ ere->fromkernel = fromkernel;
+
+ mq_add_handler(ere, rib_meta_queue_early_route_add);
}
@@ -3835,36 +4180,23 @@ int rib_add(afi_t afi, safi_t safi, vrf_id_t vrf_id, int type,
uint8_t distance, route_tag_t tag, bool startup)
{
struct route_entry *re = NULL;
- struct nexthop *nexthop = NULL;
- struct nexthop_group *ng = NULL;
+ struct nexthop nexthop = {};
+ struct nexthop_group ng = {};
/* Allocate new route_entry structure. */
- re = XCALLOC(MTYPE_RE, sizeof(struct route_entry));
- re->type = type;
- re->instance = instance;
- re->distance = distance;
- re->flags = flags;
- re->metric = metric;
- re->mtu = mtu;
- re->table = table_id;
- re->vrf_id = vrf_id;
- re->uptime = monotime(NULL);
- re->tag = tag;
- re->nhe_id = nhe_id;
+ re = zebra_rib_route_entry_new(vrf_id, type, instance, flags, nhe_id,
+ table_id, metric, mtu, distance, tag);
/* If the owner of the route supplies a shared nexthop-group id,
* we'll use that. Otherwise, pass the nexthop along directly.
*/
if (!nhe_id) {
- ng = nexthop_group_new();
-
/* Add nexthop. */
- nexthop = nexthop_new();
- *nexthop = *nh;
- nexthop_group_add_sorted(ng, nexthop);
+ nexthop = *nh;
+ nexthop_group_add_sorted(&ng, &nexthop);
}
- return rib_add_multipath(afi, safi, p, src_p, re, ng, startup);
+ return rib_add_multipath(afi, safi, p, src_p, re, &ng, startup);
}
static const char *rib_update_event2str(enum rib_update_event event)
@@ -4367,6 +4699,11 @@ static void rib_process_dplane_results(struct thread *thread)
zebra_if_dplane_result(ctx);
break;
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
+ break;
+
/* Some op codes not handled here */
case DPLANE_OP_ADDR_INSTALL:
case DPLANE_OP_ADDR_UNINSTALL:
diff --git a/zebra/zebra_router.c b/zebra/zebra_router.c
index f7ad30b41f..c66849863e 100644
--- a/zebra/zebra_router.c
+++ b/zebra/zebra_router.c
@@ -239,13 +239,14 @@ void zebra_router_terminate(void)
zebra_router_free_table(zrt);
work_queue_free_and_null(&zrouter.ribq);
- meta_queue_free(zrouter.mq);
+ meta_queue_free(zrouter.mq, NULL);
zebra_vxlan_disable();
zebra_mlag_terminate();
zebra_neigh_terminate();
/* Free NHE in ID table only since it has unhashable entries as well */
+ hash_iterate(zrouter.nhgs_id, zebra_nhg_hash_free_zero_id, NULL);
hash_clean(zrouter.nhgs_id, zebra_nhg_hash_free);
hash_free(zrouter.nhgs_id);
hash_clean(zrouter.nhgs, NULL);
diff --git a/zebra/zebra_router.h b/zebra/zebra_router.h
index 0e2725c977..992bcd5c08 100644
--- a/zebra/zebra_router.h
+++ b/zebra/zebra_router.h
@@ -285,6 +285,11 @@ static inline void zebra_router_set_supports_nhgs(bool support)
zrouter.supports_nhgs = support;
}
+static inline bool zebra_router_in_shutdown(void)
+{
+ return atomic_load_explicit(&zrouter.in_shutdown, memory_order_relaxed);
+}
+
/* zebra_northbound.c */
extern const struct frr_yang_module_info frr_zebra_info;
diff --git a/zebra/zebra_script.c b/zebra/zebra_script.c
index d247f87708..2e2f4159cd 100644
--- a/zebra/zebra_script.c
+++ b/zebra/zebra_script.c
@@ -329,14 +329,6 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
lua_setfield(L, -2, "ipset");
break;
}
- case DPLANE_OP_ADDR_INSTALL:
- case DPLANE_OP_ADDR_UNINSTALL:
- case DPLANE_OP_INTF_ADDR_ADD:
- case DPLANE_OP_INTF_ADDR_DEL:
- case DPLANE_OP_INTF_INSTALL:
- case DPLANE_OP_INTF_UPDATE:
- case DPLANE_OP_INTF_DELETE:
- break;
case DPLANE_OP_NEIGH_INSTALL:
case DPLANE_OP_NEIGH_UPDATE:
case DPLANE_OP_NEIGH_DELETE:
@@ -418,6 +410,17 @@ void lua_pushzebra_dplane_ctx(lua_State *L, const struct zebra_dplane_ctx *ctx)
}
lua_setfield(L, -2, "gre");
+ case DPLANE_OP_ADDR_INSTALL:
+ case DPLANE_OP_ADDR_UNINSTALL:
+ case DPLANE_OP_INTF_ADDR_ADD:
+ case DPLANE_OP_INTF_ADDR_DEL:
+ case DPLANE_OP_INTF_INSTALL:
+ case DPLANE_OP_INTF_UPDATE:
+ case DPLANE_OP_INTF_DELETE:
+ case DPLANE_OP_TC_INSTALL:
+ case DPLANE_OP_TC_UPDATE:
+ case DPLANE_OP_TC_DELETE:
+ /* Not currently handled */
case DPLANE_OP_INTF_NETCONFIG: /*NYI*/
case DPLANE_OP_NONE:
break;
diff --git a/zebra/zebra_srv6.c b/zebra/zebra_srv6.c
index 219d047694..36506cacc7 100644
--- a/zebra/zebra_srv6.c
+++ b/zebra/zebra_srv6.c
@@ -162,6 +162,7 @@ void zebra_srv6_locator_delete(struct srv6_locator *locator)
}
listnode_delete(srv6->locators, locator);
+ srv6_locator_free(locator);
}
struct srv6_locator *zebra_srv6_locator_lookup(const char *name)
diff --git a/zebra/zebra_vrf.c b/zebra/zebra_vrf.c
index 553864d089..a2844ca956 100644
--- a/zebra/zebra_vrf.c
+++ b/zebra/zebra_vrf.c
@@ -218,7 +218,7 @@ static int zebra_vrf_disable(struct vrf *vrf)
if_nbr_ipv6ll_to_ipv4ll_neigh_del_all(ifp);
/* clean-up work queues */
- rib_meta_queue_free_vrf(zrouter.mq, zvrf);
+ meta_queue_free(zrouter.mq, zvrf);
/* Cleanup (free) routing tables and NHT tables. */
for (afi = AFI_IP; afi <= AFI_IP6; afi++) {
@@ -253,7 +253,7 @@ static int zebra_vrf_delete(struct vrf *vrf)
table_manager_disable(zvrf);
/* clean-up work queues */
- rib_meta_queue_free_vrf(zrouter.mq, zvrf);
+ meta_queue_free(zrouter.mq, zvrf);
/* Free Vxlan and MPLS. */
zebra_vxlan_close_tables(zvrf);
@@ -595,7 +595,7 @@ int zebra_vrf_netns_handler_create(struct vty *vty, struct vrf *vrf,
zlog_info(
"VRF %u already configured with NETNS %s",
vrf->vrf_id, ns->name);
- return CMD_WARNING_CONFIG_FAILED;
+ return CMD_WARNING;
}
}
ns = ns_lookup_name(pathname);
diff --git a/zebra/zebra_vxlan.c b/zebra/zebra_vxlan.c
index dbe1ce3e46..34cce71cd7 100644
--- a/zebra/zebra_vxlan.c
+++ b/zebra/zebra_vxlan.c
@@ -2090,6 +2090,7 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
int add)
{
struct zebra_evpn *zevpn = NULL;
+ struct zebra_l3vni *zl3vni = NULL;
/* There is a possibility that VNI notification was already received
* from kernel and we programmed it as L2-VNI
@@ -2117,6 +2118,10 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
/* Free up all remote VTEPs, if any. */
zebra_evpn_vtep_del_all(zevpn, 1);
+ zl3vni = zl3vni_from_vrf(zevpn->vrf_id);
+ if (zl3vni)
+ listnode_delete(zl3vni->l2vnis, zevpn);
+
/* Delete the hash entry. */
if (zebra_evpn_vxlan_del(zevpn)) {
flog_err(EC_ZEBRA_VNI_DEL_FAILED,
@@ -2172,8 +2177,12 @@ static int zebra_vxlan_handle_vni_transition(struct zebra_vrf *zvrf, vni_t vni,
/* Find bridge interface for the VNI */
vlan_if = zvni_map_to_svi(vxl->access_vlan,
zif->brslave_info.br_if);
- if (vlan_if)
+ if (vlan_if) {
zevpn->vrf_id = vlan_if->vrf->vrf_id;
+ zl3vni = zl3vni_from_vrf(vlan_if->vrf->vrf_id);
+ if (zl3vni)
+ listnode_add_sort_nodup(zl3vni->l2vnis, zevpn);
+ }
zevpn->vxlan_if = ifp;
zevpn->local_vtep_ip = vxl->vtep_ip;
@@ -4038,6 +4047,19 @@ int zebra_vxlan_dp_network_mac_add(struct interface *ifp,
struct zebra_evpn_es *es;
struct interface *acc_ifp;
+ /* If netlink message is with vid, it will have no nexthop.
+ * So skip it.
+ */
+ if (vid) {
+ if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
+ zlog_debug("dpAdd MAC %pEA VID %u - ignore as no nhid",
+ macaddr, vid);
+ return 0;
+ }
+
+ /* Get vxlan's vid for netlink message has no it. */
+ vid = ((struct zebra_if *)ifp->info)->l2info.vxl.access_vlan;
+
/* if remote mac delete the local entry */
if (!nhg_id || !zebra_evpn_nhg_is_local_es(nhg_id, &es)
|| !zebra_evpn_es_local_mac_via_network_port(es)) {
@@ -4049,7 +4071,7 @@ int zebra_vxlan_dp_network_mac_add(struct interface *ifp,
}
/* If local MAC on a down local ES translate the network-mac-add
- * to a local-inactive-mac-add
+ * to a local-active-mac-add
*/
if (IS_ZEBRA_DEBUG_VXLAN || IS_ZEBRA_DEBUG_EVPN_MH_MAC)
zlog_debug("dpAdd local-nw-MAC %pEA VID %u", macaddr, vid);
@@ -5126,10 +5148,9 @@ int zebra_vxlan_if_update(struct interface *ifp, uint16_t chgflags)
return 0;
/* Inform BGP, if there is a change of interest. */
- if (chgflags
- & (ZEBRA_VXLIF_MASTER_CHANGE |
- ZEBRA_VXLIF_LOCAL_IP_CHANGE |
- ZEBRA_VXLIF_MCAST_GRP_CHANGE))
+ if (chgflags &
+ (ZEBRA_VXLIF_MASTER_CHANGE | ZEBRA_VXLIF_LOCAL_IP_CHANGE |
+ ZEBRA_VXLIF_MCAST_GRP_CHANGE | ZEBRA_VXLIF_VLAN_CHANGE))
zebra_evpn_send_add_to_client(zevpn);
/* If there is a valid new master or a VLAN mapping change,
diff --git a/zebra/zserv.c b/zebra/zserv.c
index f76b29deff..ebe246ffbc 100644
--- a/zebra/zserv.c
+++ b/zebra/zserv.c
@@ -228,8 +228,7 @@ static void zserv_write(struct thread *thread)
case BUFFER_ERROR:
goto zwrite_fail;
case BUFFER_PENDING:
- atomic_store_explicit(&client->last_write_time,
- (uint32_t)monotime(NULL),
+ atomic_store_explicit(&client->last_write_time, monotime(NULL),
memory_order_relaxed);
zserv_client_event(client, ZSERV_CLIENT_WRITE);
return;
@@ -264,8 +263,7 @@ static void zserv_write(struct thread *thread)
case BUFFER_ERROR:
goto zwrite_fail;
case BUFFER_PENDING:
- atomic_store_explicit(&client->last_write_time,
- (uint32_t)monotime(NULL),
+ atomic_store_explicit(&client->last_write_time, monotime(NULL),
memory_order_relaxed);
zserv_client_event(client, ZSERV_CLIENT_WRITE);
return;
@@ -276,8 +274,8 @@ static void zserv_write(struct thread *thread)
atomic_store_explicit(&client->last_write_cmd, wcmd,
memory_order_relaxed);
- atomic_store_explicit(&client->last_write_time,
- (uint32_t)monotime(NULL), memory_order_relaxed);
+ atomic_store_explicit(&client->last_write_time, monotime(NULL),
+ memory_order_relaxed);
return;
@@ -748,7 +746,7 @@ static struct zserv *zserv_client_create(int sock)
client->wb = buffer_new(0);
TAILQ_INIT(&(client->gr_info_queue));
- atomic_store_explicit(&client->connect_time, (uint32_t) monotime(NULL),
+ atomic_store_explicit(&client->connect_time, monotime(NULL),
memory_order_relaxed);
/* Initialize flags */
diff --git a/zebra/zserv.h b/zebra/zserv.h
index 9986cc9f7e..db7b70d7c4 100644
--- a/zebra/zserv.h
+++ b/zebra/zserv.h
@@ -216,15 +216,15 @@ struct zserv {
*/
/* monotime of client creation */
- _Atomic uint32_t connect_time;
+ _Atomic uint64_t connect_time;
/* monotime of last message received */
- _Atomic uint32_t last_read_time;
+ _Atomic uint64_t last_read_time;
/* monotime of last message sent */
- _Atomic uint32_t last_write_time;
+ _Atomic uint64_t last_write_time;
/* command code of last message read */
- _Atomic uint32_t last_read_cmd;
+ _Atomic uint64_t last_read_cmd;
/* command code of last message written */
- _Atomic uint32_t last_write_cmd;
+ _Atomic uint64_t last_write_cmd;
/*
* Number of instances configured with